nodemcu / nodemcu-firmware

Lua based interactive firmware for ESP8266, ESP8285 and ESP32
https://nodemcu.readthedocs.io
MIT License
7.64k stars 3.12k forks source link

uart.on to read teleinfo (EDF) for french users #466

Closed Overcrash86 closed 8 years ago

Overcrash86 commented 9 years ago

Is it possible to add an option to read french teleinfo serial datas ? i'm not developper so i have not successfully get datas and pulled to LUA. the french teleinfo is simple uart with these parameters :

i'm able to display the correct datas with these lines added to uart.c :

  char *char_teleinfo;
  int charpos;
  while (charpos<len)
    {
      c_printf("%c", buf[charpos]&0x7f);
      charpos++;
    }

but i'm unable to pull this to LUA... I just want to migrate from a big arduino to a small powerful ESP8266... the arduino code is like this :

#define startFrame 0x02
#define endFrame 0x03
void setup()
{
  Serial.begin(115200);
  Serial1.begin(1200);
}
void loop()
{
    char charIn = 0;
    if (Serial1.available())
    {
      charIn = Serial1.read() & 0x7F;
      Serial.print(charIn);
    }
    Serial.println("");
}

Regards

TerryE commented 9 years ago

Hi @Overcrash86, this issues list is for Lua developers to post issues / bugs about the firmware itself. This is a more general "howto" Q. Try one of the developer forums such as Stackoverflow or esp8266.com :smile:

TheoHarbers commented 9 years ago

I believe the teleinfo data from the French electricity meter is 1200bps 7 databits, even parity, 1 stopbit. But even parity is not supported so if you use 8 databits with no parity, then mask the msb, the data should be ok. You could then send the data through an IP socket to your server / database or whatever. I have done this before on other platforms and i will do it for the ESP8266 as soon as i have some time.

MarsTechHAN commented 9 years ago

Can we have a look about your Lua code?

Overcrash86 commented 9 years ago

hi,

my simple lua test code is : (already tried to play with stop bits, parity, etc. with no success)

uart.setup(0, 1200, 8, 0, 1, 0)
print("Init ok !")

uart.on("data",255, function(d)
    print(d)
end, 0)

with this code, i got this result:

MÏÔDÅÔAÔ 000000 B�
PPÏÔ 00 £‚
ADÃÏ 050²²60669·´ Æ�
ÏPÔAÒÉÆ HÃ.. <�
ÉSÏUSà²0 ¸�
HÃHà03·3¸¸´65 ²�
HÃHP 0²·¸09309 9�
PÔÅàHP..  �
ÉÉNSÔ± 00² Ê�
ÉÉNSÔ² 00± Ê�
ÉÉNSÔ3 00² Ì�
ÉMAر 0±9 :�
ÉMAز 0²0 3�
ÉMAØ3 0±¸ »�
PMAØ 0¸3¸0 9�
PAPP ðÊ‚[j
HHP
HàŠ0ý*õ&úÿýý
MÏÔDÅÔAÔ 000000 B�
PPÏÔ 00 £�‚
ADÃÏ 050²²60669·´ Æ�
ÏPÔAÒÉþ.. <�þÿ®55 ²0 ¸�
HÃHà03·3¸¸´65 ²�
HÃHP 0²·¸093±0 ±�
PÔÅàHP..  �
ÉÉNSÔ± 00² Ê�
ÉÉNSÔ² 00± Ê�
ÉÉNSÔ3 00² Ì�MAر 0±9 :�
ÉMAز 0²0 3�
ÉMAØ3 0±¸ »�
PMAØ 0¸3¸0 9�
PAPP 0±090 +�
HHPHÃ

instead of :

ADCO 012345678901 F
OPTARIF HC.. <
ISOUSC 20 8
HCHC 036424518 '
HCHP 026582379 =
PTEC HP..
IINST1 003 K
IINST2 000 I
IINST3 001 K
IMAX1 019 :
IMAX2 020 3
IMAX3 018 ;
PMAX 08380 9
PAPP 00970 1
HHPHC E 0
MOTDETAT 000000 B
PPOT 00 #
hallard commented 9 years ago

Hi Overcrash86 Luckily you're there, and I feel less alone ;-)

I working also for an Wifi Teleinfo with ESP8266, It's not my first try with teleinfo, I think I've got some enough experience ( see there http://hallard.me/category/teleinformation-2/ ) to suspect we have a problem.

I'm not using LUA but Arduino IDE ESP8266, and I've got the same problems, reception is absolutely not reliable at 1200 7E1, I even changed some resistors values but no luck not working 100% and the HW module I'm using is the same than I do for Arduino, Spark Core, Raspberry, PC and on all these devices, it works everytime.

As you use LUA and me just the compiler and we have same problems. I could suspect something wrong with the serial at 1200 kpbs. When I tried test sketch send/receive Serial.write(Serial.read()) at 1200 it worked fine when I'm using at init Serial.begin(1200); but as soon as I put teleinfo protocol mode (7 bits, Even Parity, 1 Stop bit) Serial.begin(1200, SERIAL_7E1); things does not works anymore (tested with putty of course because Arduino Serial Monitor does not do 7E1).

Does someone has any documentation on the value #define SERIAL_7E1 0x1a that is put in the register USC0 in HardwareSerial.cpp

uart_set_baudrate(uart, baudrate);
USC0(uart->uart_nr) = config;

may be it's just a wrong value for constant SERIAL_7E1 worth checking that is 1st time

Oh forgot to mention I also tested swapping pin with Serial.swap(), same result. I also tried with a non nodeMCU board, just basic ESP12 (so no Serial adapters or relative hardware, except mine when flashing), same thing.

hallard commented 9 years ago

Teleinfo protocol is 1200 bps, 7 bits, Parity Even; 1 stop Could you try uart.setup(0, 1200, 7, 0, 1, 0) to see if it's better ?

NodeMCU documentation on uart.setup does no tell anything about parity parameter (4th), just 0 is none, but looking into the firmware code the enum 0 looks more than EVEN and not NONE

// Parity
enum
{
PLATFORM_UART_PARITY_EVEN,
PLATFORM_UART_PARITY_ODD,
PLATFORM_UART_PARITY_NONE,
PLATFORM_UART_PARITY_MARK,
PLATFORM_UART_PARITY_SPACE
};
Overcrash86 commented 9 years ago

Bonsoir Charles,

Moi aussi je me sens moins seul !

Je trouves très compliqué pour moi non développeur d’arriver à faire quelque chose qui devrait être ultra simple…

Donc si je comprends bien, vous n’utilisez pas du LUA (donc pas nodeMCU) mais directement en C sur l’ESP ?

Si c’est le cas, je suis en mesure (avec un firmware recompilé et un pauvre fprint) d’afficher les bonnes valeurs, mais il m’est impossible par la suite de l’envoyer en LUA pour la traiter plus facilement de mon côté.

Désolé pour le retard de réponse, j’ai pas mal d’occupations en ce moment du coup c’est plus compliqué pour moi :)

PS : j’ai aussi ouvert un topic suite à la remarque de TerryE m’expliquant bien que je n’avais rien à faire ici avec ma question…

Je suppose que Charly86 c’est vous ? http://www.esp8266.com/viewtopic.php?f=21 http://www.esp8266.com/viewtopic.php?f=21&t=3425&start=0 &t=3425&start=0

De : Charles [mailto:notifications@github.com] Envoyé : samedi 27 juin 2015 01:09 À : nodemcu/nodemcu-firmware Cc : Overcrash86 Objet : Re: [nodemcu-firmware] uart.on to read teleinfo (EDF) for french users (#466)

Teleinfo protocol is 1200 bps, 7 bits, Parity Even; 1 stop Could you try uart.setup(0, 1200, 7, 0, 1, 0) to see if it's better ?

NodeMCU documentation on uart.setup does no tell anything about parity parameter (4th), just 0 is none, but looking into the firmware code the enum 0 looks more than EVEN and not NONE

// Parity enum { PLATFORM_UART_PARITY_EVEN, PLATFORM_UART_PARITY_ODD, PLATFORM_UART_PARITY_NONE, PLATFORM_UART_PARITY_MARK, PLATFORM_UART_PARITY_SPACE };

— Reply to this email directly or view it on GitHub https://github.com/nodemcu/nodemcu-firmware/issues/466#issuecomment-115913511 . https://github.com/notifications/beacon/AHnVXp0t7_tiBVZ_7mKVQvP_YRbDfEc2ks5oXdL2gaJpZM4E4jBO.gif

hallard commented 9 years ago

Bonsoir, Oui Charly86 c'est bien moi, je suis démasqué ;-) en fait j'utilise l'ESP avec l'environnement Arduino, çà fait un moment que je regarde ces chip mais je trouvais l'environnement de dev trop barbare. Maintenant avec NodeMCU c'est mieux mais je préfère l'environnement Arduino et çà marche plutôt bien maintenant, les gars d'expressif font un boulot de dingue ;-)

La mauvaise nouvelle du jour c'est qu'avec l'opto SHF6206 (le classique) ça ne fonctionne pas avec l'ESP, c'est un montage empirique qui fonctionne sur Arduino et Raspberry mais malheureusement pas sur l'ESP sauf à jouer avec les valeurs de résistances et encore c'est pas fiable. Résultat avec un vrai module téléino çà fonctionne nickel Donc le soucis ne vient pas de vous mais de l'architecture hard de l'ESP couplé au faible "fonctionnement" du montage à base du SFH6206;-)

TerryE commented 9 years ago

Roughly translated for those that can't read French (perhaps hallard can correct anything that is materially wrong). I am also not sure of some of the idioms, e.g : de dingue = amazing or botched?

@Overcrash86 wrote:

Hello Charles Good evening, I also feel less on my own! I find very difficult to get the developers to do something that should be very simple ... So if I understand correctly, you aren't using Lua (so no nodeMCU) but programming the ESP directly in C? In this case, I can display the correct values (with a recompiled firmware with a cut-down fprint), but I can't then easily send them from Lua to my end. Sorry my delated reply, I have a lot of other things to do, and now suddenly it's a lot more complicated :smile: PS: I also opened a topic (Uart.on to read teleinfo (EDF) for french users) following a comment by TerryE explaining that my question didn't belong here ... I guess that Charly86 is you?

@hallard wrote:

Yes, Charly86 is me. I am unmasked :wink: In fact I use ESP with the Arduino environment, and there was a time looking that this chip when I found the dev environment far too primitive. Now it's better with NodeMCU, but I prefer the Arduino environment and it works pretty well now. The Espressif guys did a crazy job;-)

The bad news is that the SHF6206 (classic) opto doesn't work with the ESP. There is an adaptor that works with the Arduino and Raspberry, but unfortunately not the ESP (unless you play around with the resistance values, and this isn't reliable as yet), the end result with a real teleinfo meter works (??nickel??) So the issue facing you is more the ESP architecture coupled with detailed adapter / interfaced based on the SFH6206 :wink:

Oh, the trials of this multi-national world. Think how we would cope if we all had to use Chinese!

hallard commented 9 years ago

Terry, Sorry about that French, it was just because the Teleinfo system is only used in France, and thus was easier for us to talk in French because no one from other countries are able to have this system. Anyway, problem is now solved on my side, I took time to write a dedicated article on my blog. Sorry it's in French on my blog.

TerryE commented 9 years ago

@hallard, no apologies needed. I only added my poor translation so that those with English as a first or second language can track the thread :smile:

hallard commented 9 years ago

@Terry, Your translation is pretty fine ;-) For information "Nickel" is like "F....g pretty good!" ;-)

TheoHarbers commented 9 years ago

When using 8 data bits instead of 7, the parity bit from the teleinfo will be the most significant bit in the character received.

The Start of Frame: 0x02 becomes 0x82 with parity bit, CR (0x0D) becomes 0x8D, End of Frame: 0x03 stays the same.

uart.setup( 0,  1200, 8,    0,   1,    0    ) -- NodeMCU can't do 7 databits Even parity

-- trigger receiver on receiving end of line CR 0x0D (13) => 0x8D (141) with parity bit -- following function will print teleinfo line by line, TX connected to your terminal, RX to optocoupler

uart.on("data", "\141", function(raw)

    local rec = ""
    local i

    for i = 1, #raw do
     rec = rec .. string.char(bit.band(raw:byte(i), 0x7f))  -- strip parity bit
    end

     print(rec)

  end, 0)
TheoHarbers commented 8 years ago

EDF teleinfo receiver and decoder, although not fully tested it should work. Checksum is calculated and data is send to a server. Please let me know your experience with this code, i'am sure we can make improvements.

-- -----------------------------------------------------------------------------
-- EDF TeleInfo Meter Reader for ESP8266 & NodeMcu
-- LICENCE: http://opensource.org/licenses/MIT
-- Theo Harbers harbers.theo@gmail.com
------------------------------------------------------------------------------
-- EDF Teleinfo format:
-- Start of Frame: 0x02 (0x82 with parity)
-- LF (0x0A) Label (4 to 8 bytes) SP (0x20) value (1 to 12 bytes) SP (0x20) CS (checksum byte) CR (0x0D)
-- End of Frame: 0x03

-- HCHC ( 9 bytes Wh )
-- HCHP ( 9 bytes Wh )
-- tarif: PTEC ( 4 bytes .. )
-- power: PAPP ( 5 bytes VA )

 sk = nil -- global socket discriptor
 j = ''
 t = ''

 gw = -- put here ip address of server to send the data
 pt = -- put here port number of server to send data to

-- Configure eMeter UART, only use RX to read eMeter data (1200 bps, 7, E, 2)
-- uart.setup( id,  baud, bits, par, stop, echo )
    uart.setup( 0,  1200, 8,    0,   1,    0    ) -- NodeMCU can't do 7 databits Even parity and 2 stopbits

-- trigger receiver on receiving CR 0x0D (13) => 0x8D (141) with parity bit

    uart.on("data", "\141", function(raw)

        local rec = ''
        local i,lab,val
        local cs = 0x20  -- checksum start value
        local cb = 0

        for i = 1, #raw-3 do
         cb = bit.band(raw:byte(i), 0x7f)   -- get data byte and strip parity bit
         if cb > 0x20 then cs = cs + cb end -- add to checksum anything bigger then space 0x20
         rec = rec .. string.char(cb)
        end

-- End of frame ? then output the data and clear buffer
        if rec:byte(1) == 0x03 then 
--         print(j)
         t = j  -- use temporary string t because sending is async to collecting
-- send the data to server
         sk=nil
         sk = net.createConnection(net.TCP,0) --not secure
         sk:on("connection", function() sk:send( t .. "\r\n" ) end )
         sk:on("sent", function() sk:close() end )
         sk:connect(pt, gw)
         j = ''
        end

-- if CS matches Checksum character, extract only the label and value and add to output buffer

        if string.char(bit.band(cs,0x3f) + 0x20) == string.char(bit.band(raw:byte(-2), 0x7f)) then

         lab, val = rec:match("(%u+)%s([%u%d]+)")
         j = j .. lab .. "=" .. val .. ';' -- or any other format you would like to send to server
--         print(lab .. "=" .. val)

        end

      end, 0)
devsaurus commented 8 years ago

See #719.