iriskawow

СЕНСОРЫ ТЕМПЕРАТУРЫ И ВЛАЖНОСТИ НА ОСНОВЕ МИКРОКОНТРОЛЛЕРА AVR ATmega-IO-M16

ВВЕДЕНИЕ

На сегодняшний день разработаны и выпускаются готовые малые аэропонные установки для дома с эргономичным дизайном, так называемые комнатные аэропонные фермы. AeroGrow - первая компания, которая предложила на рынок эту технологию, работала больше трех лет, чтобы создать достаточно простой для использования потребителей "домашний сад", см. рис. 1.

Рис. 1. Аэропонная установка с микропроцессорным поливом и растение-космонавт

Подобные установки можно считать контейнерами будущего для выращивания растений, см. тематические сайты artspb.com и mathscinet.ru. Еще их называют "умные фермы", так как автоматика контролирует параметры микроклимата в полости для корней, снабжая их необходимыми минералами и микроэлементами. Существуют эффектные проекты бегающих за солнцем растений и растения-комонавты. Но это уж слишком. Их мы обсуждать пока не будем. До того, как эти устройства станут столь же утилитарными, как мобильный телефон, осталось немного времени, но этот момент еще не наступил. Поэтому резонно расмотреть вопрос о построении их на базе распространенных в продаже составных частей, см. сайт магазина Мега-электроника http://www.megachip.ru.

КОНЦЕПЦИЯ МИКРОПРОЦЕССОРНОЙ СИСТЕМЫ

Рис. 2. Уменьшение размеров аппаратуры применением микроконтроллеров

Аппаратная часть строится на основе AVR-IO-M16, что позволяет минимизировать размеры, см. рис. 2. Обсудим концепцию построения программного обеспечения. Какие части оно должно содержать.

Часы Для ориентации во времени нужны часы: подпрограмма, переводящая абстрактное время таймера T в секунды, минуты, часы и день недели. Так как кнопок настройки часов нет, нужна и инверсная функция, которая по заданному времени настроит таймер T.

Кольцевой почасовой буфер на 24-ре часа складывания данных о текущих температуре и влажности. Время измерения: запоминать текущий час.

Опорные точки полива. Реле помпы полива должно включаться по часам, опираясь на точки полива. По умолчанию - полив через день, в 9 утра.

Прямое управление с компьютера. Команды управления должны включать в себя: запрос текущего времени и установку часов, установку параметров полива, чтение кольцевого буфера данных, особо: опрос любого датчика, включение-выключение реле.

Безопасность. Программа для микроконтроллера учитывает помехи в цепи радиоканала, поэтому все команды предваряются посылкой кода 29 (внимание). Для дистанцирования от нуля, к данным прибавляется единица: простейшее помехозащитное кодирование. Параметры настроек системы передаются в буфер UU, и только после перекрестной его проверки обратным считыванием, устанавливаются часы. Переход в режим считывания накопленного буфера данных о влажности или тепературы проверяется подачей кодов 26, 27 возвращаемых эхосигналом. Код 28 выводит из режима считывания. Отключение связи фиксируется и сопровождается командой отключения реле (по времени не более 5 минут).

Особенности UART. Длина слова в рабочем диапазоне UART колеблется от 5-ти до 9-ти бит. На частоте 115200 стенд с ATmega16 независимо от того, проводное это соединение или беспроводное (с bluetooth-WT12-A-AI3), диапазон сужен до минимальных 5-ти (0-31), из принимаемых значений нужно вычитать 128 (на 9600 этого делать не нужно). WT12-A-AI3 нешибко, но засоряет канал обмена информационными сообщениями, на которые следует поставить подмотку. И без того малая длина слова сужается довольно частым проскакиванием в канале 10-ки (нежелательный код в роли управляющей команды).

В проекте ниже сбойность и узость канала используется для тренировки передачи сообщений в неблагоприятных условиях (как модельная задача).

Написаны функции разделения данного на два байта с передачей старшего и младшего байтов по запросам (предваряющим командам) 29 и 31. Введен буфер переданного параметра UU с его поверочным чтением, перед использованием. Для упрощения программы рекомендуется разобраться в настройках расширения длины слова, хотя проработка мер повышения надежности в любом случае сохранит свое значение. Рекомендуется расширить длину предваряющих команд, так как опыт показал, что вероятность проскакивания случайного кода 29 от помех (при включении сторонней сенсорной радиосети, например) велика.


#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*976
unsigned 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 SUPPORT

void 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 SUPPORT

int 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(); 
// LIGHT
DDRD |= 1<<PD7;
PORTD &= ~_BV(PD7);
// RELE
DDRB |= 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;
       case 24 : PORTB &= ~_BV(PB1); break;
       case 26 : w=c; U=c+1; sent2bite(); break;
       case 27 : w=c; U=c+1; sent2bite(); break;
       default : w=0; U=c+1; sent2bite(); break;  
       }}}}}//ifswitch
    }//while
    return 0; 
}

ПАЙКА и ГРАДУИРОВКА ДАТЧИКОВ

Крепеж (как паять лучше) Под колодкой ICSP есть две проволочные перемычки. ЗЕМЛЯ 0V и +5Вольт !!!

Паять сверху лучше.

Датчик AD22100KT

Распиновка следующая, если повернуть элемент плоской стороной к себе, ножками книзу, то справа будет земля, слева питание +5В. Т.е. питается тем же, что и щуп влажности. Паяется ПИТАНИЕМ прямо к контактам конденсатора C3 (а сверху - к жестяным перемычкам), средняя ножка (СИГНАЛ) изолируется кембриком и идет изолированным проводком на PA7 (паять тоже аккуратно если снизу - чтобы транзистор не замыкал и не ломал контакты), см. след. стр.

Формула для подсчета температуры по уровню напряжения датчика u (вольт) при 5 вольтовом питании

T=(u-1.375)/0.0225 (градусов)

неотградуированное АЦП снимает, естественно, свое (некое) значение U, такое, что u=kU (вольт), k - масштабный коэффициент. Подставим u=kU в формулу выше и перепишем ее относительно неизвестного

k = (1.375+0.0225*T)/U,

по которому находим k при тестовых значениях T, U. В дальнейшем k не меняется и присуще этому типу датчика и этой схеме. Пусть микроконтроллер передает нам U (подправил), а расчет температуры идет на стороне компьютера в measure (подправил, см. ниже).

По датчику влажности нужно снять U при зацеплении контактов, это будет отвечать u=mU=5 (вольт)

V=100*u/5 (процентов),

аналогично m=5/U, U - тестовое значение выхода при зацеплении.

Примечание: unsigned char U - не может принимать численное значение, которое превышает передаваемые по каналу значения 0-255. Будем надеяться, что при +5 вольт на входе при присвоении (косвенном, через подпрограмму) U=ADCr (int -32768 ... 32767) не произойдет среза. Надо настороженно воспринимать U близкое к 255 (особенно, при измерении температуры).

Предположим "плохое", что 5 вольт датчика влажности дает 1024, ясно, что надо экспериментнуть (поработать) с понижением типа U=ADC_read()/10 !!! Если понижение дает слепые результаты - на стороне компьютера сигнал слаб, то эта проблема снимается. Никто канал ATmega16 пока не прокачивал при работе с датчиками.

СТОРОНА КОМПЬЮТЕРА

Зип интерфейса экрана, скачать: orangery.box.

Картинка интерфейса двойная, стартует с термометра, но если кликнуть по экрану, переходит на часы, у птички - установка часов (заблокировано логикой), у Valmar - вывод буфера (заблокировано логикой), под стрелками - переходит обратно к термометру и режиму работы с интернет.


% BACKGROUND IMAGE
open orangery, open scene fito
open background image.jpg [:].
% SET COM-PORT COMMUNICATION
% BY Default is 9600  
% e=write(0,'com152000') 
do 12, x=read('com13'), end, inicomm()  
% BEGINNING PARAMETERS
matrices: Hc,Mc,Sc,Dc
% g=[1 25 50],  save matrix g, pause
F=1, S=0, M=1, c=123, R=0, % e=readig(R)
open matrix g, w=g(1)', K=0, m=61, H=w(1), % ?AN  
% INITIALIZATION
measure, capture 
e=write(0,'folder=marley_file=image.jpg'), pause 2
e=write(0,'folder=marley_file=command.xml'), pause 2

% MAIN CYCLE
Open System Mouse Support
Do, command, 
      RealTimeControl
end

% LIBRARY

function: command
if S=1,
  Hc=clock(1), Mc=clock(2), Sc=clock(3), Dc=clock(8)
  % m=[H M S D],  putm(m)
  Clock Hour turns at 360*Hc/12
  its Min turns at 360*Mc/60
  its Sec turns at 360*Sc/60.
  pause 0.2
else,
% GET MINUTES
e=clock(2),  if F=1, m=61, end,
if m<>e, 
% PROVE INTERVAL,
if F=1, e=M, end,
if M*floor(e/M)=e, e=clock(2),  m=e, play pock.wav
% GET SERVER
c=123,  c=read('folder=marley_file=command.xml'), pause 2,  c=? 
if c=123, % SERVER'S ABSENT 
else,      
% PROVE SERVER  COMMAND   
 if c>0, 
 % SEND IMAGE AND DATA TABLE
 e=write(0,'folder=marley_file=image.jpg'), pause 2,
 e=write(round(g),'folder=marley_file=plant.xml'), pause 2,  
 c=-1, e=write(c,'folder=marley_file=command.xml'), pause 2, c=?
 F=1 
 else, if c<0,  
 F=1, % FINISH
 e=write(0,'folder=marley_file=command.xml'), pause 5, 
 end end
end 
%
end end 
pause 2 
end

function: RealTimeControl  
h=clock(1), % HOUR
if h<>H, H=h, K=K+1, 
 measure,  capture
%% MAKE DATA TABLE
  if cols(g)<2, g=w', else, 
  if rows(g)>24, g=g(1:24,:), end,  g=[w'; g], end
  save matrix g, % TO HARD DISK
%% SOME ELSE
  % if h=12, R=0, d=clock(7), 
     % if 3*round(d/3)=d,  e=readig(4),  pause 5,  e=readig(0), end
     % e=readig(R),
  % end
  % if h=23, R=0, e=readig(R),  end 
%% SEND IMAGE AND DATA TABLE TO SERVER 
  if c<>123,  
  e=write(round(g),'folder=marley_file=plant.xml'), pause 2,  
  e=write(0,'folder=marley_file=image.jpg'), pause 2, 
  end 
end

function: measure
T=25, V=50
% MAKE DATA STRING
w(1)=clock(1) 
% READ TEMPERATURE 
c=7, x=readc(c), x=?, 
k=... (опытным путем), T=(k*x-1.375)/0.0225, 
w(2)=T 
% READ WATER DATA
% need to switch on voltage
e=write(29,'com'), e=write(23,'com'), pause 2
c=6, x=readc(c), x=?, m=... (опытным путем), V=100*m*x/5, 
% switch off voltage
e=write(29,'com'), e=write(24,'com'), 
w(3)=V, [T V]=?
% LCARD ADC-DAC  
% e=0, y=[0 0 0 0]', u=[5 5]',  z=[0 0]', 
% Do 2, y=read(u), pause 0.5, end, e=read(z), 
% w(2)=(y(1)-1.375)/0.0225  
% w(3)=100*diode(1-exp(-y(4)))
% w(4)=12.75*y(2),  if w(4)=0, w(4)=0.01, end
% w(5)=(y(3)-0.8)/0.0307      
showscreen  

function: showscreen
% REFLECT DATA ON THE SCREEN
if w(3)>5, L=w(3), else, L=5, end, L=L/67
Table Temperature  expands 0.01+w(2)/20 vertically 
Table Water expands 0.01+w(3)/50 vertically 
% Table Water2 expands w(5)/50 vertically
% Table Light  expands L vertically
Show 
Table Temperature  diminishes 0.01+w(2)/20 vertically 
Table Water  diminishes 0.01+w(3)/50 vertically
% Table Water2 diminishes  w(5)/50 vertically
% Table Light  diminishes L vertically

function: capture
% WEBCAMERA
x=0, y=0, do while x=y, 
X=read('camera.bmp:2'), x=norm(X),
Y=read('camera.bmp:2'), y=norm(Y),  end
e=write(0,'camera:file=image.jpg')
open background image.jpg [:], showscreen

% MICROCONTROLLER 

word: click
if S=0, S=1, open scene data, else, 
% SET DATA of MICROCONTROLLER
if near Clock Body,
S=0, open scene fito, show, end
if near Clock Button,
if 0=1, % SET CLOCK
Close System Mouse Support
x=61, Dc=clock(8), do while x<>Dc, x=Dc, 
 c=14, writeone(x), c=19, x=readc(c),  m=x, putm(m), end
x=61, Hc=clock(1), do while x<>Hc, x=Hc, 
 c=11, writeone(x), c=19, x=readc(c), m=x, putm(m), end
x=61, Mc=clock(2), do while x<>Mc, x=Mc, 
 c=12, writec(x),  c=19, x=readc(c),  m=x, putm(m), end
x=61, Sc=clock(3), do while x<>Sc, x=Sc,  
 c=13, writec(x),  c=19, x=readc(c),  m=x, putm(m), end
 % SET CLOCK
x=27, c=20, writeone(x), c=19, x=readc(c),  m=x, putm(m)   
end
if 1=1, % GET CLOCK
Close System Mouse Support
% READ CLOCK
c=1, x=readc(c), H=x,  c=2, x=readc(c), M=x, 
c=3, x=readc(c), S=x,  c=4, x=readc(c), D=x, 
m=[H M S D], m=? % putm(m) 
end 
end
if near Clock Buffer,
if 0=1, % GET BUFFER
Close System Mouse Support
% READ BUFFER B=one(B)-exp(-0.1*B),
 s=timebuff(), s=?
 N=26, B=readbuff(N), inicomm(), V=B    
 N=27, B=readbuff(N), inicomm(), B=[V B], B=?, B=??    
end end
Open System Mouse Support
end

function: inicomm()
x=0, do while x<>28, c=28,  x=readc(c), end

function: s=timebuff()
x=24, do while x>23, c=5,  x=readc(c), s=x, end

function: B=readbuff(N)
for b=0:s,  
x=-1, do while x<0,
do while x<>N, c=N, x=readc(c), end 
c=b+1, x=readc(c), end
if b=0, B=x, else, B=[B;x], end, B=?? 
end 

function: x=comm(c)
if c<>31, e=write(29,'com'), end, e=write(c,'com')
x=0, do 2, if x=0, x=read('com'),  end end,  
x=x-1  % for 115200 x=x-129

function: x=readc(c)
y=-1, C=c,  
do while y<=0, 
c=C,  x=comm(c), y=x, 
c=31, x=comm(c), y=30*y+x 
if y>110, y=-1, end, end, x=y-1

function: writeone(x)
e=write(29,'com'), e=write(c,'com'), 
e=write(29,'com'), e=write(1+x,'com')

function: writec(x)
y=floor(x/30), x=x-30*y,  
e=write(29,'com'), e=write(c,'com'),  
e=write(29,'com'), e=write(y+1,'com'), 
e=write(29,'com'), e=write(x+1,'com')

function: putm(m)
e=PutLine(1,'window'), e=GetMatrix(m), 
e=PutLine(1,'window') 

Головная программа перед чтением данных с датчика влажности почвы обязана предварительно включить то реле, через которое на нее через щуп подается 5 вольт. С реле связаны команды 21,22 (первое реле, включает моторчик) и 23,24 (включить, выключить напряжение на почве).

ОТЛАДОЧНАЯ ПРОГРАММА С ЧАСАМИ

Программа мониторинга на стороне компьютера отображает ЧАСЫ и организует обмен данными с микроконтроллером при кликаньи на именованные элементы декора: птичка (установить часы), Valmar (считать буфер). Флаг F определяет, будут ли переустанавливаться часы.


F=0, inicomm(), iniclock() % 20 58 48 5

for i do
   H=clock(1), M=clock(2), S=clock(3), D=clock(8)
   % m=[H M S D],  putm(m)
   Clock Hour turns at 360*H/12
   its Min turns at 360*M/60
   its Sec turns at 360*S/60.
% READ WATER+TEMPERATURE DATA,
if i=0, % if i=1, e=write(23,'com'), end
c=6, x=readc(c), V=x, 
c=7, x=readc(c), T=x, m=[V T], e=PutLine(1,'window'), putm(m)
if i=1, g=[T V], else, g=[T V; g], end, g=?? 
end 
end

word: click
if near Button, Close System Mouse Support
if F=1, 
% SET CLOCK
x=61, D=clock(8), do while x<>D, x=D, 
c=14, writeone(x), c=19, x=readc(c),  m=x, putm(m), end
x=61, H=clock(1), do while x<>H, x=H, 
c=11, writeone(x), c=19, x=readc(c), m=x, putm(m), end
x=61, M=clock(2), do while x<>M, x=M, 
c=12, writec(x),  c=19, x=readc(c),  m=x, putm(m), end
x=61, S=clock(3), do while x<>S, x=S,  
c=13, writec(x),  c=19, x=readc(c),  m=x, putm(m), end
x=27, c=20, writeone(x), c=19, x=readc(c),  m=x, putm(m)   
F=0
end
% READ CLOCK
c=1, x=readc(c), H=x,  c=2, x=readc(c), M=x, 
c=3, x=readc(c), S=x,  c=4, x=readc(c), D=x, 
m=[H M S D],  putm(m) 
Open System Mouse Support
end
if near Buffer, Close System Mouse Support
% READ BUFFER B=one(B)-exp(-0.1*B),
s=timebuff(), s=?
N=26, B=readbuff(N), inicomm(), V=B    
N=27, B=readbuff(N), inicomm(), [V B]=??    
Open System Mouse Support
end

function: inicomm()
do 12, x=read('com4'), x=?, end, x=26 
x=0, do while x<>28, c=28, x=readc(c), x=?, end

function: iniclock()
H=clock(1), M=clock(2), S=clock(3), D=clock(8)
Open System Mouse Support, Open clock image. 

function: s=timebuff()
x=24, do while x>23, c=5,  x=readc(c), s=x, end

function: B=readbuff(N)
for b=0:s,  
x=0, do while x=0,
do while x<>N, c=N, x=readc(c), end 
c=b+1, x=readc(c), end
if b=0, B=x, else, B=[B;x], end, B=?? 
end 

function: x=comm(c)
if c<>31, e=write(29,'com'), end, e=write(c,'com')
x=0, do 2, if x=0, x=read('com'),  end end,  x=x-129 

function: x=readc(c)
y=-1, C=c,  
do while y<=0, 
c=C,  x=comm(c), y=x, 
c=31, x=comm(c), y=30*y+x 
if y>110, y=-1, end, end, x=y-1

function: writeone(x)
e=write(29,'com'), e=write(c,'com'), 
e=write(29,'com'), e=write(1+x,'com')

function: writec(x)
y=floor(x/30), x=x-30*y,  
e=write(29,'com'), e=write(c,'com'),  
e=write(29,'com'), e=write(y+1,'com'), 
e=write(29,'com'), e=write(1+x,'com')

function: putm(m)
e=PutLine(1,'window'), e=GetMatrix(m), e=PutLine(1,'window') 

ГИДРАВЛИЧЕСКАЯ СХЕМА.

Рис. 3. Схема полива по принципу сифона Герона

На рис. 3 изображена система полива на основе сифона Герона. Нагнетаемая со дна помпой вода поступает по трубке наверх в поддон-непроливашку с дырочками по бордюру для слива излишка воды в контейнер. При отключении помпы атмосферное давление загоняет воду по той же трубочке в основную емкость, обеспечивая корням выставленных на поддон растений аэрацию. Эта схема полива привлекает простотой реализации из подручных элементов. Необходимые для питания растений вещества находятся в самом горшке, фактически, система позволяет перевести типичное домашнее хозяйство на автоматику без больших вложений.

Рис. 4. Автоматические контейнеры с рассадой на балконе

МИКРОКОНТРОЛЛЕР.

Плата AVR ATmega-IO-M16 (см. характеристики на olimex.com) привлекает готовым набором из четырех силовых реле, удобных для включения помпы, света, питания датчиков влажности и bluetooth связи с центральным компьютером, см. рис. 5.

Рис. 5. Микроконтроллер AVR ATmega-IO-M16

На фотографии платы хорошо видны контакты АЦП PA7-PA4 для подпайки датчиков (температурный паяется снизу к плате), напряжение 5 вольт берется с выхода расположенного на ней стабилизатора, входные 12 вольт идут только на реле. На плате имеется готовый com-порт. Он связан с линиями UART PD0, PD1 микропроцессора ATmega16, легко доступными на монтаже оборотной стороны платы, что позволяет организовать еще и беспроводную связь с компьютером.

Для изоляции контактов годится пластиковый корпус G738 для радио-электронной аппаратуры (РЭА) 140х110х35 мм. В нее с трудом, но влезает блок питания KIT PW12045PS размером 75x40x20 мм, возможен выпил небольшого куска текстолита у стойки. Cтабилизатор питания на 3.3 вольта LP2950ACZ-3.3G и bluetooth микросхема WT12-A-AI вмещаются без проблем. На передней панели удобно размещать парные клеммы для подключения помпы, см. рис. 6.

Рис. 6. Пластиковый корпус G738, блок питания и клемма

Добавим еще разъем щупа влажности и выключатель беспроводной связи с центральным компьютером. Коробка крепится винтами на бок пластиковой "умной фермы".

Рис. 7. Два поколения блоков, большой (старый) и маленький (новый)

СЕНСОРНАЯ СИСТЕМА

Сенсорная система. Далее обсудим легко доставаемые датчики с напряжением питания 5 вольт, распространенные в продаже.

Рис. 4. Датчики температуры AD22100KT,
влажности HIH-4000-002, освещенности BPW20RF

Линейными характеристиками обладает датчик температуры AD22100KT, см. рис. 3, слева. Распиновка следующая, если повернуть элемент плоской стороной к себе, ножками книзу, то справа будет земля, слева питание. Ноль градусов отвечает напряжению 1.375 вольт. На каждый градус температуры приходится 0.0225 вольта. Рабочий ток небольшой, около 0.5 ма. Универсальное применение находят датчики освещенности, например, фотодиод BPW20RF, см. рис. 3, справа. Ножка плюса фотодиода заметно изолирована от корпуса. Включается в инверсном направлении: на корпус подается 5 вольт, изолированная ножка идет к контакту АЦП, заземленному через сопротивление около 100 кОм. При попадании даже рассеянного света на фотодиод наводится сигнал порядка половины вольта.

Для измерения влажности воздуха есть дорогие и не очень датчики. Можно воспользоваться относительно дешевым, например, HIH-4000-002, см. рис. 3, середина. Поворачиваем лицом к себе, ножки вниз. Слева минус, справа плюс питания. Выход посередине. Отдельной проблемой при поливе растений стоит датчик влажности почвы. Одно из простых решений для домашней "лаборатории" состоит в подаче напряжения 5 вольт через реле на один из штырей щупа, погруженного в землю. Другой штырь щупа соединяется с заземленным через резистор около 3 кОм входом АЦП микроконтроллера, для измерения наводимого потенциала.

Фрагмент кодов на языке AVR GCC, описывающих подпрограммы опроса сенсоров, приведен ниже. Подпрограмма ADC_init(X) настраивает параметры для подпрограммы чтения напряжения U=ADC_read(), где значение X - номер (4-7) входа АЦП PAX. Для отстраивания от помех чтение производится 8 раз с соответствующим накоплением суммы и осреднением.



#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)) 

// СУППОРТ АЦП

int ADC_read(void) {
    char i; int ADC_temp; int ADCr = 0;    
    sbiBF(ADCSRA, ADEN); // Включить АЦП
    // сделать сначала фиктивное чтение
    ADCSRA |= (1<<ADSC); // начать преобразование
    // ждать завершения преобразования и установки флага ADIF
    while(!(ADCSRA & 0x10));
    // сделать АЦП преобразование 8 раз для большей точности 
    for(i=0;i<8;i++) {
        ADCSRA |= (1<<ADSC); // начать преобразование
        // ждать завершения преобразования и установки флага ADIF
        while(!(ADCSRA & 0x10));       
        ADC_temp = ADCL; // читать регистр ADCL
        ADC_temp += (ADCH << 8); // читать регистр ADCH
        ADCr += ADC_temp; // накопить результат
    }
    ADCr = ADCr >> 3; // усреднить 8 измерений
    cbiBF(ADCSRA, ADEN); // выключить АЦП
    return ADCr;
}

void ADC_init(char input) {
   int Temp; ADMUX = input; // номер пина
   // установить шкалу АЦП 1MHz / 8 = 125kHz
   ADCSRA = (1<<ADEN)|(1<<ADPS1)|(1<<ADPS0); 
   Temp = ADC_read(); 
}

Головная программа перед чтением данных с датчика влажности почвы обязана предварительно включить то реле, через которое на нее через щуп подается 5 вольт.

Заключение. В этой небольшой по размерам статье освещено построение системы полива на базе распространенных в продаже микроконтроллеров, исполнительных устройств (помп, осветителей) и датчиков. Повышенное внимание уделяется программному обеспечению сенсоров. В перспективе эта система может быть значительно минимизирована привлечением таких компонентов сенсорных сетей, как ETRX357, интегрирующих в себя микроконтроллер и радиосвязь и питаемых от небольшой батарейки.

Литература.

1. Горчаков Л.В., Королев Б.В. Терморегулятор на основе платы AVR-IO-M16. //Седьмая международная научно-методическая конференция Новые образовательные технологии в вузе (НОТВ – 2010), Томск: 2010. – С. 216-219.

2. Горчаков Л.В., Королев Б.В. Использование микроконтроллеров для управоения физическим экспериментом. //Седьмая международная научно-методическая конференция Новые образовательные технологии в вузе (НОТВ – 2010), Томск: 2010. – С. 216-219.

3. Татьяна Кривченко. Zigbee-модемы ETRX компании Telegenesis. //Беспроводные технологии. 2006. N2. - C. 28-30.

4. Татьяна Кривченко. Zigbee-модемы ETRX2 компании Telegenesis: что нового? //Беспроводные технологии. 2007. N2. - C. 28-30.

 admin

 admin

УЧЕБНЫЕ ДЕЛА

Информация о специальности в блоге Ирины: на mathscinet.ru.

Расписание Юры: занятия по философии и по английскому для аспирантов и соискателей будут проходить: английский: с 6 октября вторник 16:00-17:20 на кафедре ИнЯз (Гастелло) среда 14:00-17:00 там же преподаватель - Громова Ирина Ивановна

6 октября в 14:00 в а. 34-16 (Гастелло) пройдет организационное собрание по ИнЯз, философия: с 26 октября вторник 17:20-20:00 а. 12-02 (Гастелло) преподаватель - Михайловский Валерий Николаевич.

Математеская подготовка: Тиртишников Е.Е. просто о матрицах | Исследование адамаровых матриц, на этом ресурсе.

Научные социальные сети, сама matscinet.ru и иной пример: Scipeople.ru | Дела практические: дооборудовать цветочное направление - серверный компьютер, водяная помпа 220 в. (возможно, добавить температурный датчик, датчик влажности (щуп)) дадут стационарный стенд с вебкамерой. Тележка с гусеницами и блу-тутс управлением в заделе.

 admin

НАУКА И ЖИЗНЬ 1890 ГОДА

ОГУРЦЫ В ТЕПЛИЦАХ ЛОНДОНА, 1890 г.

См. http://publ.lib.ru/ARCHIVES/N/''Nauka_i_jizn'''/_''Nauka_i_jizn'''_1890_.html

 admin

ПРОГРАММА ФИТО-СВЯЗИ С ИНТЕРНЕТОМ

Обслуживание вебкамеры

Компактная система Visual Matlab имеет несколько конфигураций, ориентированных на разные классы задач, в частности, вебкамеру обслуживает pcMatLab.exe. Сбор информации идет в цикле с паузой (в секундах):


do
X=read('camera.bmp')
e=write(0,'camera:file=image.jpg')
open background image.jpg [:], show
pause 1
end

Команда X=read('camera.bmp') чтения изображения в память X. Некоторые драйверы вебкамер требуют контроля считываемости.

Команда e=write(0,'camera:file=image.jpg:2') записи изображения на диск с масштабным делителем (может отсутствовать). Есть дополнительная пара команд визуализации open background image.jpg [:], show. Усечение e=write(0,'camera:') передает информацию на экран и есть опции коррекции.

Цикл с паузой в одну секунду - это слишком часто. Команда ниже используется не в цикле, а отвечает на запрос фото, поступающий с сервера (асинхронный режим связи с сервером см. ниже).

e=write(0,'folder=name_file=image.jpg'), pause 5, позволяет записать фото в каталог name на сервере (folder=robots/for/fito), на операцию отводится 5 секунд (лимит времени для асинхронного режима, в течении которых нельзя писать другие данные). В приемном каталоге вебкниги зарезервировано стандартное наименование для изображения вебкамеры image.jpg.

На форуме фото появляется простой ссылкой на него. Горошок с растением будет появляться тут (и можно разнообразить режим показа, снабдив фото кнопочкой запроса на обновление и т.п.)

Асинхронный режим связи с сервером

Сервер или модем не всегда включены. Чтобы заметить отсутствие связи, на сервер (в каталог форума folder=robots/for/fito) размещают коммандный файл command.xml и чтение начинается с него


A=123, 
A=read('folder=robots/for/fito_file=command.xml'), pause 5, 
if A<>123, ..., end

если A отлично от предустановки 123 (любое число, заведомо отличное от содержимого command.xml), то данные с сервера (команда), дошли до клиента. Можно начинать считывать или записывать данные в сходном режиме.


A=[1 2 3 4], 
e=write(A,'folder=robots/for/fito_file=file.xml'), pause 5

записывает число, вектор (график процесса) или матрицу A на сервер за 5 секунд (лимит).

Связь COM-портом (RS232, UART)

Режим передача и прием через com-порт номер 9 (номер запоминается) организуется, например, так


A=1, e=write(A,'com9'), B=0, do 2, if B=0, B=read('com'), end, B=?

Предусмотрено сбрасывание зависшего соединения, надежность считывания обеспечивается дублированием и троированием (не должно быть большим). Предустановлена стандартная частота 9600, иначе пишем e=write(0,'com152000'), закрываем порт по e=write(0,'comclose').

Интерфейс связи с сервером

Visual Matlab имеет редактор, с помощью которого рисуется картинка интерфеса прибора с кнопками. Есть простой штамп программы, позволяющей различать, какая кнопка нажата пользователем. Все те команды, что выше, используются в ней для управления микроконтроллером (в основе - чтение и запись кодов, передаваемых по UART) или связью с интернет (в основе - чтение и запись кодов и картинок с вебкамеры).

Для фитооранжереи штамп готов, и нам его надо будет вместе запустить, поскольку настройку проще сделает опытный человек. Разобрать настроенную программу по косточкам, используя описание выше, будет несложно.

Есть еще одна сторона - интернет форум. На форуме есть средства создать сходный интерфейс, таким образом, Visual Matlab образует локальный контур управления с места (если рядом с цветком не планируется человек-оператор, то такой контур нужен для аварийных ситуаций, допустим, прервать управление из сети). Глобальный контур управления происходит из интернет подачей управляющих команд, причем в этом контуре предусмотрены средства (светофор) разделения пользователей во времени.

Разработка контура управления раскладывается на стадии:

1. Проверка связи с сервером и с микроконтроллером (тестирование)
2. Настройка штампа локального контура на базе Visual Matlab
3. Настройка штампа глобального контура на базе iMatLab.



Rambler's Top100