Bonjour,
Depuis peu je m’intéresse au protocole Modbus, particulièrement en TCP/IP. Je me suis créer des coffrets I/O sur une base d’Arduino nano + Shield Ethernet ENC28J60 associé à une cartes à 8 relais 230V.
Jusqu’à présent ces coffrets sont intégrés à mon Jeedom via le plugin JEEDUINO. Ça fonctionnait parfaitement mais le nano avec le sketch Jeeduino était à saturation. Sa réactivité de 3 secondes avec parfois des actions ou des retours qui ne fonctionnait pas mon pour un temps retardé quant a l’implantation physique de ces coffrets.
Il y a peu j’ai croisé la route de @bebel27 et de son plugin Mymodbus (beta), j’avais 2-3 automate en Modbus alors en collaboration on les a intégrés à mon Jeedom. (Adam6050 pour ceux qui connaisse).
Et la une petite idée à germée pourquoi pas mes coffrets en Modbus, Google m’a aidé ainsi que @Mmx.
Ça c’était pour l’histoire. Et fini par un happy end…
A la manière d’une recette voici les ingrédients :
-
Un Arduino pour moi le nano pour l’encombrement,
-
Un Shield Ethernet ENC28J60, pour nano aussi.
-
Une carte relais de 2 à 16 relais (Ps sur 16 relais seulement 14 sont utilisables par le nano)
-
Des fils DuPont
-
Alim 5Vdc 2A
-
Un peu de créativité.
En pièce détaché :
Et assemblé :
L’alimentation 5V se fera par le câble réseau au moyen d’un injecteur POE passif (coté alim) et d’un séparateur (côté coffret)
Le coffret physiquement est en ABS et mesure 200x120x80. Pratique mais pas top peut être que j’en imprimerais un plus adapté. Ces coffrets pour moi seront à destination des combles.
Le matériel présenté, entrons dans le vif du sujet.
Il existe des bibliothèque Modbus pour Arduino, plein. Après en avoir testé quelques-unes je me suis arrêté sur Modbus-arduino car elle est compatible avec beaucoup de shield réseau.
W5100, ENC28J60, ESP8266, etc.
Les résultats sont excellents, je peux au travers du plugin Mymodbus piloter mes 8 relais, des essais concluants on était réalisé avec des entrées analogiques avec la participation de @Mmx.
J’ai donc réalisé un sketch qui va encore évoluer, mais qui pour l’instant permet de commuter simplement les sorties numériques, interroger les entrées analogiques.
EDIT DU 19/08/20 Mise a jour du script pour de l’ethernet :
/*
Carte I/O modbus TCP/IP + fonction température DS18B20.
Hardware: Nano + ethernet shield ENC28J60
Carte 8 relais 5vdc / 230v 10A
Fonction: Pilotage des entrées sorties d'un arduino par modbus. Relève de température DS18B20.
Commentaires : Alimentation 5Vdc auxiliaire requise, pour eviter une surconsomation sur l'arduino, sinon ça ne répond plus.
IP / Mac fixe.
Source : André Sarmento Barbosa http://github.com/andresarmento/modbus-arduino
*/
/*--------------------------BIBLIOTHEQUES-----------------------------*/
#include <ModbusIP_ENC28J60.h> //Mode TCP/IP
#include <DallasTemperature.h>
#include <OneWire.h>
/*-----------RENSEIGNER ADRESSE IP ET MAC (MODE TCP/IP)---------------*/
//Adresse MAC de votre shield.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xE8 };
//Adresse IP de votre shield.
byte ip[] = {192, 168, 1, 51};
/**------------------CONFIGURATION DES I/O et PIN --------------------*/
//Pins 10, 11, 12, 13 non dispo pour ENC28J60.
//Digitales
#define NBRE_DO 8
byte DigitalOut [NBRE_DO]; //Tableau Digital Output
const byte First_pinDO = 2; //Numéro 1er DO
#define NBRE_DI 0
byte DigitalIn [NBRE_DI]; //Tableau Digital Input
const byte First_pinDI = (First_pinDO + NBRE_DO); //Numéro 1er DI sauf si NBRE_DO=8
//Analogiques
#define NBRE_ANO 0
const byte First_pinANO = 15; //Numéro 1er ANO "15" alias "A1"
byte AnalogOut [NBRE_ANO]; //Tableau Analog Output
#define NBRE_ANI 0
const byte First_pinANI = (First_pinANO + NBRE_ANO); //Numéro 1er ANI
byte AnalogIn [NBRE_ANI]; //Tableau Analog Input
//Configuration des registres modbus (adr. possible 0-9999) par catégories.
const byte First_RegDO = 100; //Numéro 1er DO
byte REG_DOut [NBRE_DO]; //Tableau registre Digital Output
const byte First_RegDI = 200; //Numéro 1er DI
byte REG_DIn [NBRE_DI]; //Tableau registre Digital Input
const byte First_RegANO = 300; //Numéro 1er ANO
byte REG_ANO [NBRE_ANO]; //Tableau registre Analog Output
const byte First_RegANI = 400; //Numéro 1er ANI
byte REG_ANI [NBRE_ANI]; //Tableau registre Analog Input
/*-----------------Configuration onewire-dallas----------------------*/
OneWire oneWire(14); // pin 14 (A0)
DallasTemperature sensors(&oneWire);
/*Configuration sonde multiple*/
#define NBRE_SONDE 1
/*Configuration valeur de départ*/
int REG_SONDE [NBRE_SONDE]; //Tableau registre sonde
const int First_REGSONDE = 500; //Numéro 1er registre
int SONDE [NBRE_SONDE]; //Tableau des sondes
const int First_SONDE = 0; //Numéro 1ere sonde
/*VARAIBLES*/
float TEMPFLOAT; //Variables temp flotant negatif possible
int TEMPCALC; //Variables temp entier
/*-----------------Configuration des fonctions----------------------*/
//ModbusIP object
ModbusIP mb;
/*TEMPO EN MILLISECONDES*/
long ts;
/*-------------------------------------------------------------------*/
void setup() {
//Config Modbus IP
mb.config(mac, ip);
Serial.begin(9600);
sensors.begin();
if (NBRE_DO > 0) {
for (int i, j = 0; i, j < NBRE_DO; i++, j++) {
byte pin = First_pinDO + i;
DigitalOut[i] = pin;
pinMode (DigitalOut[i], OUTPUT); //Toutes les pins sont en OUT
byte reg = First_RegDO + j;
REG_DOut [j] = reg;
mb.addCoil(REG_DOut [j], HIGH); //addCoil() pour digital outputs initialise a Off les relais
}
}
if (NBRE_SONDE > 0){
for (int i = 0; i < NBRE_SONDE; i++){
int Sx = First_REGSONDE + i;
REG_SONDE[i] = Sx;
sensors.begin();
mb.addHreg(REG_SONDE[i], true);
}
}
ts = millis();
}
void loop() {
//Call once inside loop() - all magic here
mb.task();
/*Gestion des sorties*/
if (NBRE_DO > 0) {
for (int i = 0; i < NBRE_DO; i++) {
byte pin = First_pinDO + i;
DigitalOut[i] = pin;
int reg = First_RegDO + i;
REG_DOut [i] = reg;
digitalWrite (DigitalOut [i], mb.Coil(REG_DOut[i])); //Association registres/pins
} //EndFor
} //Endif
/*Relève des températures*/
if (millis() > ts + 3000) {
ts = millis();
if (NBRE_SONDE > 0){
for (int i = 0; i < NBRE_SONDE; i++){
int Sx = First_SONDE + i;
SONDE[i] = Sx;
int Reg = First_REGSONDE + i;
REG_SONDE[i] = Reg;
sensors.requestTemperatures();
TEMPFLOAT = sensors.getTempCByIndex(SONDE[i]);
TEMPCALC = (int((TEMPFLOAT+100)*100));
Serial.print("Relève sonde ");
Serial.print(SONDE[i]);
Serial.print(" : ");
Serial.println(TEMPFLOAT);
Serial.print("Valeur converti :");
Serial.print(TEMPCALC);
Serial.print(" envoyé sur le registre :");
Serial.println(REG_SONDE[i]);
mb.Hreg(REG_SONDE[i],(TEMPCALC));// Registre
} //EndFor
} //Endif NBRE
} //Endif millis
}
L’objectif est de vous fournir un sketch étoffé, dans un package avec les bibliothèques qui vont bien.
J’ajouterais les analogiques outputs et digital inputs prochainement. Et avec l’ESP8266 pourquoi pas un module Wifi pour modbus…
Je rappelle aussi une chose importante ces cartes relais (chinoiseries) faut l’avoué sont donné pour 10A, attention cependant ne pas trop les surchargés. De la même manière faites très attention lors de câblage sur des tensions de 230V il y a des risques d’électrisation soyez prudents ou ne faites rien si vous ne le sentez pas.
Et pour finir si ces cartes ne vous dise rien sachez que l’Arduino tourne sous 5V et qu’il pourrait piloter des relais plus « Safe » sur rail Din. Ainsi on peut coder seulement l’Arduino en esclave Modbus et l’assembler à ce que l’on veut derrière.
La tension de commutation des bobines des relais devra être en 5V.
Il existe aussi des relais plus compacts, des relais statiques, qui n’ont pas de mécanique (bobines) et qui ont une coupure d’intensité inférieure au relais traditionnel.
Voilà c’était un peu long mais j’essaye d’être complet.
Je me permets d’inviter @Rigolman69 au sujet vu sont post récent, et de remercier les deux collaborateurs @Bebel27 et @Mmx pour leur participation respective.
A+
Fab.