ШИМ и светодиод

Тема в разделе "Микроконтроллеры AVR", создана пользователем ELITE, 20 ноя 2018.

  1. ELITE

    ELITE Гик

    Код (C++):


    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>

    //макросы для включения, выключения светодиодов
    //низкий уровень - на ножке 0 вольт, высокий уровень - на ножке 5 вольт
    #define LED1_OFF PORTB &= ~(1<<PB0); //Низкий уровень ножки PB0 (синий)
    #define LED2_OFF PORTB &= ~(1<<PB1); //Низкий уровень ножки PB1 (зеленый)
    #define LED3_OFF PORTB &= ~(1<<PB2); //Низкий уровень ножки PB2 (красный)
    #define LED1_ON PORTB |= _BV(PB0);  //Высокий уровень ножки PB0
    /*#define LED1_ON PORTB |= (1<<PB0);  //Высокий уровень ножки PB0 */
    #define LED2_ON PORTB |= (1<<PB1);  //Высокий уровень ножки PB1
    #define LED3_ON PORTB |= (1<<PB2); //Высокий уровень ножки PB2

    #define ANALOG_IN PB3 //ADC3

    uint8_t counter=0, i=0, j=0, ci=0;
    uint8_t lev_ch[3];
    uint8_t ch[3];
    uint8_t mods = 0; //кнопки выбора режима
    uint16_t vol = 0;

    ISR(TIM0_OVF_vect){

      if (++counter==0) //счетчик перехода таймера через ноль
      {
      LED1_ON; LED2_ON; LED3_ON; // PORTB |=(1<<PB0)|(1<<PB1)|(1<<PB2); //подаем 1 на все каналы BGR (0=B 1=G 2=R)
      }
     
      if (counter>=lev_ch[0]) LED1_OFF; //подаем 0 на канал
      if (counter>=lev_ch[1]) LED2_OFF; //по достижении
      if (counter>=lev_ch[2]) LED3_OFF; //заданной длительности.

    }
    ISR(ADC_vect){// срабатывает при каждом окончании замера напряжения

      vol = ADCH;
    if (vol > 0 && vol <= 28 ) mods=1; /*   0 авто       */
    if (vol > 28 && vol <= 32 ) mods=2; /*   1    r   */
    if (vol > 32 && vol <= 41 ) mods=3; /*   2    g   */
    if (vol > 41 && vol <= 44 ) mods=4; /*   1-2       */
    if (vol > 44 && vol <= 50 ) mods=5; /*   3    b   */
    if (vol > 50 && vol <= 69 ) mods=6; /*   1-3       */
    if (vol > 69 && vol <= 101 ) mods=7; /*   2-3       */
    if (vol > 101 && vol <= 130 ) mods=8; /*  4    белый    */
    if (vol > 240 && vol <= 255 ) mods=9; /*  5  ноч бел 1/3 яркости     */

    }



    int main(void)
    {
      DDRB=0b00000111; // установка PortB пины 0,1,2 выходы
      TCCR0B = _BV(CS00);   // таймер работает без предделителя
      TIMSK0 = _BV(TOIE0);// прерывания по переполнению таймера разрешены  

    // Настройка АЦП: http://avr-prog.blogspot.com/2014/02/attiny13_5.html
      ADMUX =  0b00100011; // опорное напряжение - VCC, левое ориентирование данных, выбран вход ADC2(pb4) (на нём висит перем. резистор)

     
      ADCSRA = 0b11101111; // АЦП включен, запуск преобразования, режим автоизмерения, прерывание по окончанию преобразования, частота CLK/128
      ADCSRB = 0b00000000; // режим автоизмерения: постоянно запущено
      DIDR0 |= (1 << ANALOG_IN); // запрещаем цифровой вход на ноге аналогового входа

     
      sei();// глобально прерывания так же разрешены

      lev_ch[0]=0;     //Синий цвет
      lev_ch[1]=0;     //Зеленый цвет
      lev_ch[2]=0;     //Красный цвет



    while (1)     //бесконечная шарманка
      {

    //lev_ch[0]=127;  _delay_ms (200);
    //lev_ch[0]=255;  _delay_ms (200);
    //lev_ch[0]=192;  _delay_ms (200);

    // for (int i = 0; i<=8;i++){lev_ch[0]<<1; _delay_ms (20);}
    //for (int i = 0; i<vol;i++) {lev_ch[0]=127;  _delay_ms (20);   lev_ch[0]=0;  _delay_ms (20);}  _delay_ms (500);
    /****************************************/  
    mods=1;
      if (mods==1) {     //формирование с полными переходами
     
           j=i++/2;
           if (j==0) ci++;    
           
           if( ci==0) {      lev_ch[0]=j;       lev_ch[1]=0;      lev_ch[2]=127;         }
           if( ci==1) {      lev_ch[0]=127;     lev_ch[1]=0;      lev_ch[2]=127-j;       }
           if( ci==2) {      lev_ch[0]=127;     lev_ch[1]=j;      lev_ch[2]=0;           }
           if( ci==3) {      lev_ch[0]=127-j;   lev_ch[1]=127;    lev_ch[2]=0;           }
           if( ci==4) {      lev_ch[0]=0;       lev_ch[1]=127;    lev_ch[2]=j;           }
           if( ci==5) {      lev_ch[0]=0;       lev_ch[1]=127-j;  lev_ch[2]=127;    ci=0;      }
       
           // _delay_us(10000); //Пауза 5мс
           _delay_ms (25);
        }
                     //   синий             зелены            красный
        if (mods==2) {  lev_ch[0]=0;       lev_ch[1]=0;      lev_ch[2]=127;   }     //красный
        if (mods==3) {  lev_ch[0]=0;       lev_ch[1]=127;    lev_ch[2]=0;     }     //зеленый
        if (mods==4) {  lev_ch[0]=0;       lev_ch[1]=90;     lev_ch[2]=127;   }       //желтый
        if (mods==5) {  lev_ch[0]=127;     lev_ch[1]=0;      lev_ch[2]=0;     }     //синий
        if (mods==6) {  lev_ch[0]=127;     lev_ch[1]=0;      lev_ch[2]=127;   }       //сиреневый
        if (mods==7) {  lev_ch[0]=115;     lev_ch[1]=127;    lev_ch[2]=0;     }       //изумрудный
        if (mods==8) {  lev_ch[0]=127;     lev_ch[1]=127;    lev_ch[2]=127;   }         //белый
        if (mods==9) {  lev_ch[0]=5;       lev_ch[1]=5;      lev_ch[2]=5;    }         //белый 30%
     
      }
    }
     
  2. Что это такое? Это ваш код? И где шим? Где мап? Где таблица? Почему вы сначала говорите про библиотеку ардуино, а потом приводите код для голого авр?
     
  3. Asper Daffy

    Asper Daffy Иксперд

    И 20 языков выше университетского, я в курсе.

    В общем, если у тебя мап на 13-ой тиньке 500Кб сжирает, то тогда конечно. Сказал бы сразу, я бы и не дёргался :(
     
    DetSimen нравится это.
  4. ELITE

    ELITE Гик

    - у тини13 всего 2 аппаратных ШИМа - а мне надо 3 - он сделан программно
    - мап и таблицу я убрал - не проходят по ресурсам, код "текущий" без корректировки шима :(
    - почему про ардуино? - потому, что код пишу, компилирую и прошиваю через IDE (прошиваю по средствам меги по спи)
     
  5. parovoZZ

    parovoZZ Гуру

    судя по коду - он для всех трех сделан программно?
     
  6. ELITE

    ELITE Гик

    да
     
  7. parovoZZ

    parovoZZ Гуру

    Ставь вторую тиню рядом))
     
  8. ELITE

    ELITE Гик

    зачем? по сути аппаратный и программный ШИМ работают одинаково достаточно для поставленных задач... частоты достаточно....
     
  9. parovoZZ

    parovoZZ Гуру

    зато места прибавится для таблицы/)
     
  10. Ну как не влезает, когда 300 байт свободно? 100 уровней влезет без напряга совершенно. А с учетом того, что разрешение шима у вас 256, то там никакими 100 уровнями и не пахнет, а скорее 20-30
     
  11. Пожалуйста, накидал таблицу на 12 значений, места мама не горюй. Можно и удвоить и утроить. Все портянки на if тоже оптимизировать в таблицы, и весь скетч поместится в 50%, я вам гарантирую.
    20.1% (used 206 bytes from 1024 bytes)

    Код (C++):
    #include <avr/io.h>
    #include <stdlib.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>

    uint8_t levels[] = {3, 6, 10, 13, 26, 38, 51, 64, 112, 176, 224, 255};

    //макросы для включения, выключения светодиодов
    //низкий уровень - на ножке 0 вольт, высокий уровень - на ножке 5 вольт
    #define LED1_OFF PORTB &= ~(1<<PB0); //Низкий уровень ножки PB0 (синий)
    #define LED2_OFF PORTB &= ~(1<<PB1); //Низкий уровень ножки PB1 (зеленый)
    #define LED3_OFF PORTB &= ~(1<<PB2); //Низкий уровень ножки PB2 (красный)
    #define LED1_ON PORTB |= _BV(PB0);  //Высокий уровень ножки PB0
    /*#define LED1_ON PORTB |= (1<<PB0);  //Высокий уровень ножки PB0 */
    #define LED2_ON PORTB |= (1<<PB1);  //Высокий уровень ножки PB1
    #define LED3_ON PORTB |= (1<<PB2); //Высокий уровень ножки PB2

    #define ANALOG_IN PB3 //ADC3

    uint8_t counter=0, i=0, j=0, ci=0;
    uint8_t lev_ch[3];
    uint8_t ch[3];
    uint8_t mods = 0; //кнопки выбора режима
    uint16_t vol = 0;

    ISR(TIM0_OVF_vect){

      if (++counter==0) //счетчик перехода таймера через ноль
      {
      LED1_ON; LED2_ON; LED3_ON; // PORTB |=(1<<PB0)|(1<<PB1)|(1<<PB2); //подаем 1 на все каналы BGR (0=B 1=G 2=R)
      }
      if (counter>=lev_ch[0]) LED1_OFF; //подаем 0 на канал
      if (counter>=lev_ch[1]) LED2_OFF; //по достижении
      if (counter>=lev_ch[2]) LED3_OFF; //заданной длительности.

    }
    ISR(ADC_vect){// срабатывает при каждом окончании замера напряжения

      vol = ADCH;
    if (vol > 0 && vol <= 28 ) mods=1; /*   0 авто       */
    if (vol > 28 && vol <= 32 ) mods=2; /*   1    r   */
    if (vol > 32 && vol <= 41 ) mods=3; /*   2    g   */
    if (vol > 41 && vol <= 44 ) mods=4; /*   1-2       */
    if (vol > 44 && vol <= 50 ) mods=5; /*   3    b   */
    if (vol > 50 && vol <= 69 ) mods=6; /*   1-3       */
    if (vol > 69 && vol <= 101 ) mods=7; /*   2-3       */
    if (vol > 101 && vol <= 130 ) mods=8; /*  4    белый    */
    if (vol > 240 && vol <= 255 ) mods=9; /*  5  ноч бел 1/3 яркости     */

    }

    int main(void)
    {
      DDRB=0b00000111; // установка PortB пины 0,1,2 выходы
      TCCR0B = _BV(CS00);   // таймер работает без предделителя
      TIMSK0 = _BV(TOIE0);// прерывания по переполнению таймера разрешены

    // Настройка АЦП: http://avr-prog.blogspot.com/2014/02/attiny13_5.html
      ADMUX =  0b00100011; // опорное напряжение - VCC, левое ориентирование данных, выбран вход ADC2(pb4) (на нём висит перем. резистор)

      ADCSRA = 0b11101111; // АЦП включен, запуск преобразования, режим автоизмерения, прерывание по окончанию преобразования, частота CLK/128
      ADCSRB = 0b00000000; // режим автоизмерения: постоянно запущено
      DIDR0 |= (1 << ANALOG_IN); // запрещаем цифровой вход на ноге аналогового входа

      sei();// глобально прерывания так же разрешены

      lev_ch[0]=0;     //Синий цвет
      lev_ch[1]=0;     //Зеленый цвет
      lev_ch[2]=0;     //Красный цвет



      while (1)     //бесконечная шарманка
      {
        for (auto i = 0; i < 3; i++) {
          for(auto l = 0; l < 12; l++) {
            lev_ch[i] = levels[i];
          };
        }
      }
    }
     
    ELITE нравится это.
  12. DetSimen

    DetSimen Guest

    дядяВитя, не забывай про volatile.
     
  13. Да, только это не ко мне.
     
  14. ELITE

    ELITE Гик

    спасибо, но 12 мало - явно видны ступени
    минимум 36 и то видны переходы...а памяти всего 64
     
  15. Код оптимизируйте. Там дохрена чего можно выкинуть. И 64 ступени с таким шимом вы все равно не получите никак. Делайте фильтр аппаратный, если совсем уж никак.
     
  16. ELITE

    ELITE Гик

    вот почему нельзя было сделать ИК с доустанавливаемой памятью... размер то позволяет, продавалибы модули паняти - по сути размер как у СМД - вполне можно ставить....

    купил Мк воткнул в него доп памяти и норм
     
  17. parovoZZ

    parovoZZ Гуру

    надо мк выбирать под задачу, а не наоборот))