Bonjour à tous, je post sur ce forum pour avoir de l'aide concernant un module arduino nano avec montage pour teleinfo linky + envoi RF en simulant une sonde oregon.
Voici le bout de code
/***********************************************************************
Récepteur TIC Linky
Mode historique
V03 : External SoftwareSerial. Tested OK on 07/03/18.
V04 : Replaced available() by new(). Tested Ok on 08/03/18.
V05 : Internal SoftwareSerial. Cf special construction syntax.
V06 : Separate compilation version.
***********************************************************************/
/***************************** Includes *******************************/
#include <string.h>
#include <Streaming.h>
#include "LinkyHistTIC.h"
#include <SoftwareSerial.h>
/****************************** Defines *******************************/
/****************************** Constants *****************************/
const uint8_t pin_LkyRx = 8;
const uint8_t pin_LkyTx = 3; /* !!! Not used but reserved !!!
* Do not use for anything else */
const byte TX_PIN = 3; //emetteur 433 MHZ
const unsigned long TIME = 488;
const unsigned long TWOTIME = TIME*2;
/************************* Global variables ***************************/
unsigned long chksum_CM180;
#define SEND_HIGH() digitalWrite(pin_LkyTx, HIGH)
#define SEND_LOW() digitalWrite(pin_LkyTx, LOW)
byte OregonMessageBuffer[13]; // OWL180
unsigned long PAPP_arrondi;
int PAPP;
unsigned long long HCP;
/************************* Object instanciation ***********************/
LinkyHistTIC Linky(pin_LkyRx, pin_LkyTx);
/**************************** Routines ******************************/
/**************************** Functions ******************************/
/**
* \brief Send logical "0" over RF
* \details azero bit be represented by an off-to-on transition
* \ of the RF signal at the middle of a clock period.
* \ Remenber, the Oregon v2.1 protocol add an inverted bit first
*/
inline void sendZero(void)
{
SEND_LOW();
delayMicroseconds(TIME);
SEND_HIGH();
delayMicroseconds(TIME);
}
/**
* \brief Send logical "1" over RF
* \details a one bit be represented by an on-to-off transition
* \ of the RF signal at the middle of a clock period.
* \ Remenber, the Oregon v2.1 protocol add an inverted bit first
*/
inline void sendOne(void)
{
SEND_HIGH();
delayMicroseconds(TIME);
SEND_LOW();
delayMicroseconds(TIME);
}
/**
* \brief Send a buffer over RF
* \param data Data to send
* \param size size of data to send
*/
void sendData(byte *data, byte size)
{
for(byte i = 0; i < size; ++i)
{
(bitRead(data[i], 0)) ? sendOne() : sendZero();
(bitRead(data[i], 1)) ? sendOne() : sendZero();
(bitRead(data[i], 2)) ? sendOne() : sendZero();
(bitRead(data[i], 3)) ? sendOne() : sendZero();
(bitRead(data[i], 4)) ? sendOne() : sendZero();
(bitRead(data[i], 5)) ? sendOne() : sendZero();
(bitRead(data[i], 6)) ? sendOne() : sendZero();
(bitRead(data[i], 7)) ? sendOne() : sendZero();
}
}
/**
* \brief Send an Oregon message
* \param data The Oregon message
*/
void sendOregon(byte *data, byte size)
{
sendPreamble();
sendData(data,size);
sendPostamble();
}
/**
* \brief Send preamble
* \details The preamble consists of 10 X "1" bits (minimum)
*/
inline void sendPreamble(void)
{
for(byte i = 0; i < 10; ++i) //OWL CM180
{
sendOne();
}
}
/**
* \brief Send postamble
*/
inline void sendPostamble(void)
{
for(byte i = 0; i <4 ; ++i) //OWL CM180
{
sendZero() ;
}
SEND_LOW();
delayMicroseconds(TIME);
}
void encodeur_OWL_CM180()
{
OregonMessageBuffer[0] =0x62; // imposé
OregonMessageBuffer[1] =0x80; // GH G= non décodé par RFXCOLM, H = Count
//OregonMessageBuffer[3] =0xE1; // KL K sert pour puissance instantanée, L sert pour identifiant compteur
PAPP_arrondi=long(long(PAPP)*497/500/16);
// améliore un peu la précision de la puissance apparente encodée (le CM180 transmet la PAPP * 497/500/16)
if ((float(PAPP)*497/500/16-PAPP_arrondi)>0.5)
{
++PAPP_arrondi;
}
OregonMessageBuffer[3]=(PAPP_arrondi&0x0F)<<4;
//OregonMessageBuffer[4] =0x00; // MN puissance instantée = (P MN K)*16 soit : (P*16*16*16 + M*16*16 +N*16+K)*16*500/497. attention RFXCOM corrige cette valeur en multipliant par 16 puis 500/497.
OregonMessageBuffer[4]=(PAPP_arrondi>>4)&0xFF;
//OregonMessageBuffer[5] =0xCD; // OP Total conso : YZ WX UV ST QR O : Y*16^10 + Z*16^9..R*16 + O
OregonMessageBuffer[5] =((PAPP_arrondi>>12)&0X0F)+((HCP&0x0F)<<4);
//OregonMessageBuffer[6] =0x97; // QR sert total conso
OregonMessageBuffer[6] =(HCP>>4)&0xFF;
//OregonMessageBuffer[7] =0xCE; // ST sert total conso
OregonMessageBuffer[7] =(HCP>>12)&0xFF; // ST sert total conso
//OregonMessageBuffer[8] =0x12; // UV sert total conso
OregonMessageBuffer[8] =(HCP>>20)&0xFF; // UV sert total conso
//OregonMessageBuffer[9] =0x00; // WX sert total conso
OregonMessageBuffer[9] =(HCP>>28)&0xFF;
//OregonMessageBuffer[10] =0x00; //YZ sert total conso
OregonMessageBuffer[10] =(HCP>>36)&0xFF;
chksum_CM180= 0;
for (byte i=0; i<11; i++)
{
chksum_CM180 += long(OregonMessageBuffer[i]&0x0F) + long(OregonMessageBuffer[i]>>4) ;
}
chksum_CM180 -=2; // = =b*16^2 + d*16+ a ou [b d a]
//OregonMessageBuffer[11] =0xD0; //ab sert CHECKSUM somme(nibbles ci-dessuus)=b*16^2 + d*16+ a + 2
OregonMessageBuffer[11] =((chksum_CM180&0x0F)<<4) + ((chksum_CM180>>8)&0x0F);
//OregonMessageBuffer[12] =0xF6; //cd d sert checksum, a non décodé par RFXCOM
OregonMessageBuffer[12] =(int(chksum_CM180>>4)&0x0F); //C = 0 mais inutilisé
}
/****************************** Setup *******************************/
void setup()
{
/* Initialise serial link */
Serial.begin(9600);
/* Initialise the Linky receiver */
Linky.Init();
Serial << F("Bonjour") << endl;
}
/******************************* Loop *********************************/
void loop()
{
Linky.Update();
if (Linky.baseIsNew())
{
Serial << F("Index base = ") << Linky.base() << F(" Wh") << endl;
}
if (Linky.iinstIsNew())
{
Serial << F("I instant. = ") << Linky.iinst() << F(" A") << endl;
}
if (Linky.pappIsNew())
{
Serial << F("Puis. app. = ") << Linky.papp() << F(" VA") << endl;
PAPP = int(Linky.papp());
Serial << F("Valeur = ")<< PAPP << endl;
}
encodeur_OWL_CM180();
sendOregon(OregonMessageBuffer, sizeof(OregonMessageBuffer)); // Send the Message over RF
};
Là où je commence à péter un câble c'est de coupler la reception des datas du linky et l'envoi du RF.
Je pense que j'ai une incompréhension dans la partie gestion des Serial. En effet, si dans la partie setup je commente le Linky.Init(); et en mettant une valeur de PAPP à la main, l'envoi en RF fonctionne parfaitement. Si je décommente Linky.Init(); pas d'envoi en RF.
J'ai bien remarqué également que d'activer l'encoding en OWL génére des erreurs dans la collecte des datas du linky. En jouant sur la variable TIME = 488 à 25 cela ne perturbe plus la récup des datas mais une valeur aussi faible ne permet pas l'envoi en RF. Bref je dois merd... sur la gestion des Serial. J'ai bien tenté de séparer avec des softwareserial différent mais avec une lib .cpp + un softwareserial dans le code direct cela ne fait pas bon ménage.... Une idée ? Merci à vous.