Téléinfo sans fil avec Arduino – Partie 2 : le capteur

Téléinfo sans fil avec Arduino – Partie 2 : le capteur

Transformation du signal

Comme on a vu dans la partie 1, le signal est composé d’une porteuse à 50kHz présente pour représenter un 0 et absente pour représenter un 1.

Détail de la trame téléinfo

Il va d’abord falloir convertir ce signal en vrai trame série avec les mêmes paramètres de transmission, à savoir 1200 7E1 (1200 baud, 7bits, parité paire, 1 bit de stop).

Trame téléinfo en jaune et trame décodée en bleu
Zoom sur la trame décodée

Le schéma

Schéma de l’émetteur téléinfo

A la base, le circuit est fait pour tourner sur un Atmega328p seul, sans être un arduino. Le circuit est alimenté avec un chargeur de téléphone portable sous 5V. Le bloc du bas basé sur un optocoupleur 6N138 permet de convertir le signal téléinfo en signal TTL compréhensible par l’uart de l’Atmega. Si on utilise un arduino, la partie conversion 5V vers 3.3V ainsi que la partie horloge (le quartz et ses deux condensateurs) sont inutiles car intégrées à l’arduino.

 

Le programme

Le programme est prévu pour une installation avec heures creuses et heures pleines (HCHC et HCHP). Pour d’autres types de contrat (Base ou Tempo) il est nécessaire de le modifier.

#include <nRF24L01.h>
#include <printf.h>
#include <RF24.h>
#include <RF24_config.h>
#include <stdint.h>
#include <avr/pgmspace.h>
#include <SoftwareSerial.h>

/* COMMON CONFIG*/
#define RF24_CH 25
#define DEBUG 0
/* ------- */

#define CNT_CS 180
#define CNT_PA 5
#define VT_PIN 1
#define RF24_ON 7
#define BUFFER_TELEINFO_SIZE 768
#define START_FRAME 0x02
#define END_FRAME 0x03
#define START_LINE 0x0A
#define END_LINE 0x0D
#define END_DATA 0x04

/* COMMON */
uint16_t nodeId = 1;
uint8_t node_address[5] = {"1Node"};
uint8_t server_address[5] = {"2Node"};
/* ------- */

RF24 radio(9,10);

uint8_t plainRadioBuffer[32] = {0};
char bufferTeleinfo[BUFFER_TELEINFO_SIZE] = {0};
uint16_t bufferTeleinfoPos = 0;
char newChar = 0;
uint8_t serialStatus = 0;
bool readyForData = false;
uint32_t hchp = 0;
uint32_t hchc = 0;
char adco[12] = {0};
char opratif[4] = {0};
uint8_t isousc = 0;
char ptec[5] = {0};
uint8_t iinst = 0;
uint8_t adps = 0;
uint8_t imax = 0;
uint16_t papp = 1;
char hhphc = 0;
char motdetat[6] = {0};
uint16_t cntCS = 0;
uint16_t cntPA = 0;

#if DEBUG==1
SoftwareSerial cptSerial(2, 3);
#endif

void setup_radio(){
radio.begin();
radio.setChannel(RF24_CH);
radio.setDataRate(RF24_250KBPS);
radio.setPALevel(RF24_PA_MAX);
radio.setCRCLength(RF24_CRC_16);
radio.setRetries(3, 15);
radio.setAutoAck(1);
radio.openReadingPipe(1, node_address);
radio.openWritingPipe(server_address);

#if DEBUG==1
radio.printDetails();
#endif
}

void setup() {
delay(100);

#if DEBUG==1
Serial.begin(115200);
printf_begin();
Serial.println(F("Setup"));
#endif
setup_radio();

//start teleinfo listening
#if DEBUG==1
cptSerial.begin(1200);
#else
Serial.begin(1200, SERIAL_7N1);
#endif

}

void incCnt(){
++cntCS;
++cntPA;
}



void serialEvent() {

#if DEBUG==1
while (cptSerial.available()) {
newChar = (char)(cptSerial.read() & 0x7F);
#else
while (Serial.available()) {
newChar = (char)(Serial.read() & 0x7F);
#endif

if(newChar == START_FRAME){
//new frame, reset the buffer
#if DEBUG==1
Serial.println();
#endif
bufferTeleinfoPos = 0;
readyForData = true;
}
else if(readyForData && newChar == END_FRAME){
readyForData = false;

#if DEBUG==1
cptSerial.end();
Serial.println(F("-------"));
#else
Serial.end();
#endif

incCnt();
parseData(bufferTeleinfoPos);
sendPA_IFN();
sendCS_IFN(false);

#if DEBUG==1
cptSerial.begin(1200);
#else
Serial.begin(1200, SERIAL_7N1);
#endif
}
else if(readyForData && newChar == END_DATA){
//End of transmission (during telereport)
bufferTeleinfoPos = 0;
readyForData = false;
}
else if(readyForData && bufferTeleinfoPos<(BUFFER_TELEINFO_SIZE-2)){
#if DEBUG==1
Serial.print(newChar);
#endif
bufferTeleinfo[bufferTeleinfoPos] = newChar;
++bufferTeleinfoPos;
}
}

}



void parseData(uint16_t bufferTeleinfoMaxPos){
bufferTeleinfo[bufferTeleinfoMaxPos] = '\0';

uint16_t offset = 0;
char* startPtr = NULL;
char* endPtr = NULL;
uint16_t startPos = 0;
uint16_t endPos = 0;

while(true)
{
startPtr = strchr(bufferTeleinfo + offset, START_LINE);
endPtr = strchr(startPtr, END_LINE);
if(startPtr == 0 || endPtr == 0) break;

startPos = startPtr - bufferTeleinfo;
endPos = endPtr - bufferTeleinfo;

offset = endPos;


//process the checksum
uint16_t iLoop = 0;
uint8_t sum = 0;
uint16_t frameLength = endPos-startPos;
for(iLoop=1; iLoop<(frameLength-2); iLoop++)
{
sum = sum + bufferTeleinfo[startPos+iLoop];
}
sum = (sum & 0x3F) + 0x20;

if(sum == bufferTeleinfo[endPos-1])
{
if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("ADCO "), 5) == 0){
strlcpy(adco, &bufferTeleinfo[startPos+6], 12);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("HCHP "), 5) == 0){
hchp = atol(&bufferTeleinfo[startPos+6]);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("HCHC "), 5) == 0){
hchc = atol(&bufferTeleinfo[startPos+6]);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("OPTARIF "), 8) == 0){
strlcpy(opratif, &bufferTeleinfo[startPos+9], 4);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("ISOUSC "), 7) == 0){
isousc = atol(&bufferTeleinfo[startPos+8]);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("PTEC "), 5) == 0){
if(strncmp(ptec, &bufferTeleinfo[startPos+6], 4) != 0){
memcpy(ptec, &bufferTeleinfo[startPos+6], 4);
sendCS_IFN(true);
}
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("IINST "), 6) == 0){
iinst = atol(&bufferTeleinfo[startPos+7]);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("IMAX "), 5) == 0){
imax = atol(&bufferTeleinfo[startPos+6]);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("PAPP "), 5) == 0){
papp = atol(&bufferTeleinfo[startPos+6]);
}
else if(strncmp_P(&bufferTeleinfo[startPos+1], PSTR("HHPHC "), 6) == 0){
//strlcpy(hhp, &bufferTeleinfo[startPos+7], 1);
}
else if (strncmp_P(&bufferTeleinfo[startPos+1], PSTR("ADPS "), 5) == 0){
adps = atol(&bufferTeleinfo[startPos+6]);
}
}
}
}


void sendCS_IFN(bool force ){
if(cntCS >= CNT_CS || force)
{
memcpy(plainRadioBuffer, "CS", 2);
memcpy(plainRadioBuffer+2, &hchp, 4);
memcpy(plainRadioBuffer+6, &hchc, 4);
memcpy(plainRadioBuffer+10, &ptec, 4);
radio.write(plainRadioBuffer, 32);
cntCS = 0;
}
}

void sendPA_IFN(){
if(cntPA >= CNT_PA)
{
memcpy(plainRadioBuffer, "PA", 2);
memcpy(plainRadioBuffer+2, &papp, 4);
memset(plainRadioBuffer+6, 0, 24);
radio.write(plainRadioBuffer, 32);
cntPA = 0;
}
}


void loop() {
serialEvent();
}

Installation

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *