即時的平均值自動亮度調整

近期製作新的時鐘新增了一項功能: 讓顯示器的亮度能夠自動隨環境的亮度做調整,可以避免晚上太亮太刺眼或白天看不清楚的問題。原先的做法就是每一分鐘會讀取AD的值並由讀值來調整顯示器亮度,這種做法雖然能達成自動亮度調整但稍嫌不完美,例如睡前將燈光關閉後可能得等上一分鐘才會調整好舒適的亮度。如果為了解決這個問題而將取樣率及亮度更新率提高到每秒鐘或十秒鐘一次,萬一AD的讀值剛好在調整亮度的臨界值(顯示器的亮度分為8個階級)就會讓亮度一直改變,可能會困擾使用者。

以下方法可以獲取一段時間的平均值並將亮度即時地調整、又不會因為微小的變化或臨界值造成亮度不斷的改變。邏輯上就是將當前的AD讀值加進一個變數中,再把最舊的數值(480次前的數值,由陣列紀錄)減去,做為處理後的信號源。
int ad = A5;
int led = 9;

int arr[480] = { 0 };
long avg_value = 0;
int pwm;
int i=0;

void setup() {
  pinMode(ad, INPUT);
  Serial.begin(115200);
}

void loop() {
  Serial.print(millis()/1000, DEC);
  Serial.print("$ ");
  arr[i] = analogRead(ad);
  avg_value+=arr[i];
  Serial.print("current: ");
  Serial.print(arr[i], DEC);
  if(i==480) {
    i=0;
    avg_value-=arr[i];
  }
  else {
    avg_value-=arr[++i];
  }
    

  pwm = map(avg_value, 0, 491040, 0, 7); //將加總值量化為0~7, analogRead() max value=1023, 1023*480 times = 491040
  pwm = map(pwm, 0, 7, 10, 255);
  analogWrite(led, pwm); //將量化後的值(0~7)輸出至PWM,最低亮度(0)的PWM值為10、最高亮度(7)的PWM值為255

  Serial.print("   avg: ");
  Serial.print((avg_value/480), DEC);
  Serial.print("   pwm: ");
  Serial.println(pwm, DEC);
  delay(125);
}

留言

這個網誌中的熱門文章

無法被取代的指針型三用電表(一):前言

關於新唐科技NuMicro ISP的介紹和使用方式

新唐火神板開箱實作(一):NuMaker-Volcano與NuEclipse IDE入門篇