pour ceux qui comme moi on besoin de contrôler des télérupteurs, volet roulant filaire et/ou radiateur sur fil pilote, et surtout qui souhaitent faire cela en filaire (Ethernet Rj45), je vous présente mes petits bous de codes qui le permettent assez simplement je l'espères.
Il existent surement d'autres façon de faire (surement meilleur), mais c'est la seule qui m'est venue
Le montage en test avec 2 volets roulants de connecter : Coté Arduino, j'utilise un Méga (bien plus d'I/O) et un ethernet shield WizNet, dont voici le code :
Code : Tout sélectionner
#include <EEPROM.h>
#include <OneWire.h>
#include <SPI.h>
#include <Ethernet.h>
OneWire ds(2); // on pin 2 (a 4.7K resistor is necessary)
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 10, 177);
EthernetServer server(80);
String EepromValues;
String toString(float value, byte decimals) {
String sValue = String(value, decimals);
sValue.trim();
return sValue;
}
void clearEEPROM() {
for (int i = 0; i < 365; ++i) { EEPROM.write(i, 0); }
//EEPROM.commit();
return;
}
String readEEPROM(int debut,int fin) {
//Serial.println(valeur);
int value;
Serial.println("");
EepromValues = "";
for (int i = debut; i < fin+1; ++i)
{
value = EEPROM.read(i)-48;
//Serial.print("Read: ");
//Serial.print(value);
//Serial.print(" in: ");
//Serial.println(i);
EepromValues += toString(value,0);
}
//EEPROM.commit();
return EepromValues;
}
void writeEEPROM(int debut,String valeur) {
//Serial.println(valeur);
Serial.println("");
for (int i = debut; i < debut+valeur.length(); ++i)
{
EEPROM.update(i, valeur[i-debut]);
//Serial.print("Wrote: ");
//Serial.print(valeur[i-debut]);
//Serial.print(" in: ");
//Serial.println(i);
}
return;
}
void SaveToEEPROM () {
String fullstate = "";
for (int i=4;i<10;i++) {
fullstate += toString(digitalRead(i),0);
}
for (int i=14;i<51;i++) {
fullstate += toString(digitalRead(i),0);
}
writeEEPROM (0,fullstate);
Serial.println(fullstate);
}
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
//pinMode(2, INPUT); // onewire pin
//pinMode(3, INPUT); // rf rx pin
String EEPROMvalues=readEEPROM(0,42);
Serial.println(EEPROMvalues);
//paramétrage des pin digital en output pour radiateur et relay en Low par defaut
String mode ="";
for (int i=4;i<10;i++) {
mode = EEPROMvalues.substring(i-4,i-3);
pinMode(i, OUTPUT);
if (mode=="1") {digitalWrite(i, HIGH);}
if (mode=="0") {digitalWrite(i, LOW);}
}
//pin 10 à 13 reservé au module ethernet
for (int i=14;i<51;i++) {
mode = EEPROMvalues.substring(i-8,i-7);
pinMode(i, OUTPUT);
if (mode=="1") {digitalWrite(i, HIGH);}
if (mode=="0") {digitalWrite(i, LOW);}
}
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void receivedata() {
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
String line;
String command;
//String type;
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
line +=c;
//Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
String s;
s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from MegaHomeServer <br><br>";
String TempC=temperature();
s += "<br>Temperature : ";
s += TempC;
for (int i=4;i<10;i++) {
String x =toString(i,0);
s += "</br>D-out";
s +=x;
s +=":";
String state = toString(digitalRead(i),0);
s +=state;
}
for (int i=14;i<51;i++) {
String x =toString(i,0);
s += "</br>D-out";
s +=x;
s +=":";
String state = toString(digitalRead(i),0);
s +=state;
}
client.println(s);
for (int analogChannel = 0; analogChannel < 16; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("<br>A-In");
client.print(analogChannel);
client.print(":");
client.println(sensorReading);
}
client.println("</html>\r\n\r\n");
break;
}
if (c == '\n') {
// you're starting a new line
String tmpline = "";
tmpline = line.substring(4,line.indexOf('=')+1);
if (tmpline == "/a?command=") {
command = line.substring(line.lastIndexOf('=')+1);
command = command.substring(0,command.lastIndexOf(' '));
//command = command.substring(0,command.lastIndexOf('-'));
//type = line.substring(line.lastIndexOf('-')+1);
//type = type.substring(0,type.lastIndexOf(' '));
Serial.print ("command : ");
Serial.println(command);
if (command == "reset") {
Serial.println("Reset EEPROM to off");
for (int i=4;i<10;i++) { digitalWrite(i, HIGH); }
for (int i=14;i<51;i++) { digitalWrite(i, HIGH); }
}
for (int i=4;i<10;i++) {
String Tmp = toString(i,0);
Tmp += "on";
if (command == Tmp)
{
digitalWrite(i, LOW); // on
Serial.print("pin ");
Serial.print(i);
Serial.println(" on ");
//Serial.println(type);
}
Tmp = toString(i,0);
Tmp += "off";
if (command == Tmp)
{
digitalWrite(i, HIGH); // off
Serial.print("pin ");
Serial.print(i);
Serial.println(" off ");
//Serial.println(type);
}
}
for (int i=14;i<51;i++) {
String Tmp = toString(i,0);
Tmp += "on";
if (command == Tmp)
{
digitalWrite(i, LOW); // on
Serial.print("pin ");
Serial.print(i);
Serial.println(" on ");
//Serial.println(type);
}
Tmp = toString(i,0);
Tmp += "off";
if (command == Tmp)
{
digitalWrite(i, HIGH); // off
Serial.print("pin ");
Serial.print(i);
Serial.println(" off ");
//Serial.println(type);
}
}
SaveToEEPROM ();
}
currentLineIsBlank = true;
line ="";
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
String temperature() {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
String result;
if ( !ds.search(addr)) {
Serial.println("No more addresses.");
Serial.println();
ds.reset_search();
delay(250);
result = "DS18B20 absent";
return result;
}
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr[i], HEX);
}
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
Serial.println();
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
Serial.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
Serial.println(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
Serial.print(" Data = ");
Serial.print(present, HEX);
Serial.print(" ");
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
Serial.print(data[i], HEX);
Serial.print(" ");
}
Serial.print(" CRC=");
Serial.print(OneWire::crc8(data, 8), HEX);
Serial.println();
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
Serial.print(" Temperature = ");
Serial.print(celsius);
Serial.print(" Celsius, ");
Serial.print(fahrenheit);
Serial.println(" Fahrenheit");
return toString(celsius,2);
}
void loop() {
// listen for incoming clients
receivedata();
}
- 3 pour une sonde de temperature DS18B20 (pratique pour connaitre la temperature de tout le système une fois en boite
) - de 4 à 9 en digital output pour les relais
- de 14 à 50 en digital output pour les relais
- Les valeurs reçu par les pin analogique sont affichés dans une page web (avec les valeurs courantes de la sondes et des pin digital précédemment cités) ==> en cour de développement pour le moment.
En cas de reboot de l'arduino suite à une coupure ou autre, celui-ci ce remet dans l'état d'avant coupure/reboot/reset.
Il ainsi possible d’accéder à votre arduino depuis n'importe quelle navigateur internet à l'adresse IP que vous aurez configurer dans ce code
Et pour changer la valeur de la pin 4
- à on : http://IP_Arduino/a?command=4on
- à off : http://IP_Arduino/a?command=4off
Coté Domoticz:
creer des capteurs virtuels :
- Pour les lumières :
de type : Light/Switch
sous type : Switch
Aller éditer le nouvel interrupteur et mettre dans Action On:ou 22 est le numéro de l'I/O relié à un relaisCode : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/light.sh 22 on
et dans Action Off:Le code à ajouter dans /home/pi/domoticz/scripts/MegaHomeServer/ :Code : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/light.sh 22 offCode : Tout sélectionner
#!/bin/bash # #light script # # $1 => id Digital Output number # $2 => satus on or off ==> desactivé pour telerupteur if [ -n "$1" ]; then if [ -n "$2" ]; then # wget http://192.168.10.177/a?command=$1$2 tmp # cas interrupteur simlpe wget http://192.168.10.177/a?command=$1on tmplight # cas telerupteur wget http://192.168.10.177/a?command=$1off tmplight # cas telerupteur exit fi fi - Pour les volets roulants :
de type : Light/Switch
sous type : Selector Switch
Aller éditer le nouvel interrupteur, conserver 3 Niveaux du sélecteur :- Arret
- Monter
- Descendre
pour Monter mettre :Code : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/volet.sh 24 25 stoppour Descendre mettre :Code : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/volet.sh 24 25 upou 24 et 25 sont les I/O reliés à des relais (un relais par i/oCode : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/volet.sh 24 25 down
)
Le code à ajouter dans /home/pi/domoticz/scripts/MegaHomeServer/ :
Code : Tout sélectionner
#!/bin/bash # #Volet script # # $1 => id Digital Output number for up # $2 => id Digital Output number for down # $3 => satus up or down or stop if [ -n "$1" ]; then if [ -n "$2" ]; then if [ "$3" = "up" ]; then wget http://192.168.10.177/a?command=$2off tmp wget http://192.168.10.177/a?command=$1on tmp exit fi if [ "$3" = "down" ]; then wget http://192.168.10.177/a?command=$1off tmp wget http://192.168.10.177/a?command=$2on tmp exit fi if [ "$3" = "stop" ]; then wget http://192.168.10.177/a?command=$1off tmp wget http://192.168.10.177/a?command=$2off tmp exit fi fi fi - Pour les radiateurs :
de type : Light/Switch
sous type : Selector Switch
Aller éditer le nouvel interrupteur, conserver 4 Niveaux du sélecteur :- Arret
- Hors Gel
- Eco
- Confort
pour Hors Gel mettre :Code : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 stoppour Eco mettre :Code : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 gelpour Confort mettre :Code : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 ecoou 26 et 27 sont les I/O reliés à des relais (un relais par i/oCode : Tout sélectionner
script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 confort
)
Le code à ajouter dans /home/pi/domoticz/scripts/MegaHomeServer/ :
Code : Tout sélectionner
#!/bin/bash # #Radiateur script # #utilisation de 2 pin pour envoyer 4ordres # # $1 => id Digital Output number 1 # $2 => id Digital Output number 2 # $3 => satus stop , eco , gel , confort if [ -n "$1" ]; then if [ -n "$2" ]; then if [ "$3" = "stop" ]; then wget http://192.168.10.177/a?command=$2off tmp wget http://192.168.10.177/a?command=$1on tmp exit fi if [ "$3" = "eco" ]; then wget http://192.168.10.177/a?command=$1on tmp wget http://192.168.10.177/a?command=$2on tmp exit fi if [ "$3" = "gel" ]; then wget http://192.168.10.177/a?command=$1off tmp wget http://192.168.10.177/a?command=$2on tmp exit fi if [ "$3" = "confort" ]; then wget http://192.168.10.177/a?command=$1off tmp wget http://192.168.10.177/a?command=$2off tmp exit fi fi fi
Et n’hésitez pas à me faire part de vos commentaires
TODO :
- Mettre en place un retour d'état qd un interrupteurs physiques est utiisé (concervé au cas la partie domotique tombe en panne
)