題:
使用PWM時LED的非線性亮度校正
Toby Jaffey
2010-03-23 04:43:17 UTC
view on stackexchange narkive permalink

用PWM驅動LED時,亮度(我認為是亮度)不會隨佔空比線性變化。亮度緩慢上升,然後隨佔空比呈指數增加。

誰能建議使用經驗法則作為校正因子或其他解決方法?

當我製作一對Knight Rider袖扣時,我不得不使用x ^ 10來使淡出效果看起來不錯!
您確定不是“亮度最初呈指數增長,然後緩慢上升”嗎?
我相信我們的眼睛對亮度做出對數響應。
九 答案:
starblue
2010-03-24 02:17:08 UTC
view on stackexchange narkive permalink

從理論上講,它應該是指數級的,但是通過使用二次函數,我獲得了最好的淡入淡出結果。

我還認為您倒數了。在低佔空比下,感知到的亮度增加遠大於幾乎在整個佔空比下(幾乎看不到亮度增加)。

另請參見[伽瑪校正](https://en.wikipedia.org/wiki/Gamma_correction#Power_law_for_video_display)。
BG100
2011-03-06 17:50:37 UTC
view on stackexchange narkive permalink

在過去的幾天裡,我一直在研究這個問題,因為我有同樣的問題...試圖以可見的線性方式使用PWM調光LED,但是我想要完整的256步分辨率。嘗試猜測256個數字以手動創建曲線不是一件容易的事!

我不是專業的數學家,但是我足夠了解通過結合一些函數和公式來生成一些基本曲線的知識,而實際上並不知道他們如何工作。我發現使用電子表格(我使用Excel)可以處理一組從0到255的數字,在下一個單元格中放置一些公式,然後對它們進行圖形繪製。

我正在使用pic彙編程序進行衰落,因此您甚至可以獲取電子表格以使用公式( =“ retlw 0x” & DEC2HEX(A2))生成彙編程序代碼。

在使用LOG和SIN函數,這兩個函數的平均值以及其他一些東西之後,我真的不能得到正確的曲線。發生的情況是,淡入淡出的中間部分比較高和較低的水平慢。同樣,如果在淡入淡出之後立即進行淡入淡出,則強度會出現明顯的尖峰。 (我認為)需要一條S曲線。

Wikipedia的快速搜索提出了S曲線所需的公式。我將其插入到電子表格中,並進行了一些調整以使其在我的值範圍內相乘,然後得出以下結論:

S curve

我使用的Excel公式是:

  = 1 /(1 + EXP((((A2 / 21)-6)* -1))* 255  

,其中A2是A列中的第一個值,每個值都會增加A3,A4,...,A256。

I不知道這在數學上是否正確,但是會產生所需的結果。

這是我使用的全套256個級別:

  0x00,0x00 ,0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x00、0x01、0x01、0x01、0x01、0x01、0x01,
0x01、0x01、0x01、0x01、0x01、0x01、0x01、0x01、0x01、0x02、0x02、0x02、0x02、0x02、0x02、0x02、0x02、0x02、0x03、0x03、0x03、0x03、0x03、0x03、0x03 0x04、0x04、0x04、0x04、0x05、0x05、0x05、0x05、0x06、0x06、0x06、0x07、0x07、0x07、0x08、0x08、0x08、0x09、0x09、0x0A,0x0A,0x0B,0x0B,0x0B 0x0D,0x0D,0x0E,0x0F,0x0F,0x10、0x11、0x11、0x12、0x13、0x14、0x15、0x16、0x17、0x18、0x19、0x1A,0x1B,0x1C,0x1D,0x1F,0x20、0x20 0x26、0x27、0x29、0x2B,0x2C,0x2E,0x30、0x32、0x34、0x36、0x38、0x3A,0x3C,0x3E,0x40、0x43、0x45、0x47、0x4A,0x4C,0x4F,0x51、0x51 0x5C,0x5F,0x62、0x64、0x67、0x6A,0x6D,0x70、0x73、0x76、0x79、0x7C,0x7F,0x82、0x85、0x88、0x8B,0x8E,0x91、0x94、0x97、0x9A,0x9A,0x9A 0xA5、0xA7、0xAA,0xAD,0xAF,0xB2、0xB4、0xB7、0xB9、0xBB,0xBE,0xC0、0xC2、0xC4、0xC6、0xC8、0xCA,0xCC,0xCE,0xD0、0xD0、0xD2、0xD0、0xD2 0xDA,0xDB,0xDD,0xDE,0xDF,0xE1、0xE2、0xE3、0xE4、0xE5、0xE6、0xE7、0xE8、0xE9、0xEA,0xEB,0xEC,0xED,0x ED,0xEE,0xEF,0xEF,0xF0、0xF1、0xF1、0xF2、0xF2、0xF3、0xF3、0xF4、0xF4、0xF5、0xF5、0xF6、0xF6、0xF6、0xF7、0xF7、0xF7、0xF7、0xF7 0xF9、0xF9、0xF9、0xFA,0xFA,0xFA,0xFA,0xFA,0xFB,0xFB,0xFB,0xFB,0xFB,0xFB,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFD,0xFD,0xFD 0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,0xFF  
>
這個方程對我來說非常合適。
Axeman
2010-03-23 13:34:06 UTC
view on stackexchange narkive permalink

對於16級,很容易“手動”製作一個簡單的查找表,並將4位值轉換為8位值以傳遞給PWM控制器:這是我在FPGA led陣列中使用的組件驅動程序。對於8位級別的控制器,您至少需要從查詢表中輸出11-12位。

 庫IEEE;使用IEEE.Std_logic_1164.all;實體線性化isport (reqlev:in std_logic_vector(3降至0); pwmdrive:out std_logic_vector(7降至0))); end Linearize; Linearize的體系結構LUT以reqlev選擇pwmdrive < =“ 00000000”,“ 0000”,“ 00000010”,“ 0001”,“ 00000100”,“ 0010”,“ 00000111”,“ 0011”,“ 00001011”當“ 0100”,“ 00010010”,“ 0101”,“ 00011110”,“ 0110”,“ 00101000”,“ 0111”,“ 00110010”,“ 1000”,“ 01000001”,“ 1001”,“ 01010000”時“ 1010”,“ 01100100”,“ 1011”,“ 01111101”,“ 1100”,“ 10100000”,“ 1101”,“ 11001000”,“ 1110”,“ 11111111”,“ 1111”,“ 00000000”結束LUT;  
我試圖弄清楚您的公式是什麼。它非常接近f(x)= x ^ 2,但是曲線還不夠深。 f(x)= x ^ 3/13使我更加接近。
這不是公式(不是故意的)...我已經猜到線性化器的初始值了:-)。然後,我為陣列供電,以亮度順序驅動led列,並調整值以獲得均勻的斜率。只有16個級別,這真的很容易。
AiliwartshCMT - looks more like \$2^n\$ to me: the first `1` bit more or less shifts left 1 position to the left with each step.
tash
2014-07-07 05:26:43 UTC
view on stackexchange narkive permalink

我當時正在使用ATtiny照明甲板。亮度是通過連接到ADC引腳的電位計來控制的。

嘗試了指數函數,基於此的PWM輸出似乎使感知的亮度線性增加。

我正在使用此公式:

  out = pow(out_max,in / in_max) 

Attiny85 @ 8MHz大約需要210us來執行上述計算。為了提高性能,做了一個查詢表。由於輸入來自10位ADC,並且ATtiny內存受到限制,因此我也想創建一個較短的表。

與其創建具有1024個條目的查找表,不如創建具有256個條目(512個)的反向查找表字節)在程序存儲器(PGMEM)中。編寫了一個函數來對該表執行二進制搜索。每次查找僅需28uS。如果使用直接查找表,它將需要2kb的內存,但是查找只需要4uS左右。

查找表中的計算值僅使用輸入範圍32-991,丟棄ADC的較低/較高範圍,以防電路出現問題。

下面是我現在所擁有的。

 // anti_log測試程序/ * LED連接到PIN6(PB1)* /#define LED 1 // //反日誌(反向)查找表格// y = 0-255(pwm輸出),y_range = 256 // x = 0-1023(10位ADC輸入); // //假設無法使用ADC輸出值的較低/較高端//放棄前32個值和後32個值.// min_x = 32,max_x = 1023-min_x,x_range = 1024-2 * min_x // ANTI_LOG [y] = round(x_range * log(y,base = y_range)+ min_x)//給定x值,在下表下執行二進制查找// Attiny85 @ 8MHz clock大約花費28uS PROGMEM prog_uint16_t ANTI_LOG [] = {0x0000,0x0020, 0x0098、0x00de,0x0110、0x0137、0x0156、0x0171、0x0188、0x019c,0x01af,0x01bf,0x01ce,0x01dc,0x01e9、0x01f5、0x0200、0x020a,0x0214、0x021e,0x2540、0x0f,0x020、0x020、0x020、0x020、0x020、0x020、0x020、0x020、0x020、0x020、0x020、0x0207 0x025b,0x0261、0x0267、0x026d,0x0273,
0x0278、0x027d,0x0282、0x0288、0x028c,0x0291、0x0296、0x029a,0x029f,0x02a3、0x02a7、0x02ab,0x02af,0x02b3、0x02b7、0x02bb,0x02be,0x02c2 0、0x02c2 0、0x02c2、0x02c2 0 0x02dc,0x02df,0x02e2、0x02e5、0x02e8、0x02eb,0x02ed,0x02f0、0x02f3、0x02f5、0x02f8、0x02fa,0x02fd,0x0300、0x0302、0x0304、0x0307、0x1 0、0x10、0x10 0、0x10 0、0x10 0、0x10 0、0x10 0 0x031b,0x031d,0x031f,0x0321、0x0323、0x0325、0x0327、0x0329、0x032b,0x032d,0x032f,0x0331、0x0333、0x0334、0x0336、0x0338、0x033a,0x033c,0x033d,0x033c,0x0334、0x0330、0x0330、0x0330、0x0330、0x0330、0x0332、0x0330、0x0330、0x0332、0x0330 0x0349、0x034b,0x034c,0x034e,0x034f,0x0351、0x0352、0x0354、0x0355、0x0357、0x0358、0x035a,0x035b,0x035d,0x035e,0x0360、0x0361、0x0363、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360、0x0360 0 0x036d,0x036f,0x0370、0x0371、0x0372、0x0374、0x0375、0x0376、0x0378、0x0379、0x037a,0x037b,0x037c,0x037e,0x037f,0x0380、0x0381、0x0382、0x0383、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、0x0380、00380 x038a,0x038b,0x038c,0x038e,0x038f,0x0390、0x0391、0x0392、0x0393、0x0394、0x0395、0x0396、0x0397、0x0398、0x0399、0x039a,0x039b,0x039c,0x039d,0x0a,0x0a,0x0a,0x03a 0 0x03a4、0x03a5、0x03a6、0x03a7、0x03a8、0x03a9、0x03aa,0x03ab,0x03ab,0x03ac,0x03ad,0x03ae,0x03af,0x03b0、0x03b1、0x03b2、0x03b3、0x03b6、0x03b4、0x03b3、0x03b4、0x03b4、0x03b4、0x03b4、0x03b4、0x03b4、0x03b4、0x03b4、0x03b3 0x03ba,0x03bb,0x03bc,0x03bd,0x03be,0x03bf,0x03bf,0x03c0、0x03c1、0x03c2、0x03c3、0x03c3、0x03c4、0x03c5、0x03c6、0x03c7、0x030、0x03c7、0x030、0x03c7、0x03b,0x03c7、0x03b 0x03ce,0x03cf,0x03d0、0x03d0、0x03d1、0x03d2、0x03d3、0x03d3、0x03d4、0x03d5、0x03d6、0x03d6、0x03d7、0x03d8、0x03d8、0x03d9、0x03d0、03x03 0d,0x03d0、03x03 0d,0x03d0、03x03 0d,0x03d9、0x03d0、03x03 0d,0x03d0、0x03d0、03x03 0d,0x03d0、03x03 0d,0x03d0, ; //使用上表進行二進制查找。byte antilog(int x){byte y = 0x80; int av; for(int i = 0x40; i> 0; i >> = 1){av = pgm_read_word_near(ANTI_LOG + y);如果(av> x){
y-= i; } if(av < x){y | = i; } else {返回y;如果(pgm_read_word_near(ANTI_LOG + y)> x){y-= 1; } return y;} void setup(){pinMode(LED,OUTPUT); digitalWrite(LED,LOW);}#定義MIN_X 0#定義MAX_X 1024void loop(){int i; // antilog_drive for(i = MIN_X; i<MAX_X; i ++){AnalogWrite(LED,antilog(i));延遲(2); } for(--i; i> = MIN_X; i--){AnalogWrite(LED,antilog(i));延遲(2); } delay(1000); //線性驅動for(i = MIN_X; i<MAX_X; i ++){AnalogWrite(LED,i >> 2);延遲(2); } for(-i; i> = MIN_X; i--){AnalogWrite(LED,i >> 2);延遲(2); } delay(2000);} 
davr
2010-03-23 06:05:41 UTC
view on stackexchange narkive permalink

我發現了這個傢伙,他使用一種稱為“反日誌驅動器”的方法。這是他的信息的直接下載鏈接

FarO
2017-01-24 05:20:26 UTC
view on stackexchange narkive permalink

此PDF解釋了所需的曲線,顯然是對數曲線。如果您有線性調光器(您的PWM值),則該函數應為對數。

在這裡,您可以找到8位PWM的32級亮度查找表。

此處 16個步驟。

Jacob Yiendedoi
2019-06-15 03:10:42 UTC
view on stackexchange narkive permalink

這是我根據 arduino論壇回复做的事情。 我已經計算出0到255之間的值,因此可以很容易地在arduino上與pwm一起使用

  byte ledLookupTable [] = {0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1, 1,2,2,2,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,5,6,6,6,7,7,7, 8,8,8,9,9,9,10,10,11,11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18, 19,19,20,20,21,21,22,23,23,24,24,25,26,26,27,28,28,29,30,30,31,32,32,33,34, 35,35,36,37,38,38,39,40,41,42,42,43,44,45,46,47,47,48,49,50,51,52,53,54,55, 56,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,73,74,75,76,77,78,79,80, 81,82,84,85,86,87,88,89,91,92,93,94,95,97,98,99,100,102,103,104,105,107,108,109,111,112,113,115,116,117,119,120,121,123,124,126,127,128,130,131,133,134,136,137,139,140,​​142,143,145,146,148,149,151,152,154,155,157,158,160,162,163,165,166,168,170,171,173,175,176,178,180,181,183,185,186,188,190,192,193,195,197,199,200,202,204,206,207,209,211,213,215,217,218,220,222,224,226,228,230,232,233,235,237,239,241,243,245,247,249,251,253,255};
 

然後在Arduino上使用就可以做到:

  analogWrite(ledPin,ledLookupTable [brightness]); //亮度在0到255之間
 

希望對某些人有幫助;)

user112358
2019-06-17 23:16:46 UTC
view on stackexchange narkive permalink

我現在正在處理這個問題,並且我採用的方法略有不同。我想要256級亮度,但是將線性0-255範圍映射到非線性0-255範圍會逐漸結束,正如您在其他一些答案中所看到的那樣,其中包含大量重複項。 (即,您的多個輸入值會產生相同的亮度級別。)

我嘗試修改算法以將0-256輸入範圍映射到0-1023輸出範圍,但是即使有多個值映射到0,所以我嘗試了一些不同的操作-我使用的是0 -255級別使用 sin()生成0-769範圍內的非線性值(即1023減去255),然後將其添加到輸入級別以獲取0-1023範圍內的輸出沒有重複。我將配置一個計時器以使用1023計數器,並根據我想要的照明級別(0-255)將PWM輸出的比較器設置為查找表中的值。

這是我用來生成查詢表的C程序:

  #include <stdio.h>
#include <math.h>

int main(){
    我
    雙j;
    int k;

    printf(“ int bright [] = {\ n”);
    for(i = 0; i<256; i ++){
        // 0-255 = > 1.0-0.0,乘以90度(以弧度為單位)
        j =(1-(i / 255.0))* M_PI / 2;
        j = sin(j);
        k =(1023-255)-j *(1023-255);
        printf(“%s%d%s%s”,
                ((((i%8)== 0)?“”:“”),//行首的前導空格
                k + i
                ((i < 255)?“,”:“”),//逗號,除了最後一個值
                ((((i%8)== 7)?“ \ n”:“”)//每8個項目換行
              );
    }
    printf(“}; \ n”);
}
 

這是桌子:

  int亮度[] = {
    0、1、2、3、4、5、6、7
    8、10、11、12、14、15、16、18,
    19、21、22、24、25、27、29、30,
    32、34、35、37、39、41、43、44
    46、48、50、52、54、56、58、61,
    63、65、67、69、72、74、76、78,
81、83、86、88、91、93、96、98,
    101、103、106、109、111、114、117、120,
    122、125、128、131、134、137、140、143,
    146、149、152、155、158、161、164、168,
    171、174、177、181、184、187、191、194,
    198、201、205、208、212、215、219、222,
    226、230、233、237、241、244、248、252,
    256、260、263、267、271、275、279、283,
    287、291、295、299、303、307、312、316,
    320、324、328、333、337、341、345、350,
    354、358、363、367、372、376、381、385,
    390、394、399、403、408、412、417、422,
    426、431、436、440、445、450、455、459,
    464、469、474、479、484、489、493、498,
    503、508、513、518、523、528、533、538,
    543、548、554、559、564、569、574、579,
    584、590、595、600、605、610、616、621,
    626、632、637、642、647、653、658、664,
    669、674、680、685、690、696、701、707,
    712、718、723、729、734、740、745、751,
    756、762、767、773、778、784、790、795,
    801、806、812、818、823、829、834、840,
    846、851、857、863、868、874、880、885,
    891、897、902、908、914、920、925、931,
    937、942、948、954、960、965、971、977,
    982、988、994、1000、1005、1011、1017、1023
};
 

啟動並運行該功能後,我可能會研究其他功能(例如 log())。



該問答將自動從英語翻譯而來。原始內容可在stackexchange上找到,我們感謝它分發的cc by-sa 2.0許可。
Loading...