Мониторинг климата в серверной.
- Войдите на сайт для отправки комментариев
Пилотный проект, на который на работе выдедлили средства.
Использовались:
Arduino Nano V 3.0
ENC28J60 Ethernet Shield
DHT 22 - модулем.
DS18B20 - 2 штуки.
Relay module 5v
Nano I/0 9v 2.5mm Power Sensor Expansion - в качестве распаячной платы.
Светодиод 1.37v (замерял сам) - 2шт.
Резистор 4.7кОм

Задача устройства такова:
Измерение и температуры и влажности с 3-х датчиков, передача данных на сервер.
В роли сервера выступает Processing

В Processinge данные обрабатываются, выводятся в терминал в виде динамичных термометров, так же выводится информация о текущем времени, времени в работе, IP адрес Arduino и IP адрес WEB страницы с данными, которую генерирует сам процессинг. Так же каждые 30 минут записывются усредненные данные в лог файл формата .csv, раз в сутки (ровно в полночь) создается новый лог файл.

Когда температура выходит за пределы допустимых параметров:
В Ардуино:
Замыкается реле (подключение физической сигнализации).
В процессинге:
На веб страницу выводится сигнал аварии с сопровождением звукового сигнала "СИРЕНА".
Диоды:
1. Просто информирует о включенном или выключенном состоянии устройства
2. Горит при наличии сетевого соединения (DCHP).
Ну вот вроде и все. Все еще следует доробатывать и оптимизировать. В планах сделать динамичный график изменения температуры, более красивый интерфейс HTML и терминала Processing.
Спасибо за внимание.
Скетчи ниже.
Processing:
import processing.net.*;
PImage IMG;
//Связь с Ethernet клиентом и сервером
int html_port = 80;
int arduino_port = 82;
String IP_arduino = "10.168.2.129";
Server server;
Client client;
int connect_arduino=0;
int connect_server=0;
//Символ до которого будем считывать данные
byte flag=62;
//Переменные с данными
float fl_data1=0.0, fl_data2=0.0, fl_data3=0.0, fl_data4=0.0, fl_data5=0.0, fl_data6=0.0, fl_data7=0.0;
String str_data[];
//Вывод данных в терминал
PFont font26, font36, font36_2;
long time_previousMillis = 0;
int min_2=0, hr_2=0, day_2=0;
String data1="", data2="", data3="", data4="", data5="", data6="", data7="";
boolean start_2=true;
float y1,h1,y2,h2,y3,h3,y4,y5;
//
String climate;
//Логфайл
String filename, row_data;
PrintWriter save;
int sec, min, hr, day, month, year;
//Интервал записи в лог
long interval = 59000;
long previousMillis = 0;
boolean start=true;
//Интервал записи в массив
long array_previousMillis = 0;
int x=0;
//Массивы float численных данных за 30 минут
float DS18B20_1=0.0, DS18B20_2=0.0, DHT_T=0.0, DHT_H=0.0;
void setup()
{
size(800, 600);
IMG = loadImage ("theme.JPG");
font26 = loadFont("ArialMT-26.vlw");
font36 = loadFont("ArialMT-36.vlw");
font36_2 = loadFont("AntiqueOlive-Italic-36.vlw");
server = new Server(this, html_port);
delay(3000);
min = minute(); // Values from 0 - 59
hr = hour(); // Values from 0 - 23
day = day();
month = month();
year = year();
filename = "DataLogger_"+hr+"_"+min+"_"+day+"_"+month+"_"+year+".csv";
save = createWriter(filename);
save.println("Time_Data;T1;T2;T3;H");
save.flush (); // записывает данные, оставшиеся в файл
}
void draw()
{
sec = second(); // Values from 0 - 59
min = minute(); // Values from 0 - 59
hr = hour(); // Values from 0 - 23
day = day();
month = month();
year = year();
background (208, 208, 208);
image(IMG,0,0);
//Прием данных с ардуино
client = new Client(this, IP_arduino, arduino_port);
delay (2000);
client.write ("GET/Processing 2.0 ");
delay (1000);
while (client.available()>0){
if (client !=null) {
connect_arduino = 1;
String list = client.readStringUntil(flag);
if (list != null) {
str_data = split(list, ';');
}
} else {connect_arduino = 0;}
client.stop ();
//Преобразование string в float
for (int i=1; i<5; i++){
if (str_data[1] != null) {fl_data1=float(str_data[1]);}
if (str_data[2] != null) {fl_data2=float(str_data[2]);}
if (str_data[3] != null) {fl_data3=float(str_data[3]);}
if (str_data[4] != null) {fl_data4=float(str_data[4]);}
if (str_data[5] != null) {fl_data5=float(str_data[5]);}
if (str_data[6] != null) {fl_data6=float(str_data[6]);}
if (str_data[7] != null) {fl_data7=float(str_data[7]);}
}
}
// Вывод данных на экран
// for (int i=1; i<9; i++) {
// println (str_data[i]);}
// Запускаем html СЕРВЕР
Client thisClient = server.available();
if (thisClient != null) {
connect_server = 1;
String whatClientSaid = thisClient.readString();
if (whatClientSaid != null) {
server.write ("<!DOCTYPE HTML>");
server.write ("<html>");
server.write ("<head> ");
server.write ("<meta http-equiv= refresh content=60;>");
server.write ("<meta http-equiv='Content-Type' content='text/html; charset='utf-8' /> ");
server.write ("</head> ");
server.write ("<body>");
server.write ("<b><font size='+3'>Микроклимат серверной: ");
if (str_data[8].equals("bad")) {
server.write ("<FONT color='#ff0000'>АВАРИЯ!!!</FONT>");
server.write ("<audio autoplay='autoplay' loop='loop'>");
server.write ("<source src='http://allsoundsaround.com/files/sounds/allsoundsaround.com-1270097130-Warning%20Siren-AllSoundsAround.com.mp3' type='audio/mpeg'>");
server.write ("<source src='http://allsoundsaround.com/files/sounds/allsoundsaround.com-1270097130-Warning%20Siren-AllSoundsAround.com.wav' type='audio/wav'>");
server.write ("</audio>"); }
if (str_data[8].equals("good")) {server.write ("норма");}
server.write ("</font></b>");
server.write ("<br> ");
server.write ("<b>Датчик №1</b>");
server.write ("<br> ");
server.write ("Температура: ");
server.write (str_data[1]);
server.write (" *C");
server.write ("<br>");
server.write ("Влажность: ");
server.write (str_data[2]);
server.write (" %");
server.write ("<br> ");
server.write ("<b>Датчик №2</b>");
server.write ("<br> ");
server.write ("Температура: ");
server.write (str_data[3]);
server.write (" *C");
server.write ("<br> ");
server.write ("<b>Датчик №3</b>");
server.write ("<br> ");
server.write ("Температура: ");
server.write (str_data[4]);
server.write (" *C");
server.write ("<br> ");
server.write ("<hr>");
server.write ("<b><font size='+1'>Уставки сигналов аварии:</font></b>");
server.write ("<br> ");
server.write ("Верхний предел температуры: ");
server.write (str_data[5]);
server.write (" *C");
server.write ("<br> ");
server.write ("Нижний предел температуры: ");
server.write (str_data[6]);
server.write (" *C");
server.write ("<br> ");
server.write ("Аварийный максимум влажности воздуха: ");
server.write (str_data[7]);
server.write (" %");
server.write ("<br> ");
server.write ("<hr>");
server.write ("</body></html>");
server.disconnect(thisClient);
}
} else {connect_server=0;} //Конц html сервера
// расчет средней температуры за период времени
//запись данных в лог
if(millis() - array_previousMillis > interval) {
array_previousMillis = millis();
x++;
DHT_T +=fl_data1;
DHT_H +=fl_data2;
DS18B20_1 +=fl_data3;
DS18B20_2 +=fl_data4;
println (DHT_T);
println (DHT_H);
println (DS18B20_1);
println (DS18B20_2);
println (x);
if (min == 29 || min == 59 || start == true) {
DHT_T = DHT_T/x;
DHT_H = DHT_H/x;
DS18B20_1 = DS18B20_1/x;
DS18B20_2 = DS18B20_2/x;
row_data=hr+":"+min+" "+day+"."+month+";"+DHT_T+";"+DS18B20_1+";"+DS18B20_2+";"+DHT_H;
save.println(row_data);
println (row_data);
save.flush (); // записывает данные, оставшиеся в файл
start=false;
DHT_T = 0.0;
DHT_H = 0.0;
DS18B20_1 = 0.0;
DS18B20_2 = 0.0;
x=0;
}
}
// Создание нового лог файла
if(millis() - previousMillis > interval) {
previousMillis = millis();
if (hr==0 && min==0) {
save.close ();
filename = "DataLogger_"+hr+"_"+min+"_"+day+"_"+month+"_"+year+".csv";
save = createWriter(filename);
save.println("Time_Data;T1;T2;T3;H");
save.flush ();
}
}
//Вывод в граффическое окно
//Расчет времени
//Время текущее
if (day<10) {data1 = ""+"0"+day;}else{data1=""+day;}
if (month<10) {data2 = ""+"0"+month;}else{data2=""+month;}
if (hr<10) {data3 = ""+"0"+hr;}else{data3=""+hr;}
if (min<10) {data4 = ""+"0"+min;}else{data4=""+min;}
//Время в работе
if(millis() - time_previousMillis > interval || start_2 == true) {
time_previousMillis = millis();
min_2++;
start_2 = false;
if (min_2 > 59) {hr_2++; min_2=0;}
if (hr_2 >23) {day_2++; hr=0;}
if (day_2<10) {data5 = ""+"0"+day_2;}else{data5=""+day_2;}
if (hr_2<10) {data6 = ""+"0"+hr_2;}else{data6=""+hr_2;}
if (min_2<10) {data7 = ""+"0"+min_2;}else{data7=""+min_2;}
}
textFont(font26, 26);
fill (0);
text (Server.ip(), 197, 175); //Server IP
text (html_port, 467, 175); //Server port
text (IP_arduino, 197, 207); //Arduino IP
text (arduino_port, 467, 207); //Arduino IP
text (data1+"."+data2+"."+year+" "+data3+":"+data4, 128, 100);
text (data5+" days "+data6+":"+data7, 569, 100);
textFont(font36, 36);
text (str_data[2]+"%", 632, 383); //Влажность
textFont (font36_2, 28);
if (connect_arduino == 1) {
fill (0, 255, 0);
text ("Ok", 527, 207);}
else {fill (255, 0, 0); text ("Not", 527, 207);}
if (connect_server == 1) {
fill (0, 255, 0);
text ("Ok", 527, 175);}
else {
fill (255, 0, 0);
text ("Not", 527, 175);}
//Термометры
fill(235,29, 31);
stroke(235,29, 31);
y1 = 438-12*(fl_data1-15);
h1 = 438-y1;
rect(93, y1, 15, h1);
y2 = 438-12*(fl_data3-15);
h2 = 438-y2;
rect(262, y2, 15, h2);
y3 = 438-12*(fl_data4-15);
h3 = 438-y3;
rect(430, y3, 15, h3);
//Уставки на термометрах
y4= 438-12*(fl_data5-15);
line (116, y4+1, 136, y4+1);
line (116, y4 , 136, y4);
line (285, y4+1, 305, y4+1);
line (285, y4 , 305, y4);
line (453, y4+1, 473, y4+1);
line (453, y4 , 473, y4);
stroke(38,38, 255);
y5= 438-12*(fl_data6-15);
line (116, y5+1, 136, y5+1);
line (116, y5 , 136, y5);
line (285, y5+1, 305, y5+1);
line (285, y5 , 305, y5);
line (453, y5+1, 473, y5+1);
line (453, y5 , 473, y5);
}
Arduino:
#include <EtherCard.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <EEPROM.h>
// DHT 22
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
float h, t;
char H[5];
char T[5];
//DS18B20
#define ONE_WIRE_BUS 5
#define TEMPERATURE_PRECISION 9
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
float t1, t2;
char T1[6];
char T2[6];
//Реле 1шт
int Relay=6;
//EEPROM Уставки сигналов аварий 1-в.пред.темп, 2-н.пред.темп, 3-в.пред.вл.
float sp1, sp2, sp3;
int simbol;
char U1[3], U2[3], U3[3];
//Ethernet
static byte mymac[] = {0x00, 0x04, 0xA3, 0x21, 0xCA, 0x38};
byte Ethernet::buffer[1024];
//временной интервал
long previousMillis = 0;
long interval = 10000;
boolean x=true;
//Уставки
char* climate;
// PROGMEM
char good [] PROGMEM =
"good";
char bad [] PROGMEM =
"bad";
//LED ON/OFF, Ethernet_connect
int LED_ON = 9; //
int LED_E_C = 3; //
int brightness = 66; //яркость светодиода на 1.3v
// SETUP
void setup () {
Serial.begin(9600);
dht.begin();//DHT22
sensors.begin(); //DS18B20
//Реле 1 шт.
pinMode(Relay, OUTPUT);
digitalWrite(Relay, HIGH);
//LED ON/OFF, Ethernet_connect
pinMode(LED_ON, OUTPUT);
pinMode(LED_E_C, OUTPUT);
analogWrite(LED_ON, brightness);
//EEPROM
sp1 = EEPROM.read(1);
dtostrf(sp1, 2, 0, U1);
Serial.println (sp1);
sp2 = EEPROM.read(2);
dtostrf(sp2, 2, 0, U2);
Serial.println (sp2);
sp3 = EEPROM.read(3);
dtostrf(sp3, 2, 0, U3);
Serial.println (sp3);
if (!ether.begin(sizeof Ethernet::buffer, mymac, 10)){
Serial.println( "No");}
else{
Serial.println("Ok");
}
if (!ether.dhcpSetup()){
Serial.println("No");
}
else {
Serial.println("Ok");
ether.printIp("IP:\t", ether.myip);
ether.printIp("Mask:\t", ether.mymask);
ether.printIp("Host:\t", ether.gwip);
Serial.println();
ether.hisport = 82;
analogWrite(LED_E_C, brightness);
}
}
void loop() {
//Смена уставок
if(Serial.available()){
simbol=Serial.read ();
if (simbol==117) {
byte t[3] = {0, 0, 0};
for(byte i = 1; i < 4; i++)
{
t[i] = Serial.parseInt();
EEPROM.write(i, t[i]);
}
for(byte i = 1; i < 4; i++)
{
t[i] = EEPROM.read(i);
Serial.print(t[i]);
if(i < 1) Serial.print(',');
else Serial.println();
}
}
}
//Снятие показаний с датчиков
//Установка интервала считывания
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval || x==true) {
previousMillis = currentMillis;
x=false;
//DHT22
h = dht.readHumidity();
dtostrf(h, 4, 1, H);
t = dht.readTemperature();
dtostrf(t, 4, 1, T);
//DS18B20
sensors.requestTemperatures();
t1 = sensors.getTempCByIndex(0);
delay (50);
dtostrf(t1, 5, 2, T1);
t2 = sensors.getTempCByIndex(1);
delay (50);
dtostrf(t2, 5, 2, T2);
Serial.println();
Serial.print("T= ");
Serial.println(T);
Serial.print("H= ");
Serial.println(H);
Serial.print("T1= ");
Serial.println(T1);
Serial.print("T2= ");
Serial.println(T2);
}
//Аварии
if (t < sp2 || t1 <sp2 || t2 <sp2 || h > sp3) {
digitalWrite (Relay, HIGH);
climate=bad;
}
else
{ if (t > sp1 || t1 > sp1 || t2 > sp1 || h > sp3) {
digitalWrite (Relay, HIGH);
climate=bad;
}
else
{
digitalWrite (Relay, LOW);
climate=good;}
}
//Ethernet
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
if(pos) {
// Serial.println("---------------------------------------- NEW PACKET ----------------------------------------");
// Serial.println((char *)Ethernet::buffer + pos);
// Serial.println("--------------------------------------------------------------------------------------------");
// Serial.println();
BufferFiller bfill = ether.tcpOffset();
bfill.emit_p(PSTR(";$S;$S;$S;$S;$S;$S;$S;$F;>")
, T, H, T1, T2, U1, U2, U3, climate);
ether.httpServerReply(bfill.position());
}
}
121 server.write ("<source src='<a href="http://allsoundsaround.com/files/sounds/allsoundsaround.com-1270097130-Warning%20Siren-AllSoundsAround.com.mp3" rel="nofollow">http://allsoundsaround.com/files/sounds/allsoundsaround.com-1270097130-Warning%20Siren-AllSoundsAround.com.mp3</a>' type='audio/mpeg'>"); 122 server.write ("<source src='<a href="http://allsoundsaround.com/files/sounds/allsoundsaround.com-1270097130-Warning%20Siren-AllSoundsAround.com.wav" rel="nofollow">http://allsoundsaround.com/files/sounds/allsoundsaround.com-1270097130-Warning%20Siren-AllSoundsAround.com.wav</a>' type='audio/wav'>");Тут выдает ошибку, что-то с кавычками не понятное