Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Forum pour tous les autres objets : sondes météo, capteurs, actionneurs ...
Vous avez un besoin mais vous ne savez pas quel matériel choisir ? C'est ici.
zaraki673
Messages : 229
Inscription : 07 oct. 2016, 04:29

Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par zaraki673 »

Bonjour à tous,

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. :D
Il existent surement d'autres façon de faire (surement meilleur), mais c'est la seule qui m'est venue :lol:

Le montage en test avec 2 volets roulants de connecter :
Domoticz-inter-Volet-2.png
Domoticz-inter-Volet-2.png (158.33 Kio) Consulté 16092 fois
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();
}
Les pin utilisés sont :
  • 3 pour une sonde de temperature DS18B20 (pratique pour connaitre la temperature de tout le système une fois en boite :P )
  • 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.
Il faut configurer l'adresse IP de l'arduino ethernet au début du code (j'ai eu la flemme de mettre via dhcp, comme pour faire un code propre du coté DS18B20 :D , ca viendra plus tard )

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
Pour faire un reset des valeurs à off faites : http://IP_Arduino/a?command=reset

Coté Domoticz:
creer des capteurs virtuels :
  • Pour les lumières :
    Domoticz-inter-Light-1.png
    Domoticz-inter-Light-1.png (12.56 Kio) Consulté 16092 fois
    de type : Light/Switch
    sous type : Switch
    Aller éditer le nouvel interrupteur et mettre dans Action On:

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/light.sh 22 on
    ou 22 est le numéro de l'I/O relié à un relais
    et dans Action Off:

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/light.sh 22 off
    Domoticz-inter-Volet-1.png
    Domoticz-inter-Volet-1.png (16.65 Kio) Consulté 16092 fois
    Le code à ajouter dans /home/pi/domoticz/scripts/MegaHomeServer/ :

    Code : 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 :
    Domoticz-inter-Light-2.png
    Domoticz-inter-Light-2.png (97.5 Kio) Consulté 16092 fois
    de type : Light/Switch
    sous type : Selector Switch
    Aller éditer le nouvel interrupteur, conserver 3 Niveaux du sélecteur :
    • Arret
    • Monter
    • Descendre
    puis dans Actions du sélecteur pour Arret mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/volet.sh 24 25 stop
    pour Monter mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/volet.sh 24 25 up
    pour Descendre mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/volet.sh 24 25 down
    ou 24 et 25 sont les I/O reliés à des relais (un relais par i/o ;) )
    Domoticz-MegaHomeServer.jpg
    Domoticz-MegaHomeServer.jpg (115.18 Kio) Consulté 16092 fois
    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 :
    Domoticz-inter-Radiateur-2.png
    Domoticz-inter-Radiateur-2.png (199.32 Kio) Consulté 16092 fois
    de type : Light/Switch
    sous type : Selector Switch
    Aller éditer le nouvel interrupteur, conserver 4 Niveaux du sélecteur :
    • Arret
    • Hors Gel
    • Eco
    • Confort
    puis dans Actions du sélecteur pour Arret mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 stop
    pour Hors Gel mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 gel
    pour Eco mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 eco
    pour Confort mettre :

    Code : Tout sélectionner

    script:///home/pi/domoticz/scripts/MegaHomeServer/radiateur.sh 26 27 confort
    ou 26 et 27 sont les I/O reliés à des relais (un relais par i/o ;) )
    Domoticz-inter-Radiateur-1.png
    Domoticz-inter-Radiateur-1.png (17.23 Kio) Consulté 16092 fois
    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
    
    
Voila, merci pour la patiente de votre lecture :P

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 :( )
Dernière modification par zaraki673 le 07 oct. 2016, 23:49, modifié 2 fois.
deennoo
Messages : 4036
Inscription : 25 janv. 2015, 02:00

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par deennoo »

Super tuto !

Et enfin un exemple fonctionnel.

Si tu as des photos de ton montage a mettre ce serait nickel !
De quoi se faire Plaisir et essayer d'aider...
http://www.domo-attitude.fr
zaraki673
Messages : 229
Inscription : 07 oct. 2016, 04:29

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par zaraki673 »

Merci :D

tuto ==> du coup je suis pas au bonne endroit :oops:

Voila une photo du montage (y en aura d'autres plus WAF qd j'aurais finaliser la boite qui va accueillir tout ça) et des screenshoots pour la configuration ;)
Titof2375
Messages : 91
Inscription : 19 avr. 2017, 21:40

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par Titof2375 »

Bonjour
Petite question sur les volets roulants,peut tu faire des scénario et peut tu les ouvrirent à mi auteur.
zaraki673
Messages : 229
Inscription : 07 oct. 2016, 04:29

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par zaraki673 »

scenario oui
ouvrir a mi hauteur non, je n ai pas inclus de tempo dans le code de l arduino (c est sur ma todo list :D ), mais ca peut etre ajouter coté script, par contre il faudra connaitre le temps de fermeture/ouverture pour le mi niveau ou pour chaque palier souhaité (et calculer le delais entre chaque palier, et ce pour chaque volet

bref c'est jouable :D, juste une variable a ajouter à la commande envoyé par domoticz
je regarderais des que possible
Titof2375
Messages : 91
Inscription : 19 avr. 2017, 21:40

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par Titof2375 »

Bonjour.
Je voudrais savoir si tu a rasbery pour piloté ton installation.
zaraki673
Messages : 229
Inscription : 07 oct. 2016, 04:29

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par zaraki673 »

oui les scripts (et domoticz) sont executer sur un pi3, mais sur tout linux ca doit fonctionner
Titof2375
Messages : 91
Inscription : 19 avr. 2017, 21:40

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par Titof2375 »

et a relier les 2 par un câble réseau.
zaraki673
Messages : 229
Inscription : 07 oct. 2016, 04:29

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par zaraki673 »

bah oui , je vois pas le problème c est du lan, tant que tu configures bien ton lan, oui ca fonctionne

tu peux mettre un switch entre les deux (mon cas et le plus simple je dirais), ou un cable entre les deux directement, mais un cable croisée, et faire le paramétrage manuel du reseau sur le pi ... enfin la c est de la config réseau, je te laisse te renseigné sur le comment fonctionne un réseau local sur google ;)
Titof2375
Messages : 91
Inscription : 19 avr. 2017, 21:40

Re: Arduino Mega Ethernet Shield et relay switch (volet roulant, lumière et radiateur)

Message par Titof2375 »

Mes question sont peur bête pour toi. Mais pour moi qui débute , elle sont importantes,car tu a matérialise l'idée que j'avais en tête.
Et que je te copie un peu car j'ai acheté le même matériels que toi.
Répondre