Seite auswählen

Homeduino 3.0 … das ultimative IO-Modul für die Hausautomation

, ,
Homeduino 3.0 … das ultimative IO-Modul für die Hausautomation
Print Friendly

Wichtiger Hinweis: Es gibt mittlerweile eine neue Softwareversion:   Homduino 4.0

Für die Ungeduldigen ist hier die erste vorläufige Version der Homeduino 3.0 Software veröffentlicht. An der Software wird noch gearbeitet und einige Funktionalitäten für  Infrarot- und 433Mhz-Module fehlen noch. Darüberhinaus ist auch noch eine LCD-Anzeige geplant.

Unterstützt werden das IO-Shield20 und das IO-Shield-Plus

Hier die Installationshinweise:

1. Installation der Arduino 1.6.3 IDE

2. Kopieren der zusätzlichen Libraries in das Library-Verzeichnis:
https://www.stall.biz/wp/wp-content/uploads/2015/04/homeduino_libraries30.zip

3. Ausführen der aktuellen Version : (mit W5100-Ethernet-Shield oder CC3000 Shield )

Anmerkung 07.05.2015:  Die aktuelle Version homeduino30_03 ist noch nicht komplett getestet !!

Rückmeldungen erwünscht .

Beide folgenden Versionen (W5100 mit LAN und CC3000 mit WLAN) könnte man in einem Sketch mit sog. „conditional compilation“ zusammenfassen, aber leider gibt es damit noch Fehlermeldungen, die aktuell (noch) nicht beseitigt werden konnten. Deshalb hier aktuell noch zwei Versionen:

 

 Hier die LAN-Version:

/*Ver.: "homeduino30_03_LAN.ino / Stand: 2015.05.11 / Verfasser: Eugen Stall
 
LAN-Version mit W5100 Shield
 
hier ist immer die aktuelle Version:
Home
das folgende homeduino-programm sendet messdaten zur ccu (homeduino als webclient) ...
und empfängt ausgabedaten für die homeduino-outputs (homeduino als webserver)
____________________ ___________________
 | | 
 server port 8181 |<------------<| client 
 | | 
 CCU | | Homeduino 
 | | 
 client |>------------>| server port 80
____________________| |___________________
 
erprobt fuer Arduino Mega 2560 mit Arduino 1.6.3
diese Software steuert referenziert die signale an den Arduino-pins mit entsprechenden systemvariablen in der Homematic ccu
mit dem Befehl: http://<ip der ccu>:8181/GET /xy.exe?antwort=dom.GetObject('<systemvariable>').State(" + value + ")"
/Quellen:Arduino website plus http://arduino.cc/en/Tutorial/WebClient und ...
 http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino und ...
*/
 
#include <SPI.h>
#include <Wire.h> 
#include <OneWire.h> //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h> //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h" //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
#include <RCSwitch.h> // läuft noch nicht!
//#include <IRremote.h> // läuft noch nicht!
 
//Kommunikationsweg  festlegen
#define com_mode 0  //"0"  W5100, "1" CC300 Breakout                                     <<user-eingabe<< 
 
/*
//der folgende Bereich ist die Initialisierung des CC3000 Wifi auf dem IO-Shield-Plus 
#include <SFE_CC3000.h>// fuer cc3000 wifi http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip
#include <SFE_CC3000_Client.h>
// Pins
#define CC3000_INT 18 // int-Pin mit Wifi Shield ist D3, mit breakout auf IO-Shield-Plus ist D18
#define CC3000_EN 46 // en-Pin mit Wifi Shield ist D5, mit breakout auf IO-Shield-Plus ist D46
#define CC3000_CS 53 // cs-Pin mit Wifi Shield ist D10, mit breakout auf IO-Shield-Plus ist D53
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
// Constants
char ap_ssid[] = "ssid"; // SSID Name des WLAN in Anführungszeichen                       <<user-eingabe<< 
char ap_password[] = "passwort"; // Passwort des WLAN in Anführungszeichen                <<user-eingabe<< 
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
unsigned int timeout = 30000; // Milliseconds
//char server[] = "192,168,178,50"; // Remote host site
*/
 
//der folgende Bereich ist die Initialisierung des LAN bei Verwendung des LAN-Shields
#include <Ethernet.h> 
EthernetClient client;
EthernetServer server(80);
 
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU <<user-eingabe<< 
byte mac[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; //bei mehreren homeduinos ändern!!    <<user-eingabe<<
byte homeduino[] = { 192, 168, 178, 52 }; //das ist feste IP dieses Homeduino,             <<user-eingabe<< 
 //wenn DHCP versagt
String homeduino_nummer = "xyz"; //indiv. Bezeichnung dieses homeduino                     <<user-eingabe<< 
 //das ist bel. String ohne 
 //sonderzeichen und öäüß... 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
 
//Input-Kennung: hier wird die Funktion aller verwendbaren IO´s mit einer Kennziffer festgelegt 
//dabei haben alle IO´s die Standardfunktionen plus spez. Sonderfunktionen
byte iomodus_D[70] = 
{ 0, //D0 : '0' = andere Nutzg; 
 0, //D1 : '0' = andere Nutzg; 
 
//Standardfkt:'0' =andere Nutzg; '1' =dig_input; '2' =dig_output; '3' =1wire '4' =DHTxx; '5' =U_Schall 
 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield20 +++++++++++++++++ 
 2, //D2 : Standardfkt; '5' = IR_Rx?? '6' =ImpCount;                        <<user-eingabe für IO-Shield20<< 
 2, //D3 : Standardfkt; '7' = 433_Rx?? '6' =ImpCount;                       <<user-eingabe für IO-Shield20<< 
 0, //D4 : Standardfkt; '7' = 433_Tx?? '0' =W5100/SS-Pin                    <<user-eingabe für IO-Shield20<< 
 2, //D5 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D6 : Standardfkt; '9' = buzzer                                        <<user-eingabe für IO-Shield20<< 
 0, //D7 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D8 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 1, //D9 : Standardfkt; '5' = IR_Tx??                                       <<user-eingabe für IO-Shield20<< 
 0, //D10 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D11 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D12 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D13 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield_Plus ++++++++++++++ 
 3, //D14 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D15 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D16 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D17 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 0, //D18 : Standardfkt; '6' =ImpCount; '0' =CC3000                     <user-eingabe für IO-Shield-Plus20<< 
 3, //D19 : Standardfkt; '6' =ImpCount;                                 <user-eingabe für IO-Shield-Plus20<< 
 1, //D20 : Standardfkt; '6' =ImpCount; '8' =I2C;SDA                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D21 : Standardfkt; '6' =ImpCount; '8' =I2C;SCL                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D22 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D23 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D24 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D25 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D26 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D27 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D28 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D29 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
//hier wird die Funktion der Eingänge A0 bis A15 festgelegt
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield20 ++++++++++++++++++
 3, //D54 A0 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 2, //D55 A1 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D56 A2 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D57 A3 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D58 A4 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D59 A5 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D60 A6 : "0" =andere Nutzg; 
 0, //D61 A7 : "0" =andere Nutzg; 
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield_Plus +++++++++++++++
 1, //D62 A8 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D63 A9 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D64 A10 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D65 A11 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D66 A12 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D67 A13 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D68 A14 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1 //D69 A15 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
}; 
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro = 0; //'0' =nc; '1' =BMP180, dann auch oben I2C setzen <<user-eingabe für IO-Shield-Plus<<
byte iomodus_lux = 0; //'0' =nc; '1' =BH1750, dann auch oben I2C setzen  <<user-eingabe für IO-Shield-Plus<<
 
//hier werden die Kennwerte fuer die Impulszaehler festgelegt
unsigned zaehlwert;
unsigned last_zaehlwert[6] = {0,0,0,0,0,0};
volatile unsigned long pulsecounter[6] = 
{ 0, //Zaehlerstand fuer D2 -Impulseingang bei Reset                        <<user-eingabe für IO-Shield20<<
 0, //Zaehlerstand fuer D3 -Impulseingang bei Reset                         <<user-eingabe für IO-Shield20<<
 4711, //Zaehlerstand fuer D21-Impulseingang bei Reset                   <<user-eingabe für IO-Shield-Plus<< 
 3, //Zaehlerstand fuer D20-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 4, //Zaehlerstand fuer D19-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 5 //Zaehlerstand fuer D18-Impulseingang bei Reset                       <<user-eingabe für IO-Shield-Plus<< 
}; 
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = 
{ 1, //Teilerfaktor D2 :                                                    <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D3 :                                                     <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D21 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D20 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D19 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D18 :                                                 <<user-eingabe für IO-Shield-Plus<<
}; 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digital_value_D[70];
float last_value_D[70];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1; // wenn 1, dann einmal komplett durchlaufen
 
String header = String(20);
String befehl;
String sub_command = String(20);
String parameter = String(20);
int param;
int port_pin;
boolean port_data;
 
boolean value;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.2; //Deltas für Sendeauslösung 
float delta_DHT = 0.2; //in °C 
float delta_us = 3.0; // in cm
float delta_analog = 2.0; // in inkrement
float delta_ntc = 0.5; //in °C
float delta_lux = 20; //in lux
float delta_counter = 5; //in counter inkrement
double delta_baro = 0.2; //in mB
double delta_baroT = 0.5; //in °C
 
long duration, cm; //variable für Ultraschallsensor
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 3600000; // jede Stunde werden alle Inputs aktualisiert
unsigned long delta_tx = 500; //in ms, minimaler Abstand der Telegramme an die CCU
unsigned long next_tx = 0;
unsigned long time_DHT = 0; 
 
int rf_key;
String rfkey;
RCSwitch mySwitch = RCSwitch();
 
//************************************************************************************************** 
AS_BH1750 sensor; //Initialize BH1750 Luxmeter library
#define ALTITUDE 299.0 // eigene seehoehe in metern              <<user-eingabe für IO-Shield-Plus<<
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
boolean reading = false;
String command = String(200);
 
//************************************************************************************************** 
//************************************************************************************************** 
void setup() 
{Serial.begin(115200); 
 
//einrichtung der interrupts fuer impulszahler D2,D3,D18,D19,D20,D21
if ((pulsedivider[0] > 0) && (iomodus_D[2] == 6)) {pinMode(2, INPUT_PULLUP); attachInterrupt(0, ISR_0, FALLING);}
if ((pulsedivider[1] > 0) && (iomodus_D[3] == 6)) {pinMode(3, INPUT_PULLUP); attachInterrupt(1, ISR_1, FALLING);} 
if ((pulsedivider[2] > 0) && (iomodus_D[21] == 6)) {pinMode(21, INPUT_PULLUP); attachInterrupt(2, ISR_2, FALLING);}
if ((pulsedivider[3] > 0) && (iomodus_D[20] == 6)) {pinMode(20, INPUT_PULLUP); attachInterrupt(3, ISR_3, FALLING);}
if ((pulsedivider[4] > 0) && (iomodus_D[19] == 6)) {pinMode(19, INPUT_PULLUP); attachInterrupt(4, ISR_4, FALLING);}
#if com_mode == 0 
if ((pulsedivider[5] > 0) && (iomodus_D[18] == 6)) {pinMode(18, INPUT_PULLUP); attachInterrupt(5, ISR_5, FALLING);}
#endif 
 
 
//+++++++ hier folgt die LAN Initialisierung
 if (Ethernet.begin(mac) == 0) // start the Ethernet connection:
 {Serial.println("Failed to configure Ethernet using DHCP"); Ethernet.begin(mac, homeduino);}
 delay(1000);// give the Ethernet shield a second to initialize:
 Serial.println("connecting..."); // if you get a connection, report back via serial:
 if (client.connect(ccu, 8181)) {}
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24]; //IP auslesen
 IPAddress myIp = Ethernet.localIP();
 sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]); 
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar(); 
 server.begin();
 
/*
//+++++++ hier folgt die CC3000 Initialisierung
 ConnectionInfo connection_info;
 int i;
 byte IP_ADDR_LEN =4;
 Serial.println("SparkFun CC3000 - WebClient");
 if ( wifi.init() ) {Serial.println("init complete");} 
 else {Serial.println("problem with init!");}
 // Connect using DHCP
 if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout)) {Serial.println("no connection to AP");}
 // Gather connection details and print IP address
 if ( !wifi.getConnectionInfo(connection_info) ) {Serial.println("no connection details");} 
 else {for (i = 0; i < IP_ADDR_LEN; i++) 
 {Serial.print(connection_info.ip_address[i]);
 if ( i < IP_ADDR_LEN - 1 ) {Serial.print(".");}
 }
 Serial.println(" ist aktuelle IP-Adresse"); 
 }
 
 if (client.connect(ccu, 8181)) {} // Make a TCP connection to remote host
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop();
*/
 
}
//************************************************************************************************** 
//************************************************************************************************** 
void loop() 
{complete_loop = 0;
 if (millis() > next_full_loop) //mindestens jede Stunde eine komplette Aktualisierung
 {complete_loop = 1; next_full_loop = millis() + delta_time; 
 if (next_full_loop < millis()) {complete_loop = 0;} //wichtig wegen Zahlensprung von millis() alle 50 Tage
 } 
 for (int i = 2; i < 70; i++) //behandlung aller Ports D2 bis D69 
 {if (i== 30) {i = 54;} // unbenutzte pins überspringen
 
 //************************************************************************************************** 
 if (iomodus_D[i] == 1) //behandlung digitaleingänge 
 {pinMode(i, INPUT_PULLUP); 
 digitalWrite(i, HIGH);
 value =digitalRead(i);
 if ((!value == last_digital_value_D[i]) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
 set_sysvar();
 last_digital_value_D[i] = value;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 3) //behandlung onewire 
 {pinMode(i, INPUT_PULLUP);
 digitalWrite(i, HIGH);
 OneWire ds(i); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 
 byte present = 0;
 byte data[12];
 byte addr[8];
 temp_tur = 1000.0;
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
 if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
 if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
 if (temp_tur > -1000.0) 
 {ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5 // Calculate temperature value 18S20
 }
 if ((temp_tur > (last_value_D[i] + delta_onewire)) 
 || (temp_tur < (last_value_D[i] - delta_onewire)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 4) //behandlung DHT temperatur- und feuchtesensoren
 {DHT dht(i, DHT22); //je nach verwendetem sensor "DHT11" oder "DHT22" (AM2302) oder "DHT 21" (AM2301)
 dht.begin();
 //delay(2000); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
 time_DHT = millis() +2000;
 while (millis() < time_DHT) {datenempfang();} //wahrend der 2s wartezeit, daten empfangen
 humidity = dht.readHumidity(); // Read temperature as Celsius
 temp_tur = dht.readTemperature(); 
 if (isnan(humidity) || isnan(temp_tur) ) // Check if any reads failed and 
 { //Serial.println("Failed to read from DHT sensor!");
 temp_tur = -1000;
 }
 if ((temp_tur > (last_value_D[i] + delta_DHT)) || (temp_tur < (last_value_D[i] - delta_DHT)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "1').State(" + humidity + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 } 
 //************************************************************************************************** 
 if (iomodus_D[i] == 5) //behandlung ultraschallsensoren achtung: zu beachten 
 //bei verwendung der US-Sensoren beim IO-Shield-Plus sind die 150-Ohm-Schutzwiderstände 
 //zu überbrücken , entsprechend beim IO-Shield20 der digitale Jumper 4-5 zu setzen!! 
 {NewPing sonar(i, i, 200); // NewPing setup of pin and maximum distance.
 unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
 int cm = uS / US_ROUNDTRIP_CM;
 if ((cm > (last_value_D[i] + delta_us)) || (cm < (last_value_D[i] - delta_us)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + cm + ")";
 set_sysvar();
 last_value_D[i] = cm;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 10) //behandlung analogeingänge 
 {analogwert =analogRead(i); 
 if ((analogwert > (last_value_D[i] + delta_analog)) || (analogwert < (last_value_D[i] - delta_analog)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + analogwert + ")";
 set_sysvar();
 last_value_D[i] = analogwert;
 } 
 } 
//**************************************************************************************************
 if (iomodus_D[i] == 11) //behandlung NTC 
 {Rt = Rv/((1024.0/analogRead(i))- 1.0);
 tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
 if ((tempNTC > (last_value_D[70] + delta_ntc)) || (tempNTC < (last_value_D[70] - delta_ntc)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + tempNTC + ")";
 set_sysvar();
 last_value_D[i] = tempNTC;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 6) //behandlung impulszahler D2,D3,D21,D20,D19,D18 
 {byte offset =23;
 if (i ==2) {offset = 4;} if (i ==3) {offset = 6;}
 zaehlwert = pulsecounter[offset - i ] / pulsedivider[offset - i ];
 if ((pulsedivider[offset -i] > 0) && ((zaehlwert > (last_zaehlwert[offset - i]+ delta_counter) || complete_loop))) 
 {I = String(offset -i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "imp" + I + "').State(" + zaehlwert + ")";
 set_sysvar();
 last_zaehlwert[offset - i] = zaehlwert;
 } 
 } 
//**************************************************************************************************
//behandlung Luxmeter BH1750 an SCL pin21 und SDA pin 20
// for normal sensor resolution (1 lx resolution, 0-65535 lx, 120ms, no PowerDown) use: sensor.begin(RESOLUTION_NORMAL, false); 
 if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1) && (iomodus_lux ==1))
 {if(!sensor.begin()) { Serial.println("Sensor not present"); }
 float lux = sensor.readLightLevel(); delay(1000);
 Serial.print("Helligkeit/lux: "); Serial.print(lux); Serial.println();
 if ((lux > (last_lux_value + delta_lux)) || (lux < (last_lux_value - delta_lux)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "lux" + "').State(" + lux + ")";
 set_sysvar();
 last_lux_value = lux;
 } 
 } 
//**************************************************************************************************
//behandlung barometer BMP180 an SCL pin21 und SDA pin 20
 if ((iomodus_D[20] == 8) && (iomodus_D[21] == 8)&& (iomodus_baro ==1))
 {if (pressure.begin()) {status = pressure.startTemperature();}
 if (status) {delay(status); status = pressure.getTemperature(T);} //messung T
 if (status) {status = pressure.startPressure(3);} // //messung P mit resolution 0 bis 3
 if (status) {delay(status); status = pressure.getPressure(P,T);}
 if (status) {p0 = pressure.sealevel(P,ALTITUDE);} // umrechnung auf N.N.
 Serial.print("Hoehe/m: "); Serial.print(ALTITUDE); Serial.print(" Temperatur/C: "); Serial.print(T); Serial.print(" Normaldruck /mb: "); Serial.println(p0); 
 if ((p0 > (last_baro_value + delta_baro)) || (p0 < (last_baro_value - delta_baro)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baro" + "').State(" + p0 + ")";
 set_sysvar();
 last_baro_value = p0;
 }
 if ((T > (last_baroT_value + delta_baroT)) || (p0 < (last_baroT_value - delta_baroT)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baroT" + "').State(" + T + ")";
 set_sysvar();
 last_baroT_value = T;
 }
 }
 }
//**************************************************************************************************
 if (iomodus_D[3] == 7) //behandlung 433Mhz-rx 
 {if (mySwitch.available()) 
 {int value = mySwitch.getReceivedValue();
 if (value == 0) {client.print("Unknown encoding");} 
 else {Serial.print("Pin D3 received : ");
 Serial.print (mySwitch.getReceivedValue() );
 Serial.print (" / ");
 Serial.print( mySwitch.getReceivedBitlength() );
 Serial.print("bit Protocol: ");
 Serial.println( mySwitch.getReceivedProtocol() + " \n\r" );
 }
 mySwitch.resetAvailable();
 }
 } 
//**************************************************************************************************
 
datenempfang(); 
} 
 
//##############################################################
//##############################################################
void datenempfang() //Unterprogramm datenempfang: daten von ccu an homeduino
{command = ""; 
 
 EthernetClient client = server.available();   //mit W5100
 //SFE_CC3000_Client client = SFE_CC3000_Client(wifi);   //mit CC3000
 
 if (client) 
 { // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected())
 {if (client.available()) 
 {char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; // beginn der Befehlssequenz 
 if (reading) 
 {//read char by char HTTP request
 if (command.length() < 100) 
 { //store characters to string
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') {currentLineIsBlank = true;} 
 else if (c != '\r') { currentLineIsBlank = false;}
 } 
 } 
 client.println(command);
 delay(1); 
 client.stop();
//**************************************************************************************************
 if (command.length() > 2) //behandlung Datenempfang: port auf 0 / 1 setzen 
 {Serial.println(command); //empfangenen befehl ausgeben
 client.print(command); 
 //befehl dekodieren 
 int colonPosition = command.indexOf(':');
 sub_command = command.substring(2,colonPosition); //portpin erkennen
 Serial.print("D" + sub_command + " :");
 port_pin = sub_command.toInt();
 command = command.substring((colonPosition+1)); //Rest-command bilden
 if ((iomodus_D[port_pin] == 2) && (command == "0")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, LOW); Serial.println(command);}
 if ((iomodus_D[port_pin] == 2) && (command == "1")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, HIGH); Serial.println(command);}
 if ((iomodus_D[port_pin] == 7) && (port_pin ==4)) 
 { rf_send(command); Serial.println(command);} 
 if ((iomodus_D[port_pin] == 5) && (port_pin ==9)) 
 { ir_send(command); Serial.println(command);} 
 
 }
 
 } 
} 
//##############################################################
void set_sysvar() // subroutine HTTP request absetzen:
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 if (client.connect(ccu, 8181)) 
 {Serial.println(befehl);
 client.println(befehl);
 client.println();
 client.stop();
 }
}
//##############################################################
void rf_send(String rf_command) // subroutine rf telegramm senden
{
 }
//##############################################################
void ir_send(String ir_command) // subroutine ir telegramm senden
{
 }
 
//##############################################################
//hier sind die interrupt-service-routinen fuer die impulszaehler
void ISR_0() //Interrupt an D2
{pulsecounter[0]++;}
 
void ISR_1() //Interrupt an D3
{pulsecounter[1]++;}
 
 
void ISR_2() //Interrupt an D21
{pulsecounter[2]++;}
 
void ISR_3() //Interrupt an D20
{pulsecounter[3]++;}
 
void ISR_4() //Interrupt an D19
{pulsecounter[4]++;}
 
void ISR_5() //Interrupt an D18 
{pulsecounter[5]++;}

 

 

Und hier die Wifi-Version :

/*Ver.: "homeduino30_03_wifi.ino / Stand: 2015.05.07 / Verfasser: Eugen Stall
 
Wifi-Version mit CC3000-Breakout
 
hier ist immer die aktuelle Version:
Home
das folgende homeduino-programm sendet messdaten zur ccu (homeduino als webclient) ...
und empfängt ausgabedaten für die homeduino-outputs (homeduino als webserver)
____________________ ___________________
 | | 
 server port 8181 |<------------<| client 
 | | 
 CCU | | Homeduino 
 | | 
 client |>------------>| server port 80
____________________| |___________________
 
erprobt fuer Arduino Mega 2560 mit Arduino 1.6.3
diese Software steuert referenziert die signale an den Arduino-pins mit entsprechenden systemvariablen in der Homematic ccu
mit dem Befehl: http://<ip der ccu>:8181/GET /xy.exe?antwort=dom.GetObject('<systemvariable>').State(" + value + ")"
/Quellen:Arduino website plus http://arduino.cc/en/Tutorial/WebClient und ...
 http://tushev.org/articles/arduino/item/52-how-it-works-ds18b20-and-arduino und ...
*/
 
#include <SPI.h>
#include <Wire.h> 
#include <OneWire.h> //für Temperatursensoren DS18B20 http://www.hacktronics.com/code/OneWire.zip
#include <NewPing.h> //für Ultraschallsensoren SR04 https://arduino-new-ping.googlecode.com/files/NewPing_v1.5.zip
#include "DHT.h" //für Temperatursensoren SHT22 https://github.com/adafruit/DHT-sensor-library/archive/master.zip
#include <AS_BH1750.h> //für I2C-Luxmeter https://github.com/hexenmeister/AS_BH1750/archive/master.zip
#include <SFE_BMP180.h>//für I2C-Barometer https://github.com/sparkfun/BMP180_Breakout/archive/master.zip
#include <RCSwitch.h> // läuft noch nicht!
//#include <IRremote.h> // läuft noch nicht!
 
//Kommunikationsweg  festlegen
#define com_mode 1  //"0"  W5100, "1" CC300 Breakout                                     <<user-eingabe<< 
 
 
//der folgende Bereich ist die Initialisierung des CC3000 Wifi auf dem IO-Shield-Plus 
#include <SFE_CC3000.h>// fuer cc3000 wifi http://github.com/sparkfun/SFE_CC3000_Library/archive/master.zip
#include <SFE_CC3000_Client.h>
// Pins
#define CC3000_INT 18 // int-Pin mit Wifi Shield ist D3, mit breakout auf IO-Shield-Plus ist D18
#define CC3000_EN 46 // en-Pin mit Wifi Shield ist D5, mit breakout auf IO-Shield-Plus ist D46
#define CC3000_CS 53 // cs-Pin mit Wifi Shield ist D10, mit breakout auf IO-Shield-Plus ist D53
SFE_CC3000 wifi = SFE_CC3000(CC3000_INT, CC3000_EN, CC3000_CS);
SFE_CC3000_Client client = SFE_CC3000_Client(wifi);
// Constants
char ap_ssid[] = "ssid"; // SSID Name des WLAN in Anführungszeichen                       <<user-eingabe<< 
char ap_password[] = "passwort"; // Passwort des WLAN in Anführungszeichen                <<user-eingabe<< 
unsigned int ap_security = WLAN_SEC_WPA2; // Security of network
unsigned int timeout = 30000; // Milliseconds
//char server[] = "192,168,178,50"; // Remote host site
 
/*
//der folgende Bereich ist die Initialisierung des LAN bei Verwendung des LAN-Shields
#include <Ethernet.h> 
EthernetClient client;
EthernetServer server(80);
*/
 
byte ccu[] = { 192, 168, 178, 50 }; //das ist die IP der CCU <<user-eingabe<< 
byte mac[] = { 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC }; //bei mehreren homeduinos ändern!!    <<user-eingabe<<
byte homeduino[] = { 192, 168, 178, 52 }; //das ist feste IP dieses Homeduino,             <<user-eingabe<< 
 //wenn DHCP versagt
String homeduino_nummer = "xyz"; //indiv. Bezeichnung dieses homeduino                     <<user-eingabe<< 
 //das ist bel. String ohne 
 //sonderzeichen und öäüß... 
String hm_systemvariable = "homeduino_" + homeduino_nummer +"_";
 
 
//Input-Kennung: hier wird die Funktion aller verwendbaren IO´s mit einer Kennziffer festgelegt 
//dabei haben alle IO´s die Standardfunktionen plus spez. Sonderfunktionen
byte iomodus_D[70] = 
{ 0, //D0 : '0' = andere Nutzg; 
 0, //D1 : '0' = andere Nutzg; 
 
//Standardfkt:'0' =andere Nutzg; '1' =dig_input; '2' =dig_output; '3' =1wire '4' =DHTxx; '5' =U_Schall 
 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield20 +++++++++++++++++ 
 2, //D2 : Standardfkt; '5' = IR_Rx?? '6' =ImpCount;                        <<user-eingabe für IO-Shield20<< 
 2, //D3 : Standardfkt; '7' = 433_Rx?? '6' =ImpCount;                       <<user-eingabe für IO-Shield20<< 
 0, //D4 : Standardfkt; '7' = 433_Tx?? '0' =W5100/SS-Pin                    <<user-eingabe für IO-Shield20<< 
 2, //D5 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D6 : Standardfkt; '9' = buzzer                                        <<user-eingabe für IO-Shield20<< 
 0, //D7 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 0, //D8 : Standardfkt;                                                     <<user-eingabe für IO-Shield20<< 
 1, //D9 : Standardfkt; '5' = IR_Tx??                                       <<user-eingabe für IO-Shield20<< 
 0, //D10 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D11 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D12 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
 0, //D13 : '0' =andere Nutzg;'0' =W5100 '2' = digital in; 
//++++++++++++++ hier folgt die Festlegung der digitalen Pinfunktionen für das IO-Shield_Plus ++++++++++++++ 
 3, //D14 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D15 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D16 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 2, //D17 : Standardfkt; '7' =ESP8266;                                  <user-eingabe für IO-Shield-Plus20<< 
 0, //D18 : Standardfkt; '6' =ImpCount; '0' =CC3000                     <user-eingabe für IO-Shield-Plus20<< 
 3, //D19 : Standardfkt; '6' =ImpCount;                                 <user-eingabe für IO-Shield-Plus20<< 
 1, //D20 : Standardfkt; '6' =ImpCount; '8' =I2C;SDA                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D21 : Standardfkt; '6' =ImpCount; '8' =I2C;SCL                    <user-eingabe für IO-Shield-Plus20<< 
 1, //D22 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D23 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D24 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D25 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D26 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D27 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D28 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 1, //D29 : Standardfkt;                                                <user-eingabe für IO-Shield-Plus20<< 
 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 
//hier wird die Funktion der Eingänge A0 bis A15 festgelegt
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield20 ++++++++++++++++++
 3, //D54 A0 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 2, //D55 A1 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D56 A2 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D57 A3 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D58 A4 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 3, //D59 A5 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 0, //D60 A6 : "0" =andere Nutzg; 
 0, //D61 A7 : "0" =andere Nutzg; 
//++++++++++++++ hier folgt die Festlegung der analogen Pinfunktionen für das IO-Shield_Plus +++++++++++++++
 1, //D62 A8 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D63 A9 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
 1, //D64 A10 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D65 A11 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D66 A12 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D67 A13 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1, //D68 A14 : Standardfkt; '10' =anal_Inp '11' =NTC                  <<user-eingabe für IO-Shield-Plus20<< 
 1 //D69 A15 : Standardfkt; '10' =anal_Inp '11' =NTC                   <<user-eingabe für IO-Shield-Plus20<< 
}; 
//hier werden Sensoren am I2C-Eingang aktiviert
byte iomodus_baro = 0; //'0' =nc; '1' =BMP180, dann auch oben I2C setzen <<user-eingabe für IO-Shield-Plus<<
byte iomodus_lux = 0; //'0' =nc; '1' =BH1750, dann auch oben I2C setzen  <<user-eingabe für IO-Shield-Plus<<
 
//hier werden die Kennwerte fuer die Impulszaehler festgelegt
unsigned zaehlwert;
unsigned last_zaehlwert[6] = {0,0,0,0,0,0};
volatile unsigned long pulsecounter[6] = 
{ 0, //Zaehlerstand fuer D2 -Impulseingang bei Reset                        <<user-eingabe für IO-Shield20<<
 0, //Zaehlerstand fuer D3 -Impulseingang bei Reset                         <<user-eingabe für IO-Shield20<<
 4711, //Zaehlerstand fuer D21-Impulseingang bei Reset                   <<user-eingabe für IO-Shield-Plus<< 
 3, //Zaehlerstand fuer D20-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 4, //Zaehlerstand fuer D19-Impulseingang bei Reset                      <<user-eingabe für IO-Shield-Plus<< 
 5 //Zaehlerstand fuer D18-Impulseingang bei Reset                       <<user-eingabe für IO-Shield-Plus<< 
}; 
//hier wird der Teilerfaktor für die Impulszaehler festgelegt
int pulsedivider[6] = 
{ 1, //Teilerfaktor D2 :                                                    <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D3 :                                                     <<user-eingabe für IO-Shield20<<
 1, //Teilerfaktor D21 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D20 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D19 :                                                 <<user-eingabe für IO-Shield-Plus<<
 1, //Teilerfaktor D18 :                                                 <<user-eingabe für IO-Shield-Plus<<
}; 
 
//hier werden die zuletzt gesendeten sytemvariablen gespeichert
boolean last_digital_value_D[70];
float last_value_D[70];
float last_IR_value;
float last_RF_value;
float last_lux_value;
double last_baro_value;
double last_baroT_value;
 
boolean complete_loop =1; // wenn 1, dann einmal komplett durchlaufen
 
String header = String(20);
String befehl;
String sub_command = String(20);
String parameter = String(20);
int param;
int port_pin;
boolean port_data;
 
boolean value;
String I;
int analogwert;
 
float tempNTC;
float B_wert = 3950; //aus dem Datenblatt des NTC //<<user-eingabe<<
float Tn = 298.15; //25°Celsius in °Kelvin 
float Rv = 10000; //Vorwiderstand
float Rn = 10000; //NTC-Widerstand bei 25°C
float Rt ; 
float temp_tur;
float humidity;
 
float delta_onewire = 0.2; //Deltas für Sendeauslösung 
float delta_DHT = 0.2; //in °C 
float delta_us = 3.0; // in cm
float delta_analog = 2.0; // in inkrement
float delta_ntc = 0.5; //in °C
float delta_lux = 20; //in lux
float delta_counter = 5; //in counter inkrement
double delta_baro = 0.2; //in mB
double delta_baroT = 0.5; //in °C
 
long duration, cm; //variable für Ultraschallsensor
 
unsigned long next_full_loop = 0;
unsigned long delta_time = 3600000; // jede Stunde werden alle Inputs aktualisiert
unsigned long delta_tx = 500; //in ms, minimaler Abstand der Telegramme an die CCU
unsigned long next_tx = 0;
unsigned long time_DHT = 0; 
 
int rf_key;
String rfkey;
RCSwitch mySwitch = RCSwitch();
 
//************************************************************************************************** 
AS_BH1750 sensor; //Initialize BH1750 Luxmeter library
#define ALTITUDE 299.0 // eigene seehoehe in metern              <<user-eingabe für IO-Shield-Plus<<
SFE_BMP180 pressure;
char status;
double T,P,p0;
 
boolean reading = false;
String command = String(200);
 
//************************************************************************************************** 
//************************************************************************************************** 
void setup() 
{Serial.begin(115200); 
 
//einrichtung der interrupts fuer impulszahler D2,D3,D18,D19,D20,D21
if ((pulsedivider[0] > 0) && (iomodus_D[2] == 6)) {pinMode(2, INPUT_PULLUP); attachInterrupt(0, ISR_0, FALLING);}
if ((pulsedivider[1] > 0) && (iomodus_D[3] == 6)) {pinMode(3, INPUT_PULLUP); attachInterrupt(1, ISR_1, FALLING);} 
if ((pulsedivider[2] > 0) && (iomodus_D[21] == 6)) {pinMode(21, INPUT_PULLUP); attachInterrupt(2, ISR_2, FALLING);}
if ((pulsedivider[3] > 0) && (iomodus_D[20] == 6)) {pinMode(20, INPUT_PULLUP); attachInterrupt(3, ISR_3, FALLING);}
if ((pulsedivider[4] > 0) && (iomodus_D[19] == 6)) {pinMode(19, INPUT_PULLUP); attachInterrupt(4, ISR_4, FALLING);}
#if com_mode == 0 
if ((pulsedivider[5] > 0) && (iomodus_D[18] == 6)) {pinMode(18, INPUT_PULLUP); attachInterrupt(5, ISR_5, FALLING);}
#endif 
 
/*
//+++++++ hier folgt die LAN Initialisierung
 if (Ethernet.begin(mac) == 0) // start the Ethernet connection:
 {Serial.println("Failed to configure Ethernet using DHCP"); Ethernet.begin(mac, homeduino);}
 delay(1000);// give the Ethernet shield a second to initialize:
 Serial.println("connecting..."); // if you get a connection, report back via serial:
 if (client.connect(ccu, 8181)) {}
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop(); 
 char myIpString[24]; //IP auslesen
 IPAddress myIp = Ethernet.localIP();
 sprintf(myIpString, "%d.%d.%d.%d", myIp[0], myIp[1], myIp[2], myIp[3]); 
 I = myIpString;
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "IP" + "').State('" + I + "')";
 set_sysvar(); 
 server.begin();
*/ 
 
//+++++++ hier folgt die CC3000 Initialisierung
 ConnectionInfo connection_info;
 int i;
 byte IP_ADDR_LEN =4;
 Serial.println("SparkFun CC3000 - WebClient");
 if ( wifi.init() ) {Serial.println("init complete");} 
 else {Serial.println("problem with init!");}
 // Connect using DHCP
 if(!wifi.connect(ap_ssid, ap_security, ap_password, timeout)) {Serial.println("no connection to AP");}
 // Gather connection details and print IP address
 if ( !wifi.getConnectionInfo(connection_info) ) {Serial.println("no connection details");} 
 else {for (i = 0; i < IP_ADDR_LEN; i++) 
 {Serial.print(connection_info.ip_address[i]);
 if ( i < IP_ADDR_LEN - 1 ) {Serial.print(".");}
 }
 Serial.println(" ist aktuelle IP-Adresse"); 
 }
 
 if (client.connect(ccu, 8181)) {} // Make a TCP connection to remote host
 else {Serial.println("connection failed");} // if you didn't get a connection to the server:
 client.stop();
 
 
}
//************************************************************************************************** 
//************************************************************************************************** 
void loop() 
{complete_loop = 0;
 if (millis() > next_full_loop) //mindestens jede Stunde eine komplette Aktualisierung
 {complete_loop = 1; next_full_loop = millis() + delta_time; 
 if (next_full_loop < millis()) {complete_loop = 0;} //wichtig wegen Zahlensprung von millis() alle 50 Tage
 } 
 for (int i = 2; i < 70; i++) //behandlung aller Ports D2 bis D69 
 {if (i== 30) {i = 54;} // unbenutzte pins überspringen
 
 //************************************************************************************************** 
 if (iomodus_D[i] == 1) //behandlung digitaleingänge 
 {pinMode(i, INPUT_PULLUP); 
 digitalWrite(i, HIGH);
 value =digitalRead(i);
 if ((!value == last_digital_value_D[i]) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + value + ")";
 set_sysvar();
 last_digital_value_D[i] = value;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 3) //behandlung onewire 
 {pinMode(i, INPUT_PULLUP);
 digitalWrite(i, HIGH);
 OneWire ds(i); 
 #define DS18S20_ID 0x10
 #define DS18B20_ID 0x28 
 
 byte present = 0;
 byte data[12];
 byte addr[8];
 temp_tur = 1000.0;
 if (!ds.search(addr)) { ds.reset_search(); temp_tur = -1000.0; } //find a device
 if ((OneWire::crc8( addr, 7) != addr[7]) && (temp_tur > -1000.0)) {temp_tur = -1000.0; }
 if ((addr[0] != DS18S20_ID && addr[0] != DS18B20_ID)&& (temp_tur > -1000.0)) {temp_tur = -1000.0;}
 if (temp_tur > -1000.0) 
 {ds.reset(); 
 ds.select(addr); 
 ds.write(0x44, 1); // Start conversion
 delay(850); // Wait some time...
 present = ds.reset(); 
 ds.select(addr);
 ds.write(0xBE); // Issue Read scratchpad command
 for ( int k = 0; k < 9; k++) { data[k] = ds.read(); } // Receive 9 bytes
 temp_tur = ( (data[1] << 8) + data[0] )*0.0625; // Calculate temperature value 18B20
 //temp_tur = ( (data[1] << 8) + data[0] )*0.5 // Calculate temperature value 18S20
 }
 if ((temp_tur > (last_value_D[i] + delta_onewire)) 
 || (temp_tur < (last_value_D[i] - delta_onewire)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 }
//************************************************************************************************** 
 if (iomodus_D[i] == 4) //behandlung DHT temperatur- und feuchtesensoren
 {DHT dht(i, DHT22); //je nach verwendetem sensor "DHT11" oder "DHT22" (AM2302) oder "DHT 21" (AM2301)
 dht.begin();
 //delay(2000); // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
 time_DHT = millis() +2000;
 while (millis() < time_DHT) {datenempfang();} //wahrend der 2s wartezeit, daten empfangen
 humidity = dht.readHumidity(); // Read temperature as Celsius
 temp_tur = dht.readTemperature(); 
 if (isnan(humidity) || isnan(temp_tur) ) // Check if any reads failed and 
 { //Serial.println("Failed to read from DHT sensor!");
 temp_tur = -1000;
 }
 if ((temp_tur > (last_value_D[i] + delta_DHT)) || (temp_tur < (last_value_D[i] - delta_DHT)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + temp_tur + ")";
 set_sysvar();
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "1').State(" + humidity + ")";
 set_sysvar();
 last_value_D[i] = temp_tur;
 } 
 } 
 //************************************************************************************************** 
 if (iomodus_D[i] == 5) //behandlung ultraschallsensoren achtung: zu beachten 
 //bei verwendung der US-Sensoren beim IO-Shield-Plus sind die 150-Ohm-Schutzwiderstände 
 //zu überbrücken , entsprechend beim IO-Shield20 der digitale Jumper 4-5 zu setzen!! 
 {NewPing sonar(i, i, 200); // NewPing setup of pin and maximum distance.
 unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
 int cm = uS / US_ROUNDTRIP_CM;
 if ((cm > (last_value_D[i] + delta_us)) || (cm < (last_value_D[i] - delta_us)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + cm + ")";
 set_sysvar();
 last_value_D[i] = cm;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 10) //behandlung analogeingänge 
 {analogwert =analogRead(i); 
 if ((analogwert > (last_value_D[i] + delta_analog)) || (analogwert < (last_value_D[i] - delta_analog)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + analogwert + ")";
 set_sysvar();
 last_value_D[i] = analogwert;
 } 
 } 
//**************************************************************************************************
 if (iomodus_D[i] == 11) //behandlung NTC 
 {Rt = Rv/((1024.0/analogRead(i))- 1.0);
 tempNTC = (B_wert * Tn / ( B_wert + (Tn * log(Rt/Rn)))) -Tn +25.0 ;
 if ((tempNTC > (last_value_D[70] + delta_ntc)) || (tempNTC < (last_value_D[70] - delta_ntc)) || complete_loop) 
 {I = String(i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "D" + I + "').State(" + tempNTC + ")";
 set_sysvar();
 last_value_D[i] = tempNTC;
 } 
 } 
//************************************************************************************************** 
 if (iomodus_D[i] == 6) //behandlung impulszahler D2,D3,D21,D20,D19,D18 
 {byte offset =23;
 if (i ==2) {offset = 4;} if (i ==3) {offset = 6;}
 zaehlwert = pulsecounter[offset - i ] / pulsedivider[offset - i ];
 if ((pulsedivider[offset -i] > 0) && ((zaehlwert > (last_zaehlwert[offset - i]+ delta_counter) || complete_loop))) 
 {I = String(offset -i);
 befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "imp" + I + "').State(" + zaehlwert + ")";
 set_sysvar();
 last_zaehlwert[offset - i] = zaehlwert;
 } 
 } 
//**************************************************************************************************
//behandlung Luxmeter BH1750 an SCL pin21 und SDA pin 20
// for normal sensor resolution (1 lx resolution, 0-65535 lx, 120ms, no PowerDown) use: sensor.begin(RESOLUTION_NORMAL, false); 
 if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1) && (iomodus_lux ==1))
 {if(!sensor.begin()) { Serial.println("Sensor not present"); }
 float lux = sensor.readLightLevel(); delay(1000);
 Serial.print("Helligkeit/lux: "); Serial.print(lux); Serial.println();
 if ((lux > (last_lux_value + delta_lux)) || (lux < (last_lux_value - delta_lux)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "lux" + "').State(" + lux + ")";
 set_sysvar();
 last_lux_value = lux;
 } 
 } 
//**************************************************************************************************
//behandlung barometer BMP180 an SCL pin21 und SDA pin 20
 if ((iomodus_D[20] == 8) && (iomodus_D[21] == 8)&& (iomodus_baro ==1))
 {if (pressure.begin()) {status = pressure.startTemperature();}
 if (status) {delay(status); status = pressure.getTemperature(T);} //messung T
 if (status) {status = pressure.startPressure(3);} // //messung P mit resolution 0 bis 3
 if (status) {delay(status); status = pressure.getPressure(P,T);}
 if (status) {p0 = pressure.sealevel(P,ALTITUDE);} // umrechnung auf N.N.
 Serial.print("Hoehe/m: "); Serial.print(ALTITUDE); Serial.print(" Temperatur/C: "); Serial.print(T); Serial.print(" Normaldruck /mb: "); Serial.println(p0); 
 if ((p0 > (last_baro_value + delta_baro)) || (p0 < (last_baro_value - delta_baro)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baro" + "').State(" + p0 + ")";
 set_sysvar();
 last_baro_value = p0;
 }
 if ((T > (last_baroT_value + delta_baroT)) || (p0 < (last_baroT_value - delta_baroT)) || complete_loop) 
 {befehl = "GET /xy.exe?antwort=dom.GetObject('" + hm_systemvariable + "baroT" + "').State(" + T + ")";
 set_sysvar();
 last_baroT_value = T;
 }
 }
 }
//**************************************************************************************************
 if (iomodus_D[3] == 7) //behandlung 433Mhz-rx 
 {if (mySwitch.available()) 
 {int value = mySwitch.getReceivedValue();
 if (value == 0) {client.print("Unknown encoding");} 
 else {Serial.print("Pin D3 received : ");
 Serial.print (mySwitch.getReceivedValue() );
 Serial.print (" / ");
 Serial.print( mySwitch.getReceivedBitlength() );
 Serial.print("bit Protocol: ");
 Serial.println( mySwitch.getReceivedProtocol() + " \n\r" );
 }
 mySwitch.resetAvailable();
 }
 } 
//**************************************************************************************************
 
datenempfang(); 
} 
 
//##############################################################
//##############################################################
void datenempfang() //Unterprogramm datenempfang: daten von ccu an homeduino
{command = ""; 
 
 //EthernetClient client = server.available();   //mit W5100
 SFE_CC3000_Client client = SFE_CC3000_Client(wifi);   //mit CC3000
 
 if (client) 
 { // an http request ends with a blank line
 boolean currentLineIsBlank = true;
 while (client.connected())
 {if (client.available()) 
 {char c = client.read();
 if (reading && c == ' ') reading =false;
 if (c == '?') reading = true; // beginn der Befehlssequenz 
 if (reading) 
 {//read char by char HTTP request
 if (command.length() < 100) 
 { //store characters to string
 command = command + c;
 }
 } 
 if (c == '\n' && currentLineIsBlank) break;
 if (c == '\n') {currentLineIsBlank = true;} 
 else if (c != '\r') { currentLineIsBlank = false;}
 } 
 } 
 client.println(command);
 delay(1); 
 client.stop();
//**************************************************************************************************
 if (command.length() > 2) //behandlung Datenempfang: port auf 0 / 1 setzen 
 {Serial.println(command); //empfangenen befehl ausgeben
 client.print(command); 
 //befehl dekodieren 
 int colonPosition = command.indexOf(':');
 sub_command = command.substring(2,colonPosition); //portpin erkennen
 Serial.print("D" + sub_command + " :");
 port_pin = sub_command.toInt();
 command = command.substring((colonPosition+1)); //Rest-command bilden
 if ((iomodus_D[port_pin] == 2) && (command == "0")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, LOW); Serial.println(command);}
 if ((iomodus_D[port_pin] == 2) && (command == "1")) 
 {pinMode(port_pin, OUTPUT); digitalWrite(port_pin, HIGH); Serial.println(command);}
 if ((iomodus_D[port_pin] == 7) && (port_pin ==4)) 
 { rf_send(command); Serial.println(command);} 
 if ((iomodus_D[port_pin] == 5) && (port_pin ==9)) 
 { ir_send(command); Serial.println(command);} 
 
 }
 
 } 
} 
//##############################################################
void set_sysvar() // subroutine HTTP request absetzen:
{ //while (millis() < next_tx) {} //warten bis time > next_tx oder timeout
 next_tx = millis() +delta_tx;
 if (client.connect(ccu, 8181)) 
 {Serial.println(befehl);
 client.println(befehl);
 client.println();
 client.stop();
 }
}
//##############################################################
void rf_send(String rf_command) // subroutine rf telegramm senden
{
 }
//##############################################################
void ir_send(String ir_command) // subroutine ir telegramm senden
{
 }
 
//##############################################################
//hier sind die interrupt-service-routinen fuer die impulszaehler
void ISR_0() //Interrupt an D2
{pulsecounter[0]++;}
 
void ISR_1() //Interrupt an D3
{pulsecounter[1]++;}
 
 
void ISR_2() //Interrupt an D21
{pulsecounter[2]++;}
 
void ISR_3() //Interrupt an D20
{pulsecounter[3]++;}
 
void ISR_4() //Interrupt an D19
{pulsecounter[4]++;}
 
void ISR_5() //Interrupt an D18 
{pulsecounter[5]++;}

 

 

Damit ist es jetzt möglich, auch Daten von der CCU  an den Homeduino zu senden, um beispielsweise einen beliebigen Port zu setzen. Der Weg zurück erfolgt automatisch, indem bei Veränderung der Sensorsignale die korrespondierenden Systemvariablen gesetzt werden.

Eine detaillierte Anleitung und Beschreibung erfolgt später. Wichtig: Gegenüber den bisherigen Versionen wurde aus verschiedenen Gründen die Portbezeichnung und die Port-Funktionskennung geändert. Mein aktueller Homeduino heißt homeduino_xyz. Wichtig bei der richtigen Benennung der verwendeten Systemvariablen !

 

Ein Beispiel für ein HM-Skript, mit dem man einen Ausgang auf dem Homeduino schalten kann ist hier:

 

var send_data = "homeduino_xyz/D9:0"; !##########################
!beim  "homeduino_xyz"  Pin D9 auf 0 / 1 setzen #####  Stand 12.04.2015  stall.biz  
integer word_position = send_data.Find("/");
var h_duino = send_data.Substr(0, word_position) + "_IP";
h_duino = dom.GetObject(h_duino).State();
send_data = "http://" + h_duino + "/?" + send_data.Substr(word_position+1, 30);
string stdout;
string stderr;
 
!verwendung system.Exec
!system.Exec("wget -q -O - '"#send_data#"'", &stdout, &stderr);
 
!verwendung CUxD
dom.GetObject("CUxD.CUX2801001:1.CMD_SETS").State("wget -q -O - '"#send_data#"'");
dom.GetObject("CUxD.CUX2801001:1.CMD_QUERY_RET").State(1);
stdout = dom.GetObject("CUxD.CUX2801001:1.CMD_RETS").State();
 
!fehler behandlung fehlt noch
boolean fehler = 1;
if (stdout.Length() >0) {fehler =0;} 
dom.GetObject("CUxD.CUX2801001:1.SYSLOG").State("eine Statusmeldung");

 

Wichtig:
Die neue Homeduino 3.0 Software ist sowohl für das
>>> Basis-Shield  IO-Shield20 als auch für das …
>>> Ergänzungs-Shield IO-Shield-Plus geeignet!

Rückmeldungen und Erfahrungen sind willkommen.

Haftungs- und Sicherheitshinweise

Beim Nachbau müssen natürlich alle wichtigen einschlägigen Sicherheitsvorschriften für den Umgang mit gefährlichen Spannungen  eingehalten werden. Fundierte theoretische und praktische Fachkenntnisse der Elektrotechnik und für den Umgang mit gefährlichen Spannungen sind unverzichtbar!!

Durch eine unsachgemäße Installation gefährden Sie ihr Leben und das Leben ihrer Mitmenschen! Darüberhinaus riskieren Sie erhebliche Sachschäden , welche durch Brand etc. hervorgerufen werden können ! Für alle Personen- und Sachschäden durch falsche Installation etc. ist nicht der Hersteller sondern nur der Betreiber verantwortlich.

Ich verweise hier unbedingt auf  die  „Sicherheitshinweise und Haftungsausschluss„-Seite dieses Blogs.

 

 

 

Fähigkeiten

Gepostet am

13. April 2015

14 Kommentare

  1. Hallo,

    welche Jumperstellung muss auf dem I/O Shield 2.0 gestellt werden damit man Ausgänge (D.. oder A..) schalten kann ich habe nun schon alles probiert und bekomme es nicht zum laufen…

    Danke, Viele Grüße

  2. Hallo Admin,

    nochmal Danke für die Antwort. Ich kann bestätigen, dass das Skript funktioniert. Falls jemand auf das gleiche Problem wie ich kommt:

    Erst mein Setup:
    1. Arduino_001_D9 als Systemvariable – im Homeduino als Eingang
    2. Im Homeduino D20 als Ausgang.

    Das Problem:
    Mit dem obigen Skript wurde D20 nicht geschaltet, wenn der Zustand von D9 geändert wurde.

    Die Lösung:
    Das Programm in der Homematic war fehlerhaft. Ich hatte den Eingang D9 auf „nur prüfen“ abgefragt. Es funktioniert aber nur mit „bei Änderung“.

    Vielleicht hilft das anderen auch. Ansonsten bitte diesen Post wieder entfernen – danke!

    Viele Grüße
    Sam

  3. Hallo,
    eigentlich muß für die Ausführung des Skripts auf der CCU nur CuxD installiert sein. Für die alternative Lösung mit system.exec müssen die entsprechenden auskommentierten Zeilen wieder aktiviert werden.

  4. Hallo,

    vielen Dank für das tolle Projekt.
    Mit dem Skript bekomme ich auf der homematic (neue Version) keinen Ausgang geschaltet. Ich habe das obige Skript 1:1 probiert, jedoch kommt von der ccu am arduino nichts an. Umgekehrt sehe ich in der homematic die Zustände der Systemvariablen. Muss man beim Skript in der Homematic noch etwas besonderes beachten, z.B. $var setzen oder ähnliches?

    Danke und Grüße
    Sam

  5. Danke für den Hinweis. Ist korrigiert!

  6. Der BMP180 funktioniert mit obigem Sketch nur, wenn anstatt „if ((iomodus_D[20] == 1) && (iomodus_D[21] == 1)&& (iomodus_baro ==1))“ der Code geändert wird zu „if ((iomodus_D[20] == 8) && (iomodus_D[21] == 8)&& (iomodus_baro ==1))“.

  7. Hallo Wolfgang,
    Danke für den Hinweis. Ist schon korrigiert.
    Grüße

    Eugen

  8. Hallo Eugen,
    damit alle Eingänge , also auch D69 genutzt werden können
    muss im Programm die folgende Zeile geändert werden:

    for (int i = 2; i < 70; i++) //behandlung aller Ports D2 bis D69

    also nicht 69 sondern 70

    Gruss
    Wolfgang

  9. ggf mal aus der 115200 eine 9600 machen…?

  10. Das CC3000 kann mit den richtigen Libraries genauso angesprochen werden wie das Ethernet Shield W5100. Lediglich ein zusätzlicher Interrupt ist notwendig. Beim Nano wäre dafür nur D2 oder D3 geeignet. Das ust der Grund warum ich zur Zeit das CC3000 Modul bevorzuge. Der ESP8266 liegt hier, aber die Implementierung ist schwieriger.
    Beim von mir geplanten „Wohnzimmersensor“ verwende ich auch den Nano in Verbindung mit dem Wifi CC3000. Funktioniert ganz gut, aber der Nano ist dann leistungsmäßig ziemlich ausgelastet.
    Schau mal hier: http://homematic-forum.de/forum/viewtopic.php?f=27&t=21815&hilit=wohnzimmersensor#p183408

  11. …ich nutze leider nicht das IO Board, sondern mangels Platz einen Arduino Nano. Pullup ist dran und Wifi im Sketch aktiviert. Ethernet ist auskommentiert. Der DS18B20 hängt an D6 und ich kann auch problemlos die richtigen DS18B20 Werte an die CCU(1) übermitteln. Nur im Standard Serial Monitor wird die Temperatur als „)“ angezeigt. Übertragungsrate ist 115200 Baud. Werde dem am WE mal auf den Grund gehen.

    Unklar ist mir, ob die Funktion „void datenempfang()“ auch für CC3000 Wifi Module funktioniert. Die Befehle („EthernetClient client = server.available()“…) deuten stark auf das Ethernet-Shield hin, oder ist der Code universell auch für WIFI-Shields geeignet? Konkret möchte ich aus der CCU heraus ein Relais an D9 des Arduino schalten.

  12. … pullup Widerstand eingeschaltet ? Welchen Port/Pin benutzt Du ?
    Aktuell ist die Wifi Datenübertragung im Sketch auskommentiert. Wifi läuft aber, wenn Du den CC3000 Bereich einschaltest und den LAN Bereich durch Auskommentieren ausschaltest.

  13. Schönes Projekt, da bleiben keine Wünsche mehr offen. Leider zeigt der Sketch die Temperatur meines DS18b20 nur als Buchstabensalat an. Bei v2.0 hats noch funktioniert.
    Der Datenempfang scheint für LAN Shield zu sein und nicht für das CC3000 Breakout Board, oder irre ich? Freue mich schon auf die Weiterentwicklung!!

    Gruß,
    Chris

Kommentar absenden

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Translate »