Защита от глубокого разряда на ATtiny13A

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Там старьё одно могу новые закинуть.

Есть несколько идей, например добавлю отключение при завышенном напряжении в 15 В, что расширяет границы применения моего девайса, например можно будет использовать в полуавтоматическом ЗУ для аккума.

Ещё хочу научить всетодиод 35% мигать в зависимости от уровня заряда, тоесть от 35% и до 0% будет мигать с разной интенсивностью, сначало быстро а потом медленей...

 

Может у кого-то будут какие-то идеи или же предложения?

 

ЗЫ посоветуйте хороший обменник на который было бы удобно выгружать файлы?

 

Rimidalw
Offline
Зарегистрирован: 04.04.2012

HWman пишет:

ЗЫ посоветуйте хороший обменник на который было бы удобно выгружать файлы?

dropbox.com

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

урааа! analogRead() таперь заработал.

Качать последнюю версию реализа(на сегодня это core13_018.zip), положить по адресу "\Documents\Arduino\hardware\attiny13\cores\core13" должно получится чтото типо "C:\Users\Администратор\Documents\Arduino\hardware\attiny13\cores\core13" ну и в настройках платы выбрать attiny13 9.6 мГц, на других частотах почему то все задержки не такие как задаю, на 128 кГц всё в 2-3 раза быстрее.

Смоделировал в Proteus 7 Professional всё работает, всем спасибо за помощь.

Великих Вам проектов на attiny13, да и поменьше размером :)

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Rimidalw спасибо, но там нужно регатся...

 

Вот выгрузил файлы проекта, пользуйтесь.

Изменил схему как рекомендовали:

Вот скетч:



//#include <util/delay.h> // уменьшим вес прошивки
int V = 0; // обнулим, мало ли ;)
void setup(){
   pinMode(3, INPUT);      // вольтметр, делитель из 5 кОм и 1 кОм(земля), значение в 1023 это будет 24.35 В тоесть 33.87 на вольт
   pinMode(4, OUTPUT);     // релюха
   pinMode(0, OUTPUT);     // 1-й светодиод 100% заряда - 12.5 В.
   pinMode(1, OUTPUT);     // 2-й светодиод 65% заряда - 11.7 В.
   pinMode(2, OUTPUT);     // 3-й светодиод 35% заряда - 11.1 В.
   // диагностика:   
   digitalWrite(0, HIGH); delay(1000); digitalWrite(0, LOW); delay(1000);   
   digitalWrite(1, HIGH); delay(1000); digitalWrite(1, LOW); delay(1000);  
   digitalWrite(2, HIGH); delay(1000); digitalWrite(2, LOW); delay(1000);
   digitalWrite(4, HIGH); delay(1000); digitalWrite(4, LOW);
   // всё работает?
}
void loop()
{
    digitalWrite(0, LOW); 
    digitalWrite(1, LOW);  //тушим диоды 100/65/35
    digitalWrite(2, LOW);    
    int V = analogRead(3);   
        if(V >= 362 && V <= 511) { digitalWrite(4, HIGH);  // если больше 10.5 и меньше 15 приступаем, включаем реле
        if(V >= 443 ) {  // если напряжение больше 13 В мигаем 
          delay((((520 - V) / 4) * 100)); } // интенсивность мигания зависит от величины напряжения
        if(V >= 426 ) { digitalWrite(0, HIGH); }  // 1-й светодиод 100% заряда - 12.5 В.
        if(V >= 399 ) { digitalWrite(1, HIGH); }  // 2-й светодиод 65% заряда - 11.7 В.
        if(V >= 379 ) { digitalWrite(2, HIGH); }  // 3-й светодиод 35% заряда - 11.1 В.  
        if(V <= 379 ) { digitalWrite(2, HIGH);    // если напряжение заряда ниже 11.1 В. тогда мигаем  
          delay(((V - 350) * 100)); // интенсивность мигания зависит от величины напряжения
          digitalWrite(2, LOW); }
        delay(500); }  // ждём как минимум 0.5 сек во избежания дребезжания контактов реле    
            else { digitalWrite(4, LOW); }
//delay(1000);   // ждём 1 сек во избежания дребезжания контактов реле
}

Всё проверил программно, всё работает, железо ещё не тестил. 784 байт. Я вполне доволен, сделал всё что хотел и ещё осталось пару сотен кило...

toc
Offline
Зарегистрирован: 09.02.2013

почему в схеме МК не подключён к vcc и gnd? или я не понимаю

как вы его питаете в железной схеме?

помните МК измеряет напряжение отнрсительно vcc?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Неразобрался я ещё толком с протэусом, там нельзя сделать видимыми ноги питания почему-то, питать буду через 5-ти вольтовый  линейный стабилизатор 78L05. Для тонкой подстройки добавил резистор R8 на 500 Ом но позволит опустить напряжение срабатования если что.

Единственное что ещё беспокоит - стоит ли добавлять диод к аналоговом входе PB3. Что будет с ним при переполюсовке?

Сейчас уже другие трудности появились, что-то с дуиной стало или тини перегорела, немогу прошить... вроде что-то коротнуло при процесе прошивки или что...

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

После похода в гугл обновил немного код:





#include <avr/pgmspace.h>
#include <avr/sleep.h> // sleep code by insidegadgets.com
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
int V = 0; // обнулим, мало ли ;)
void setup(){
   pinMode(3, INPUT);      // вольтметр, делитель из 5 кОм и 1 кОм(земля), значение в 1023 это будет 24.35 В тоесть 33.87 на вольт
   pinMode(4, OUTPUT);     // релюха
   pinMode(0, OUTPUT);     // 1-й светодиод 100% заряда - 12.5 В.
   pinMode(1, OUTPUT);     // 2-й светодиод 65% заряда - 11.7 В.
   pinMode(2, OUTPUT);     // 3-й светодиод 35% заряда - 11.1 В.
   // диагностика:   
   digitalWrite(0, HIGH); delay(1000); digitalWrite(0, LOW); delay(1000);   
   digitalWrite(1, HIGH); delay(1000); digitalWrite(1, LOW); delay(1000);  
   digitalWrite(2, HIGH); delay(1000); digitalWrite(2, LOW); delay(1000);
   digitalWrite(4, HIGH); delay(1000); digitalWrite(4, LOW);
   // всё работает?
}
void loop()
{
    digitalWrite(0, LOW); 
    digitalWrite(1, LOW);  //тушим диоды 100/65/35
    digitalWrite(2, LOW);    
    int V = analogRead(3);   
        if(V >= 362 && V <= 511) { digitalWrite(4, HIGH);  // если больше 10.5 и меньше 15 приступаем, включаем реле
        if(V >= 443 ) {  // если напряжение больше 13 В мигаем 
          delay((((520 - V) / 4) * 100)); } // интенсивность мигания зависит от величины напряжения
        if(V >= 426 ) { digitalWrite(0, HIGH); }  // 1-й светодиод 100% заряда - 12.5 В.
        if(V >= 399 ) { digitalWrite(1, HIGH); }  // 2-й светодиод 65% заряда - 11.7 В.
        if(V >= 379 ) { digitalWrite(2, HIGH); }  // 3-й светодиод 35% заряда - 11.1 В.  
        if(V <= 379 ) { digitalWrite(2, HIGH);    // если напряжение заряда ниже 11.1 В. тогда мигаем  
          delay(((V - 350) * 100)); // интенсивность мигания зависит от величины напряжения
          digitalWrite(2, LOW); }
          delay(500); }  // ждём как минимум 0.5 сек во избежания дребезжания контактов реле    
            else { digitalWrite(4, LOW);
            system_sleep(); }
}
// interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void system_sleep() {
  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  //sleep_mode(); // System sleeps here
  sleep_enable(); // разрешаем сон
  sleep_cpu(); // спать!
  //sbi(ADCSRA,ADEN);  // Switch Analog to Digital converter ON
}
 
ISR(PCINT0_vect) {
 
}

Как мне кажется теперь должен засыпать, по крайней мере IDE уже не ругается на меня, мол, я не-з-на-юу таких слов, иди отсюда! Не уверен что всё что в шапке #define нужны, может кто подскажет? 

Proteus 7 Professional показывает никакой спад по току, как было 0.09 А так и осталось...

ЗЫ Софтово будить МК не хочу, лучше отключу ему питание и потом поять подам, или же ресетом буду "поднимать всю глубину наших глубин".  

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

немогу прошить микруху, регается

avrdude: please define PAGEL and BS2 signals in the configuration file for part ATtiny13
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

всё проверил три раза подключил всё верно, есть возможность того что убил микросхему? 

maksim
Offline
Зарегистрирован: 12.02.2012

Как и чем шьете?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

http://www.instructables.com/id/Programming-an-ATTiny13A-using-Arduino-s...

Вот так как тут. Сначало всё нормально шилось, а пото м что-то случилось, возможно что-то где-то коротнуло или ещё что...

Вечером попробую на другой микрухе

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Поставил новую микруху, сделал более менее удобный программатор для дуинки:


 

и заработало.

Видео:

http://www.youtube.com/watch?v=oEIAmJ6VZiU

Ещё нуждается в настройке, немного изменил скетч, в часности цифры для аналогового входа...

Ток потребления в режыме stand bye 6 мА когда работает 50 мА, 85 % жрет реле. Почти закончил, осталось к ресету кнопку приделать перепаять диоды на другую платку у всё уложыть в крачивый корпус. Всем спасибо кто откликнулся за помощь.

После тестирования отпишусь.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Наконец-то настроил как программно так и аппаратно, войдя во вкус оптимизации и прислушиваться к вашим советам я немного переделал скетч:

#include <avr/sleep.h> 
int main( void )
{
  DDRB = 0b10111;
  
  /*
   PB3 вольтметр, делитель из 5 кОм и 1 кОм(земля)
   PB4 релюха
   PB0 1-й светодиод 100% заряда - 12.5 В.
   PB1 2-й светодиод 65% заряда - 11.7 В.
   PB2 3-й светодиод 35% заряда - 11.1 В.
   */
   
   // диагностика:  
for(byte i = 0; i < 3; i++){
    PORTB = 1<<i;
  delay(300);}
    PORTB |= (1<<4); delay(300); PORTB &= ~(1<<4);
   // всё работает?
   
 while(1){
     PORTB &= ~(1<<0);
     PORTB &= ~(1<<1); //тушим диоды 100/65/35
     PORTB &= ~(1<<2);    
        if(ADC_READ() >= 358 && ADC_READ() <= 512) { PORTB |= (1<<4);  // если больше 10.5 и меньше 15 приступаем, включаем реле
        if(ADC_READ() >= 445 ) {  // если напряжение больше 13 В то мигаем 
          delay((((542 - ADC_READ()) / 4) * 50)); } // интенсивность мигания зависит от величины напряжения
        if(ADC_READ() >= 428 ) { PORTB |= (1<<0); }  // 1-й светодиод 100% заряда - 12.5 В.
        if(ADC_READ() >= 401 ) { PORTB |= (1<<1); }  // 2-й светодиод 65% заряда - 11.7 В.
        if(ADC_READ() >= 378 ) {PORTB |= (1<<2); }  // 3-й светодиод 35% заряда - 11.1 В.  
        if(ADC_READ() <= 377 ) { PORTB |= (1<<2);    // если напряжение заряда ниже 11.1 В. тогда мигаем  
          delay((((ADC_READ() - 350) / 4) * 50)); // интенсивность мигания зависит от величины напряжения
          PORTB &= ~(1<<2); }
          delay(300); }  // ждём как минимум 0.3 сек во избежания дребезжания контактов реле    
            else { PORTB &= ~(1<<4);
            system_sleep(); } // иначе реле выкл и бай бай до ресета
      }
  return 0;
}

unsigned int ADC_READ(){
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF; 
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
  return (high << 8) | low;
}

void system_sleep() {
  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  sleep_enable(); // разрешаем сон
  sleep_cpu(); // спать!
}


Размер скетча в двоичном коде: 446 байт (из 1 024 байт максимум), супер :)

Вот фото девайса:

 

 

Алгоритм настройки думаю вопросов не вызовет.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Ох сколько раз я ещё возвращался к этому "проекту" кстати, всем огромное спасибо за помощь.

Как показала практика если перепутать полярность то полевик релюхи стреляет и выходит из строя, так что перед им нужен предохранитель на 100-200 мА ибо при переполюсовке ток сильно возрастает.

По данной схемке успешно сдал курсачь, его добавил в архив где есть всё по даной теме, при желании курсачь можно спокойно перевести на Русский при помощи гугл-переводчика.

По этой теме у меня пожалуй все, не думаю что "проект" буду продолжать улучшать так как надобность этого девайся уже отпала.

 

toc
Offline
Зарегистрирован: 09.02.2013

HWman пишет:
добавил в архив где есть всё по даной теме

там нет файла

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Скорей всего на сайт нужно зайти под Украинским прокси.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Перезалил себе все файлы на хостинг, вот тут есть ядро нужное для тини, в первом сообщении всё ссылки во втором файлы ядра.

Немного изменил код:

#include <avr/sleep.h> 
#include <avr/io.h>
unsigned int adc = 0;

int main( void )
{
  DDRB = 0b10111;  // порти PB0-PB2 и PB4 встановленні на вихід, PB3 на вхід.
  
  /*
   PB3 вольтметр, дільник напруги, 5 кОм и 1 кОм(земля)
   PB4 реле
   PB0 1-й світолодіод 100% заряду - 12.5 В.
   PB1 2-й світолодіод 65% заряду - 11.7 В.
   PB2 3-й світолодіод 35% заряду - 11.1 В.
   */
   
  for(byte i = 0; i < 3; i++){    // проведемо діагностику 
    PORTB = 1<<i;
    delay(300); //_delay_ms(300);
  }

  while(1){
    PORTB &= ~(1<<0);
    PORTB &= ~(1<<1);  // гасимо світлодіоди 100% 65% 35%
    PORTB &= ~(1<<2); 
    // "10 раз измерим...
    adc = 0;
    for(byte c = 0; c < 10; c++){
      adc = adc + ADC_READ();
    }  
    adc = adc / 10;
    // ...онин раз отрежем"
    if(adc >= 358 && adc <= 512) { 
      PORTB |= (1<<4);  // Якщо  напруга більше ніж 10.5 і менше чим 15 В вмикаємо реле і запускаємо виконання циклу
      if(adc >= 445 ) {  // якщо  напруга більше ніж 13 В то мигаємо усіма світлодіодами 
        delay((((542 - adc) / 4) * 50)); 
      } // інтенсивність мигання залежить від величини напруги, є 4 режими інтенсивності
      if(adc >= 428 ) { 
        PORTB |= (1<<0); 
      }  // 1-й світолодіод 100% заряда - 12.5 В.
      if(adc >= 401 ) { 
        PORTB |= (1<<1); 
      }  // 2-й світолодіод 65% заряда - 11.7 В.
      if(adc >= 378 ) {
        PORTB |= (1<<2); 
      }  // 3-й світолодіод 35% заряда - 11.1 В.  
      if(adc <= 377 ) { 
        PORTB |= (1<<2);    // якщо напруга нижче 11.1 В. тоді мигаємо світлодіодом 30% інтенсивність залежить від величина нипруги   
        delay((((adc - 350) / 4) * 50)); // інтенсивність залежить від величина напруги   
        PORTB &= ~(1<<2); 
      }
      delay(300); 
    }  // чекаємо як мінімум 0.3 сек    
    else { 
      PORTB &= ~(1<<4); //
      system_sleep(); 
    } // інакше реле вимикаємо і засинаємо до ресету
  }
  return 0;
}

unsigned int ADC_READ(){  // ініціалізуємо АЦП
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF; 
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  return (high << 8) | low;
}

void system_sleep() {
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // повністю засинаємо
  sleep_enable(); // сон дозволено
  sleep_cpu(); 
}

Если в схеме заменить реле полевым транзистором с очень малым сопротивлением СИ - 0,00* Ом то выйдет довольно неплохая схемка с малым потреблением, реле кушает около 40 мА а транзистор почти ничего не кушает. Вот набросал схемку с транзистором вместо реле:

Кстати, при такой схеме:

При переполюсовке транзистор вылетает с треском, не могу понять почему. 

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

HWman пишет:

При переполюсовке транзистор вылетает с треском, не могу понять почему. 

Коротыш через блокирующий диод реле. Поставьте мосфет ампер на 50 - вылетит диод. :)

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

А ещё лучше предохранитель, возможно даже самовосстанавливающийся.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

HWman пишет:

А ещё лучше предохранитель, возможно даже самовосстанавливающийся.

Зачем?? Для защиты схем от переполюсовки обычно ставят мосфет по схеме "идеального диода"... Если защищать только транзистор и цепи питания реле - то можно запитать реле (с блокирующим диодом) через диодный мост: ему все равно, он полярность сам поправит как надо. Или последовательно с блокирующим диодом поставить стабилитрон на номинал напряжения питания...

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

По моему самовостанавливающийся предохранитель будет получше в плане КПД схемы.

Клапауций
Offline
Зарегистрирован: 10.02.2013

HWman пишет:

По моему самовостанавливающийся предохранитель будет получше в плане КПД схемы.

зачем? часто путаешь питание?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Клапауций пишет:

HWman пишет:

По моему самовостанавливающийся предохранитель будет получше в плане КПД схемы.

зачем? часто путаешь питание?

Просто хочется сделать нормально, хотя иногда бывает затупишь и только дымок улетает, как говорил один человек, это духи умерших деталей.

Клапауций
Offline
Зарегистрирован: 10.02.2013

HWman пишет:

Просто хочется сделать нормально, хотя иногда бывает затупишь и только дымок улетает, как говорил один человек, это духи умерших деталей.

чёрным маркером земляные провода метишь... и всё

"нормально" не получится, а если защиту от переполюсовки не втуда воткнёшь - как от такого обезопаситься?

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Всего не предусмотришь, но защиту от переполюсовки делать нужно, это уже принцип.

Для защиты "от дурака" в схемах не хватает предохранителей, можно даже ставить самовосстанавливающиеся.

На этом считаю проект законченным, возможно потом буду делать что-то типо такого:

http://www.youtube.com/watch?v=rA7TbwtcdU8

Естественно на меге8-й.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Здравствуйте!

Меня очень заинтересовало это устройство. Хочу его применить для резервного питания базы домашнего радиотелефона, когда происходят перебои с электроэнергией. Можно вместо функции сна сделать чтобы при возобновлении подачи электроэнергии в сеть, это устройство включало нагрузку но не сразу а когда аккумулятор немного зарядится до определенного напряжения? Ну хотя бы до 12-13 вольт. Тогда бы вышло отличное устройство бесперебойного питания с системой защиты от глубокого разряда.

Заранее спасибо всем кто откликнется на просьбу.

 

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Можно, я как раз осваиваю прерывания по таймеру.
Жаль что железа уже у меня нет, могу только код набросать, протестировать тут уж Вы сами.

#include <avr/io.h>
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/power.h>

int main( void )
{
  DDRB = 0b10111;  // порти PB0-PB2 и PB4 встановленні на вихід, PB3 на вхід.

  /*
   PB3 делитель 5 кОм и 1 кОм(земля) + подстроечный резистор на 500 Ом 
   PB4 реле
   PB0 1-й светодод 100% заряда - 12.5 В.
   PB1 2-й светодод 65% заряда - 11.7 В.
   PB2 3-й светодод 35% заряда - 11.1 В.
   */

  if(analogReadOversampled() <= 377 ) { // Если напряжение < 11.1 В. тогда сон на 2 сек.  
    system_sleep_4S();
  } 

  PORTB = 1<<0; // диагностика
  PORTB = 1<<1;
  PORTB = 1<<2;
  delay(100); 

  while(1){
    PORTB &= ~(1<<0);
    PORTB &= ~(1<<1);  // тушим светодиоды 100% 65% 35%
    PORTB &= ~(1<<2); 

    if(analogReadOversampled() >= 358 && analogReadOversampled() <= 512) { 
      PORTB |= (1<<4);  // Якщо  напруга більше ніж 10.5 і менше чим 15 В вмикаємо реле і запускаємо виконання циклу
      if(analogReadOversampled() >= 445 ) {  // якщо  напруга більше ніж 13 В то мигаємо усіма світлодіодами 
        delay((((542 - analogReadOversampled()) / 4) * 50)); 
      } // інтенсивність мигання залежить від величини напруги, є 4 режими інтенсивності
      if(analogReadOversampled() >= 428 ) { 
        PORTB |= (1<<0); 
      }  // 1-й світолодіод 100% заряда - 12.5 В.
      if(analogReadOversampled() >= 401 ) { 
        PORTB |= (1<<1); 
      }  // 2-й світолодіод 65% заряда - 11.7 В.
      if(analogReadOversampled() >= 378 ) {
        PORTB |= (1<<2); 
      }  // 3-й світолодіод 35% заряда - 11.1 В.  
      if(analogReadOversampled() <= 377 ) { 
        PORTB |= (1<<2);    // якщо напруга нижче 11.1 В. тоді мигаємо світлодіодом 30% інтенсивність залежить від величина нипруги   
        delay((((analogReadOversampled() - 350) / 4) * 50)); // інтенсивність залежить від величина напруги   
        PORTB &= ~(1<<2); 
      }
      delay(10); 
    }   
    else { 
      PORTB &= ~(1<<4); // для мосфета
      system_sleep_4S(); 
    } // інакше реле вимикаємо і засинаємо до ресету
  }
  return 0;
}

unsigned int ADC_READ(){  // ініціалізуємо АЦП
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF; 
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  return (high << 8) | low;
}

void system_sleep_4S(){ // сон на 2 сек
  wdt_reset(); // сброс
  wdt_enable(WDTO_4S); // разрешение ватчдога раз в 2с
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  while(1) {
    sleep_enable(); // разрешаем сон
    sleep_cpu(); // спать!
  }
}

// оверсемплинг для большей точности и меньших шумов
unsigned int analogReadOversampled(){
  unsigned long aSum = 0;   // the sum of all analog readings
  for(int i = 0; i < 16; i++) 
    aSum += ADC_READ(); // read and sum 16 ADС probes
  return aSum >> 4;   // ..
}

Данный код вместо того чтобы усыпить МК навечно когда напряжение упало ниже критичного уровня усыпляет его на 4 сек, просыпается проверяет не поднялась ли напруга до 11.1 В - да включает нагрузку, нет дальше сон на 4 сек...
А нужна ли Вам эта индикация уровня заряда? Можно сделать проще, причём даже без МК, TL431 + парочка резисторов и мосфет, схема будет очень простой.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Спасибо за помощь! Завщтра попробую реализовать ваше решение в железе. О результатах отпишусь. А поповоду применения крен19(TL431) проводил опыты и сталкнулся проблемой переходных процессов в момент порога срабатывания. Полуяается чтото вроде генеразтора, когда снимается энагрузка напряжение на аккумуляторе поднимается и происходит подключение нагрузки и так по кругу вплодь до дребезжания реле. Как раз в таком случае и нужен своеобръазный гистерезис для исключения такого эффекта.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

По моему можно и сделать гистерезис для TL431, сам пока не сталкивался ничего подсказать не могу.

Если бы мне приходилось выбирать между аналоговой автоматикой и цифровой то я бы выбрал первую.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Сейчас проверил в железе ваш новый код. При включении никакой диагностики не происходит. Реле РВ4 не включается, а только  если напряжение меньше 11.1 вольта то все молчит, если больше- то быстро мигает светодиод РВ2.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

dimaris пишет:

Хочу его применить для резервного питания базы домашнего радиотелефона, когда происходят перебои с электроэнергией. Можно вместо функции сна сделать чтобы при возобновлении подачи электроэнергии в сеть, это устройство включало нагрузку но не сразу а когда аккумулятор немного зарядится до определенного напряжения? Ну хотя бы до 12-13 вольт. Тогда бы вышло отличное устройство бесперебойного питания с системой защиты от глубокого разряда.

Вам обязательно задействовать tiny, или сойдет что-то типа DW01, которые стоят в защите батареек сотовых телефонов?

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Тк эта микруха для одной банки литиевого аккумулятора.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

dimaris пишет:

Тк эта микруха для одной банки литиевого аккумулятора.

TL431, следуя Вашей логике, "только для 2.5 вольт". :)

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Обращаюсь к HWman. Несколько раз протестировал вашу прграмму в железе с применением лабораторного блока питания, выяснил что устройство прохлдит цикл разряда аккумулятора со световой индикацией уровней напряжения. Но после ухода во временной спящий режим происходит какое-то зацикливание или неправильный выход из сна, вызывающий частое мигание одним оз светодиодов. Пробовал проверить на другой тини 13 (может чего с контроллелром) симптомы такие же.

С уважеднием dimaris.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Попробуйте этот код:

#include <avr/io.h>
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/power.h>

int main( void )
{
  DDRB = 0b10111;  // порти PB0-PB2 и PB4 встановленні на вихід, PB3 на вхід.

  if(analogReadOversampled() <= 401 ) { // Если напряжение < 11.7 В. тогда сон на 4 сек.  
    PORTB &= ~(1<<2); 
    system_sleep_4S();
  }

  /*
   PB3 делитель 5 кОм и 1 кОм(земля) + подстроечный резистор на 500 Ом 
   PB4 реле
   PB0 1-й светодод 100% заряда - 12.5 В.
   PB1 2-й светодод 65% заряда - 11.7 В.
   PB2 3-й светодод 35% заряда - 11.1 В.
   */

  PORTB = 1<<0; // диагностика
  PORTB = 1<<1;
  PORTB = 1<<2;
  delay(10); 

  while(1){

    PORTB &= ~(1<<0);
    PORTB &= ~(1<<1);  // тушим светодиоды 100% 65% 35%
    PORTB &= ~(1<<2); 

    if(analogReadOversampled() >= 358 && analogReadOversampled() <= 512) { 
      PORTB |= (1<<4);  // Якщо  напруга більше ніж 10.5 і менше чим 15 В вмикаємо реле і запускаємо виконання циклу
      if(analogReadOversampled() >= 445 ) {  // якщо  напруга більше ніж 13 В то мигаємо усіма світлодіодами 
        delay((((542 - analogReadOversampled()) / 4) * 50)); 
      } // інтенсивність мигання залежить від величини напруги, є 4 режими інтенсивності
      if(analogReadOversampled() >= 428 ) { 
        PORTB |= (1<<0); 
      }  // 1-й світолодіод 100% заряда - 12.5 В.
      if(analogReadOversampled() >= 401 ) { 
        PORTB |= (1<<1); 
      }  // 2-й світолодіод 65% заряда - 11.7 В.
      if(analogReadOversampled() >= 378 ) {
        PORTB |= (1<<2); 
      }  // 3-й світолодіод 35% заряда - 11.1 В.  
      if(analogReadOversampled() <= 377 ) { 
        PORTB |= (1<<2);    // якщо напруга нижче 11.1 В. тоді мигаємо світлодіодом 30% інтенсивність залежить від величина нипруги   
        delay((((analogReadOversampled() - 350) / 4) * 50)); // інтенсивність залежить від величина напруги   
        PORTB &= ~(1<<2); 
      }
      delay(10); 
    }   
    else { 
      PORTB &= ~(1<<2); 
      PORTB &= ~(1<<4); // для мосфета
      system_sleep_4S(); 
    } // інакше реле вимикаємо і засинаємо до ресету
  }
  return 0;
}

unsigned int ADC_READ(){  // ініціалізуємо АЦП
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF; 
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  return (high << 8) | low;
}

void system_sleep_4S(){ // сон на 2 сек
  wdt_reset(); // сброс
  wdt_enable(WDTO_4S); // разрешение ватчдога раз в 4с
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  while(1) {
    sleep_enable(); // разрешаем сон
    sleep_cpu(); // спать!
  }
}

// оверсемплинг для большей точности и меньших шумов
unsigned int analogReadOversampled(){
  unsigned long aSum = 0;   // the sum of all analog readings
  for(int i = 0; i < 16; i++) 
    aSum += ADC_READ(); // read and sum 16 ADС probes
  return aSum >> 4;   // ..
}

То что есть лаб бп - хорошо, постарайтесь сделать как можно больше сценариев, меряйте ток потребления когда МК уснул, когда просыпается чтобы "пощупать"  питание.

Поднял напряжение включения(гистерезис) до < 11.7 В и вроде сделал так что светодиод 35% уже не будет гореть.
Тестируйте, по возможности выкладывайте видео.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Протестировать смогу не раньше понедельника, о результатах отпишусь. Насчет видео, я пока проверяю проект на беспаечной макетной плате. Как начнет работать стабильно то сразу воплащу все это на печатной плате с фотографиями и возможно видео. Постараюсь разместить в этой ветке готовые результаты.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Пробовал несколько раз заливать скетч. Один и тот-же результат. Начинает постоянномигать светодиод на 7-й ноге при напряжении выше 11,7 вольта, больше ничего не происходит. Ниже 11,7 вольт вся схема молчит.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Жаль что вам больше не интересен этот проект..

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

При программном моделировании вроде как начинает работать но не сразу...

А ядро юзаете отсюда?

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Еще раз все проверил, перезакачал ядро, результат тот же. Причем заливаю кос из #66 поста все работает исправно. Значит с ядром все нормально. Еще заметил одну особеннось во времени, ровно в 10 раз медленнее. Тоесть 1000мс это на самом деле 10000мс, проверял в железе через Blink. Может дело в настройках фьюзов в самом ядре чего? Прошиваю пока через ардуино уно (attiny13 9.6 мГц, BOD 2.7 V), но могу и USBAspшкой попробовать хотя разницы быть не должно..

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Сейчас пробовал заливать тот же последний код но с настройками платы под 1 Mhz и в результате программа прекрасно отрабатывает индикацию в процессе имитации разрядки аккумулятора. Но после отключения реле я через некоторое время начинаю поднимать напряжение до 11 вольт и выше начинает мигать светодиод 7й ноге и больше ничего на происходит.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Попробуйте этот:

#include <avr/io.h>
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/power.h>
//#include <avr/interrupt.h> // работа с прерываниями

int main( void )
{
  DDRB = 0b10111;  // порти PB0-PB2 и PB4 встановленні на вихід, PB3 на вхід.
  PORTB = 0x00;  // установим низкий уровень на всех портах
  WDTCR |= _BV(WDE); // разрешаем WDTIE

  /*
   PB3 делитель 5 кОм и 1 кОм(земля) + подстроечный резистор на 500 Ом 
   PB4 реле
   PB0 1-й светодод 100% заряда - 12.5 В.
   PB1 2-й светодод 65% заряда - 11.7 В.
   PB2 3-й светодод 35% заряда - 11.1 В.
   */
if(analogReadOversampled() <= 401 ) { // для обеспечения гистерезиса после отключения
    // при 11.7 В просыпаемся 
    PORTB |= (1<<2); // подмигнём, типа спим но питание есть
    system_sleep_8S();
 }
  
  /*for(byte i = 0; i <= 2; i++){    // диагностика
   PORTB = 1<<i;
   delay(500); //_delay_ms(50);
   }*/
   
  while(1){
    //wdt_enable(WDTO_1S); // защита от зависаний, не сбросим через
    // если не сбросим тогда будет ресет 
    PORTB &= ~(1<<0);
    PORTB &= ~(1<<1);  // гасимо світлодіоди 100% 65% 35%
    PORTB &= ~(1<<2);
    
    int voltage = analogReadOversampled(); 
    
    if(voltage >= 358 && voltage <= 512) { 
      PORTB |= (1<<4);  // Якщо  напруга більше ніж 10.5 і менше чим 15 В вмикаємо реле і запускаємо виконання циклу
      if(voltage >= 445 ) {  // якщо  напруга більше ніж 13 В то мигаємо усіма світлодіодами 
        delay((((542 - voltage) / 4) * 50)); 
      } // інтенсивність мигання залежить від величини напруги, є 4 режими інтенсивності
      if(voltage >= 428 ) { 
        PORTB |= (1<<0); 
      }  // 1-й світолодіод 100% заряда - 12.5 В.
      if(voltage >= 401 ) { 
        PORTB |= (1<<1); 
      }  // 2-й світолодіод 65% заряда - 11.7 В.
      if(voltage >= 378 ) {
        PORTB |= (1<<2); 
      }  // 3-й світолодіод 35% заряда - 11.1 В.  
      if(voltage <= 377 ) { 
        PORTB |= (1<<2);    // якщо напруга нижче 11.1 В. тоді мигаємо світлодіодом 30% інтенсивність залежить від величина нипруги   
        delay((((voltage - 350) / 4) * 50)); // інтенсивність залежить від величина напруги   
        PORTB &= ~(1<<2); 
      }
      delay(10); 
      //wdt_reset(); // если дошли до сюда тогда
      // сбросим защиту от зависаний
    }   
    else { 
      //PORTB &= ~(1<<4); // для мосфета
      system_sleep_8S(); 
    } // інакше реле вимикаємо і засинаємо до ресету
  }
  return 0;
}

unsigned int ADC_READ(){  // ініціалізуємо АЦП
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF; 
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  return (high << 8) | low;
}

void system_sleep_8S(){ // сон на 8 сек
  PORTB = 0x00; // потушым все диоди и откл. реле
  wdt_reset(); // сбрасываем ватчдог
  wdt_enable(WDTO_1S); // разрешаем ватчдог 8 сек(1 сек для отладки)
  //WDTCR |= (1<<WDE); // разрешаем прерывания по ватчдогу. Иначе будет резет.
  //sei(); // разрешаем прерывания
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  while(1) {
    sleep_enable(); // разрешаем сон
    sleep_cpu(); // спать!
  }
}

// оверсемплинг для большей точности и меньших шумов
unsigned int analogReadOversampled(){
  unsigned long aSum = 0;   // the sum of all analog readings
  for(int i = 0; i < 16; i++) 
    aSum += ADC_READ(); // read and sum 16 ADС probes
  return aSum >> 4;   // ..
}

Программно вроде как работает.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Так вот я тоже любитель проверять для начала в протеусе, но лишь для проверки того что код живой и только после этого смотрю в железе. А тут какой-то подвох, у вас в эмуляторе все работает а у меня не совсем.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

И всетаки я больше склоняюсь в сторону фьюзов и не совсем корректного ядра. В электронике я имею больший опыт чем в программировании микроконтроллеров, проверять в железе готов и дальше, может вскроются еще какие нибудь особенности тини13..

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Еще один вопрос - Ваш новый код проверять в железе всетаки при 9,6 Мгц или 1Мгц? разница есть а что эмулятор выкинуть может мне известно.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Берите 1 мГц, там фюзы как в тинки с завода.

Может завтра возьму железо и тоже поиграюсь, пока в протеусе толком ничего не понятно.

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Эээх жаль не могу протастировать ваш новый код. Все оставил на работе...

dimaris
dimaris аватар
Offline
Зарегистрирован: 27.03.2012

Проверил новый скейтч, работа следующая: при напряжении больше 12 вольт- быстро мигает РВ4, ниже 12 но выше 11,5 вообще все мигает, от 11,5 до 10,7 мигают РВ4 РВ2 РВ1, ниже 10,7 все молчит.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Попробуйте вот этот:

#include <avr/io.h>
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/power.h>

int main( void )
{
  wdt_reset(); // надо же, сколько над этим бился
  // просто ватчдог после перезагрузки включен
  DDRB = 0b10111;  // порты PB0-PB2 и PB4 установленные на выход, PB3 на вход.
  /*
   PB3 делитель напряжения, 5 кОм и 1 кОм(земля)
   PB4 реле
   PB0 1-й светодиод 100% заряда - 12.5 В.
   PB1 2-й светодиод 65% заряда - 11.7 В.
   PB2 3-й светодиод 35% заряда - 11.1 В.
   */

  /*
  for(byte led_test = 0; led_test >= 2; led_test++){    // проведемо діагностику 
   PORTB = 1<<led_test;
   delay(100); //_delay_ms(300);
   }
   */

  unsigned int adc_in_main = analogReadOversampled();
  if(adc_in_main <= 410 || adc_in_main >= 462) { // для обеспечения гистерезиса после отключения
    // при > 12.0 / < 13.2 В просыпаемся
    //PORTB |= (1<<4); // подмигнём, типа спим но питание есть
    system_sleep();
  }

  while(1){
    wdt_enable(WDTO_2S); // защита от случайных зависаний
    // если не сбросить через 2 сек будет ресет
    PORTB &= ~(1<<0);
    PORTB &= ~(1<<1);  // тушим светодиодиы 100% 65% 35%
    PORTB &= ~(1<<2); 

    unsigned int adc = analogReadOversampled();

    if(adc >= 358 && adc <= 512) { 
      PORTB |= (1<<4);  // Якщо  напруга більше ніж 10.5 і менше чим 15 В вмикаємо реле і запускаємо виконання циклу
      if(adc >= 445 ) {  // якщо  напруга більше ніж 13 В то мигаємо усіма світлодіодами 
        delay((((542 - adc) / 4) * 50)); 
      } // інтенсивність мигання залежить від величини напруги, є 4 режими інтенсивності
      if(adc >= 428 ) { 
        PORTB |= (1<<0); 
      }  // 1-й світолодіод 100% заряда - 12.5 В.
      if(adc >= 401 ) { 
        PORTB |= (1<<1); 
      }  // 2-й світолодіод 65% заряда - 11.7 В.
      if(adc >= 378 ) {
        PORTB |= (1<<2); 
      }  // 3-й світолодіод 35% заряда - 11.1 В.  
      if(adc <= 377 ) { 
        PORTB |= (1<<2);    // якщо напруга нижче 11.1 В. тоді мигаємо світлодіодом 30% інтенсивність залежить від величина нипруги   
        delay((((adc - 350) / 4) * 50)); // інтенсивність залежить від величина напруги   
        PORTB &= ~(1<<2); 
      }
      wdt_reset(); // сбросим защиту от зависаний
      delay(300); 
    }  // чекаємо як мінімум 0.3 сек    
    else { 
      //PORTB &= ~(1<<4); //
      system_sleep(); 
    } // інакше реле вимикаємо і засинаємо до ресету
  }
  return 0;
}

unsigned int ADC_READ(){  // ініціалізуємо АЦП
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF;
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  return (high << 8) | low;
}

unsigned int analogReadOversampled(){
  unsigned long aSum = 0;   // the sum of all analog readings
  for(int i = 0; i < 32; i++)
    aSum += ADC_READ(); // read and sum 16 ADС probes
  return aSum >> 5;   // ..
}
void system_sleep() {
  PORTB = 0x00; // потушым все диоди и откл. реле
  wdt_reset(); // сбрасываем ватчдог measure current
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  MCUSR &= ~(1<<WDRF);
  /* Start the WDT Config change sequence. */
  WDTCR |= (1<<WDCE) | (1<<WDE);
  /* Configure the prescaler and the WDT for interrupt mode only*/
  WDTCR = (1<<WDP0) | (1<<WDP3) | (1<<WDTIE); // 8sec
  //WDTCR = (1<<WDP2) | (1<<WDP1) | (1<<WDTIE); // 4sec
  //WDTCR = (1<<WDP2) | (1<<WDP0) | (1<<WDTIE); // 0.5sec
  WDTCR |= (1<<WDTIE);

  sei(); // Enable global interrupts 

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  while(1) {
    sleep_enable(); // разрешаем сон
    sleep_cpu(); // спать!
    sleep_disable();
  }
}

У меня всё в железе работает, толком потестить не успел, спать охота, но вроде работает.

Кстати, я обновил файлы ядра для тиньки.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Провёл замирения то поку потребления - 40 мА в работе 5 мА когда спит, как-то многовато, наверное делитель нужно по другому рассчитать и заменить реле на полевик, тогда будет можно сделать автоматическое переключение 12/24 В.

Доработал немного код:

/*
 PB3 вольтметр, делитель напряжения, 5 кОм и 1 кОм + 500 Ом подстроечный(земля)
 PB4 реле
 PB0 1-й светодиод 100% заряда - 12.5 В.
 PB1 2-й светодиод 65% заряда - 11.7 В.
 PB2 3-й светодиод 35% заряда - 11.1 В.
 
 Фюзы по умолчанию:
 low_fuses=0x6A
 high_fuses=0xFF 
 Частота 1,2 MHz
 */

#include <avr/io.h>
#include <avr/wdt.h> // здесь организована работа с ватчдогом
#include <avr/sleep.h> // здесь описаны режимы сна
#include <avr/power.h>
//#include <avr/delay.h>

int main( void )
{
  wdt_reset(); // надо же, сколько над этим бился
  // просто ватчдог после перезагрузки включен
  DDRB = 0b10111;  // порти PB0-PB2 и PB4 встановленні на вихід, PB3 на вхід.
  PORTB |= (1<<2); // подмигнём, типа спим но питание есть

  /*for(byte led_test = 1; led_test >= 0; led_test--){    // проведемо діагностику 
   PORTB = 1<<led_test;
   delay(300); //_delay_ms(300);
   }*/

  unsigned int adc_in_main = analogReadOversampled();
  if(adc_in_main <= 410 || adc_in_main >= 472) { // для обеспечения гистерезиса после отключения
    // при > 12.0 В или < 13.5 В просыпаемся
    system_sleep();
  }

  for(byte led_test = 0; led_test < 2; led_test++){    // проведемо діагностику 
    PORTB = 1<<led_test;
    delay(300);
  }

  while(1){
    wdt_enable(WDTO_2S); // защита от случайных зависаний
    // если не сбросить через 2 сек будет ресет
    PORTB &= ~(1<<0);
    PORTB &= ~(1<<1);  // тушым светодиоди 100% 65% 35%
    PORTB &= ~(1<<2); 

    unsigned int adc = analogReadOversampled();

    if(adc >= 358 && adc <= 512) { 
      PORTB |= (1<<4);  // напряжение > 10.5 В < 15 В поехали!
      if(adc >= 445 ) {  // > 13 В мигаем всема светодиодами
        delay((((542 - adc) / 4) * 50)); 
      } // интенсивность мигания зависит от напряжения
      if(adc >= 428 ) { 
        PORTB |= (1<<0); 
      }  // 1-й светодиод 100% заряда > 12.5 В.
      if(adc >= 401 ) { 
        PORTB |= (1<<1); 
      }  // 2-й светодиод 65% заряда > 11.7 В.
      if(adc >= 378 ) {
        PORTB |= (1<<2); 
      }  // 3-й светодиод 35% заряда > 11.1 В.  
      if(adc <= 377 ) { 
        PORTB |= (1<<2);    // < 11.1 В. мигаем светодиодом 30%
        delay((((adc - 350) / 4) * 50)); // интенсивность мигания зависит от напряжения  
        PORTB &= ~(1<<2); 
      }
      wdt_reset(); // сбросим защиту от зависаний
      delay(300);  // ждём как минимум 0.3 сек 
    }    
    else { 
      //PORTB &= ~(1<<4); //
      system_sleep(); 
    } // если условие > 10.5 В < 15 В не выполняется - сон 
  }
  return 0;
}

unsigned int ADC_READ(){  
  ADMUX = 3; // ADC pin
  ADCSRA |= 1<<ADEN;
  ADCSRA |= 1<<ADSC;
  while(!(ADCSRA & (1<<ADIF)));
  ADCSRA |= 1<<ADIF;
  byte low  = ADCL;
  byte high = ADCH;
  ADCSRA &= ~(1 << ADEN);  // отключаем АЦП
  return (high << 8) | low;
}

unsigned int analogReadOversampled(){
  unsigned long aSum = 0;   // the sum of all analog readings
  for(int i = 0; i < 32; i++)
    aSum += ADC_READ(); // read and sum 16 ADС probes
  return aSum >> 5;   // ..
}
void system_sleep() {
  wdt_reset(); // сбрасываем ватчдог measure current
  PORTB = 0x00; // потушым все диоди и откл. реле
  ADCSRA &= ~(1 << ADEN);  // вимикаємо АЦП
  
  MCUSR &= ~(1<<WDRF);
  /* Start the WDT Config change sequence. */
  WDTCR |= (1<<WDCE) | (1<<WDE);
  /* Configure the prescaler and the WDT for interrupt mode only*/
  WDTCR = (1<<WDP0) | (1<<WDP3) | (1<<WDTIE); // 8sec
  //WDTCR = (1<<WDP2) | (1<<WDP1) | (1<<WDTIE); // 4sec
  //WDTCR = (1<<WDP2) | (1<<WDP0) | (1<<WDTIE); // 0.5sec
  WDTCR |= (1<<WDTIE);

  sei(); // Enable global interrupts 

  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
  while(1) {
    sleep_enable(); // разрешаем сон
    sleep_cpu(); // спать!
    sleep_disable();
  }
}

Или можно скачать всё в архиве у меня на хостинге, там и хекс файл и схема и фьюзи.

Когда сделаю автоматическое переключение 12/24 тогда перезалью.

Буду рад конструктивной критике.

HWman
HWman аватар
Offline
Зарегистрирован: 26.02.2013

Тест на солнечной панели http://www.youtube.com/watch?v=EPeW1IzQ7jA