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

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

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

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

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

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

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

 
Опции темы

Помогиге с кодом по датчику света - отключение, attiny13

Непрочитано 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.RUN
 
Регистрация: 15.08.2010
Адрес: Днепр
Сообщений: 841
Сказал спасибо: 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.RUN
 
Регистрация: 28.02.2010
Сообщений: 2,294
Сказал спасибо: 52
Сказали Спасибо 460 раз(а) в 391 сообщении(ях)
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, время: 14:32.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.