LED Driver на Attiny13A
- Сообщения: 66
- Зарегистрирован: Вт авг 07, 2018 09:44:46
slav0n, я перепишу его, когда разберусь с проблемой, сейчас мне первостепенно, чтобы заработало, в чем проблема помочь так?
- Реклама
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
О да.Bondosha писал(а):когда разберусь с проблемой
Изучили таймер, прочитали АЦП, а вот доступ к портам I/O по чему-то пропустили.
Может вам, для начала, почитать тут?
А проблемаBondosha писал(а):в чем проблема
Спойлер
Код: Выделить всё
timer1++;
PORTB = 0b00001001;
if(timer1 == 100)
{
PORTB = 0b00001000;
timer1 = 0;
}
РВ1 - экономный режим свечения
РВ2 - красный индикатор
РВ3 - синий индикатор
И так timer1 досчитал до 100, вырубаем РВ0, и через 3 милли секунды врубаем опять РВ0. Процедура повторится через 365мс.
slav0nу работы на 30 минут была бы схема устройства и внятное ТЗ.
а Bondosha думает, что должно быть так:
ohmycode!
primuss3.com
primuss3.com
- Сообщения: 1759
- Зарегистрирован: Пт июн 01, 2018 07:28:45
[uquote="Bondosha",url="/forum/viewtopic.php?p=4090835#p4090835"]slav0n, допустим, но мне бы лучше не по сокращению кода, а именно по проблеме помощь[/uquote]
изучи конечные автоматы.
изучи конечные автоматы.
- Сообщения: 66
- Зарегистрирован: Вт авг 07, 2018 09:44:46
Dimon456, вот схема и тех задание
Алгоритм работы:
1) Нажали кнопку, она замкнулась - 1 на порт PB0 (нога 5)
2) Полунажатие кнопки (кнопка KAN15-A, контакты на долю секунды размыкаются) - 1 на порт PB0 (нога 5) и 1 на порт PB1 (нога 6), повторное полунажатие приводит к пункту 1.
3) Контроль уровня батареи:
а) уровень напряжения 3.1-3.6 В (R5=30 кОм, R6=10 кОм - резистивный делитель) - зажигается синяя лампочка (0 на PB3, нога 2) в дополнение к пунктам 1 и 2
б) уровень напряжения 2.3-3.0 В - зажигается красная лампочка (0 на PB2, нога 7) + PB0(по пункту 1) или PB0 и PB1 (по пункту 2) горит 365 мс, затем кратковременно потухает на 3 мс и зажигается вновь.
в) уровень напряжения 1.8-2.2 В - наступает по уровню напряжения или спустя 30 минут от пункта б), что наступит первым. Красная лампочка не горит (1 на PB2, нога 7) + PB0(по пункту 1) или PB0 и PB1 (по пункту 2) не горит 365 мс, затем горит 15 мс и потухает опять.
Добавлено after 47 seconds:
slav0n, ну и переписала я, как вы хотели и ровно 0 изменений.
Алгоритм работы:
1) Нажали кнопку, она замкнулась - 1 на порт PB0 (нога 5)
2) Полунажатие кнопки (кнопка KAN15-A, контакты на долю секунды размыкаются) - 1 на порт PB0 (нога 5) и 1 на порт PB1 (нога 6), повторное полунажатие приводит к пункту 1.
3) Контроль уровня батареи:
а) уровень напряжения 3.1-3.6 В (R5=30 кОм, R6=10 кОм - резистивный делитель) - зажигается синяя лампочка (0 на PB3, нога 2) в дополнение к пунктам 1 и 2
б) уровень напряжения 2.3-3.0 В - зажигается красная лампочка (0 на PB2, нога 7) + PB0(по пункту 1) или PB0 и PB1 (по пункту 2) горит 365 мс, затем кратковременно потухает на 3 мс и зажигается вновь.
в) уровень напряжения 1.8-2.2 В - наступает по уровню напряжения или спустя 30 минут от пункта б), что наступит первым. Красная лампочка не горит (1 на PB2, нога 7) + PB0(по пункту 1) или PB0 и PB1 (по пункту 2) не горит 365 мс, затем горит 15 мс и потухает опять.
Добавлено after 47 seconds:
slav0n, ну и переписала я, как вы хотели и ровно 0 изменений.
Код: Выделить всё
#ifndef MAIN_H_
#define MAIN_H_
// Определение частоты для компилятора.
#define F_CPU 9600000UL // Attiny13 9.6MHz / PWM 36.8 KHz / CKDIV8 = 1
#include <util/delay.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <stdbool.h> // bool in C99
#define nop __asm__ __volatile__ ("nop");
typedef uint8_t u8;
typedef uint16_t u16;
int main(void);
static void setup(void);
static void wakeup(void);;
static u8 bat_getvoltage(void);
#endif /* MAIN_H_ */
#include <util/delay.h>
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <stdbool.h> // bool in C99
int count = 0;
volatile uint8_t timer1 = 0;
volatile uint8_t timer2 = 0;
volatile uint8_t timerADC = 0;
volatile uint8_t countMode = 0; //????? ?????????? ??????
volatile uint8_t reqChangeMode = 0; //????, ???????????? ????? ????????? ???????? ?????
u8 adc_raw = 0;
u8 adc_raw2 = 0;
volatile uint8_t timerADC2 = 0;
volatile uint16_t voltage_buffer = 0;
volatile uint16_t voltage_counter = 0;
ISR(TIM0_COMPA_vect)
{
knopka_check();
bat_check();
}
void bat_check(void)
{
u8 adc_raw = bat_getvoltage();
if ((adc_raw <= 207)&&(adc_raw > 183))
{
PORTB = (countMode) ? 0b0111 : 0b0101;
} else if ((adc_raw <= 183)&&(adc_raw > 130))
{
if(++timer1 == 100)
{
PORTB = 0b1000;
timer1 = 0;
}
else PORTB = (countMode) ? 0b1011 : 0b1001;
}
else if (adc_raw <= 130)
{
if (++timer2 >= 100)
{
PORTB = (countMode) ? 0b1111 : 0b1101;
timer2 = 0;
}
else PORTB = 0b1100;
}
if (adc_raw > 210)
{
PORTB = (countMode) ? 0b1111 : 0b1101;
}
if (adc_raw < 30)
{
DDRB = 0b00000011;
PORTB = 0b00000000;
}
}
void knopka_check(void) {
u8 adc_knopki = bat_getvoltage();
if (adc_knopki < 90)
{
if (count < 250)
count++;
} else {
if (count > 0)
count--;
if ((count >= 4)&&(count < 50))
{
countMode = (countMode + 1) & 0x1;
reqChangeMode = 1;
count = 0;
}
}
if (reqChangeMode) {
reqChangeMode = 0;
switch (countMode) {
case 0:
{
PORTB = 0b00001101;
}
break;
case 1:
{
PORTB = 0b00001111;
}
break;
}
}
}
int main(void) {
setup();
sei ();
while(1) {
}
}
void setup(void){
ADMUX =
(1 << ADLAR) | (1 << REFS0) | (1 << MUX1) | (0 << MUX0);
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1);
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (1<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
TCCR0B = (0 << CS02) | (1 << CS01) | (1 << CS00 );
TCCR0A = (0 << WGM02) | (1 << WGM01) | (0 << WGM00);
OCR0A = 69;
TCNT0 = 0;
TIMSK0|=(1<<OCIE0A)|(0<<TOIE0);
DDRB = 0b00001111;
PORTB = 0b00001101;
wakeup();
}
void wakeup(void) {
ADCSRA |= (1 << ADSC);
}
u8 bat_getvoltage(void) {
_delay_us(50);
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
return ADCH;
}
- Вложения
-
- схема.jpg
- (106.72 КБ) 812 скачиваний
- Реклама
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Если на долю секунды разомкнуть кнопку, то ...Bondosha писал(а):Полунажатие кнопки (кнопка KAN15-A, контакты на долю секунды размыкаются)
На сколь С4 установлен? Нужно удержать питание МК на эту долю секунды.
- Сообщения: 66
- Зарегистрирован: Вт авг 07, 2018 09:44:46
Dimon456, там ловится этот момент по ацп и вроде как он работает отлично сейчас, а вот с режимами: между б и в ловит помеху какую-то или перепады резкие от акб и получается очень быстрый стробоскоп.
С4 на 100 мкФ
С4 на 100 мкФ
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Держите, пробуйте
Спойлер
Код: Выделить всё
#define ClearBit(reg, bit) reg &= (~(1<<(bit)))
#define SetBit(reg, bit) reg |= (1<<(bit))
#define InvBit(reg, bit) reg ^= (1<<(bit))
#define led_red 2
#define led_blu 3
#define pow_0 0
#define pow_1 1
ISR(TIM0_COMPA_vect)
{
knopka_check();
bat_check();
}
void bat_check(void)
{ static u16 count1=0, count2=0;
static u8 adc_raw =0;
adc_raw= bat_getvoltage();
if ((adc_raw <= 207)&&(adc_raw > 183))
{
//PORTB = (countMode) ? 0b0111 : 0b0101;
if(countMode) SetBit(PORTB,pow_1); else ClearBit(PORTB,pow_1);
SetBit(PORTB,pow_0);
SetBit(PORTB,led_red);
//ClearBit(PORTB,led_blu); // 3000/3.8ms=789
if(++count1 == 789)
{ count1 = 0;
InvBit(PORTB,led_blu);
}
} else if ((adc_raw <= 183)&&(adc_raw > 130))
{
if(++timer1 == 100)
{
//PORTB = 0b1000;
ClearBit(PORTB,pow_1); ClearBit(PORTB,pow_0);
timer1 = 0;
} else /*PORTB = (countMode) ? 0b1011 : 0b1001; */ { SetBit(PORTB,pow_0); if(countMode) SetBit(PORTB,pow_1); else ClearBit(PORTB,pow_1); }
SetBit(PORTB,led_blu);
// 1000/3.8ms=263
if(++count2 == 263)
{ count2 = 0;
InvBit(PORTB,led_red);
}
}
else if (adc_raw <= 130)
{
SetBit(PORTB,pow_0);
SetBit(PORTB,led_red);
SetBit(PORTB,led_blu);
if (++timer2 >= 100)
{
//PORTB = (countMode) ? 0b1111 : 0b1101;
if(countMode) SetBit(PORTB,pow_1); else ClearBit(PORTB,pow_1);
timer2 = 0;
}
else /* PORTB = 0b1100; */ { SetBit(PORTB,led_blu); SetBit(PORTB,led_red); ClearBit(PORTB,pow_1); ClearBit(PORTB,pow_0); }
} else { // если в условие не попали
SetBit(PORTB,led_blu); SetBit(PORTB,led_red);
}
if (adc_raw > 210)
{
//PORTB = (countMode) ? 0b1111 : 0b1101;
if(countMode) SetBit(PORTB,pow_1); else ClearBit(PORTB,pow_1);
SetBit(PORTB,pow_0);
SetBit(PORTB,led_red);
SetBit(PORTB,led_blu);
}
if (adc_raw < 30)
{
//DDRB = 0b00000011; // этой командой отключаете светодиоды, где включаете?
DDRB = 0b00001111;
PORTB = 0b00000000;
}
}
void knopka_check(void) {
u8 adc_knopki = bat_getvoltage();
if (adc_knopki < 90)
{
if (count < 250)
count++;
} else {
if (count > 0)
count--;
if ((count >= 4)&&(count < 50))
{
countMode = (countMode + 1) & 0x1;
reqChangeMode = 1;
count = 0;
}
}
if (reqChangeMode) {
reqChangeMode = 0;
switch (countMode) {
case 0:
{
//PORTB = 0b00001101;
SetBit(PORTB,pow_0);
ClearBit(PORTB,pow_1);
SetBit(PORTB,led_red);
SetBit(PORTB,led_blu);
}
break;
case 1:
{
//PORTB = 0b00001111;
SetBit(PORTB,pow_0);
SetBit(PORTB,pow_1);
SetBit(PORTB,led_red);
SetBit(PORTB,led_blu);
}
break;
}
}
}нет гистерезисаBondosha писал(а): между б и в ловит помеху какую-то или перепады резкие от акб и получается очень быстрый стробоскоп.
и я бы тоже разделил индикацию и управление, чтобы все время не дергать countMode
Код: Выделить всё
#define RedLight_ON() DDRB |= (1<<PB2)
#define RedLight_OFF() DDRB &=~(1<<PB2)
#define BlueLight_ON() DDRB |= (1<<PB3)
#define BlueLight_OFF() DDRB &=~(1<<PB3)
#define out1_set() DDRB |= (1<<PB0)+(1<<PB1); PORTB = (1<<PB0)
#define out1_clr() PORTB &=~(1<<PB0)
#define out2_set() PORTB |= (1<<PB1)
#define out2_clr() PORTB &=~(1<<PB1)ohmycode!
primuss3.com
primuss3.com
- Сообщения: 66
- Зарегистрирован: Вт авг 07, 2018 09:44:46
slav0n, а пример этого гистерезиса можно, пожалуйста?
Dimon456, макет остался на работе, завтра утром ваш вариант проверю
Dimon456, макет остался на работе, завтра утром ваш вариант проверю
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
не в гистерезисе дело.slav0n писал(а):нет гистерезиса
Вот ее стробоскоп
Спойлер
Код: Выделить всё
if(++timer1 == 100)
{
PORTB = 0b1000;
timer1 = 0;
} else PORTB = (countMode) ? 0b1011 : 0b1001;А в зависимости и от режима еще и PB1 подергаем.
Или это лампочками должно управлять?
РВ0 - 5 вывод МК
РВ1 - 6 вывод МК
РВ2 - 7 вывод МК
РВ3 - 2 вывод МК
В чем проблема?
Спойлер
Код: Выделить всё
void bat_check(void)
{ static u8 timer1=0, timer2=0;
static u8 adc_raw =0;
adc_raw= bat_getvoltage();
if ((adc_raw <= 207)&&(adc_raw > 183)) // 3.1-3.6 В
{
SetBit(PORTB,led_red);
ClearBit(PORTB,led_blu);
} else if ((adc_raw <= 183)&&(adc_raw > 130)) // 2.3-3.0 В
{
SetBit(PORTB,led_blu);
timer1++;
if(++timer1 == 100) //
{
SetBit(PORTB,led_red);
timer1 = 0;
} else ClearBit(PORTB,led_red);
}
else if (adc_raw <= 130) // <2.3
{
SetBit(PORTB,led_blu);
timer1++;
if(++timer1 == 100)
{
ClearBit(PORTB,led_red);
timer1 = 0;
} else SetBit(PORTB,led_red);
} else { // если в условие не попали
SetBit(PORTB,led_blu); SetBit(PORTB,led_red);
}
if (adc_raw > 210) // > 3.6
{
SetBit(PORTB,led_red);
SetBit(PORTB,led_blu);
}
if (adc_raw < 30) // <0.5
{
//DDRB = 0b00000011; // этой командой отключаете лампочки, где включаете?
DDRB = 0b00001111;
PORTB = 0b00000000;
}
}
будь ласка:Bondosha писал(а):а пример этого гистерезиса можно, пожалуйста?
Код: Выделить всё
void bat_check(void)
{
u8 adc_raw = bat_getvoltage();
if(adc_raw > 210) {//MAX - 211
...
} else
if(adc_raw > 183) {//210 - 184
...
} else
if(adc_raw < 170) //HYSTERESIS 183 - 170
if(adc_raw > 150) {//169 - 151
...
} else
if(adc_raw > 30) {//150 - 31
...
} else { // adc_raw <= 30
...
}
} ohmycode!
primuss3.com
primuss3.com
- Сообщения: 66
- Зарегистрирован: Вт авг 07, 2018 09:44:46
slav0n, тогда на том участке между 150 и 170 вообще ничего не происходит, а это тоже не подходит под задание
в том и смысл гистерезиса.
на его участке сохраняется предыдущее состояние системы
Добавлено after 31 minute 13 seconds:
Добавлено after 3 hours 4 minutes 5 seconds:
мигание лампочками.
если не нужен гистерезис - просто закоментить его строку
на его участке сохраняется предыдущее состояние системы
Добавлено after 31 minute 13 seconds:
там же написано:Bondosha писал(а):между 150 и 170 вообще ничего не происходит
Код: Выделить всё
//HYSTERESIS 183 - 170мигание лампочками.
если не нужен гистерезис - просто закоментить его строку
Код: Выделить всё
void bat_check(void)
{
static u8 dutycycle;
u8 adc_raw = bat_getvoltage();
if (adc_raw > 210) { //MAX - 211
BlueLight_ON();
dutycycle = 0;
} else
if (adc_raw > 183) { //210 - 184
BlueLight_OFF();
dutycycle = 5;
} else
if (adc_raw < 170) //HYSTERESIS 183 - 170
if (adc_raw > 150) { //169 - 151
BlueLight_OFF();
dutycycle = 95;
} else
if (adc_raw > 30) { //150 - 31
BlueLight_OFF();
dutycycle = 0;
} else { // adc_raw <= 30
BlueLight_OFF();
dutycycle = 0;
}
static u8 timer;
if(++timer >= 100) timer = 0;
if(dutycycle && timer > dutycycle) RedLight_ON();
else RedLight_OFF();
}ohmycode!
primuss3.com
primuss3.com
- Сообщения: 66
- Зарегистрирован: Вт авг 07, 2018 09:44:46
slav0n, видимо, он все же нужен, ибо без него по прежнему мигало, но завтра еще ваш последний вариант посмотрю
гистерезис (зона нечувствительности) нужен обязательно.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
в алгоритм надо еще добавить начальную инициализацию состояния
если при включении напряжение попадет в зоны нечувствительности
если при включении напряжение попадет в зоны нечувствительности
ohmycode!
primuss3.com
primuss3.com
- Сообщения: 1849
- Зарегистрирован: Вс дек 25, 2016 08:34:54
Starichok51 и slav0n, вы что несете оба?
Вы схему смотрели?
Диод VD3 и кондер С4, нагрузка VD1 VD2 и МК.
Время разряда конденсатора С4(100мкФ) до напряжения 1,5В заряженного до 3В током всего 10 миллиА составляет 20 милли секунд.
Там на 1000мкФ надо ставить и то мало будет.
Вы схему смотрели?
Диод VD3 и кондер С4, нагрузка VD1 VD2 и МК.
Время разряда конденсатора С4(100мкФ) до напряжения 1,5В заряженного до 3В током всего 10 миллиА составляет 20 милли секунд.
Там на 1000мкФ надо ставить и то мало будет.
речь пока про лампочки,
до кнопки дело еще не дошло
до кнопки дело еще не дошло
ohmycode!
primuss3.com
primuss3.com
попробовал посмотреть схему. я со своим цветоаномальным зрением ничего в этой цветовой палитре рассмотреть и понять не могу.
Мудрость приходит вместе с импотенцией...
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.


