• Главная
  • Блог
  • Компенсация ШИМ для равномерного свечения диодов

Компенсация ШИМ для равномерного свечения диодов

Это статья про то, как добиться более-менее равномерного изменения яркости светодиода с помощью ШИМ. Если лень читать, чтожно посмотреть минутный ролик. Если не лень - добро пожаловать под кат.

 

Для управления яркостью светодиодами используется ШИМ (широтно-импульсная модуляция). Изменяя скважность импульсов, подаваемых на диод, можно добиться плавного изменения уровня яркости.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// название для пина 6
#define LED_PIN 6
 
// текущий уровень "яркости" светодиода
uint8_t level = 0;
// шаг изменения "яркости" светодиода
int8_t lstep = 1;
 
void setup(){}
 
void loop(){
  // увеличение или уменьшение уровня "яркости" на шаг
  level += lstep;
  // если уровень достиг верхнего или нижнего предела - 
  // меняем шаг на противоположный
  if (level == 255 || level == 0) 
    lstep *= -1;
  // генерация ШИМ
  analogWrite(LED_PIN,level);
  // отдыхаем, оно шимит само
  delay(10);
}

Однако, как показывает практика, яркость светодиода зависит от скважности нелинейно. Можно увидеть, что диод сначала прибавляет в яркости очень быстро и выходит на почти максимальное значение, а затем изменения в яркости практически незаметны.

Другими словами, если мы изменим желаемый уровень яркости с 1 на 2, то реально яркость изменятся, условно, на 100 единиц, а если мы изменим желаемый уровень яркости с 254 на 255, то реально яркость изменится на 1 единицу.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// названия для пинов
#define LIN_PWM_PIN 5
#define LOG_PWM_PIN 6
#define SIN_PWM_PIN 9
 
// логарифмическая таблица
const int logPwm[256] = {
  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  3,
  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,  5,  5,  6,  6,
  6,  6,  6,  7,  7,  7,  7,  7,  8,  8,  8,  8,  8,  9,  9,  9,
  9,  10, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13,
  13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17,
  17, 17, 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 21, 21, 21,
  21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26,
  26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31,
  32, 32, 32, 33, 33, 34, 34, 34, 35, 35, 35, 36, 36, 37, 37, 37,
  38, 38, 39, 39, 40, 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 44,
  45, 45, 46, 46, 47, 47, 48, 48, 49, 49, 50, 51, 51, 52, 52, 53,
  53, 54, 55, 55, 56, 56, 57, 58, 58, 59, 59, 60, 61, 62, 62, 63,
  64, 64, 65, 66, 67, 67, 68, 69, 70, 71, 71, 72, 73, 74, 75, 76,
  77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 88, 89, 90, 91, 93, 94,
  96, 97, 98, 100,102,103,105,107,109,111,113,115,117,120,122,125,
  127,130,134,137,141,145,149,154,159,165,173,181,191,204,223,255
};
 
// синусоидальная таблица
const int sinPwm[256] = {
  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  1,
  1,  1,  1,  1,  1,  1,  1,  1,  1,  2,  2,  2,  2,  2,  2,  2,
  2,  2,  3,  3,  3,  3,  3,  3,  4,  4,  4,  4,  4,  5,  5,  5,
  5,  6,  6,  6,  7,  7,  7,  8,  8,  8,  9,  9,  10, 10, 11, 11,
  12, 12, 13, 13, 14, 15, 15, 16, 17, 17, 18, 19, 20, 21, 22, 23,
  24, 25, 26, 27, 28, 29, 31, 32, 33, 35, 36, 38, 39, 41, 43, 44,
  46, 48, 50, 52, 54, 56, 57, 60, 62, 64, 67, 69, 71, 74, 76, 79,
  81, 84, 87, 89, 92, 95, 98, 100,103,106,109,112,115,118,121,124,
  127,130,133,136,139,142,145,147,151,154,156,159,162,165,167,170,
  174,175,178,180,183,185,187,190,192,194,196,198,200,202,204,206,
  208,210,211,213,215,216,218,219,221,222,223,225,226,227,228,229,
  230,231,232,233,234,235,236,237,237,238,239,239,240,241,241,242,
  242,243,243,244,244,245,245,246,246,246,247,247,247,248,248,248,
  249,249,249,249,250,250,250,250,250,251,251,251,251,251,251,252,
  252,252,252,252,252,252,252,252,253,253,253,253,253,253,253,253,
  253,253,253,253,253,253,253,254,254,254,254,254,254,254,255,255
};
 
// текущий уровень "яркости" светодиода
uint8_t level = 0;
// шаг изменения "яркости" светодиода
int8_t lstep = 1;
 
void setup(){}
 
void loop(){
  // увеличение или уменьшение уровня "яркости" на шаг
  level += lstep;
  // если уровень достиг верхнего или нижнего предела - 
  // меняем шаг на противоположный
  if (level == 255 || level == 0) 
    lstep *= -1;
  // генерация ШИМ
  analogWrite(LIN_PWM_PIN,level);
  analogWrite(LOG_PWM_PIN,logPwm[level]);
  analogWrite(SIN_PWM_PIN,sinPwm[level]);
  // отдыхаем, оно шимит само
  delay(10);
}

 

 

 

Метки: программирование, Arduino, hack, код, ШИМ

Добавить комментарий