Есть несколько идей, например добавлю отключение при завышенном напряжении в 15 В, что расширяет границы применения моего девайса, например можно будет использовать в полуавтоматическом ЗУ для аккума.
Ещё хочу научить всетодиод 35% мигать в зависимости от уровня заряда, тоесть от 35% и до 0% будет мигать с разной интенсивностью, сначало быстро а потом медленей...
Может у кого-то будут какие-то идеи или же предложения?
ЗЫ посоветуйте хороший обменник на который было бы удобно выгружать файлы?
Качать последнюю версию реализа(на сегодня это 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, да и поменьше размером :)
Неразобрался я ещё толком с протэусом, там нельзя сделать видимыми ноги питания почему-то, питать буду через 5-ти вольтовый линейный стабилизатор 78L05. Для тонкой подстройки добавил резистор R8 на 500 Ом но позволит опустить напряжение срабатования если что.
Единственное что ещё беспокоит - стоит ли добавлять диод к аналоговом входе PB3. Что будет с ним при переполюсовке?
Сейчас уже другие трудности появились, что-то с дуиной стало или тини перегорела, немогу прошить... вроде что-то коротнуло при процесе прошивки или что...
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
46
//sleep_mode(); // System sleeps here
47
sleep_enable(); // разрешаем сон
48
sleep_cpu(); // спать!
49
//sbi(ADCSRA,ADEN); // Switch Analog to Digital converter ON
50
}
51
52
ISR(PCINT0_vect) {
53
54
}
Как мне кажется теперь должен засыпать, по крайней мере IDE уже не ругается на меня, мол, я не-з-на-юу таких слов, иди отсюда! Не уверен что всё что в шапке #define нужны, может кто подскажет?
Proteus 7 Professional показывает никакой спад по току, как было 0.09 А так и осталось...
ЗЫ Софтово будить МК не хочу, лучше отключу ему питание и потом поять подам, или же ресетом буду "поднимать всю глубину наших глубин".
Ещё нуждается в настройке, немного изменил скетч, в часности цифры для аналогового входа...
Ток потребления в режыме stand bye 6 мА когда работает 50 мА, 85 % жрет реле. Почти закончил, осталось к ресету кнопку приделать перепаять диоды на другую платку у всё уложыть в крачивый корпус. Всем спасибо кто откликнулся за помощь.
Ох сколько раз я ещё возвращался к этому "проекту" кстати, всем огромное спасибо за помощь.
Как показала практика если перепутать полярность то полевик релюхи стреляет и выходит из строя, так что перед им нужен предохранитель на 100-200 мА ибо при переполюсовке ток сильно возрастает.
По данной схемке успешно сдал курсачь, его добавил в архив где есть всё по даной теме, при желании курсачь можно спокойно перевести на Русский при помощи гугл-переводчика.
По этой теме у меня пожалуй все, не думаю что "проект" буду продолжать улучшать так как надобность этого девайся уже отпала.
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();
} // інакше реле вимикаємо і засинаємо до ресету
}
return0;
}
unsigned intADC_READ(){ // ініціалізуємо АЦП
ADMUX = 3; // ADC pin
ADCSRA |= 1<<ADEN;
ADCSRA |= 1<<ADSC;
while(!(ADCSRA & (1<<ADIF)));
ADCSRA |= 1<<ADIF;
bytelow = ADCL;
bytehigh = ADCH;
ADCSRA &= ~(1 << ADEN); // вимикаємо АЦП
return(high << 8) | low;
}
voidsystem_sleep() {
ADCSRA &= ~(1 << ADEN); // вимикаємо АЦП
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // повністю засинаємо
sleep_enable(); // сон дозволено
sleep_cpu();
}
Если в схеме заменить реле полевым транзистором с очень малым сопротивлением СИ - 0,00* Ом то выйдет довольно неплохая схемка с малым потреблением, реле кушает около 40 мА а транзистор почти ничего не кушает. Вот набросал схемку с транзистором вместо реле:
Кстати, при такой схеме:
При переполюсовке транзистор вылетает с треском, не могу понять почему.
А ещё лучше предохранитель, возможно даже самовосстанавливающийся.
Зачем?? Для защиты схем от переполюсовки обычно ставят мосфет по схеме "идеального диода"... Если защищать только транзистор и цепи питания реле - то можно запитать реле (с блокирующим диодом) через диодный мост: ему все равно, он полярность сам поправит как надо. Или последовательно с блокирующим диодом поставить стабилитрон на номинал напряжения питания...
Меня очень заинтересовало это устройство. Хочу его применить для резервного питания базы домашнего радиотелефона, когда происходят перебои с электроэнергией. Можно вместо функции сна сделать чтобы при возобновлении подачи электроэнергии в сеть, это устройство включало нагрузку но не сразу а когда аккумулятор немного зарядится до определенного напряжения? Ну хотя бы до 12-13 вольт. Тогда бы вышло отличное устройство бесперебойного питания с системой защиты от глубокого разряда.
} // інтенсивність мигання залежить від величини напруги, є 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();
} // інакше реле вимикаємо і засинаємо до ресету
}
return0;
}
unsigned intADC_READ(){ // ініціалізуємо АЦП
ADMUX = 3; // ADC pin
ADCSRA |= 1<<ADEN;
ADCSRA |= 1<<ADSC;
while(!(ADCSRA & (1<<ADIF)));
ADCSRA |= 1<<ADIF;
bytelow = ADCL;
bytehigh = ADCH;
ADCSRA &= ~(1 << ADEN); // вимикаємо АЦП
return(high << 8) | low;
}
voidsystem_sleep_4S(){ // сон на 2 сек
wdt_reset(); // сброс
wdt_enable(WDTO_4S); // разрешение ватчдога раз в 2с
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
while(1) {
sleep_enable(); // разрешаем сон
sleep_cpu(); // спать!
}
}
// оверсемплинг для большей точности и меньших шумов
unsigned intanalogReadOversampled(){
unsigned longaSum = 0; // the sum of all analog readings
for(inti = 0; i < 16; i++)
aSum += ADC_READ(); // read and sum 16 ADС probes
returnaSum >> 4; // ..
}
Данный код вместо того чтобы усыпить МК навечно когда напряжение упало ниже критичного уровня усыпляет его на 4 сек, просыпается проверяет не поднялась ли напруга до 11.1 В - да включает нагрузку, нет дальше сон на 4 сек...
А нужна ли Вам эта индикация уровня заряда? Можно сделать проще, причём даже без МК, TL431 + парочка резисторов и мосфет, схема будет очень простой.
Спасибо за помощь! Завщтра попробую реализовать ваше решение в железе. О результатах отпишусь. А поповоду применения крен19(TL431) проводил опыты и сталкнулся проблемой переходных процессов в момент порога срабатывания. Полуяается чтото вроде генеразтора, когда снимается энагрузка напряжение на аккумуляторе поднимается и происходит подключение нагрузки и так по кругу вплодь до дребезжания реле. Как раз в таком случае и нужен своеобръазный гистерезис для исключения такого эффекта.
Сейчас проверил в железе ваш новый код. При включении никакой диагностики не происходит. Реле РВ4 не включается, а только если напряжение меньше 11.1 вольта то все молчит, если больше- то быстро мигает светодиод РВ2.
Хочу его применить для резервного питания базы домашнего радиотелефона, когда происходят перебои с электроэнергией. Можно вместо функции сна сделать чтобы при возобновлении подачи электроэнергии в сеть, это устройство включало нагрузку но не сразу а когда аккумулятор немного зарядится до определенного напряжения? Ну хотя бы до 12-13 вольт. Тогда бы вышло отличное устройство бесперебойного питания с системой защиты от глубокого разряда.
Вам обязательно задействовать tiny, или сойдет что-то типа DW01, которые стоят в защите батареек сотовых телефонов?
Обращаюсь к HWman. Несколько раз протестировал вашу прграмму в железе с применением лабораторного блока питания, выяснил что устройство прохлдит цикл разряда аккумулятора со световой индикацией уровней напряжения. Но после ухода во временной спящий режим происходит какое-то зацикливание или неправильный выход из сна, вызывающий частое мигание одним оз светодиодов. Пробовал проверить на другой тини 13 (может чего с контроллелром) симптомы такие же.
} // інтенсивність мигання залежить від величини напруги, є 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();
} // інакше реле вимикаємо і засинаємо до ресету
}
return0;
}
unsigned intADC_READ(){ // ініціалізуємо АЦП
ADMUX = 3; // ADC pin
ADCSRA |= 1<<ADEN;
ADCSRA |= 1<<ADSC;
while(!(ADCSRA & (1<<ADIF)));
ADCSRA |= 1<<ADIF;
bytelow = ADCL;
bytehigh = ADCH;
ADCSRA &= ~(1 << ADEN); // вимикаємо АЦП
return(high << 8) | low;
}
voidsystem_sleep_4S(){ // сон на 2 сек
wdt_reset(); // сброс
wdt_enable(WDTO_4S); // разрешение ватчдога раз в 4с
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // если спать - то на полную
while(1) {
sleep_enable(); // разрешаем сон
sleep_cpu(); // спать!
}
}
// оверсемплинг для большей точности и меньших шумов
unsigned intanalogReadOversampled(){
unsigned longaSum = 0; // the sum of all analog readings
for(inti = 0; i < 16; i++)
aSum += ADC_READ(); // read and sum 16 ADС probes
returnaSum >> 4; // ..
}
То что есть лаб бп - хорошо, постарайтесь сделать как можно больше сценариев, меряйте ток потребления когда МК уснул, когда просыпается чтобы "пощупать" питание.
Поднял напряжение включения(гистерезис) до < 11.7 В и вроде сделал так что светодиод 35% уже не будет гореть.
Тестируйте, по возможности выкладывайте видео.
Протестировать смогу не раньше понедельника, о результатах отпишусь. Насчет видео, я пока проверяю проект на беспаечной макетной плате. Как начнет работать стабильно то сразу воплащу все это на печатной плате с фотографиями и возможно видео. Постараюсь разместить в этой ветке готовые результаты.
Пробовал несколько раз заливать скетч. Один и тот-же результат. Начинает постоянномигать светодиод на 7-й ноге при напряжении выше 11,7 вольта, больше ничего не происходит. Ниже 11,7 вольт вся схема молчит.
Еще раз все проверил, перезакачал ядро, результат тот же. Причем заливаю кос из #66 поста все работает исправно. Значит с ядром все нормально. Еще заметил одну особеннось во времени, ровно в 10 раз медленнее. Тоесть 1000мс это на самом деле 10000мс, проверял в железе через Blink. Может дело в настройках фьюзов в самом ядре чего? Прошиваю пока через ардуино уно (attiny13 9.6 мГц, BOD 2.7 V), но могу и USBAspшкой попробовать хотя разницы быть не должно..
Сейчас пробовал заливать тот же последний код но с настройками платы под 1 Mhz и в результате программа прекрасно отрабатывает индикацию в процессе имитации разрядки аккумулятора. Но после отключения реле я через некоторое время начинаю поднимать напряжение до 11 вольт и выше начинает мигать светодиод 7й ноге и больше ничего на происходит.
Так вот я тоже любитель проверять для начала в протеусе, но лишь для проверки того что код живой и только после этого смотрю в железе. А тут какой-то подвох, у вас в эмуляторе все работает а у меня не совсем.
И всетаки я больше склоняюсь в сторону фьюзов и не совсем корректного ядра. В электронике я имею больший опыт чем в программировании микроконтроллеров, проверять в железе готов и дальше, может вскроются еще какие нибудь особенности тини13..
Проверил новый скейтч, работа следующая: при напряжении больше 12 вольт- быстро мигает РВ4, ниже 12 но выше 11,5 вообще все мигает, от 11,5 до 10,7 мигают РВ4 РВ2 РВ1, ниже 10,7 все молчит.
Провёл замирения то поку потребления - 40 мА в работе 5 мА когда спит, как-то многовато, наверное делитель нужно по другому рассчитать и заменить реле на полевик, тогда будет можно сделать автоматическое переключение 12/24 В.
Там старьё одно могу новые закинуть.
Есть несколько идей, например добавлю отключение при завышенном напряжении в 15 В, что расширяет границы применения моего девайса, например можно будет использовать в полуавтоматическом ЗУ для аккума.
Ещё хочу научить всетодиод 35% мигать в зависимости от уровня заряда, тоесть от 35% и до 0% будет мигать с разной интенсивностью, сначало быстро а потом медленей...
Может у кого-то будут какие-то идеи или же предложения?
ЗЫ посоветуйте хороший обменник на который было бы удобно выгружать файлы?
ЗЫ посоветуйте хороший обменник на который было бы удобно выгружать файлы?
dropbox.com
урааа! 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, да и поменьше размером :)
Rimidalw спасибо, но там нужно регатся...
Вот выгрузил файлы проекта, пользуйтесь.
Изменил схему как рекомендовали:
Вот скетч:
01
//#include <util/delay.h> // уменьшим вес прошивки
02
int
V = 0;
// обнулим, мало ли ;)
03
void
setup
(){
04
pinMode(3, INPUT);
// вольтметр, делитель из 5 кОм и 1 кОм(земля), значение в 1023 это будет 24.35 В тоесть 33.87 на вольт
05
pinMode(4, OUTPUT);
// релюха
06
pinMode(0, OUTPUT);
// 1-й светодиод 100% заряда - 12.5 В.
07
pinMode(1, OUTPUT);
// 2-й светодиод 65% заряда - 11.7 В.
08
pinMode(2, OUTPUT);
// 3-й светодиод 35% заряда - 11.1 В.
09
// диагностика:
10
digitalWrite(0, HIGH); delay(1000); digitalWrite(0, LOW); delay(1000);
11
digitalWrite(1, HIGH); delay(1000); digitalWrite(1, LOW); delay(1000);
12
digitalWrite(2, HIGH); delay(1000); digitalWrite(2, LOW); delay(1000);
13
digitalWrite(4, HIGH); delay(1000); digitalWrite(4, LOW);
14
// всё работает?
15
}
16
void
loop
()
17
{
18
digitalWrite(0, LOW);
19
digitalWrite(1, LOW);
//тушим диоды 100/65/35
20
digitalWrite(2, LOW);
21
int
V = analogRead(3);
22
if
(V >= 362 && V <= 511) { digitalWrite(4, HIGH);
// если больше 10.5 и меньше 15 приступаем, включаем реле
23
if
(V >= 443 ) {
// если напряжение больше 13 В мигаем
24
delay((((520 - V) / 4) * 100)); }
// интенсивность мигания зависит от величины напряжения
25
if
(V >= 426 ) { digitalWrite(0, HIGH); }
// 1-й светодиод 100% заряда - 12.5 В.
26
if
(V >= 399 ) { digitalWrite(1, HIGH); }
// 2-й светодиод 65% заряда - 11.7 В.
27
if
(V >= 379 ) { digitalWrite(2, HIGH); }
// 3-й светодиод 35% заряда - 11.1 В.
28
if
(V <= 379 ) { digitalWrite(2, HIGH);
// если напряжение заряда ниже 11.1 В. тогда мигаем
29
delay(((V - 350) * 100));
// интенсивность мигания зависит от величины напряжения
30
digitalWrite(2, LOW); }
31
delay(500); }
// ждём как минимум 0.5 сек во избежания дребезжания контактов реле
32
else
{ digitalWrite(4, LOW); }
33
//delay(1000); // ждём 1 сек во избежания дребезжания контактов реле
34
}
Всё проверил программно, всё работает, железо ещё не тестил. 784 байт. Я вполне доволен, сделал всё что хотел и ещё осталось пару сотен кило...
почему в схеме МК не подключён к vcc и gnd? или я не понимаю
как вы его питаете в железной схеме?
помните МК измеряет напряжение отнрсительно vcc?
Неразобрался я ещё толком с протэусом, там нельзя сделать видимыми ноги питания почему-то, питать буду через 5-ти вольтовый линейный стабилизатор 78L05. Для тонкой подстройки добавил резистор R8 на 500 Ом но позволит опустить напряжение срабатования если что.
Единственное что ещё беспокоит - стоит ли добавлять диод к аналоговом входе PB3. Что будет с ним при переполюсовке?
Сейчас уже другие трудности появились, что-то с дуиной стало или тини перегорела, немогу прошить... вроде что-то коротнуло при процесе прошивки или что...
После похода в гугл обновил немного код:
01
#include <avr/pgmspace.h>
02
#include <avr/sleep.h> // sleep code by insidegadgets.com
03
#ifndef cbi
04
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
05
#endif
06
#ifndef sbi
07
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
08
#endif
09
int
V = 0;
// обнулим, мало ли ;)
10
void
setup
(){
11
pinMode(3, INPUT);
// вольтметр, делитель из 5 кОм и 1 кОм(земля), значение в 1023 это будет 24.35 В тоесть 33.87 на вольт
12
pinMode(4, OUTPUT);
// релюха
13
pinMode(0, OUTPUT);
// 1-й светодиод 100% заряда - 12.5 В.
14
pinMode(1, OUTPUT);
// 2-й светодиод 65% заряда - 11.7 В.
15
pinMode(2, OUTPUT);
// 3-й светодиод 35% заряда - 11.1 В.
16
// диагностика:
17
digitalWrite(0, HIGH); delay(1000); digitalWrite(0, LOW); delay(1000);
18
digitalWrite(1, HIGH); delay(1000); digitalWrite(1, LOW); delay(1000);
19
digitalWrite(2, HIGH); delay(1000); digitalWrite(2, LOW); delay(1000);
20
digitalWrite(4, HIGH); delay(1000); digitalWrite(4, LOW);
21
// всё работает?
22
}
23
void
loop
()
24
{
25
digitalWrite(0, LOW);
26
digitalWrite(1, LOW);
//тушим диоды 100/65/35
27
digitalWrite(2, LOW);
28
int
V = analogRead(3);
29
if
(V >= 362 && V <= 511) { digitalWrite(4, HIGH);
// если больше 10.5 и меньше 15 приступаем, включаем реле
30
if
(V >= 443 ) {
// если напряжение больше 13 В мигаем
31
delay((((520 - V) / 4) * 100)); }
// интенсивность мигания зависит от величины напряжения
32
if
(V >= 426 ) { digitalWrite(0, HIGH); }
// 1-й светодиод 100% заряда - 12.5 В.
33
if
(V >= 399 ) { digitalWrite(1, HIGH); }
// 2-й светодиод 65% заряда - 11.7 В.
34
if
(V >= 379 ) { digitalWrite(2, HIGH); }
// 3-й светодиод 35% заряда - 11.1 В.
35
if
(V <= 379 ) { digitalWrite(2, HIGH);
// если напряжение заряда ниже 11.1 В. тогда мигаем
36
delay(((V - 350) * 100));
// интенсивность мигания зависит от величины напряжения
37
digitalWrite(2, LOW); }
38
delay(500); }
// ждём как минимум 0.5 сек во избежания дребезжания контактов реле
39
else
{ digitalWrite(4, LOW);
40
system_sleep(); }
41
}
42
// interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
43
void
system_sleep() {
44
ADCSRA &= ~(1 << ADEN);
// отключаем АЦП
45
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// если спать - то на полную
46
//sleep_mode(); // System sleeps here
47
sleep_enable();
// разрешаем сон
48
sleep_cpu();
// спать!
49
//sbi(ADCSRA,ADEN); // Switch Analog to Digital converter ON
50
}
51
52
ISR(PCINT0_vect) {
53
54
}
Как мне кажется теперь должен засыпать, по крайней мере IDE уже не ругается на меня, мол, я не-з-на-юу таких слов, иди отсюда! Не уверен что всё что в шапке #define нужны, может кто подскажет?
Proteus 7 Professional показывает никакой спад по току, как было 0.09 А так и осталось...
ЗЫ Софтово будить МК не хочу, лучше отключу ему питание и потом поять подам, или же ресетом буду "поднимать всю глубину наших глубин".
немогу прошить микруху, регается
1
avrdude: please define PAGEL and BS2 signals
in
the configuration file
for
part ATtiny13
2
avrdude: Yikes! Invalid device signature.
3
Double check connections and
try
again, or use -F to
override
4
this
check.
всё проверил три раза подключил всё верно, есть возможность того что убил микросхему?
Как и чем шьете?
http://www.instructables.com/id/Programming-an-ATTiny13A-using-Arduino-s...
Вот так как тут. Сначало всё нормально шилось, а пото м что-то случилось, возможно что-то где-то коротнуло или ещё что...
Вечером попробую на другой микрухе
Поставил новую микруху, сделал более менее удобный программатор для дуинки:
и заработало.
Видео:
http://www.youtube.com/watch?v=oEIAmJ6VZiU
Ещё нуждается в настройке, немного изменил скетч, в часности цифры для аналогового входа...
Ток потребления в режыме stand bye 6 мА когда работает 50 мА, 85 % жрет реле. Почти закончил, осталось к ресету кнопку приделать перепаять диоды на другую платку у всё уложыть в крачивый корпус. Всем спасибо кто откликнулся за помощь.
После тестирования отпишусь.
Наконец-то настроил как программно так и аппаратно, войдя во вкус оптимизации и прислушиваться к вашим советам я немного переделал скетч:
#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 байт максимум), супер :)
Вот фото девайса:
Алгоритм настройки думаю вопросов не вызовет.
Ох сколько раз я ещё возвращался к этому "проекту" кстати, всем огромное спасибо за помощь.
Как показала практика если перепутать полярность то полевик релюхи стреляет и выходит из строя, так что перед им нужен предохранитель на 100-200 мА ибо при переполюсовке ток сильно возрастает.
По данной схемке успешно сдал курсачь, его добавил в архив где есть всё по даной теме, при желании курсачь можно спокойно перевести на Русский при помощи гугл-переводчика.
По этой теме у меня пожалуй все, не думаю что "проект" буду продолжать улучшать так как надобность этого девайся уже отпала.
там нет файла
Скорей всего на сайт нужно зайти под Украинским прокси.
Перезалил себе все файлы на хостинг, вот тут есть ядро нужное для тини, в первом сообщении всё ссылки во втором файлы ядра.
Немного изменил код:
#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 мА а транзистор почти ничего не кушает. Вот набросал схемку с транзистором вместо реле:
Кстати, при такой схеме:
При переполюсовке транзистор вылетает с треском, не могу понять почему.
При переполюсовке транзистор вылетает с треском, не могу понять почему.
Коротыш через блокирующий диод реле. Поставьте мосфет ампер на 50 - вылетит диод. :)
А ещё лучше предохранитель, возможно даже самовосстанавливающийся.
А ещё лучше предохранитель, возможно даже самовосстанавливающийся.
Зачем?? Для защиты схем от переполюсовки обычно ставят мосфет по схеме "идеального диода"... Если защищать только транзистор и цепи питания реле - то можно запитать реле (с блокирующим диодом) через диодный мост: ему все равно, он полярность сам поправит как надо. Или последовательно с блокирующим диодом поставить стабилитрон на номинал напряжения питания...
По моему самовостанавливающийся предохранитель будет получше в плане КПД схемы.
По моему самовостанавливающийся предохранитель будет получше в плане КПД схемы.
зачем? часто путаешь питание?
По моему самовостанавливающийся предохранитель будет получше в плане КПД схемы.
зачем? часто путаешь питание?
Просто хочется сделать нормально, хотя иногда бывает затупишь и только дымок улетает, как говорил один человек, это духи умерших деталей.
Просто хочется сделать нормально, хотя иногда бывает затупишь и только дымок улетает, как говорил один человек, это духи умерших деталей.
чёрным маркером земляные провода метишь... и всё
"нормально" не получится, а если защиту от переполюсовки не втуда воткнёшь - как от такого обезопаситься?
Всего не предусмотришь, но защиту от переполюсовки делать нужно, это уже принцип.
Для защиты "от дурака" в схемах не хватает предохранителей, можно даже ставить самовосстанавливающиеся.
На этом считаю проект законченным, возможно потом буду делать что-то типо такого:
http://www.youtube.com/watch?v=rA7TbwtcdU8
Естественно на меге8-й.
Здравствуйте!
Меня очень заинтересовало это устройство. Хочу его применить для резервного питания базы домашнего радиотелефона, когда происходят перебои с электроэнергией. Можно вместо функции сна сделать чтобы при возобновлении подачи электроэнергии в сеть, это устройство включало нагрузку но не сразу а когда аккумулятор немного зарядится до определенного напряжения? Ну хотя бы до 12-13 вольт. Тогда бы вышло отличное устройство бесперебойного питания с системой защиты от глубокого разряда.
Заранее спасибо всем кто откликнется на просьбу.
Можно, я как раз осваиваю прерывания по таймеру.
Жаль что железа уже у меня нет, могу только код набросать, протестировать тут уж Вы сами.
#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 + парочка резисторов и мосфет, схема будет очень простой.
Спасибо за помощь! Завщтра попробую реализовать ваше решение в железе. О результатах отпишусь. А поповоду применения крен19(TL431) проводил опыты и сталкнулся проблемой переходных процессов в момент порога срабатывания. Полуяается чтото вроде генеразтора, когда снимается энагрузка напряжение на аккумуляторе поднимается и происходит подключение нагрузки и так по кругу вплодь до дребезжания реле. Как раз в таком случае и нужен своеобръазный гистерезис для исключения такого эффекта.
По моему можно и сделать гистерезис для TL431, сам пока не сталкивался ничего подсказать не могу.
Если бы мне приходилось выбирать между аналоговой автоматикой и цифровой то я бы выбрал первую.
Сейчас проверил в железе ваш новый код. При включении никакой диагностики не происходит. Реле РВ4 не включается, а только если напряжение меньше 11.1 вольта то все молчит, если больше- то быстро мигает светодиод РВ2.
Хочу его применить для резервного питания базы домашнего радиотелефона, когда происходят перебои с электроэнергией. Можно вместо функции сна сделать чтобы при возобновлении подачи электроэнергии в сеть, это устройство включало нагрузку но не сразу а когда аккумулятор немного зарядится до определенного напряжения? Ну хотя бы до 12-13 вольт. Тогда бы вышло отличное устройство бесперебойного питания с системой защиты от глубокого разряда.
Вам обязательно задействовать tiny, или сойдет что-то типа DW01, которые стоят в защите батареек сотовых телефонов?
Тк эта микруха для одной банки литиевого аккумулятора.
Тк эта микруха для одной банки литиевого аккумулятора.
TL431, следуя Вашей логике, "только для 2.5 вольт". :)
Обращаюсь к HWman. Несколько раз протестировал вашу прграмму в железе с применением лабораторного блока питания, выяснил что устройство прохлдит цикл разряда аккумулятора со световой индикацией уровней напряжения. Но после ухода во временной спящий режим происходит какое-то зацикливание или неправильный выход из сна, вызывающий частое мигание одним оз светодиодов. Пробовал проверить на другой тини 13 (может чего с контроллелром) симптомы такие же.
С уважеднием dimaris.
Попробуйте этот код:
#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% уже не будет гореть.
Тестируйте, по возможности выкладывайте видео.
Протестировать смогу не раньше понедельника, о результатах отпишусь. Насчет видео, я пока проверяю проект на беспаечной макетной плате. Как начнет работать стабильно то сразу воплащу все это на печатной плате с фотографиями и возможно видео. Постараюсь разместить в этой ветке готовые результаты.
Пробовал несколько раз заливать скетч. Один и тот-же результат. Начинает постоянномигать светодиод на 7-й ноге при напряжении выше 11,7 вольта, больше ничего не происходит. Ниже 11,7 вольт вся схема молчит.
Жаль что вам больше не интересен этот проект..
При программном моделировании вроде как начинает работать но не сразу...
А ядро юзаете отсюда?
Еще раз все проверил, перезакачал ядро, результат тот же. Причем заливаю кос из #66 поста все работает исправно. Значит с ядром все нормально. Еще заметил одну особеннось во времени, ровно в 10 раз медленнее. Тоесть 1000мс это на самом деле 10000мс, проверял в железе через Blink. Может дело в настройках фьюзов в самом ядре чего? Прошиваю пока через ардуино уно (attiny13 9.6 мГц, BOD 2.7 V), но могу и USBAspшкой попробовать хотя разницы быть не должно..
Сейчас пробовал заливать тот же последний код но с настройками платы под 1 Mhz и в результате программа прекрасно отрабатывает индикацию в процессе имитации разрядки аккумулятора. Но после отключения реле я через некоторое время начинаю поднимать напряжение до 11 вольт и выше начинает мигать светодиод 7й ноге и больше ничего на происходит.
Попробуйте этот:
#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;
// ..
}
Программно вроде как работает.
Так вот я тоже любитель проверять для начала в протеусе, но лишь для проверки того что код живой и только после этого смотрю в железе. А тут какой-то подвох, у вас в эмуляторе все работает а у меня не совсем.
И всетаки я больше склоняюсь в сторону фьюзов и не совсем корректного ядра. В электронике я имею больший опыт чем в программировании микроконтроллеров, проверять в железе готов и дальше, может вскроются еще какие нибудь особенности тини13..
Еще один вопрос - Ваш новый код проверять в железе всетаки при 9,6 Мгц или 1Мгц? разница есть а что эмулятор выкинуть может мне известно.
Берите 1 мГц, там фюзы как в тинки с завода.
Может завтра возьму железо и тоже поиграюсь, пока в протеусе толком ничего не понятно.
Эээх жаль не могу протастировать ваш новый код. Все оставил на работе...
Проверил новый скейтч, работа следующая: при напряжении больше 12 вольт- быстро мигает РВ4, ниже 12 но выше 11,5 вообще все мигает, от 11,5 до 10,7 мигают РВ4 РВ2 РВ1, ниже 10,7 все молчит.
Попробуйте вот этот:
#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();
}
}
У меня всё в железе работает, толком потестить не успел, спать охота, но вроде работает.
Кстати, я обновил файлы ядра для тиньки.
Провёл замирения то поку потребления - 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 тогда перезалью.
Буду рад конструктивной критике.
Тест на солнечной панели http://www.youtube.com/watch?v=EPeW1IzQ7jA