#define __AVR_ATmega16__ 1#define OSCSPEED 16000000 /* Hz */#include <avr/io.h>#include <avr/interrupt.h>#define sbiBF(port,bit) (port|=(1<<bit)) #define cbiBF(port,bit) (port&=~(1<<bit)) volatile unsigned long int T,L,F=0; unsigned char c,w; int i,v,t,f,se,c1,c2,c3,c4,UU,U,V,M,S,D; int BT[24],BV[24]; int H=9; int HH=9; int MM,SS,DD;int SO=61; int MO=61; int HO=61; int DV=2; int DDV=2; int HV=9;int HHV=9; unsigned long int LV= 291824; //5 min - 299*976unsigned long int LLV= 291824; ISR(TIMER0_OVF_vect){// 604799*976 или 590284800-1?T++; if(T>590283824) T=0; // 1 sec = 976 tick}void settimer() {volatile unsigned long int Q; L=S; Q=M; L+=Q*60; Q=H; L+=Q*3600; Q=D; L+=Q*86400; L=L*976;}void settims() { settimer(); F=L; }void settime() { settimer(); T=L; }void gettime() { L=T/976; D=L/86400; L=L%86400; H=L/3600; L=L%3600; M=L/60; S=L%60; }// RS232 SUPPORTvoid UART_Init(uint32_t Baud){ unsigned int BaudRate = OSCSPEED / (16 * Baud) - 1; UBRRH = (unsigned char) BaudRate>>8; UBRRL = (unsigned char) BaudRate; UCSRB = UCSRB | 0b00011000; // RXEN & TXEN UCSRC = UCSRC | 0b10000110; // 8 bits per frame }unsigned char UART_Receive(){ if (UCSRA & 0b10000000) return UDR; else return 0;}void UART_Transmit(unsigned char Data){ while (!(UCSRA & 0b00100000)); UDR = Data;}void sent2bite() { if (c!=31) { c1=1+U/30; c2=1+U%30; UART_Transmit(c1); }else{ UART_Transmit(c2); } }void receive2bite() { if (c3==0) { c4=c-1; c3=1; }else{ c=30*c4+c-1; w=0; } }// ADC SUPPORTint ADC_read(void) { char i; int ADC_temp; int ADCr = 0; sbiBF(ADCSRA, ADEN); // Enable the ADC //do a dummy readout first ADCSRA |= (1<<ADSC); // do single conversion // wait for conversion done, ADIF flag active while(!(ADCSRA & 0x10)); // do the ADC conversion 8 times for better accuracy for(i=0;i<8;i++) { ADCSRA |= (1<<ADSC); // do single conversion // wait for conversion done, ADIF flag active while(!(ADCSRA & 0x10)); ADC_temp = ADCL; // read out ADCL register ADC_temp += (ADCH << 8); // read out ADCH register ADCr += ADC_temp; // accumulate result } ADCr = ADCr >> 3; //average the 8 samples cbiBF(ADCSRA, ADEN); // disable the ADC return ADCr;}void ADC_init(char input) { int Temp; ADMUX = input; // external AREF and ADCx // set ADC prescaler to 1MHz / 8 = 125kHz ADCSRA = (1<<ADEN)|(1<<ADPS1)|(1<<ADPS0); Temp = ADC_read(); }void getV() { ADC_init(6); U=ADC_read(); }void getT() { ADC_init(7); U=ADC_read(); }int main(void) {settime(); // LIGHTDDRD |= 1<<PD7;PORTD &= ~_BV(PD7);// RELEDDRB |= 1<<PB0; DDRB |= 1<<PB1; // TIMER TCNT0 = 0; TCCR0=(1 << CS01)|(1 << CS00); TIMSK = (1 << TOIE0); sei(); // Baud rate = 115200bps, 1MHZ, u2x=1 UART_Init(115200); // for bluetooth // UART_Init(9600); // for com-port while (1) { // Main loop gettime(); if ((S!=SO)&&(f>0)) { SO=S; if (f<3){ // FILTER getV(); V=(3*V+7*U)/10; BV[H]=U; f++; }else{ f=0; BV[H]=V; PORTB &= ~_BV(PB1);}} if (H!=HO) { HO=H; getT(); BT[H]=U; f=1; V=0; PORTB |= _BV(PB1); if ((H==HV)&&(D%DV==0)) { settims(); PORTB |= _BV(PB0); }else{ PORTB &= ~_BV(PB0);}} if (M!=MO) { MO=M; if (T-F>LV) { PORTD |= _BV(PD7); PORTB &= ~_BV(PB0); }} c=UART_Receive(); if (c==31) { UART_Transmit(c2); }else{ if ((c>0)&&(c<31)) { if (se==0) { if (c==29) se=1; }else{ se=0; switch (w) { case 11 : HH=c-1; UU=HH; w=0; break; case 12 : receive2bite(); if(w==0) { MM=c; UU=MM; } break; case 13 : receive2bite(); if(w==0) { SS=c; UU=SS; } break; case 14 : DD=c-1; UU=DD; w=0; break; case 15 : DDV=c-1; UU=DDV; w=0; break; case 16 : HHV=c-1; UU=HHV; w=0; break; case 17 : LLV=(c*60-61)*976; UU=LLV; w=0; break; case 18 : UU=c-1; if (c==28) for(i=0;i<24;i++) { BV[i]=0; BT[i]=0;} w=0; break; case 20 : UU=c-1; if (c==28) { H=HH; M=MM; S=SS; D=DD; DV=DDV; HV=HHV; LV=LLV; settime(); HO=25; } w=0; break; case 26 : if (c<25) { U=BV[c-1]; } else { if (c>27) w=0; U=w; } U=U+1; sent2bite(); break; case 27 : if (c<25) { U=BT[c-1]; } else { if (c>27) w=0; U=w; } U=U+1; sent2bite(); break; default : switch (c) { case 1 : U=1+H; sent2bite(); break; case 2 : U=1+M; sent2bite(); break; case 3 : U=1+S; sent2bite(); break; case 4 : U=1+D; sent2bite(); break; case 5 : U=1+HO; sent2bite(); break; case 6 : getV(); U=1+U; sent2bite(); break; case 7 : getT(); U=1+U; sent2bite(); break; case 11 : w=c; break; case 12 : c3=0; w=c; break; case 13 : c3=0; w=c; break; case 14 : w=c; break; case 15 : w=c; break; case 16 : w=c; break; case 17 : w=c; break; case 18 : w=c; break; case 19 : U=UU+1; sent2bite(); break; case 20 : w=c; break; case 21 : settims(); PORTB |= _BV(PB0); break; case 22 : PORTB &= ~_BV(PB0); break; case 23 : settims(); PORTB |= _BV(PB1); break;
iriskawowСЕНСОРЫ ТЕМПЕРАТУРЫ И ВЛАЖНОСТИ НА ОСНОВЕ МИКРОКОНТРОЛЛЕРА AVR ATmega-IO-M16ВВЕДЕНИЕ На сегодняшний день разработаны и выпускаются готовые малые аэропонные установки для дома с эргономичным дизайном, так называемые комнатные аэропонные фермы. AeroGrow - первая компания, которая предложила на рынок эту технологию, работала больше трех лет, чтобы создать достаточно простой для использования потребителей "домашний сад", см. рис. 1. Рис. 1. Аэропонная установка с микропроцессорным поливом и растение-космонавт Подобные установки можно считать контейнерами будущего для выращивания растений, см. тематические сайты и . Еще их называют "умные фермы", так как автоматика контролирует параметры микроклимата в полости для корней, снабжая их необходимыми минералами и микроэлементами. Существуют эффектные проекты бегающих за солнцем растений и растения-комонавты. Но это уж слишком. Их мы обсуждать пока не будем. До того, как эти устройства станут столь же утилитарными, как мобильный телефон, осталось немного времени, но этот момент еще не наступил. Поэтому резонно расмотреть вопрос о построении их на базе распространенных в продаже составных частей, см. сайт магазина Мега-электроника . КОНЦЕПЦИЯ МИКРОПРОЦЕССОРНОЙ СИСТЕМЫ Рис. 2. Уменьшение размеров аппаратуры применением микроконтроллеровАппаратная часть строится на основе AVR-IO-M16, что позволяет минимизировать размеры, см. рис. 2. Обсудим концепцию построения программного обеспечения. Какие части оно должно содержать. Часы Для ориентации во времени нужны часы: подпрограмма, переводящая абстрактное время таймера T в секунды, минуты, часы и день недели. Так как кнопок настройки часов нет, нужна и инверсная функция, которая по заданному времени настроит таймер T. Кольцевой почасовой буфер на 24-ре часа складывания данных о текущих температуре и влажности. Время измерения: запоминать текущий час. Опорные точки полива. Реле помпы полива должно включаться по часам, опираясь на точки полива. По умолчанию - полив через день, в 9 утра. Прямое управление с компьютера. Команды управления должны включать в себя: запрос текущего времени и установку часов, установку параметров полива, чтение кольцевого буфера данных, особо: опрос любого датчика, включение-выключение реле. Безопасность. Программа для микроконтроллера учитывает помехи в цепи радиоканала, поэтому все команды предваряются посылкой кода 29 (внимание). Для дистанцирования от нуля, к данным прибавляется единица: простейшее помехозащитное кодирование. Параметры настроек системы передаются в буфер UU, и только после перекрестной его проверки обратным считыванием, устанавливаются часы. Переход в режим считывания накопленного буфера данных о влажности или тепературы проверяется подачей кодов 26, 27 возвращаемых эхосигналом. Код 28 выводит из режима считывания. Отключение связи фиксируется и сопровождается командой отключения реле (по времени не более 5 минут). Особенности . Длина слова в рабочем диапазоне UART колеблется от 5-ти до 9-ти бит. На частоте 115200 стенд с ATmega16 независимо от того, проводное это соединение или беспроводное (с bluetooth-WT12-A-AI3), диапазон сужен до минимальных 5-ти (0-31), из принимаемых значений нужно вычитать 128 (на 9600 этого делать не нужно). WT12-A-AI3 нешибко, но засоряет канал обмена информационными сообщениями, на которые следует поставить подмотку. И без того малая длина слова сужается довольно частым проскакиванием в канале 10-ки (нежелательный код в роли управляющей команды).В проекте ниже сбойность и узость канала используется для тренировки передачи сообщений в неблагоприятных условиях (как модельная задача). Написаны функции разделения данного на два байта с передачей старшего и младшего байтов по запросам (предваряющим командам) 29 и 31. Введен буфер переданного параметра UU с его поверочным чтением, перед использованием. Для упрощения программы рекомендуется разобраться в настройках расширения длины слова, хотя проработка мер повышения надежности в любом случае сохранит свое значение. Рекомендуется расширить длину предваряющих команд, так как опыт показал, что вероятность проскакивания случайного кода 29 от помех (при включении сторонней сенсорной радиосети, например) велика.
Комментариев нет:
Отправить комментарий