простые интересные РАДИОСХЕМЫ сделанные своими руками

» СХЕМЫ
» ДАТАШИТЫ
Например: TDA1562
» Гость

Мы рады вас видеть. Пожалуйста зарегистрируйтесь или авторизируйтесь!





Отметить прочитанными   -   Поиск   -   Правила   -   Новые сообщения

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

GIMSK |= (1 << PCIE);
Вт, 25.06.2019, 13:35 | Сообщение # 22        
34kilowatt
аватар
  Постов: 75  Offline ОК 
Да, вроде даташит еще раз почитал, стало понятнее немного, 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

Дальше буду крутить АЦП для контроля напряжения на АКБ.


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

АЦП перед входом в сон нужно отключать, иначе будет немного отъедать лишнего. И нужно проследить отключен ли компаратор. Если нет, отключить.


Отредактировал msmmmm - Вт, 25.06.2019, 13:51
Вт, 25.06.2019, 15:37 | Сообщение # 26        
34kilowatt
аватар
  Постов: 75  Offline ОК 
Вроде все работает в протеусе, буду в железе проверять.
Всем спасибо!
Код

#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 мкА.


Отредактировал 34kilowatt - Вт, 25.06.2019, 21:25
Ср, 26.06.2019, 08:20 | Сообщение # 27        
nolpofaze
аватар
  Постов: 531  Offline Друзья 
34kilowatt, делитель АЦП съедает эти мкА.
Ср, 26.06.2019, 08:38 | Сообщение # 28        
34kilowatt
аватар
  Постов: 75  Offline ОК 
Не, не, не - это без учета делителя, делитель в макетном варианте (переменник 25к) еще 180мкА кушает (итого за 300-360мкА потребление, в зависимости от напряжения 3 - 4,2В).


Отредактировал 34kilowatt - Ср, 26.06.2019, 13:38
Ср, 26.06.2019, 13:35 | Сообщение # 29        
34kilowatt
аватар
  Постов: 75  Offline ОК 
Не, не, не - это без учета делителя, делитель в макетном варианте (переменник 25к) еще 180мкА кушает (итого за 300-360мкА потребление, в зависимости от напряжения 3 - 4,2В).

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

Добавлено (26.06.2019, 13:32)
---------------------------------------------
Не получилось ниже 160мкА снизить потребление, ну никак. Потребляет именно МК, т.к. всю обвязку убрал и подключил.
Может дело в самом МК (хотя в остальном проблем ни каких), заказаны были на Али, вроде как Tiny13А.


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

Кто есть кто на форуме радиолюбителей: Администратор Модераторы Друзья Проверенные Новички
Группа вконтакте Канал ютуб Группа в фэйсбук Моб. версия © 2010-2020, "Радиосхемы". Все права защищены. Почта