Слабое мерцание светодиодной ленты при нулевой скважности программного ШИМ
- Войдите на сайт для отправки комментариев
Добрый день. Столкнулся с такой проблемой: используя программный ШИМ при выставлении скважности на выходе 0 остается слабое свечение с мерцанием светодиодной ленты.
Вкладка программы
#define PIN_4 // подсветка FANfront №1 #define PIN_7 // подсветка FANtop int brightnessDDR = 0; // яркость модулей ОЗУ int fadeAmountDDR = 1; // прирощение яркости ОЗУ int modDDR = 0; // режим подсветки ОЗУ byte incomingByte; // переменная сериал void setup() { Init_PWM(); analog_Frequence(1); // предделитель от 1 до 7 частоты ШИМ pinMode(4, OUTPUT); pinMode(7, OUTPUT); Serial.begin(9600); // скорость порта 9600 } void loop() { if (Serial.available() > 0) { incomingByte = Serial.read() ; if(incomingByte == '0'){ modDDR = 0 ; Serial.println("Подсветка ОЗУ выключены") ; } else if (incomingByte == '1'){ modDDR = 1 ; Serial.println("Подсветка ОЗУ постоянный режим") ; } else if (incomingByte == '2'){ modDDR = 2 ; brightnessDDR = 0 ; Serial.println("Подсветка ОЗУ синхронная пульсация") ; } else if (incomingByte == '3'){ modDDR = 3 ; brightnessDDR = 0 ; Serial.println("Подсветка ОЗУ асинхронная пульсация") ; } } if (modDDR == 0) { brightnessDDR = 0 ; analog_Write(4, brightnessDDR) ; analog_Write(7, brightnessDDR) ; } if (modDDR == 1) { brightnessDDR = 50 ; analog_Write(4, brightnessDDR) ; analog_Write(7, brightnessDDR) ; } if (modDDR == 2) { analog_Write(4, brightnessDDR) ; analog_Write(7, brightnessDDR) ; brightnessDDR = brightnessDDR + fadeAmountDDR ; if (brightnessDDR == 0 || brightnessDDR == 50) { fadeAmountDDR = -fadeAmountDDR ; } } if (modDDR == 3) { analog_Write(4, 50-brightnessDDR) ; analog_Write(7, brightnessDDR) ; brightnessDDR = brightnessDDR + fadeAmountDDR ; if (brightnessDDR == 0 || brightnessDDR == 50) { fadeAmountDDR = -fadeAmountDDR ; } } delay(40); }
Вкладка PWM
#ifdef ALL #define PIN_0 #define PIN_1 #define PIN_2 #define PIN_3 #define PIN_4 #define PIN_5 #define PIN_6 #define PIN_7 #define PIN_8 #define PIN_9 #define PIN_10 #define PIN_11 #define PIN_12 #define PIN_13 #define PIN_14 #define PIN_15 #define PIN_16 #define PIN_17 #define PIN_18 #define PIN_19 #endif #define SBI(port, pin) asm volatile ("sbi %0, %1" :: "I" (_SFR_IO_ADDR(port)), "I" (pin)) #define CHECK(pwms, port, pin) \ asm volatile ( \ "cpc %0, %1 \n\t" \ "brlo 0f \n\t" \ "cbi %2, %3 \n\t" \ "rjmp 1f \n\t" \ "0: sbi %2, %3 \n\t" \ "1: nop \n\t" \ : "+r" (pwm), "+r" (pwms) \ : "I" (_SFR_IO_ADDR(port)), "I" (pin)\ )\ void Init_PWM() { cli(); TCCR2A = 0; TCCR2B = 3; //CLK OCR2A = 1; TIMSK2 = 2; //разрешаем прерывание по совпадению sei(); #ifdef PIN_0 SBI(DDRD, 0); #endif #ifdef PIN_1 SBI(DDRD, 1); #endif #ifdef PIN_2 SBI(DDRD, 2); #endif #ifdef PIN_3 SBI(DDRD, 3); #endif #ifdef PIN_4 SBI(DDRD, 4); #endif #ifdef PIN_5 SBI(DDRD, 5); #endif #ifdef PIN_6 SBI(DDRD, 6); #endif #ifdef PIN_7 SBI(DDRD, 7); #endif #ifdef PIN_8 SBI(DDRB, 0); #endif #ifdef PIN_9 SBI(DDRB, 1); #endif #ifdef PIN_10 SBI(DDRB, 2); #endif #ifdef PIN_11 SBI(DDRB, 3); #endif #ifdef PIN_12 SBI(DDRB, 4); #endif #ifdef PIN_13 SBI(DDRB, 5); #endif #ifdef PIN_14 SBI(DDRC, 0); #endif #ifdef PIN_15 SBI(DDRC, 1); #endif #ifdef PIN_16 SBI(DDRC, 2); #endif #ifdef PIN_17 SBI(DDRC, 3); #endif #ifdef PIN_18 SBI(DDRC, 4); #endif #ifdef PIN_19 SBI(DDRC, 5); #endif } volatile uint8_t pwm; volatile uint8_t pwms[20]; void analog_Frequence(byte prescaler) { TCCR2B = prescaler; //CLK } void analog_Write(byte pin, byte value) { pwms[pin] = value; } byte analog_State(byte pin) { return pwms[pin]; } ISR(TIMER2_COMPA_vect) { asm volatile ("clr %0" : "+r" (TCNT2)); // TCNT2 = 0; #ifdef PIN_0 CHECK(pwms[0], PORTD, 0); #endif #ifdef PIN_1 CHECK(pwms[1], PORTD, 1); #endif #ifdef PIN_2 CHECK(pwms[2], PORTD, 2); #endif #ifdef PIN_3 CHECK(pwms[3], PORTD, 3); #endif #ifdef PIN_4 CHECK(pwms[4], PORTD, 4); #endif #ifdef PIN_5 CHECK(pwms[5], PORTD, 5); #endif #ifdef PIN_6 CHECK(pwms[6], PORTD, 6); #endif #ifdef PIN_7 CHECK(pwms[7], PORTD, 7); #endif #ifdef PIN_8 CHECK(pwms[8], PORTB, 0); #endif #ifdef PIN_9 CHECK(pwms[9], PORTB, 1); #endif #ifdef PIN_10 CHECK(pwms[10], PORTB, 2); #endif #ifdef PIN_11 CHECK(pwms[11], PORTB, 3); #endif #ifdef PIN_12 CHECK(pwms[12], PORTB, 4); #endif #ifdef PIN_13 CHECK(pwms[13], PORTB, 5); #endif #ifdef PIN_14 CHECK(pwms[14], PORTC, 0); #endif #ifdef PIN_15 CHECK(pwms[15], PORTC, 1); #endif #ifdef PIN_16 CHECK(pwms[16], PORTC, 2); #endif #ifdef PIN_17 CHECK(pwms[17], PORTC, 3); #endif #ifdef PIN_18 CHECK(pwms[18], PORTC, 4); #endif #ifdef PIN_19 CHECK(pwms[19], PORTC, 5); #endif asm volatile ("inc %0" : "+r" (pwm)); //pwm++; }
Схема управления нагрузкой собрана на мосфетах IRF520, токоограничительные резисторы затвора 100 Ом, подтягивающие резисторы 10 кОм, лента 12 В пробовал на разных светодиодах, эффект один и тот же.
Без ардуино лента не горит вообще, утечки через мосфет нет, напряжение на выходе ардуино при скважности 0 тестером не померить, несколько милливольт, осцилографа к сожалению нет. Свечение появляется только после запуска программы контроллера и перехода в режим "отключено".
Информации по этому поводу не нашел в интернете. Само мерцание меня не напрягает и в режиме, когда лента горит или "дышит" - незаметно для глаза. Но почему при скважности 0 на затворе мосфета остается потенциал, который заставляет ленту подсвечиваться мне не понятно.
Если возможно, подскажите вариант аппаратной или программной корректировки. Было желание увеличить токоограничительный резистор, или уменьшить подтягивающий, но под рукой нет других номиналов, поможет ли это?
Заранее благодарю за ответ! Не судите строго, если просмотрел эту тему на форуме, но инфу нашел только о сглаживании пульсаций ШИМ.
ArhAngeL, неоднократно обсуждали. У ШИМа таймером нет нулевого дьюти. Загляните в родную дуиновскую функцию analogWrite, и всё поймёте.
ArhAngeL, неоднократно обсуждали. У ШИМа таймером нет нулевого дьюти. Загляните в родную дуиновскую функцию analogWrite, и всё поймёте.
Спасибо. Буду разбираться. Я так понимаю это никак не вылечить.
digitalWrite(pin, LOW) ?
конденсатор припаять к ленте - уберет мерцание
номинал подберете сами исходя из мощности ленты
Спасибо. Буду разбираться. Я так понимаю это никак не вылечить.
Очень пессимистично дорогой товарищ! Есть как минимум 2 способа, один из них в дуиновской функции.
digitalWrite(pin, LOW) ?
Попробовал на скорую руку - эффект тот же. Завтра плотно позанимаюсь.
конденсатор припаять к ленте - уберет мерцание
номинал подберете сами исходя из мощности ленты
Спасибо, но проблема не в наличии мерцания, о нем и метоах борьбы с ним я в курсе.
Очень пессимистично дорогой товарищ! Есть как минимум 2 способа, один из них в дуиновской функции.
2 часа рыл интернет, стандартные функции управления уровнем на пинах не дают ничего.
Я считал, что это гарантированно отключает PWM на пине:
Я считал, что это гарантированно отключает PWM на пине:
Спасибо, попробую завтра. Не силён в синтаксисе, значения менять в строке void digitalWrite(uint8_t pin, uint8_t val) pin = номер пина, а val в данном случае 0?
Не совсем понимаю зачем вам менять там что-то. Это исходный код digitalWrite() - внутри себя он выключает PWM на пине перед тем, как установить HIGH или LOW. Так что, на мой взгляд, использование этой функции должно было купировать проблему с мерцанием, если оно действительно вызывано работой PWM.