Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

 
Опции темы
Непрочитано 11.09.2016, 09:45  
neid_nnov
Временная регистрация
 
Регистрация: 05.10.2010
Сообщений: 68
Сказал спасибо: 12
Сказали Спасибо 8 раз(а) в 8 сообщении(ях)
neid_nnov на пути к лучшему
По умолчанию Помогиге с кодом по датчику света - отключение, attiny13

Всем привет! Решил потихоньку освоить таймеры, отсчет времени на attiny13, начал с самого простого проекта датчика света, причем он нужен для видеонаблюдения, вкл/выкл прожектора на ик-светодиодах мощных.

Вроде рассчитал время правильно. Чип от внутреннего генератора 9,6MHz, предделитель 1/1. Настраивал счетчик лопатит на 37,500кГц, указываем значение регистра сравнения равное 0хFA равно 250, 18750/250=150 в секунду. Задаю в коде 30 секунд, потом включение... в протусе насчитает 20 сек с простым кодом для проверки правильности таймера.

Алгоритм следующий, если на улице стемнело, больше указного порога который мы записали в ЕППРОМ, ждем 20 сек, если все так же темно, но включаем прожектор. И наоборот если стало светло, то через 20 сек выключаем свет. Кнопкой на PORTB.0 мы программируем порог включения-отключения света простым нажатием. Светодиод на PORTB2 показывает что якобы записали.
Код:
#include ‹tiny13.h›
#include ‹delay.h›
unsigned int timer; // наша переменна
unsigned int s;     // наша переменна для секунд
int s1=0;  // наша переменная флага
eeprom int adc;     //объявляем численную переменную, хранящийся в ЕППРОМ

// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
timer++;
if(timer==150) {s++;timer=0;} // если равно 150, увеличиваем на секунду и сбрасываем
TCNT0=0x00;
}

#define ADC_VREF_TYPE 0x00

// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

// Declare your global variables here

void main(void)
{
int i;           // переменная хранящаяся в SRAM
int eeprom *adc; // указатель ЕЕПРОМ

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=In 
// State5=T State4=T State3=T State2=0 State1=0 State0=P 
PORTB=0x01;
DDRB=0x06;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 37,500 kHz
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x04; 
TCNT0=0x00;
OCR0A=0xFA; //37500/250=150 за сеукнду
OCR0B=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;

// ADC initialization
// ADC Clock frequency: 150,000 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x86;

// Global enable interrupts
#asm("sei")
s1=0; //флаг сброшен
i=*adc; //считали значения из памяти по указателю

while(1){

//*************БЛОК ВКЛЮЧЕНИЯ ПРОЖЕКТОРА*************    
        if((read_adc(2) ‹ i) && (s1 == 0)){//если света меньше заданного порога и флаг сброшен
            s1 = 1;//включаем флаг
            
            s = 0;//секунды в ноль
        }

        if(s1 == 1){//если по прежнему сохраняется условие
            if(s == 20){//насчитал больше 20 сек
                PORTB.1 = 1;//вкл. прожектор
                s1 = 0;}//сбросил флаг
                }
                
//**************************************************  ***                
                
//************БЛОК ВЫКЛЮЧЕНИЯ ПРОЖЕКТОРА***************
        if((read_adc(2) › i) && (s1 == 0)){//если света больше заданного порога
            s1 = 2;//меняем флаг 
            
            s = 0;//секунды в ноль
        }

        if(s1 == 2){//условие сохраняется
            if(s == 20){//отсчитали 20 сек
                PORTB.1 = 0;//выкл. прожектор
                s1 = 0;}//флаг сбросили
                }
                
//**************************************************  **** 

//***********Запись в ЕЕПРОМ****************************
if (PINB.0==0){//нажали на кнопку
                PORTB.2=1;
                delay_ms(200);//светодиод моргнул
                PORTB.2=0;
                delay_ms(2000);//подождали 2 сек

                i=read_adc(2);*adc=i;//переменная равна значению АЦП, записываем значение АЦП по указателю в ЕППРОМ

                PORTB.2=1;
                delay_ms(200);
                PORTB.2=0;
                delay_ms(500);
                PORTB.2=1;
                delay_ms(200);//три раза моргнули светодиодом, фигня полнейшая
                PORTB.2=0;
                delay_ms(500);
                PORTB.2=1;
                delay_ms(200);
                PORTB.2=0;
                }                       
    }
}
Вопрос стал в следующем, если значение ацп упало ниже порога, и продержалось там более 20 сек, то включаю свет. Но если значение ацп, стало выше порога + 20 сек, то выключить свет не могу. Было несколько вариантов, как это реализовать, но условие включения перекрывало выключение, мешались друг другу... приложил свои ошибки внизу....
Код:
//*************БЛОК ВКЛЮЧЕНИЯ ПРОЖЕКТОРА************* 
if((read_adc(2) ‹ i) && (s1 == 0)){//если света меньше заданного порога и флаг сброшен
s1 = 1;//включаем флаг

s = 0;//секунды в ноль
}

if(s1 == 1){//если по прежнему сохраняется условие
if(s == 20){//насчитал больше 20 сек
PORTB.1 = 1;//вкл. прожектор
s1 = 0;}//сбросил флаг
}

//**************************************************  *** 

//************БЛОК ВЫКЛЮЧЕНИЯ ПРОЖЕКТОРА***************
if((read_adc(2) › i) && (s1 == 0)){//если света больше заданного порога
s1 = 2;//меняем флаг 

s = 0;//секунды в ноль
}

if(s1 == 2){//условие сохраняется
if(s == 20){//отсчитали 20 сек
PORTB.1 = 0;//выкл. прожектор
s1 = 0;}//флаг сбросили
}

//**************************************************  ****
или вот еще идея была:
Код:
// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
timer++;
if(timer==150) {s++;timer=0;}
if(s==5){PORTB.1==1;} else
TCNT0=0x00;
}
.....................
while (1)
{
if ((read_adc(2)‹409)){ // если напряжение на входе меньше порога
TCCR0B=0x04;//вкл.таймер
}
else{ // если напряжение на входе больше порога
TCCR0B = 0x00; // таймер ВЫКЛ.
s=0;}// сбросили секунды

if ((read_adc(2)›409)){ // если напряжение на входе меньше порога
TCCR0B=0x04;//вкл. таймер
}
else{ // если напряжение на входе больше порога
TCCR0B = 0x00; // таймер ВЫКЛ.
s=0;}// сбросили секунды
}
Реклама:

Последний раз редактировалось neid_nnov; 11.09.2016 в 09:48.
neid_nnov вне форума  
Непрочитано 16.09.2016, 19:17  
Insector
Частый гость
 
Регистрация: 24.11.2006
Сообщений: 27
Сказал спасибо: 0
Сказали Спасибо 4 раз(а) в 4 сообщении(ях)
Insector на пути к лучшему
По умолчанию Re: Помогиге с кодом по датчику света - отключение, attiny13

Конечные автоматы. Автоматное программирование. Программные таймеры.
Цикл статей для ознакомления.

Состояния:
0 - Светло. Ждем затемнения. Если светло, выход. Если стемнело, запуск программного таймера на 20 с (но этого мало, вдруг облачко набежало, так что время нужно подбирать). Установка состояния 1.
1 - Ждем пока не выйдет заданное время. Если не вышло, выход. Если вышло, включаем прожектор. Установка состояния 2.
А тут засада. Стало светло, нужно репу чесать, чтобы прожектор не светил на фотодатчик.
2 - Ждем засветки. Если темно, то выход. Если светло, запуск программного таймера на 20 с (время нужно подбирать). Установка состояния 3.
3 - Ждем пока не выйдет заданное время. Если не вышло, выход. Если вышло, выключаем прожектор. Установка состояния 0.
Insector вне форума  
Непрочитано 20.09.2016, 21:36  
МВА
Гражданин KAZUS.RU
 
Регистрация: 15.08.2010
Адрес: Днепр
Сообщений: 842
Сказал спасибо: 74
Сказали Спасибо 199 раз(а) в 174 сообщении(ях)
МВА на пути к лучшему
По умолчанию Re: Помогиге с кодом по датчику света - отключение, attiny13

Сообщение от neid_nnov Посмотреть сообщение
//*************БЛОК ВКЛЮЧЕНИЯ ПРОЖЕКТОРА*************
if((read_adc(2) ‹ i) && (s1 == 0)){//если
света меньше заданного порога и флаг сброшен
s1 = 1;//включаем флаг
s = 0;//секунды в ноль
}
if(s1 == 1){//если по прежнему сохраняется условие
if(s == 20){//насчитал больше 20 сек
PORTB.1 = 1;//вкл. прожектор
s1 = 0;}//сбросил флаг
} //************************************************** ***
Есть вопрос, если при затемнении установился флаг s1 и затемнение прошло до истечения 20 сек. где этот флаг сбросится? В таком случае включение произойдет после выдержки времени в любом случае. так же и с выключением.

PS. И не советую в условие вставлять функцию целиком. Функция read_acd() возвращает значение, ей нужно время на выполнение. Лучше занести результат измерения в какую-нибудь переменную, а потом ее сравнивать в условии.

Последний раз редактировалось МВА; 20.09.2016 в 22:17.
МВА вне форума  
Непрочитано 10.10.2016, 02:11  
OlegNZH
Почётный гражданин KAZUS.RU
 
Регистрация: 28.02.2010
Сообщений: 2,297
Сказал спасибо: 53
Сказали Спасибо 461 раз(а) в 392 сообщении(ях)
OlegNZH на пути к лучшему
По умолчанию Re: Помогиге с кодом по датчику света - отключение, attiny13

Сообщение от МВА Посмотреть сообщение
Есть вопрос, если при затемнении установился флаг s1 и затемнение прошло до истечения 20 сек. где этот флаг сбросится? В таком случае включение произойдет после выдержки времени в любом случае. так же и с выключением.

PS. И не советую в условие вставлять функцию целиком. Функция read_acd() возвращает значение, ей нужно время на выполнение. Лучше занести результат измерения в какую-нибудь переменную, а потом ее сравнивать в условии.

Да там в read_acd()
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);

Пока не родит не выйдет . Частота 150 Кгц Задержка....
Ну 100 микросекунд в АЦП побудет . Причём тут уже время выполнения ? Если речь про секунды идёт .Да и вообще непонятно - зачем куда-то заносить . Функция возвращает Результат .Вызываешь- берёшь- Пользуешься . На Прерываниях что-ли? .Нулевой Таймер - так это вообще без проблем , Ацп и не заметит , как и таймер проскочит ... Ничё не понимаю , в чём проблемы.

Последний раз редактировалось OlegNZH; 10.10.2016 в 02:34.
OlegNZH вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход


Часовой пояс GMT +4, время: 13:37.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot