РАДИОСХЕМЫ



СТАРЫЙ ФОРУМ

ФОРУМ НА ЭЛВО

РАДИОФОРУМЫ


СХЕМЫ И СТАТЬИ
  • БЛОГИ
  • НОВОЕ
  • СХЕМЫ
  • РАЗНОЕ
  • ТЕОРИЯ
  • ТЕЛЕВИДЕО
  • СВЕТОДИОД
  • МЕДТЕХНИКА
  • БЫТТЕХНИКА
  • ИЗМЕРИТЕЛИ
  • СПРАВОЧНИК
  • ТЕХНОЛОГИИ
  • РЕМОНТ СХЕМ
  • МОБИЛЬНИКИ
  • КОМПЬЮТЕРЫ
  • НАЧИНАЮЩИМ
  • ЗАРЯДКИ И АКБ
  • СИГНАЛИЗАЦИИ
  • АУДИОТЕХНИКА
  • АВТОВЕЛОМОТО
  • БЛОКИ ПИТАНИЯ
  • РАДИОПРИЁМНИКИ
  • МЕТАЛЛОИСКАТЕЛИ
  • МИКРОКОНТРОЛЛЕР
  • РАДИОПЕРЕДАТЧИКИ

  • Курс по ускорению работы Мозга на 100%


    • Страница 3 из 6
    • «
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • »
    Архив - только для чтения
    Форум радиолюбителей » СХЕМЫ » МИКРОСХЕМЫ » Драйвер для кемпингового фонаря на ATTiny13A (Нужна помощь)
    Драйвер для кемпингового фонаря на ATTiny13A
    Вт, 25.06.2019, 12:32 | Сообщение # 21        
    msmmmm
    аватар
      Постов: 891   Друзья 
    Вы прикалываетесь, какой ISC01- это же настройка INT0, у него вход на РВ1 (6 нога). Настраивай
    Цитата 34kilowatt ()
    GIMSK |= (1 << INT0); // Включаем прерывания по по кнопке

    GIMSK |= (1 << PCIE);
    Вт, 25.06.2019, 12:35 | Сообщение # 22        
    34kilowatt
    аватар
      Постов: 75   ОК 
    Да, вроде даташит еще раз почитал, стало понятнее немного, INT0 вообще не нужен. Тогда какой вектор использовать в обработчике?
    P.S. PCINT0_vect - все заработало, правда пока в протеусе...
    Еще раз спасибо всем за помощь!
    Код

    #define F_CPU 9600000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>

    #define true 1    // логическое состояние правда
    #define false 0    // логическое состояние ложь

    volatile uint16_t voltVal = 0;   // переменная для накопления значений АЦП
    volatile uint8_t sss1 = 0;    // счетчик значений АЦП
    volatile uint8_t sleep_MODE = true;  // режим сна
    volatile uint8_t flgClick = false;  // признак клика

    uint8_t PWM_MODE[4] = {255, 0, 86, 172};  // режимы PWM (100%, 67%, 33%)
    uint8_t LedMode = false;  // переключатель светодиодов  

    uint8_t butCount = 0;     // счетчик времени нажатия
    uint8_t flgPress = false;    // признак кнопка в нажатом состоянии
    uint8_t switchLED = false;    // признак переключения диодов
    uint8_t flgLngPress = false;   // признак удержания кнопки
    uint8_t i = 0;       // счетчик    

    void Set_PWM (void) {
        
        switch (LedMode) {
      case 0:
      DDRB &= ~(1 << PB1);
      DDRB |= (1 << PB0);
      OCR0A = PWM_MODE[i];
      OCR0B = PWM_MODE[0];
      break;
      
      case 1:
      DDRB &= ~(1 << PB0);
      DDRB |= (1 << PB1);
      OCR0A = PWM_MODE[0];
      OCR0B = PWM_MODE[i];
      break;
        }// end switch
        
    }// end Set_PWM()

    ISR(PCINT0_vect){
        GIMSK &= ~(1 << PCIE);    // включаем прерывания по кнопке
        PCMSK = 0x00;    // PCINT4 откл.
        if (sleep_MODE) sleep_MODE = false;  // отключаем флаг перехода в спящий режим
        DDRB |= (1 << PB3) | (1 << PB1) | (1 << PB0);  // порты на выход
        PORTB |= (1 << PB3);    // порт 3 высокий уровень
    }// ISR(INT0_vect)

    /*
    ISR (ADC_vect){    
        
        voltVal += ADCW;
        sss1++;    
        
        if (sss1 > 10) {
      voltVal = voltVal / sss1;
      sss1 = 0;
        }// end if
        
        if (voltVal < 690){
      sleep_MODE = true;
        }// end if
        
    }// end ISR (ADC_vect)
    */

    int main(void){
      
        DDRB |= (1 << PB3) | (1 << PB1) | (1 << PB0);  // порты 0, 1, 3 на выход
        PORTB |= (1 << PB3);
        _delay_ms(300); // отладка
        
        
        /*
        ADMUX |= (1 << REFS0) | (0 << ADLAR) | (1 << MUX0);    // внутреннее опорное напряжение,
                        // левое ориентирование данных, выбран вход ADC1
        ADCSRA = 0xEF;    // АЦП включен, запуск преобразования, режим автоизмерения,
         // прерывание по окончанию преобразования, частота CLK/128
        ADCSRB = 0x00;    // режим автоизмерения: постоянно запущено
        DIDR0 |= (1 << PINB2); // запрещаем цифровой вход на ноге аналогового входа
        */
       
        // Режим Fast PWM, частота сигнала=F_CPU / делитель*256
        TCCR0A |= (1<<WGM00) | (1<<WGM01);    // Режим Fast PWM, таймер считает до 255 и сбрасывается в 0
        TCCR0A |= (1<<COM0A1) | (1<<COM0A0); // 0 при равенстве регистров TCNT0 и OCROA. 1 при переполнении (инвертированный ШИМ-сигнал)
        TCCR0A |= (1<<COM0B1) | (1<<COM0B0); // 1 при равенстве регистров TCNT0 и OCROB. 0 при переполнении (неинвертированный ШИМ-сигнал)
        TCCR0B |= (1<<CS01);    // делитель 8
        OCR0A = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
        OCR0B = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
        
        // настройка режима сна (sleep.h)
        //set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
        
        // настройка режима сна
        MCUCR |= (1 << SM1) | (1 << ISC01);  // power-down mode, прерывание по изменению
        MCUCR &= ~(1 << SM0);    // power-down mode
        //MCUCR |= (1 << SE);  // режим сна включен
        
        sei();  //разрешаем глобально прерывания    
        
        while(1) {
      
      if ((PINB & (1 << PB4)) && !flgLngPress) {
       sleep_MODE = false;
       _delay_ms(10);  // задержка (защита от дребезга)
       while (PINB & (1 << PB4)) {
        butCount++;    // начало отсчета нажатия кнопки
        _delay_ms(10);
        if (butCount > 200) break;    // выходим после 2 сек в любом случае (время повтора)
       }// end while
       if (butCount >= 50){  // ~1 сек
        flgLngPress = true;
        flgPress = false;    // сбрасываем флаг нажатия
        butCount = 0;  // обнуляем счетчик времени нажатия
       }// end if
       else flgPress = true;    // клик
      }// end if
      
      if (flgLngPress && (PINB & (1 << PB4)) == 0){    // если отпустили после длительного нажатия
       switchLED = false;
       flgLngPress = false;
       flgPress = false;    // сбрасываем флаг нажатия
       flgClick = false;
      }// end if
      
      if (flgPress && (PINB & (1 << PB4)) == 0){    // отпустили кнопку
       flgClick = true;    // устанавливаем флаг клика
       flgPress = false;    // сбрасываем флаг нажатия
       butCount = 0;  // обнуляем счетчик времени нажатия
      }// end if
      
      if (flgLngPress && !switchLED){    // было удержание кнопки
       LedMode = !LedMode;  // переключаем на другой светодиод
       //if (LedMode > 1) LedMode = 0;
       i = 1;
       Set_PWM();    // устанавливаем режим светодиода
       switchLED = true;
      }// end if
      
      if (flgClick){   // был клик
       flgClick = false;    // сбрасываем флаг клика
       i++;    // инкрементируем режим PWM
       if (i > 3) i = 0;    // обнуляем счетчик
       Set_PWM();   // устанавливаем режим светодиода
       if (i == 0){sleep_MODE = true;}// end if
       else{sleep_MODE = false;}// end else
      }// end if
      
      if (sleep_MODE){
       
       PORTB &= ~(1 << PB3);
       _delay_ms(50);   // отладка
       PORTB |= (1 << PB3);
       _delay_ms(50);   // отладка
       PORTB &= ~(1 << PB3);
       _delay_ms(50);   // отладка
       PORTB |= (1 << PB3);
       _delay_ms(50);   // отладка
       PORTB &= ~(1 << PB3);
       
       GIMSK |= (1 << PCIE);    // включаем прерывания по кнопке
       PCMSK |= (1 << PCINT4); // PCINT4 для возращения в нормальный режим из сна
       DDRB &= ~((1 << PB3) | (1 << PB1) | (1 << PB0));  // выключаем светодиоды
       PORTB &= ~((1 << PB3) | (1 << PB1) | (1 << PB0));  // отключаем высокий уровень на портах
       _delay_ms(100);    // отладка
       MCUCR |= (1 << SE);  // режим сна включен
       asm("sleep");
      }// end if
      
        }// end while(1)
    }// end main

    Дальше буду крутить АЦП для контроля напряжения на АКБ.
    Вт, 25.06.2019, 12:38 | Сообщение # 23        
    msmmmm
    аватар
      Постов: 891   Друзья 
    Вектор как раз выбран правильно - PCINT0_vect. И обработчик для него написан.
    Вт, 25.06.2019, 12:40 | Сообщение # 24        
    nolpofaze
    аватар
      Постов: 442   Друзья 
    34kilowatt, вектор выбран верный (PCINT0_vect)
    Вт, 25.06.2019, 12:49 | Сообщение # 25        
    msmmmm
    аватар
      Постов: 891   Друзья 
    Цитата 34kilowatt ()
    Дальше буду крутить АЦП для контроля напряжения на АКБ.

    АЦП перед входом в сон нужно отключать, иначе будет немного отъедать лишнего. И нужно проследить отключен ли компаратор. Если нет, отключить.
    Вт, 25.06.2019, 14:37 | Сообщение # 26        
    34kilowatt
    аватар
      Постов: 75   ОК 
    Вроде все работает в протеусе, буду в железе проверять.
    Всем спасибо!
    Код

    #define F_CPU 9600000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>

    #define true 1    // логическое состояние правда
    #define false 0    // логическое состояние ложь

    volatile uint16_t voltVal = 0;   // переменная для накопления значений АЦП
    volatile uint8_t sss1 = 0;    // счетчик значений АЦП

    volatile uint8_t sleep_MODE = true;  // режим сна
    volatile uint8_t lowBat = false;  // батарея разряжена
    volatile uint8_t flgClick = false;  // признак клика

    uint8_t PWM_MODE[4] = {255, 0, 86, 172};    // режимы PWM (100%, 67%, 33%)
    uint8_t butCount = 0;      // счетчик времени нажатия
    uint8_t i = 0;        // счетчик    

    uint8_t flgPress = false;  // признак кнопка в нажатом состоянии
    uint8_t LedMode = false;  // переключатель светодиодов  
    uint8_t switchLED = false;  // признак переключения диодов
    uint8_t flgLngPress = false;    // признак удержания кнопки

    void BlinkLed(){
        PORTB &= ~(1 << PB3);
        _delay_ms(50);   // отладка
        PORTB |= (1 << PB3);
        _delay_ms(50);   // отладка
        PORTB &= ~(1 << PB3);
        _delay_ms(50);   // отладка
    }// end BlinkLed()

    void RunSleep(){
        PRR |= (1 << PRADC);    // выключаем АЦП
        GIMSK |= (1 << PCIE);    // включаем прерывания по кнопке
        PCMSK |= (1 << PCINT4); // PCINT4 для возращения в нормальный режим из сна
        DDRB &= ~((1 << PB3) | (1 << PB1) | (1 << PB0));  // выключаем светодиоды
        PORTB &= ~((1 << PB3) | (1 << PB1) | (1 << PB0));  // отключаем высокий уровень на портах
        _delay_ms(10);
        MCUCR |= (1 << SE);  // режим сна включен
        asm("sleep");    
    }// end RunSleep()

    void Set_PWM (void) {
        
        switch (LedMode) {
      case 0:
      DDRB &= ~(1 << PB1);
      DDRB |= (1 << PB0);
      OCR0A = PWM_MODE[i];
      OCR0B = PWM_MODE[0];
      break;
      
      case 1:
      DDRB &= ~(1 << PB0);
      DDRB |= (1 << PB1);
      OCR0A = PWM_MODE[0];
      OCR0B = PWM_MODE[i];
      break;
        }// end switch
        
    }// end Set_PWM()

    ISR(PCINT0_vect){
        PRR &= ~(1 << PRADC);    // включаем АЦП
        GIMSK &= ~(1 << PCIE);    // включаем прерывания по кнопке
        PCMSK = 0x00;    // PCINT4 откл.
        if (sleep_MODE) sleep_MODE = false;  // отключаем флаг перехода в спящий режим
        DDRB |= (1 << PB3) | (1 << PB1) | (1 << PB0);  // порты на выход
        PORTB |= (1 << PB3);    // порт 3 высокий уровень
        lowBat = false;
    }// ISR(INT0_vect)

    ISR (ADC_vect){    
        
        uint16_t voltValTmp = 1024;
        
        voltVal += ADCW;
        sss1++;    
        
        if (sss1 > 9) {
      voltValTmp = voltVal / (sss1);
      voltVal = 0;
      sss1 = 0;
        }// end if
        
        if (voltValTmp < 690) lowBat = true;    // ~3V
      
    }// end ISR (ADC_vect)

    int main(void){
      
        DDRB |= (1 << PB3) | (1 << PB1) | (1 << PB0);  // порты 0, 1, 3 на выход
        PORTB |= (1 << PB3);
        _delay_ms(300); // отладка
        
        
        ADMUX |= (1 << REFS0) | (1 << MUX0);    // внутреннее опорное напряжение, выбран вход ADC1
        ADCSRA |= (1 << ADEN) | (1 << ADSC)    | (1 << ADATE)    // АЦП включен, запуск преобразования, режим автоизмерения,
       | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1)    // прерывание по окончанию преобразования,
       | (1 << ADPS0);        // частота CLK/128
        ADCSRB = 0x00;    // режим автоизмерения: постоянно запущено
        DIDR0 |= (1 << PINB2); // запрещаем цифровой вход на ноге аналогового входа
        
       
        // Режим Fast PWM, частота сигнала=F_CPU / делитель*256
        TCCR0A |= (1<<WGM00) | (1<<WGM01);    // Режим Fast PWM, таймер считает до 255 и сбрасывается в 0
        TCCR0A |= (1<<COM0A1) | (1<<COM0A0); // 0 при равенстве регистров TCNT0 и OCROA. 1 при переполнении (инвертированный ШИМ-сигнал)
        TCCR0A |= (1<<COM0B1) | (1<<COM0B0); // 1 при равенстве регистров TCNT0 и OCROB. 0 при переполнении (неинвертированный ШИМ-сигнал)
        TCCR0B |= (1<<CS01);    // делитель 8
        OCR0A = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
        OCR0B = 255; // регистр сравнения (инвертированный сигнал ШИМ 0)
        
      // настройка режима сна
        MCUCR |= (1 << SM1);  // power-down mode, прерывание по изменению
        MCUCR &= ~(1 << SM0);    // power-down mode
      
        sei();  //разрешаем глобально прерывания    
        
        while(1) {
      
      if ((PINB & (1 << PB4)) && !flgLngPress) {
       sleep_MODE = false;
       _delay_ms(10);  // задержка (защита от дребезга)
       while (PINB & (1 << PB4)) {
        butCount++;    // начало отсчета нажатия кнопки
        _delay_ms(10);
        if (butCount > 200) break;    // выходим после 2 сек в любом случае (время повтора)
       }// end while
       if (butCount >= 50){  // ~1 сек
        flgLngPress = true;
        flgPress = false;    // сбрасываем флаг нажатия
        butCount = 0;  // обнуляем счетчик времени нажатия
       }// end if
       else flgPress = true;    // клик
      }// end if
      
      if (flgLngPress && (PINB & (1 << PB4)) == 0){    // если отпустили после длительного нажатия
       switchLED = false;
       flgLngPress = false;
       flgPress = false;    // сбрасываем флаг нажатия
       flgClick = false;
      }// end if
      
      if (flgPress && (PINB & (1 << PB4)) == 0){    // отпустили кнопку
       flgClick = true;    // устанавливаем флаг клика
       flgPress = false;    // сбрасываем флаг нажатия
       butCount = 0;  // обнуляем счетчик времени нажатия
      }// end if
      
      if (flgLngPress && !switchLED){    // было удержание кнопки
       LedMode = !LedMode;  // переключаем на другой светодиод
       i = 1;
       Set_PWM();    // устанавливаем режим светодиода
       switchLED = true;
      }// end if
      
      if (flgClick){   // был клик
       flgClick = false;    // сбрасываем флаг клика
       i++;    // инкрементируем режим PWM
       if (i > 3) i = 0;    // обнуляем счетчик
       Set_PWM();   // устанавливаем режим светодиода
       if (i == 0) sleep_MODE = true;
       else sleep_MODE = false;    
      }// end if
      
      if (lowBat){
       i = 0;
       BlinkLed();
       RunSleep();
      }// end if
      
      if (sleep_MODE) RunSleep();
      
        }// end while(1)
    }// end main


    P. S. Все заработало и в железе на макетке, теперь буду печатку придумывать и светодиоды полевиками заменять. Ну и программу слегка причешу...
    Всем огромное спасибо за помощь!
    P.P.S. Проверил потребление, что много, видимо засыпает не полностью, аж целых 160-170 мкА.
    Ср, 26.06.2019, 07:20 | Сообщение # 27        
    nolpofaze
    аватар
      Постов: 442   Друзья 
    34kilowatt, делитель АЦП съедает эти мкА.
    Ср, 26.06.2019, 07:38 | Сообщение # 28        
    34kilowatt
    аватар
      Постов: 75   ОК 
    Не, не, не - это без учета делителя, делитель в макетном варианте (переменник 25к) еще 180мкА кушает (итого за 300-360мкА потребление, в зависимости от напряжения 3 - 4,2В).
    Ср, 26.06.2019, 12:35 | Сообщение # 29        
    34kilowatt
    аватар
      Постов: 75   ОК 
    Не, не, не - это без учета делителя, делитель в макетном варианте (переменник 25к) еще 180мкА кушает (итого за 300-360мкА потребление, в зависимости от напряжения 3 - 4,2В).

    Может МК просто в сон не уходит? Потому, что, когда начал прошивку сочинять, потребление просто при выключенных светодиодах такое-же примерно было.
    Попробую через sleep.h перевести в сон.

    Добавлено (26.06.2019, 13:32)
    ---------------------------------------------
    Не получилось ниже 160мкА снизить потребление, ну никак. Потребляет именно МК, т.к. всю обвязку убрал и подключил.
    Может дело в самом МК (хотя в остальном проблем ни каких), заказаны были на Али, вроде как Tiny13А.
    Файлы: 8118253.jpg (224.1 Kb)
    Ср, 26.06.2019, 12:52 | Сообщение # 30        
    nolpofaze
    аватар
      Постов: 442   Друзья 
    Да уж, а должен потреблять менее 0,1мкА в режиме power-down. Может и мк, замерял в схемке на mega8L, тоже режим power-down, выходит около 3мкА. Микра в дипе, успешно выдрана со счетной машинки, не китай.
    Форум радиолюбителей » СХЕМЫ » МИКРОСХЕМЫ » Драйвер для кемпингового фонаря на ATTiny13A (Нужна помощь)
    • Страница 3 из 6
    • «
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • »
    Поиск:

    Внимание! Форум переехал на Tehnodium.ru



    © 2010-2022 "Форум Радиосхемы". All Rights Reserved  Почта  PDA