Биения ШИМ-ов

Тема в разделе "Arduino & Shields", создана пользователем Karabas, 12 май 2016.

  1. Karabas

    Karabas Гик

    Всем привет!
    Беда, как обычно пишла откуда не ждали :D
    Был собран контроллер света, четре канала, три-ШИМ один-ночничек (три белых светодиода теплого лампового света).
    И вот вдруг выяснилось, что светодиодные ленты мерцают:eek:
    Очень быстро выяснилось, что мерцание появляется если работают минимум две ленты и одна из них на 9ом пине. Использовал 5, 6 и 9 пины соответственно.
    Частота ШИМ 490 Гц, но на 5 и 6 около 1кГц.
    10 и 11 заняты радиомодулем, от одного 3го толку мало.

    Можно ли как то безболезненно поднять частоту 9го или снизить 5 и 6го?
    Так же расмативал вариант аппаратного ШИМ-а, то там может возникнуть конфликт с таймерами и не заклинит ли его при исполнении основного кода (там не много, но все же).
    Подключенные библиотеки:
    #include <SPI.h>
    #include "nRF24L01.h"
    #include "RF24.h"
    #include <IRremote.h>
     
  2. Alex19

    Alex19 Гуру

    Не все библиотеки знаю, но если у Вас есть рабочий ШИМ и необходимо просто увеличить частоту, то да. Какая примерная частота нужна на 9-том, какая нужна на 5 и 6?

    У Вас UNO?
     
  3. Karabas

    Karabas Гик

    У меня Nano, но по сути та-же Uno.
    Было бы неплохо поднять на 9ом до ~980 Гц (вроде-бы точное значение на 5 и 6- 976 Гц).
    Ну и как резервный вариант, 5 и 6- 490 Гц, на случай, если что то закофликтует по первому таймеру.
    Вообще, чисто теоретически, если какая то библиотека использует тот же таймер, при изменении частоты Шим работоспособность сохранится?
     
  4. Alex19

    Alex19 Гуру

    Да, только в экономичной упаковке.:)

    К вечеру сделаю, мне сейчас самому надо поднять до 8Khz, надо вспомнить как делал и документацию почитать на Atmega328.

    Хм, если в библиотеки используется тот же таймер, то увеличение частоты ШИМ-а, на ШИМ не повлияет. Но теоретически может повлиять на библиотеки, так как увеличение частоты ШИМ-а это изменение настройки таймера.
     
  5. Alex19

    Alex19 Гуру

    Получить, по быстрому заданные Вами 1Khz, не удалось. Одним изменением пределителя таймера тут не отделаешься, но возможно это и не нужно.

    Попробуйте этот код на 4Khz, добавьте его в setup.
    Код (C++):

    cli(); // Запрещаем все прерывания.
    TCCR1B = TCCR1B & B11111000 | B00000010; // Устанавливаем предделитель таймера 1 к 8.
    sei(); // Разрешаем обратно все прерывания.
    А дальше работайте как и работали.

    UPD. Мне уже не требуется ШИМ 8Khz, попробуйте возможно данного решения хватит, но если требуется именно 1Khz пишите, продолжу разбираться.
     
    Последнее редактирование: 14 май 2016
    Karabas нравится это.
  6. Alex19

    Alex19 Гуру

    Разобрался, вот код именно 1Khz, добавьте его в setup.
    Код (C++):

    cli(); // Запрещаем все прерывания.
    TCCR1A = TCCR1A & B11111100 | B00000011;
    TCCR1B = TCCR1B & B11111000 | B00000010; // Устанавливаем предделитель таймера 1 к 8.
    sei(); // Разрешаем обратно все прерывания.
    А дальше работайте как и работали.

    В плавную настройку не вникал, просто запустил ШИМ в режиме - PWM, Phase Correct, 10-bit.
     
    Karabas нравится это.
  7. Karabas

    Karabas Гик

    Спасибо огромное! Завтра все запущу и доложу как оно полетело :)

    Такой вопросик, как вернуть все обратно, просто залить скетч без установки делителя? То есть, этот код меняет параметры на время работы или прошивает железо?
     
  8. Alex19

    Alex19 Гуру

    Не за что, тут все помогаю друг другу по мере сил и времени. Увы не знаю как это отразится на библиотеках.

    Просто удалить эти сроки из setup, да кстати код
    Код (C++):
    byte PWM_PIN = 9;

    int pwm_value;

    void setup()
    {

      pinMode(PWM_PIN, OUTPUT);
      Serial.begin(115200);

      cli(); // Запрещаем все прерывания.
      TCCR1A = TCCR1A & B11111100 | B00000011;
      TCCR1B = TCCR1B & B11111000 | B00000010; // Устанавливаем предделитель таймера 1 к 8.
      sei(); // Разрешаем обратно все прерывания.
    }
    void loop() {
      analogWrite(PWM_PIN, 40);
    }
     
    Код грубый, чтобы просто показать куда вставлять данную секцию.

    Как только зальете другой скетч или уберете данную секцию, все вернется как было. Это просто настройка таймера 1.
     
  9. Karabas

    Karabas Гик

    Изменить частоту получилось и вродебы ничего не навернулось, но вот мигание не исчезло, но стало заметно реже, где-то раз в полсекунды.
    Так же рассмотрел в картонную трубку, что этот канал действительно мигает, а не накладывается свет (или как там), похоже какие то помехи на мосфите. Но зато теперь понятна зависимость от частот.
    Попробую собрать простенький осцилограф, чтоб посмотреть что там и как, ну и накину кондеров в разных местах.

    Но в любом случае спасибо вам за код, весьма полезная штука.
     
  10. Alex19

    Alex19 Гуру

    Тогда можно увеличить значительно частоту ШИМ, примерно на 32Khz. Сегодня не доберусь до контролеров, но завтра к вечеру постараюсь.
     
  11. Karabas

    Karabas Гик

    Думаювы правы, чем больше будет разница, тем "мельче" будут "миги".
    Но аппаратную часть тоже нужно проверить, может где "сопля".
     
  12. Alex19

    Alex19 Гуру

    Это точно.

    Скачал pdf, инет на работе ужас, но все равно жду специалиста.
    Попробуйте данный код.
    Код (C++):
    cli();// Запрещаем все прерывания.
    TCCR1B = TCCR1B & B11111000 | B00000001; // Устанавливаем предделитель таймера 1 к 1.
    sei();// Разрешаем обратно все прерывания.
    На железе сейчас проверить не смогу, он должен дать ШИМ около 64KHz. Если он не поможет, скорее всего у Вас аппаратная проблема.
     
    Karabas нравится это.
  13. Karabas

    Karabas Гик

    С вашей последней правкой все работает как надо:), по началу немного глючило из за конденсатора (зарезал ШИМ). Ничего не мигает (хотя у меня уже в глазах и так все мигает от этих светодиодов).
    И, радость-радость, ни радиомодуль, ни IR приемник не пострадали.