Mise en avant

Intro

Bonjour,

J’ai commencé le développement de régulations basées sur un Arduino.
Pourquoi je n’acquière pas un produit du commerce:
Les solution commerciales ne répondent pas à mes attentes en particulier la possibilité de dépannage en cas de problèmes. D’autres part, bien qu’équipée de bus, la communication est souvent un protocole fermé, il est plus simple de développer un système de communication que comprendre et surtout arriver à utiliser celui mis en place par le constructeur.
Je partage donc mon travail sur une régulation « loi d’eau » et une régulation pour chaudière bois ou poêle bouilleur.

formulaire contact

Régulation « loi d’eau »

page en cours de réalisation

Le sketch est inspiré des anciennes régulations Landys & Gyr qui pilotaient une vanne trois voies motorisée. La courbe de chauffe était déterminée par des potentiomètre. Dans cette version, tout les paramètres sont accessibles et modifiable via le modbus. Il sont mémorisés via une commande modbus dans l’eeprom. Le sketch tourne sur un arduino nano.
la t° de départ est soit 4° (antigel) soit fixe soit loi d’eau. Un mode booster temporisé permet de forcer la t° à 40°.
Le système fonctionne depuis fin 2022. suite a un orage, destruction des MAX31865 -> remplacement

sketch.ino

regulation poêle bouilleur

Bonjour,
Dans l’idée de limiter au maximum la consommation électrique (alimentation panneau solaire) la régulation veille à garder un delta de 10° dans l’échangeur.
Une vanne thermostatique 3 voies maintient de façon autonome la température d’entrée de l’échangeur à 55°. L’alimentation du circulateur Grundfoss Alpha1L se fait via un thermostat mécanique dont la sonde est dans un doigt de gant dans l’échangeur. Sans électronique le système est autonome.

L’algorithme gếre la mise en route, l’arrêt et la vitesse via le pwm.
Le fonctionnement peut être suivit avec le modbus. Tous les paramètres sont stockés dans l’eeprom et peuvent être modifiés via le modbus. Un script python cgi permet le lire le modbus et d’afficher les valeurs sur une page web.
Le bootloader de l’Atmega 328 est modifié pour pouvoir le reprogrammer au travers du modbus avec l’ide arduino.
schema_atmega_bouilleur
L’algorithme gếre la mise en route, l’arrêt et la vitesse via le pwm.
Le fonctionnement peut être suivit avec le modbus. Tous les paramètres sont stockés dans l’eeprom et peuvent être modifiés via le modbus. Un script python cgi permet le lire le modbus et d’afficher les valeurs sur une page web.
Le bootloader de l’Atmega 328 est modifié pour pouvoir le reprogrammer au travers du modbus avec l’ide arduino.
schema_atmega_bouilleur
code source: code.ino

Vbus 2 rs232 Json

Bonjour,
Dans cet article je propose le partage du développement que j’ai réalisé pour décoder les trames Vbus. toutes les spécification se trouvent ici: https://danielwippermann.github.io/resol-vbus/vbus-specification.html
tout à disparu de son site. Je ne l’ai hélas pas téléchargé……
Le code ci-après est dérivé du travail de M. Wipperman. Vous pouvez échanger sur le sujet en me contactant via formulaire contact
Version raspberry pi: vbus_decode

Version arduino:

/*
nouvelle version de Vbusread
* permet de selectionner un DFA
* serveur web fichiers json
* Prise en compte du CRC
* version ok  pas toucher
* 
* Legal Notices
* RESOL, VBus, VBus.net and others are trademarks or registered trademarks of RESOL - Elektronische Regelungen GmbH.
* Le sketch d'origine provient de M. Wiperman,  http://danielwippermann.github.io
* 
* Vbus 9600 bauds 8 bits pas de parité un stop bit
*  Vbus ttl avec un opto coupleur  SFH6206 une resistance de 4,7k en série avec  led, coté transistor, collecteur sur +5V,emeteur une résistance pulldown de 3,3K vers la masse
*  |  C  E |   40 @ Ic/Iin  Iin 1mA  
*  |          |
* .| in  in|

* si pas de vbus -> affiche timeout -> ok
* sonde dht22 pour température et humidité local
* test:  curl http://192.168.1.140/vbus.json
* switch debug rs232:  curl http://192.168.1.141/disp_rs232.json
http://192.168.1.141/temperatures.json
modif ligne 230 inversion poid fort et faible et _ manquant
 */
 #include <SoftwareSerial.h>
#include <EtherCard.h> //doc: https://www.aelius.com/njh/ethercard/
#include <DHT.h>
#define VERSION "0.1.04"
#define DHTPIN 7
#define soft_rxd_pin 8
#define LED 2
#define DHTTYPE DHT22 // DHT 22
DHT dht(DHTPIN, DHTTYPE);
#define FLength 6   // Framelength
#define FOffset 10  // Offset start of Frames
#define FSeptet 4   // Septet byte in Frame
#define LED 2

#define timerInterval 1500
SoftwareSerial Soft_serial(soft_rxd_pin, 9,false);

#define debug 1
//ENC28J60 ethernet
	// Ethernet uses 10,11,12,13
	static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x34 };
	#define STATIC 1 // DHCP=0 , static=1
	#define version 0.1.0
	#if STATIC
		static byte myip[] = { 192,168,1,141 }; // static ip address
	#endif
	byte Ethernet::buffer[400]; // tcp ip send and receive buffer
	BufferFiller bfill;

#define FLOATEMIT

const char header_json[] PROGMEM =
    "HTTP/1.0 200 OK\r\n"
    "content-Type: application/json;charset=utf-8\r\n"
    "\r\n";

const char header_json2[] PROGMEM =
    "HTTP/1.0 200 OK\r\n"
    "content-Type: application/json;charset=utf-8\r\n"
    "Refresh: 5\r\n"
    "\r\n";

const char header_refresh[] PROGMEM = "Refresh: 5\r\n";

const char page_help[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"content-Type: application/json;charset=utf-8\r\n"
"\r\n"
"{\"help\":{ "
	"\"compil_date\": \"" __DATE__"\","
	"\"compil_time\": \"" __TIME__"\","
	"\"src_file\": \"" __FILE__"\","
	"\"version\": \""VERSION"\""
"}}\r\n";

const char error_json[] PROGMEM =
    "HTTP/1.0 404 Not Found\r\n"
    "content-Type: application/json;charset=utf-8\r\n"
    "\r\n"
    "{\"vbus\":{ \"error\": 404}}"
    "\r\n";

bool all;
bool disp_rs232 = false;
bool refresh = false;
unsigned char Buffer[75];
char char_buffer[80];

long lastTimeTimer;
//long timerInterval =600;
//int temp;
byte i;
uint16_t networkaddress;
byte nb_crc_error;
char sensor1_tempc [6];
char sensor2_tempc [6];
char sensor3_tempc [6];
char sensor4_tempc [6];
char refresh_string [] = "false";
//char * refresh_string ;
char temp_VFD [6];
char PumpSpeed1;  // in  %
char PumpSpeed2;  //  in %
char RelaisMask;
char ErrorMask;
char Scheme;
uint16_t OperatingHoursRelais1;
uint16_t OperatingHoursRelais2;
uint32_t HeatQuantity;
uint16_t Version;
uint16_t OperatingHoursRelais1Today;
uint16_t SystemTime;

uint16_t flow_VFD;
unsigned int Destination_address;
unsigned int Source_address;
unsigned char ProtocolVersion;
unsigned int Command;
unsigned char Framecnt;
unsigned char Septet;
unsigned char Checksum;
unsigned char calc_Checksum;
unsigned char tot_crc_error =0;






void setup() {
  
	pinMode(LED, OUTPUT);
	digitalWrite(LED, HIGH);
	dht.begin();
   Serial.println("Arduino debugging started");
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
	; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Go!");
  // set the data rate for the SoftwareSerial port
  Soft_serial.begin(9600);
  	//ether.begin(sizeof Ethernet::buffer, mymac);
	if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
		Serial.println( "Failed to access Ethernet controller");
	#if STATIC
		ether.staticSetup(myip);
		Serial.println("Static IP");
	#else
	if (!ether.dhcpSetup())
		Serial.println("DHCP failed");
	#endif
	ether.printIp("IP: ", ether.myip);
	digitalWrite(LED, LOW);
}

void loop() {
      //String refresh_string = "    ";
	word pos = ether.packetLoop(ether.packetReceive());
	// check if valid tcp data is received
	if (pos) {
		char* data = (char *) Ethernet::buffer + pos;
	#if debug
		Serial.println(data);
	#endif
		if (strncmp("GET / ", data, 6) == 0) {
			//Serial.println("http Get /");
			ether.httpServerReplyAck(); // send ack to the request
			memcpy_P(ether.tcpOffset(), page_help, sizeof page_help);//only the first part will sended
			ether.httpServerReply_with_flags(sizeof page_help - 1,TCP_FLAGS_ACK_V|TCP_FLAGS_FIN_V);
		}
		else
			if (strncmp("GET /vbus.json", data, 14) == 0) {
				//Serial.println("http GET /vbus.json");
					//digitalWrite(LED, HIGH);
				if (VBusRead(0x10)){
					//Serial.println(temp);
					nb_crc_error = extract_septep();
					tot_crc_error += nb_crc_error;
					bfill = ether.tcpOffset();

                    if (refresh)  {                
                        bfill.emit_p(PSTR("$F"),header_json2);
                        strcpy(refresh_string, "true");
                    }    
                    else {
                        bfill.emit_p(PSTR("$F"),header_json); 
                        strcpy(refresh_string, "false");
                    }
					bfill.emit_p(PSTR(
					"{\"Vbus\":{"
					"\"src_address\":\"0x$H$H\","
					"\"t_1\":$S,"
					"\"t_2\":$S,"
					"\"t_3\":$S,"
					"\"t_4\":$S,"
					"\"t_VFD\":$S,"
					"\"VFD_flow\":$D,"
					"\"Vpump1\":$D,"
					"\"heures_P1\":$D,"
					"\"Vpump2\":$D,"
					"\"heures_P2\":$D,"
					"\"heure\":\"$D:$D\","
					"\"P_tot\":$L,"
					"\"ErrorMask\":\"0x$H\","
					"\"nb_crc_error\":$D,"
					"\"tot_crc_error\":$D,"
                    "\"refresh\":\"$S\""
					"}}"
					),Buffer[4],Buffer[3],sensor1_tempc,sensor2_tempc,sensor3_tempc,sensor4_tempc,temp_VFD,flow_VFD,
					  PumpSpeed1,OperatingHoursRelais1,PumpSpeed2,OperatingHoursRelais2, SystemTime/60,SystemTime%60,
					  HeatQuantity, ErrorMask,nb_crc_error, tot_crc_error,refresh_string);
					  ether.httpServerReply(bfill.position());
				}
                else {
                    bfill = ether.tcpOffset();
					bfill.emit_p(PSTR("{\"Vbus\":{\"error\" :\"timeout\" }}"));
                    ether.httpServerReply(bfill.position());
                }
			}
			else
            
				if (strncmp("GET /infos_10.json", data, 17) == 0) {
					//Serial.println("GET /infos_15.json");
				   byte vbusread_code;
				   vbusread_code = VBusRead(0x10);
					if (vbusread_code){
						extract_septep();
						bfill = ether.tcpOffset();
						bfill.emit_p(PSTR(
						"$F{\"Vbus\":{"
						"\"vbusread code\":$D,"
						"\"sync\":\"0x$H\","
						"\"Src address\":\"0x$H$H\","
						"\"Dst address\":\"0x$H$H\","
						"\"22\":$D,"
						"\"23\":$D,"
						"\"24\":$D,"
						"\"25\":$D,"
						"\"28\":$D,"
						"\"29\":$D,"
						"\"30\":$D,"
						"\"31\":$D,"
						"\"34\":$D,"
						"\"35\":$D,"
						"\"35\":$D,"
						"\"37\":$D"
						"}}"
						),header_json,vbusread_code,Buffer[0],Buffer[2],Buffer[1],Buffer[3],Buffer[4],
						Buffer[22],Buffer[23],Buffer[24],Buffer[25],
						Buffer[28],Buffer[29],Buffer[30],Buffer[31],
						Buffer[34],Buffer[35],Buffer[36],Buffer[37]
						);
						ether.httpServerReply(bfill.position());
					}
				}
				else
					if (strncmp("GET /infos.json", data, 14) == 0) {
					   byte vbusread_code;
					   vbusread_code = VBusRead(0x10);
						if (vbusread_code){
							//Serial.println(temp);
							bfill = ether.tcpOffset();
							bfill.emit_p(PSTR(
							"$F{\"Vbus\":{"
							"\"vbusread code\":$D,"
							"\"sync\":\"0x$H\","
							"\"Src address\":\"0x$H$H\","
							"\"Dst address\":\"0x$H$H\","
							"\"Protocol Version\":\"0x$H\","
							"\"Command:=\":\"0x$H$H\","
							"\"Framecount\":$D,"
							"\"Checksum\":\"0x$H\","
							"\"calc Checksum\":\"0x$H\""
							"}}"
							),header_json,vbusread_code,Buffer[0],Buffer[2],Buffer[1],Buffer[3],Buffer[4],ProtocolVersion,Buffer[6],Buffer[7],Framecnt,temp_VFD,Buffer[9],VBus_CalcCrc(Buffer, 1, 8));
							ether.httpServerReply(bfill.position());
						}
					}
					else
						if (strncmp("GET /temperatures.json", data, 22) == 0) {
							bfill = ether.tcpOffset();
							char char_value[5];
							bfill.emit_p(PSTR("$F{\"dht22\":"),header_json);
							dtostrf(dht.readHumidity(),5,1 ,char_value);
							bfill.emit_p(PSTR("{\"humidity\":$S,"),char_value);
							dtostrf(dht.readTemperature(),5,1 ,char_value);
							bfill.emit_p(PSTR("\"temperature\":$S"),  char_value);
							bfill.emit_p(PSTR("}}"));
						   ether.httpServerReply(bfill.position());
						}
						else
							if (strncmp("GET /disp_rs232.json", data, 20) == 0) {
								bfill = ether.tcpOffset();
								bfill.emit_p(PSTR("$F{\"disprs232\":"),header_json);
								disp_rs232 = (! disp_rs232);
								if (disp_rs232)
									bfill.emit_p(PSTR("\"true\"}"));
								else
									bfill.emit_p(PSTR("\"false\"}"));
							   ether.httpServerReply(bfill.position());

							}
                            else
                                if (strncmp("GET /refresh.json", data, 17) == 0) {
                                    bfill = ether.tcpOffset();
                                    bfill.emit_p(PSTR("$F{\"refresh\":"),header_json);
                                    refresh = (! refresh);
                                    if (refresh)
                                        bfill.emit_p(PSTR("\"true\"}"));
                                    else
                                        bfill.emit_p(PSTR("\"false\"}"));
                                   ether.httpServerReply(bfill.position());
                                }
                                else {
                                    ether.httpServerReplyAck(); // send ack to the request
                                    memcpy_P(ether.tcpOffset(), error_json, sizeof error_json);//only the first part will sended
                                    ether.httpServerReply_with_flags(sizeof error_json - 1,TCP_FLAGS_ACK_V|TCP_FLAGS_FIN_V);
                                }
                                
	} //if (strncmp("GET /vbus.json"

}
byte VBusRead (byte DFA) {
	/*code sortie   0 no data
	 *              3 sortie sur deuxieme Sync
	 * 				2 trop de données

	*/
	byte c;
	bool start;
	bool DFA_ok = false;
	lastTimeTimer = millis();

	int index;
	index = 0;

	while (index < 73) {
		if (Soft_serial.available()) {
			c= (byte) Soft_serial.read();
			lastTimeTimer = millis();
			if (c == 0xAA) {
				if (DFA_ok) {
					digitalWrite(LED, HIGH);
					return 3;
				}
				index = 0;
				Buffer[0]=c;
			#if debug
				Serial.println("Sync found");
			#endif
				digitalWrite(LED, LOW);
			}
			else
				if (index == 1){
					if (c == DFA)
						DFA_ok = true;
				}
			if (DFA_ok) {
				Buffer[index]=c;
			#if debug
				char s[7];
				sprintf(s, "%02X ",c);
				Serial.print(s);
			#endif
			}
			index ++;
		}
		if ((timerInterval > 0) &&  (millis() - lastTimeTimer > timerInterval )  ) {
            if (disp_rs232) {
                Serial.print("time_out ");
                Serial.println(lastTimeTimer);
            }
			return 0;

		}
	}
	digitalWrite(LED, LOW);
	return 2;
} //byte VBusRead (byte DFA)


byte extract_septep () {
	byte F;
	byte nb_crc_error =0;
	//0       SYNC byte 0XAA
	//1 2      dest address
	//3 4      source address
	//5 protocol verion
	//6 7 command
	//8 Number of payload frames
	//9 Checksum for offset 1-8
	Destination_address = Buffer[2] << 8 | Buffer[1];
	Source_address      = Buffer[4] << 8 | Buffer[3];
	Command 			= Buffer[7] << 8 | Buffer[6];
	ProtocolVersion 	= (Buffer[5]>>4) + (Buffer[5] &(1<<15));
	Framecnt = Buffer[8];
	Checksum = Buffer[9];
	calc_Checksum = VBus_CalcCrc(Buffer, 1, 8);

	///*******************  Frame 1  *******************
	F=FOffset;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum) 
		nb_crc_error ++;
    else {
        Septet=Buffer[F+FSeptet];
        InjectSeptet(Buffer,F,4);
        dtostrf(CalcTemp(Buffer[F+1], Buffer[F])  ,5,1 ,sensor1_tempc);
        dtostrf(CalcTemp(Buffer[F+3], Buffer[F+2]),5,1 ,sensor2_tempc);
    }
	///*******************  Frame 2  *******************
	F=FOffset+FLength;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum) 
		nb_crc_error ++;
    else {
        Septet=Buffer[F+FSeptet];
        InjectSeptet(Buffer,F,4);
        dtostrf(CalcTemp(Buffer[F+1], Buffer[F])  ,5,1 ,sensor3_tempc);
        dtostrf(CalcTemp(Buffer[F+3], Buffer[F+2]),5,1 ,sensor4_tempc);
    }
	///*******************  Frame 3  *******************
	F=FOffset+FLength*2;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
    if (Buffer[F+5] != calc_Checksum) {
		nb_crc_error ++;
        PumpSpeed1 =255;
    }
    else {
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
	PumpSpeed1 = ((Buffer[F] & 0X7F));
	OperatingHoursRelais1=Buffer[F+3] << 8 | Buffer[F+2];
}
	///*******************  Frame 4  *******************
	F=FOffset+FLength*3;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
    if (Buffer[F+5] != calc_Checksum) {
		nb_crc_error ++;
        PumpSpeed2 =255;
    }
    else {
        Septet=Buffer[F+FSeptet];
        InjectSeptet(Buffer,F,4);
        PumpSpeed2 = (Buffer[F+0] & 0X7F);
        OperatingHoursRelais2=Buffer[F+3] << 8| Buffer[F+2];
    }
	///*******************  Frame 5  *******************
	F=FOffset+FLength*4;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum)
		nb_crc_error ++;
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
	Scheme    =  Buffer[F+1];
	///*******************  Frame 6  *******************
	F=FOffset+FLength*5;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum)
		nb_crc_error ++;
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
	ErrorMask= Buffer[F];
	SystemTime = Buffer[F+3] << 8 | Buffer[F+2];
	///*******************  Frame 7  *******************
	F=FOffset+FLength*6;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum)
		nb_crc_error ++;
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
	///*******************  Frame 8  *******************
	F=FOffset+FLength*7;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum)
		nb_crc_error ++;
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
 //HeatQuantity = (Buffer[F + 3] << 24| Buffer[F+2]  << 16 | Buffer[F + 1] << 8 | Buffer[F]);
 HeatQuantity = (Buffer[F+2] * 65535) + word ((Buffer[F + 1] << 8 | Buffer[F]));

	//HeatQuantity = (Buffer[F + 3] << 8 | Buffer[F+2]) + word ((Buffer[F + 1] << 8 | Buffer[F]));
	///*******************  Frame 9  *******************
	F=FOffset+FLength*8;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum)
		nb_crc_error ++;
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
	Version=Buffer[F+1] << 8| Buffer[F];
	///*******************  Frame 10  *******************
	F=FOffset+FLength*9;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	if (Buffer[F+5] != calc_Checksum)
		nb_crc_error ++;
	Septet=Buffer[F+FSeptet];
	InjectSeptet(Buffer,F,4);
	dtostrf(CalcTemp(Buffer[F+1], Buffer[F])  ,5,1 ,temp_VFD);
	flow_VFD=Buffer[F+3] << 8| Buffer[F+2];
	///******************* End of frames ****************
	if (disp_rs232) {
		for (int i = 0; i < 10; i++) {
			F=FOffset+FLength * i;
			serial_print_buffer(Buffer,F,i);
		}
	}
	return nb_crc_error;
} //byte extract_septep ()

// This function converts 2 data bytes to a temperature value.
float CalcTemp(int Byte1, int Byte2) {
   int v;
	v = Byte1 << 8 | Byte2; //bit shift 8 to left, bitwise OR
	if (Byte1 == 0x00)
		v= v & 0xFF;
	if (Byte1 == 0xFF)
		v = v - 0x10000;
	return (float)((float) v * 0.1);
}

unsigned char VBus_CalcCrc(const unsigned char *Buffer, int Offset, int Length) {
	//source: VBus Protocol Specification page 9
	unsigned char Crc = 0x7F;
	for (int i = 0; i < Length; i++) {
		Crc = (Crc - Buffer [Offset + i]) & 0x7F;
	}
	return Crc;
}
// The following is needed for decoding the data
void  InjectSeptet(unsigned char *Buffer, int Offset, int Length) {
	for (unsigned int i = 0; i < Length; i++) {
		if (Septet & (1 << i)) {
			Buffer [Offset + i] |= 0x80;
		}
	}
}
void serial_print_buffer (unsigned char *Buffer,int F, int i) {
	byte calc_Checksum;
	calc_Checksum = VBus_CalcCrc(Buffer, F, 5);
	sprintf(char_buffer,"frame %02d: %03d  %03d %03d %03d",i,Buffer[F],Buffer[F+1],Buffer[F+2],Buffer[F+3]);
	Serial.print(char_buffer);
	if (Buffer[F+5] == calc_Checksum)
		Serial.println("  checksum: OK");
	else {
		Serial.print(Buffer[F+5]);
		Serial.print(" ");
		Serial.println(calc_Checksum);
	}
}

// Frame info for the Resol resol CS4 and CS plus
// modidied by Dimi
// voir doc deltasol bs+ id: 2211 
// http://danielwippermann.github.io/resol-vbus/#/#0010_1122_0100
// protocole: les bits de poids forts sont à zéro, il sont contenus dans le 5 e octet
// T° exemple 19,9°  199 D  0 D   28,6°  30 D 1 D  30 * 0.1 + 2.26 * 30
//-1,2° 244D 255D
//Offset  Size    Mask    Name                    Factor  Unit
//frame 0
//0 SYNC byte 0xAA
//1 LSB dest address appelé DFA valeur 0x10 ou 0x15
//2 MSB dest address
//3 LSB src address
//4 MSB src address
//5 protocol version
//6 LSB command  
//7 MSB command  
//      0x0100 Packet contains data for slave
//      0x0100 Packet contains data for slave
//      0x0300 Request answer of slave
//Frame 1 pour dest adress 0x0010
//10			1     Temperature sensor 1    0.1     C°
//11			1     Temperature sensor 1    25.6    C°
//12			1     Temperature sensor 2    0.1     C°
//13			1     Temperature sensor 2    25.6    C°
//frame 2
//16			1     Temperature sensor 3    0.1     C°
//17			1     Temperature sensor 3    25.6    C°
//18			1     Temperature sensor 4    0.1     C°
//19			1     Temperature sensor 4    25.6    C°
//frame 3
//22       1               Pump speed pump         %
//23       1               ?
//24      1               heure relai 1             1h
//25      1               heure relai 1             256
//frame 4
//28      2               vitesse relai 2           %
//29			?
//30      1               heure relai 2            1
//31      1               heure relai 2            256
//frame 5
//34      1               unit type       1
//35      1               system                    1
//37
//37
//frame 6
//40		0x01	sensor 1 defekt        1
//40		0x02	sensor 2 defekt        1
//40		0x04	sensor 3 defekt        1
//40		0x08	sensor 4 defekt        1
//40		0x10	sensor GFD        1
//41			error mask		256
//42 			temps en minutes	1
//43			temps			256
//frame 7
//46			status mask		1
//47			status mask		256
//48			status mask		65536
//49			status mask		16777216
//frame 8
//52			compteur energie	1	wh
//53			compteur energie	256	wh
//54			compteur energie	65536	wh
//55			compteur energie	1	wh
//frame 9
//58			sw version		0.01
//59			sw version		2.56
//60
//61
//frame 10 a verifier -> ok
//64			Temp GFD		0.1
//65			temp GFD		2.56
//66			debit1			1	l/h
//67			debit1			256	l/h

// Each frame has 6 bytes
// byte 1 to 4 are data bytes -> MSB of each bytes
// byte 5 is a septet and contains MSB of bytes 1 to 4
// byte 6 is a checksum
Shéma opto coupleur