22
2013
Делаем систему «Умный дом» на Arduino часть 1.
Добрый день сегодня хочу начать серию статей про умный дом на Ардуино. Конечно его нельзя назвать в полном смысле умным домом скорее системой мониторинга.
Сегодня выложу исходные коды и схемы модулей, смотрим под катом.
Основной идеей послужило идея обеднения и общий контроль устройств на радио сигнале 315 и 433 Мгц. К счастью на сегодняшний день таких устройств превеликое множество. Это и различные пульты, датчики движения и дыма. Контроллеры жалюзи, протечек воды. Я постараюсь показать как сделать систему автоматизации за очень небольшие деньги. Ведь тот де датчик китайский движения стоит около 300 руб.
1.Главный модуль
- Обрабатывает сигналы с радио пультов .
- Обрабатывает сигналы с измерительного модуля.
- Передает полученные команды на компьютер.
#include <RCSwitch.h> // RF подключаем библиатеку #include <RemoteReceiver.h> #include <RemoteTransmitter.h> #include <VirtualWire.h> RCSwitch mySwitch = RCSwitch(); // RF приёмник long previousMillis2 = 0; // храним время последнего переключения светодиода long previousMillis3 = 0; // храним время последнего переключения светодиода char unitID_in[11]; // Переменные для разбора буфера char numb_in[14]; // Переменные для разбора буфера char dat_in[14]; // Переменные для разбора буфера char ol_in[14]; // Переменные для разбора буфера unsigned long rf_dt, old_rf; const int ledPin = 6; // номер выхода, подключенного к светодиоду int ledState = LOW; // этой переменной устанавливаем состояние светодиода long previousMillis = 0; // храним время последнего переключения светодиода long interval = 500; // интервал между включение/выключением светодиода (1 секунда) char buffer[32]; unsigned long rf2_dt, old_rf2; void setup() { RemoteReceiver::init(1, 3, showCode); Serial.begin(9600); // Скорость компорта mySwitch.enableReceive(0); // Приемник RF 0 => это pin #2 pinMode(ledPin, OUTPUT); // задаем режим выхода для порта, подключенного к светодиоду vw_set_tx_pin(7); // VirtualWire vw_set_rx_pin(2); // VirtualWire vw_set_ptt_inverted(true); // VirtualWire vw_setup(4000); // VirtualWire vw_rx_start(); // VirtualWire mySwitch.enableTransmit(7); // Передатчик RF is connected to Arduino Pin #10 mySwitch.setRepeatTransmit(5); // Передатчик RF setRepeatTransmit Serial.println(" "); Serial.println(" WELCOME to ADATUM "); Serial.println(" MAIN MODULE v.0.9 "); Serial.println(" "); } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; if(vw_get_message(buf, &buflen)){ int i; for(i = 0; i < buflen; ++i){ buffer[i] = char(buf[i]);}buffer[i++]='\0'; Serial.println(buffer); } int i=0; if(Serial.available()){delay(100); while( Serial.available() && i< 99) { buffer[i++] = Serial.read();} buffer[i++]='\0';} if(i>0) { sscanf(buffer, "%[^','],%[^','],%[^','],%[^',']", &unitID_in, &numb_in, &dat_in, &ol_in); if ((String)unitID_in == "rn") { vw_setup(0); unsigned long n2; unsigned long m2; n2 = atol(numb_in); m2 = atol(dat_in); RemoteTransmitter::sendCode(7, n2, m2, 5);vw_setup(4000);} //отправляем команду типа rn,177075,126 if ((String)unitID_in == "rf") { vw_setup(0); unsigned long n; unsigned long m; unsigned long g; n = atol(numb_in); m = atol(dat_in); g = atol(ol_in); mySwitch.setPulseLength(g); mySwitch.send(n, m); vw_setup(4000);} if ((String)unitID_in == "ir") { char sl[32]; sprintf(sl, "ir,%s,%s,%s", numb_in, dat_in, ol_in); vw_send((uint8_t *)sl, strlen(sl)); } //ir,PAN,16825533,16388 if ((String)unitID_in == "id") { char sl[32]; sprintf(sl, "id,send"); vw_send((uint8_t *)sl, strlen(sl)); } if ((String)unitID_in == "mu") { char sl[32]; sprintf(sl, "mu,%d", numb_in); vw_send((uint8_t *)sl, strlen(sl)); } if ((String)unitID_in == "re") { char qw[32]; sprintf(qw, "re,%s,%s", numb_in, dat_in); Serial.print(qw); vw_send((uint8_t *)qw, strlen(qw)); } } if (mySwitch.available()>0 ) { rf_dt = mySwitch.getReceivedValue(); unsigned long currentMillis2 = millis(); // Приемник RF if ((old_rf != rf_dt) || (currentMillis2 - previousMillis2 > 1000)) { previousMillis2 = currentMillis2; old_rf=rf_dt; Serial.print("rf,"); Serial.print( mySwitch.getReceivedValue() ); Serial.print(","); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print(","); Serial.print( mySwitch.getReceivedDelay() );Serial.print(",");Serial.print("0");Serial.print(",");Serial.println("rf"); mySwitch.resetAvailable(); } mySwitch.resetAvailable(); } unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; if (ledState == LOW) ledState = HIGH; else ledState = LOW; digitalWrite(ledPin, ledState); } } void showCode(unsigned long receivedCode, unsigned int period) { rf2_dt = receivedCode; unsigned long currentMillis3 = millis(); if ((old_rf2 != rf2_dt) || (currentMillis3 - previousMillis3 > 500)) {previousMillis3 = currentMillis3; old_rf2=rf2_dt; Serial.print("rn,"); Serial.print(receivedCode); Serial.print(",");Serial.print(period);Serial.print(",");Serial.print("0");Serial.print(",");Serial.print("0");Serial.print(",");Serial.println("rn");} } // Приемник PT2262
2. Измерительный модуль.
- Обрабатывает сигналы с радио пультов .
- Обрабатывает сигналы с инфракрасных пультов .
- Проигрывает сигнал тревоги и другие сигналы через динамик.
- Измеряет уровень освещения.
- Измеряет влажность и температуру.
- Отправляет все данные главному модулю.
#include <VirtualWire.h> #include "DHT.h" // DHT #include <IRremote.h> // Ir управление #include <RCSwitch.h> // RF подключаем библиатеку RCSwitch mySwitch = RCSwitch(); // RF приёмник DHT dht(6, DHT11); // DHT long interval = 60000; // интервал между включение/выключением светодиода (1 секунда) long previousMillis = 0; // храним время последнего переключения светодиода long previousMillis2 = 0; // храним время последнего переключения светодиода IRrecv irrecv(8); // Ir управление decode_results results; unsigned long ir_dt, old_ir; unsigned long rf_dt, old_rf; const int ledPin = 13; // номер выхода, подключенного к светодиоду int ledState = LOW; // этой переменной устанавливаем состояние светодиода long previousMillis3 = 0; // храним время последнего переключения светодиода char unitID_in[11]; // Переменные для разбора буфера char numb_in[14]; // Переменные для разбора буфера char dat_in[14]; // Переменные для разбора буфера char ol_in[14]; // Переменные для разбора буфера IRsend irsend; // Ir управление int sensorPin = A0; // устанавливаем входную ногу для АЦП int sensorPin2 = A6; // устанавливаем входную ногу для АЦП unsigned int sensorValue = 0; // цифровое значение фоторезистора int speakerPin = 4; // Musik char buffer[32]; void setup() { Serial.begin(9600); // Musik pinMode(ledPin, OUTPUT); // задаем режим выхода для порта, подключенного к светодиоду pinMode(speakerPin, OUTPUT); // Musik mySwitch.enableReceive(0); // Приемник RF 0 => это pin #2 dht.begin(); // DHT irrecv.enableIRIn(); // Start the receiver mySwitch.enableTransmit(7); // Передатчик RF is connected to Arduino Pin #10 mySwitch.setRepeatTransmit(5); // Передатчик RF setRepeatTransmit vw_set_tx_pin(7); // VirtualWire vw_set_rx_pin(2); // VirtualWire vw_set_ptt_inverted(true); // VirtualWire vw_setup(4000); // VirtualWire vw_rx_start(); // VirtualWire Serial.println(" "); Serial.println(" WELCOME to ADATUM "); Serial.println(" RECIVER MODULE v.0.9 "); Serial.println(" "); } void loop() { uint8_t buf[VW_MAX_MESSAGE_LEN]; uint8_t buflen = VW_MAX_MESSAGE_LEN; // VirtualWire if(vw_get_message(buf, &buflen)){int i; for(i = 0; i < buflen; ++i){ buffer[i] = char(buf[i]);}buffer[i++]='\0'; sscanf(buffer, "%[^','],%[^','],%[^','],%[^',']", &unitID_in, &numb_in, &dat_in, &ol_in); if ((String)unitID_in == "id") { int s = analogRead(sensorPin2); int k = analogRead(sensorPin); int h = dht.readHumidity(); int t = dht.readTemperature(); char meteo[32]; sprintf(meteo, "id,0001,%d,%d,%d,%d,id", t,h,k,s); Serial.print("send: "); Serial.println(meteo); vw_send((uint8_t *)meteo, strlen(meteo)); } if ((String)unitID_in == "mu") {int length = 5; int tempo = 10; char notes[] = "cgcgc"; int beats[] = {1,1,1,1,1}; for (int i = 0; i < length; i++) {if (notes[i] == ' ') {delay(beats[i] * tempo);} else {playNote(notes[i], beats[i] * tempo);}delay(tempo/2);}Serial.println("MUSIC");} if ((String)unitID_in == "ir") { Serial.print("recive: "); Serial.print(buffer); if ((String)numb_in == "nec") { vw_setup(0); int long bits2 = atol(dat_in); int long value2 = atol(ol_in); irsend.sendNEC(bits2, value2); Serial.print("send: "); Serial.print("nec,"); Serial.println(bits2); vw_setup(4000); } if ((String)numb_in == "sony"){ vw_setup(0); int long bits4 = atol(dat_in); int long value4 = atol(ol_in); irsend.sendSony(bits4, value4); Serial.print("send: "); Serial.print("sony,");Serial.println(bits4); vw_setup(4000); } if ((String)numb_in == "rc5") { vw_setup(0); int long bits5 = atol(dat_in); int long value5 = atol(ol_in); irsend.sendRC5(bits5, value5); Serial.print("send: "); Serial.print("rc5,"); Serial.println(bits5); vw_setup(4000); } if ((String)numb_in == "rc6") { vw_setup(0); int long bits6 = atol(dat_in); int long value6 = atol(ol_in); irsend.sendRC6(bits6, value6); Serial.print("send: "); Serial.print("rc6,"); Serial.println(bits6); vw_setup(4000); } if ((String)numb_in == "jvc") { vw_setup(0); int long bits7 = atol(dat_in); int long value7 = atol(ol_in); irsend.sendJVC(bits7, value7, 0); Serial.print("send: "); Serial.print("jvc,"); Serial.println(bits7); vw_setup(4000); } if ((String)numb_in == "pan") { vw_setup(0); int long bits3 = atol(dat_in); int long value3 = atol(ol_in); irsend.sendPanasonic(value3,bits3); Serial.print("send: "); Serial.print("pan,"); Serial.println(bits3); vw_setup(4000); } } irrecv.enableIRIn(); } if (irrecv.decode(&results)) { if (results.value > 0 && results.value < 0xFFFFFFFF) { int count = results.rawlen; if (results.decode_type == NEC) { char text2[32]; sprintf(text2, "ir,nec,%ld,%d,0,ir", results.value, results.bits); Serial.print("reciv:");Serial.println(text2); vw_send((uint8_t *)text2, strlen(text2)); } else if (results.decode_type == SONY) { char text4[32]; sprintf(text4, "ir,sony,%ld,%d,0,ir", results.value, results.bits); Serial.print("reciv");Serial.println(text4); vw_send((uint8_t *)text4, strlen(text4)); } else if (results.decode_type == RC5) { char text5[32]; sprintf(text5, "ir,rc5,%ld,%d,0,ir", results.value, results.bits); Serial.print("reciv");Serial.println(text5); vw_send((uint8_t *)text5, strlen(text5)); } else if (results.decode_type == RC6) { char text6[32]; sprintf(text6, "ir,rc6,%ld,%d,0,ir", results.value, results.bits); Serial.print("reciv");Serial.println(text6); vw_send((uint8_t *)text6, strlen(text6)); } else if (results.decode_type == JVC) { char text7[32]; sprintf(text7, "ir,jvc,%ld,%d,0,ir", results.value, results.bits); Serial.print("reciv");Serial.println(text7); vw_send((uint8_t *)text7, strlen(text7)); } else if (results.decode_type == PANASONIC){ char text3[32]; sprintf(text3, "ir,pan,%ld,%d,0,ir", results.value, results.panasonicAddress); Serial.print("reciv");Serial.println(text3); vw_send((uint8_t *)text3, strlen(text3)); } } irrecv.enableIRIn(); } if (mySwitch.available()>0 ) { rf_dt = mySwitch.getReceivedValue(); unsigned long currentMillis2 = millis(); // Приемник RF if ((old_rf != rf_dt) || (currentMillis2 - previousMillis2 > 1000)) { previousMillis2 = currentMillis2; old_rf=rf_dt; Serial.print("reciv: "); Serial.print("rf,"); Serial.print( mySwitch.getReceivedValue() ); Serial.print(","); Serial.print( mySwitch.getReceivedBitlength() ); Serial.print(","); Serial.print( mySwitch.getReceivedDelay() ); int long n = mySwitch.getReceivedValue(); int m = mySwitch.getReceivedBitlength(); int g = mySwitch.getReceivedDelay(); vw_setup(0); // VirtualWire mySwitch.setPulseLength(g-58); mySwitch.send(n, m); vw_setup(4000); // VirtualWire char sl[32]; sprintf(sl, "%ld,%d,%d", n, m, g);Serial.print(" -> send: ");Serial.println(sl); mySwitch.resetAvailable();} mySwitch.resetAvailable(); } unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { previousMillis = currentMillis; int s = analogRead(sensorPin2); int k = analogRead(sensorPin); int h = dht.readHumidity(); int t = dht.readTemperature(); char meteo[32]; sprintf(meteo, "id,0001,%d,%d,%d,%d,id", t,h,k,s); Serial.print("send: "); Serial.println(meteo); vw_send((uint8_t *)meteo, strlen(meteo)); if (ledState == LOW) ledState = HIGH; else ledState = LOW; digitalWrite(ledPin, ledState); } } void playTone(int tone, int duration){for (long i = 0; i < duration * 1000L; i += tone * 2) {digitalWrite(speakerPin, HIGH); delayMicroseconds(tone); digitalWrite(speakerPin, LOW); delayMicroseconds(tone); }} void playNote(char note, int duration){char names[]={'c','d','e','f','g','a','b','C'}; int tones[]={1915,1700,1519,1432,1275,1136,1014,956}; for (int i=0; i<8; i++) {if (names[i] == note){playTone(tones[i], duration);}}}
По коду думаю у вас не возникнет вопросов, основные моменты прокомментированы. Все таки если возникают вопросы пишем не стесняемся, буду рад ответить.
В проекте использованы библиотеки.
- IRremote * Version 0.1 July, 2009 * Copyright 2009 Ken Shirriff.
- Virtual Wire implementation for Arduino Author: Mike McCauley (mikem@open.com.au) Copyright (C) 2008 Mike McCauley.
- DHT library written by Adafruit Industries.
- RCSwitch Suat Цzgьr. Contributors: — Andre Koehler / info(at)tomate-online(dot)de — Gordeev Andrey Vladimirovich.
- RemoteSwitch library v2.3.0 DEV made by Randy Simons.