10 разрядный шим ардуино как запустить не выходит

Тема в разделе "Arduino & Shields", создана пользователем Дятел, 26 апр 2022.

  1. Дятел

    Дятел Нерд

    Нужно регулировать свет светодиода с градацией больше, чем 255.
    1023 подходит, но не Выходит!! :(
    Не получается запустить analogWrite(9, 1023);
    Суть проблемы в том, что нормально отрабатывает до 255 а потом светодиод начинает гореть тусклее.
    Для тех, кто не в курсе, ардуино не может полноценно перестроится с 8ми битного на 10 битный шим.

    Проблема, как понял, распространенная, но вот с решением, проблемы.
    Вроде кто пишет что проблема решена, так не могу врубиться, как запустить в loop это решение.
    1.
    Пример:
    Код (C++):
    /* Вызываем для изменения скважности) */
    void analogWrite16(uint16_t value) { OCR1A = value;}

    /* Вызываем в setup() */
    void setup16bitPWM () {
    pinMode(9,OUTPUT);
    TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
    TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
    ICR1=1023;
    OCR1A=512; //50% default value
    }

    void setup() {
    Serial.begin(9600);
    analogReference(INTERNAL);
    setup16bitPWM();

    }
    В Loop чего писать? что бы допустим было как
    Код (Text):

    analogWrite(bluePin, 0);
    delay(1000);
    analogWrite(bluePin, 255);
    delay(1000);
    analogWrite(bluePin, 767);
    delay(1000);
    analogWrite(bluePin, 1023);
    delay(1000);
     

    2.
    А вот еще решение:
    Код (C++):
    bool en;

    void setup()
    {
        DDRB |= 1<<PB1;
        DDRB |= 1<<PB2;
        PORTB &= ~(1<<PB2);
        //TCCR1A=(1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);
    TCCR1A=(1<<COM1A1) | (1<<COM1B0) | (1<<WGM11);
        TCCR1B = _BV(WGM13) | _BV(WGM12)  | _BV(CS10);
        ICR1 =16383 ;
    }
    void loop()
    {
        en = 1;
         for (int i=0; i<5000; i++) {  // на 9 плавно загорается светодиод
                OCR1A = i;
                _delay_ms(1);
            }
    // включает светодиод на  10 пине
        (en) ? PORTB |= (1<<PB2) : PORTB &= ~(1<<PB2);// как понять что это 10 пин?
     }
    Проблемы с этим кодом, что на 9м пине светодиод не развивает полной яркости.

    3.

    И, почему именно до 5000? что это за цифра такая?

    4.
    Просьба, прокомментировать каждую строчку примера N2, пусть не подробно, но хотя бы хоть общее представление иметь что она делает. А то в документацию лезть с полным непониманием бесполезно :)
    Оператор FOR? можно не комментировать. А так же, void setup(), void loop() :)

    5.
    То же самое (наладить) надо будет сделать и еще на 2 любых других пинах.
    10, 11. Других вариантах, как понимаю не может быть?

    Пронумеровал все вопросы и примеры, что бы легче было отвечать.
    Спасибо.

     
  2. DetSimen

    DetSimen Гик

    если сам читать не умеешь, то обучение коррекционных поцыэнтов - 1500р в час, минималка - 2 часа
     
  3. Airbus

    Airbus Радиохулиган Модератор

    А мне вот интересно стало—а человеческий глаз сможет заметить 1023 оттенка? Где то смотрел киношку где утверждалось что человек видит только 50 градаций серого. Или вопрос чисто теоретический? Тогда берем Blink и правим как нам надо тобишь меняем скважность импульсов ( отношение делеев HIGH/LOW) вручную енкодером или кнопками или по usart или как пожелаете
     
    SergeiL нравится это.
  4. Airbus

    Airbus Радиохулиган Модератор

    Еще тема—увидел на канале у Пуного Звера про китайскую НАНУ—Wawgat. Там АЦП имеет бОльшую разрядность не 1024 а 4096. Так может и ШИМ другой не на 256?
     
    Дятел нравится это.
  5. b707

    b707 Гуру

    И не получится. analogWrite() не умеет больше 255

    Надо понимать, что если вы перестраиваете таймер на 10битный ШИМ - вы отказываетесь от использования ардуиновских функций и ардуиновское analogWrite() использовать нельзя. надо записывать скважность ШИМ прямо в регистры таймера
     
    Andrey12 и Дятел нравится это.
  6. Дятел

    Дятел Нерд

    Спасибо, но надо было в личку слать, а не сообщать на всю Ивановскую! Теперь там очередь и записали только на 27апреля 2023 года! :(

    Хочется управлять не только оттенками, но и яркостью одновременно

    Точно, у меня такая уже 2 года валяется. Спасибо за идею, надо попробовать. И, там действительно 4096 разрядность. Помню, меня это сильно удивило, хотя процессор там Atmel 328P, якобы :)

    Ах вот оно что, теперь многое прояснилось.

    То есть первая строка задает частоту генератора?
    Если да, то что это за цифра: 5000 откуда она берется?
    И, почему в крайнем значении 5000 светодиод не набирает полную яркость?

    _delay_ms -А зачем это? мы же задали частоту. И почему не просто delay?
     
  7. b707

    b707 Гуру

    если вы про эту:
    Код (C++):
    OCR1A = i;
    то она задает не частоту. а скважность
     
  8. Дятел

    Дятел Нерд

    А, ну да, так логичнее, спасибо. Как в analogWrite(9, i); был бы второй параметр i . Я понял, что (i>=0 and i<=255). Просто как аналогия для усвоения материала
    А это ( _delay_ms(1); ) тогда зачем, в том же примере?
    OCR1A = i;
    _delay_ms(1);
     
  9. b707

    b707 Гуру

    без делея весь цикл пролетит за десятую секунды. никаких измений на светики не заметите
     
    Дятел нравится это.
  10. Дятел

    Дятел Нерд

    Вроде стало прояснятся немного. Как понял, максимальное значение задается тут ICR1 =16383
    Максимальное заполнение будет
    OCR1A = 16382;
    или
    OCR1A = 16383;
    ??

    Не пойму, почему, если после OCR1A = 16382; использовать
    digitalWrite(9, HIGH);
    или
    analogWrite(9,255);
    ТО все хитрые настройки регистра сбиваются и светодиод перестает реагировать на управление: OCR1A = 16382;
    то есть больше не мигает по OCR1A = 16382; но продолжает мигать по digitalWrite(9, HIGH);
    пример
    Код (C++):
    OCR1A = 16382;
    delay (3000);
    OCR1A = 0;
    delay (500);
    digitalWrite(9, HIGH);      //ВКЛ
    delay (1000);
    digitalWrite(9, LOW);      //ВыКЛ
    delay (1000);
     
  11. b707

    b707 Гуру

    наверно ардуиновские функции возвращают таймер к дефольным настройкам... но точно не скажу, надо в исходнике смотреть
     
    Дятел нравится это.
  12. akl

    akl Гуру

    для увеличения битов вроде надо правильно прописать WGM10 WGM11 WGM12 WGM13
    Код (C++):
    Биты WGM13 (4) , WGM12 (3) регистра TCCR1B и биты WGM11 (1) , WGM10 (0) регистра TCCR1A устанавливают режим работы таймера/счетчика T1:

        0000 - обычный режим
        0001 - коррекция фазы PWM, 8-бит
        0010 - коррекция фазы PWM, 9-бит
        0011 - коррекция фазы PWM, 10-бит
        0100 - режим счета импульсов (OCR1A) (сброс при совпадении)
        0101 - PWM, 8-бит
        0110 - PWM, 9-бит
        0111 - PWM, 10-бит
    ну и функцией аналогВрайт пользоваться не стоит, хотя бы потому что там при значении 255 будет дигиталВрайт(ХАЙ)

    так же надо учесть уменьшение частоты и уменьшить делитель
     
  13. akl

    akl Гуру

    надо делать так
    TCCR1A |= (1<<COM1A1);
    OCR1A = 16382;
    потому что дигиталВрайт отключает шим
     
  14. b707

    b707 Гуру

    это только пол-таблицы... если уж разбираться, то надо тогда все в даташите читать. там про таймер1 не так и много, страниц 30 всего :)
     
  15. akl

    akl Гуру

    да не надо там 30 страниц читать. у меня всё с полстраницы летает

    но я не понимаю откуда цифра 16382
    ведь это 14 битов, а у нас максимум 10

    а понял там на второй половине страницы еще один режим
    1110 - PWM (ICR1)
     
    Последнее редактирование: 26 апр 2022
  16. b707

    b707 Гуру

    в-оот! а говорили читать не надо... :)
     
  17. parovoZZ

    parovoZZ Гуру

    Я на бредбоарде подробнейшим образом расписывал решение.,
    И да - чувствительность глаза - логарифмическая кривая, поэтому использовать все 1023 шага линейно нерационально. Я про это тоже писал.
     
  18. Дятел

    Дятел Нерд

    Решил использовать такой код, как п1. в первом сообщении
    Получилось на 9 пине повесить синий светодиод.
    Стал прикручивать зеленый на 10 пин.
    Вот так заработал зеленый на 10м

    Код (C++):

    /* Вызываем для изменения скважности) */
    void analogWriteBlue16(uint16_t value) { OCR1A = value;}
    void analogWriteGreen16(uint16_t value) { OCR1B = value;}
    /* Вызываем в setup() */
    void setupBlue16bitPWM () {
    pinMode(9,OUTPUT);
    TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
    TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
    ICR1=1023;
    OCR1A=512; //50% default value
    }

    void setupGreen16bitPWM () {
    //TCCR1A=0;
    //TCCR1B=0;
    pinMode(10,OUTPUT);

    /*
        PORTB &= ~(1<<PB2);
        TCCR1A=(1<<COM1A1) | (1<<COM1B1) | (1<<WGM11);//зеленый 10 пин
        //TCCR1A=(1<<COM1A1) | (1<<COM1B0) | (1<<WGM11); // синий 9 пин
        TCCR1B = _BV(WGM13) | _BV(WGM12)  | _BV(CS10);
        ICR1 =16383 ;
    */

    //PORTB &= ~(1<<PB2);
    TCCR1A=(1<<COM1B0) | (1<<COM1B1) | (1<<WGM11);//зеленый 10 пин
    ////////////TCCR1A=(1<<COM1A1)|(1<<COM1A0)|(1<<WGM11);
    //TCCR1B=(1<<WGM13)|(1<<WGM12)|(1<<CS10); //mode14 FastPwm
    ICR1=1023;
    //OCR1B=512; //50% default value

    ///TCCR1A |=(1 << COM1A1);
    ///TCCR1A |=(1 << COM1B1);//my

    //TCCR1A = 0b00000011;  // 10bit
    //TCCR1B = 0b00001011;  // x64 fast pwm
    }


    void setup() {
    Serial.begin(9600);
    analogReference(INTERNAL);
    setupBlue16bitPWM();
    setupGreen16bitPWM();
    }

    void loop() {
      /*
      analogWriteBlue16(1024-1023);
      delay(1000);
      analogWriteBlue16(1024-500);
      delay(1000);

        analogWriteBlue16(1024-1);
      delay(1000);
      */



      analogWriteGreen16(1024-1023);
      delay(1000);
      analogWriteGreen16(1024-500);
      delay(1000);

        analogWriteGreen16(1024-1);
      delay(1000);


    }

     
    Но если раскомментирую вывод синего, и комментирую зелены (что бы не мешал смотреть)
    ТО синий не светит, а светит зеленый. причем постоянным светом, а должен менять яркость. Раньше менял.
    Код (C++):

      analogWriteBlue16(1024-1023);
      delay(1000);
      analogWriteBlue16(1024-500);
      delay(1000);

        analogWriteBlue16(1024-1);
      delay(1000);
     

    /*
      analogWriteGreen16(1024-1023);
      delay(1000);
      analogWriteGreen16(1024-500);
      delay(1000);

        analogWriteGreen16(1024-1);
      delay(1000);
    */

     
    Как понимаю, не получается указать каким пином хочу управлять.
    Не нашел где в регистрах можно указать какой пин хочу использовать
    Таймер то один на оба, но согласно начитанному, вроде можно управлять каждым пином как хочется.
    Дело усложняет, что 1й таймер еще и 16ти бинтый. Может с 8ми битными и полегче? еще не разбирался. А придется, красный цвет надо сажать на 3й таймер

    Вроде надо менять что-то тут.
    TCCR1A = 0b00000011; // 10bit
    TCCR1B = 0b00001011; // x64 fast pwm
    В таблицах указывают значения битов что бы сменить тип и и частоту шим. Но как понимаю, тут можно еще и указать, на каком пине.
    Ил неправильно понимаю, а если правильно, то не смог найти, какой бит за каой пин отвечает
    Нашел вот такую интересную статейку,
    http://electrik.info/microcontrolle...upravleniya-portami-vvoda-vyvoda-arduino.html
    но непонятно написано, не смог усвоить про
    • PORTB – Управление состоянием вывода. Если пин находится в режиме «Выхода», то 1 и 0 определяют наличие этих же сигналов на
    • DDRB – регистр направления порта. С его помощью вы указываете микроконтроллеру чем является порт – входом или выходом, при этом «1» - выход, а «0» - вход.
      В общем, прошу помощи. Поможите кто можете! :) Или, хотя бы направление задайте :)
     
  19. parovoZZ

    parovoZZ Гуру

    На 328 нет, на тиньке 441/841 - да.
     
    Дятел нравится это.