Arduino Mega slimme meter uitlezen met Solarmeter Harold65

Arduino specifieke Software
Gebruikers-avatar
Berichten: 117
Geregistreerd: 10 Jun 2019, 12:16
Woonplaats: Amsterdam

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor master64nl » 19 Jun 2019, 06:10

Oh okay, maar kunnen we niet beginnen met dit:
- Seriele buffer verhogen (Arduino Mega has Flash 256k bytes (of which 8k is used for the bootloader) SRAM 8k bytes EEPROM 4k byte).
- De afhandeling van een regel
- Deze code Serial.println(bufpos); weg commentariëren
- Alle sscanf() te vervangen door strncmp()
- if (sscanf ... vervangen voor else if (sscanf ...

Advertisement

Gebruikers-avatar
Berichten: 117
Geregistreerd: 10 Jun 2019, 12:16
Woonplaats: Amsterdam

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor master64nl » 19 Jun 2019, 10:28

https://gathering.tweakers.net/forum/list_messages/1858733 is iemand die er iets mee gedaan heeft. Ik had hier toen op gereageerd maar helaas geen respons gekregen. Maar er staat wel een code op.

#include <SoftwareSerial.h>

SoftwareSerial softSerial(2, 3); // RX, TX

#define BUFSIZE 1024
char buffer[BUFSIZE];
int bufpos = 0;
bool reading = false;
bool lastLine = false;

void setup() {
Serial.begin(115200);
delay(1);
softSerial.begin(9600);
softSerial.println("Started, waiting for data...");
}

void loop() {
while(Serial.available()) {
char c = Serial.read();

if(reading) {
if ((lastLine && c == '\n') || bufpos == BUFSIZE-1) {
// Reached end of P1 packet (or prevent buffer overflow).
buffer[bufpos] = '\0';
softSerial.println(buffer);
softSerial.println("--------------------");
softSerial.flush();
bufpos = 0;
reading = false;
lastLine = false;

// Clear the P1 serial input buffer.
while(Serial.available()) {
char c2 = Serial.read();
}
} else {
if(c == '!') {
lastLine = true;
}
buffer[bufpos++] = c;
}
} else if(c == '/') {
// Detected start char. Start reading the new P1 packet...
reading = true;
buffer[bufpos++] = c;
}
}
}

Berichten: 17
Geregistreerd: 13 Jun 2019, 14:24

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor Handz » 19 Jun 2019, 15:44

Dat is een interessante invalshoek die misschien best eens zou kunnen werken. De Mega krijgt op die manier wat tijd om het bij te sloffen en 1 per 10 seconde uitlezen is ruim voldoende. Als ik nou goed was in programmeren......

Daarnaast blijkt uit het parallel/backup-traject ook dat er nog leven na de Arduino Mega mogelijk is. Ik heb de Nodemcu V3 ESP8266 nu lopen met behulp van de code van https://github.com/jantenhove/P1-Meter-ESP8266.

Het valt niet echt mee om alles in te stellen en het vraagt een behoorlijk steile leercurve en anders was ik misschien gewoon vergeten hoeveel ik heb lopen prutsen met de Solarmeter code van Harold een aantal jaar geleden. Maar goed. Het werkt min of meer. Mijn P1 kabel werkt erg slecht op 3.3V benodigd voor de Nodemcu. Het "voordeel" is dat de telegrammen veel fouten bevatten en de CRC controle dus erg goed getest wordt. Die werkt feilloos, alleen goede telegrammen worden doorgestuurd naar Domoticz en de ESP8266 heeft geen enkele moeite met 115200 baudrate. Nu proberen de kabel met een logical levelshifter te verbeteren zodat de telegrammen foutloos doorkomen. Binnenkort hopelijk meer.

Gebruikers-avatar
Berichten: 117
Geregistreerd: 10 Jun 2019, 12:16
Woonplaats: Amsterdam

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor master64nl » 19 Jun 2019, 16:09

Misschien dat Koepel het licht met die nieuwe code ziet. Het zou leuk zijn als Harold zijn Solarmeter geupdate word en gewoon kan werken op de Arduino Mega. Er zijn nog genoeg mensen die dit hebben draaien maar dan niet de slimme meter er op. Ik heb ook nog 2 collega`s die Solarmeter gebruiken maar geen slimme meter aangesloten krijgen.

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor Koepel » 19 Jun 2019, 17:46

master64nl schreef:Misschien dat Koepel het licht met die nieuwe code ziet

Nou, nee, ik wil liever niet beginnen aan SoftwareSerial.

Wanneer het RTS signaal bij iedereen hetzelfde werkt, dan kan dat misschien ook gebruikt worden.
Dan is het nodig dat de meter zich stil houdt en pas als er 5V op de RTS gezet wordt, dat er dan binnen 1 seconde een telegram komt.
Ik kwam een oude opgeslagen post uit 2015 tegen die dat doet via pin 13:
https://archive.codeplex.com/?p=solarmeter#, klik op "discussions" en dan op "Landis+gyr E350".

Voor wie zijn Arduino installatie om zeep wil helpen, zoek eens naar het bestand "HardwareSerial.h".
Dat staat misschien ergens hier: arduino-1.8.9/hardware/arduino/avr/cores/arduino/HardwareSerial.h

Voeg dan "#define SERIAL_RX_BUFFER_SIZE 1024" toe, na de #include "Stream.h"

Code: Alles selecteren
#include "Stream.h"

// Deze regel tijdelijk toegevoegd ! Niet in het echt gebruiken !
#define SERIAL_RX_BUFFER_SIZE 1024

// Define constants and variables for buffering incoming serial data.  We're

Dan worden alle RX buffers 1024 (daar past een geheel telegram in). Volgens mij zijn twee seriële poorten in gebruikt, dus dit geintje kost 2kbyte aan ram.

Ik weet niet of jullie het doorhebben, maar dit kan nog jaren zo door gaan. Ik zie nog steeds geen duidelijke oplossing waarvan ik weet dat het gaat werken.

Gebruikers-avatar
Berichten: 117
Geregistreerd: 10 Jun 2019, 12:16
Woonplaats: Amsterdam

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor master64nl » 19 Jun 2019, 19:31

Hi Koepel,

Zonder hulp van iemand die kennis heeft gaat het mij nooit lukken. Ik zal eerst een half jaar moeten leren voordat ik begrijp wat er gezegd word hier op het forum. Ik heb net jouw link gelezen. Het grappige is dat hij die persoon van het forum wijhebbenzon die het voor elkaar had. Ik heb hem gemaild en gevraagd of hij kan helpen. Zijn verhaal snap ik zo ver dat de oscillator moeite heeft met de baudrate en dat het te veel data is om te verwerken. Je hebt al heel veel info gegeven en wij hebben zelf ook wat gevonden zoals die code die ik laatst vond. Is niets bruikbaar?

Berichten: 17
Geregistreerd: 13 Jun 2019, 14:24

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor Handz » 19 Jun 2019, 22:06

Kop op, het gaat vast lukken. Maar dan wel met hardware die de nieuwe ESMR 5.0 meters goed kan bijbenen. Ik krijg steeds meer vertrouwen in de Nodemcu V3 ESP8266 oplossing. Data exporteren naar Domoticz en dat laten draaien op een Raspberry Pi. Heb ik eindelijk een reden om ook eens zo'n boardje te kopen.
Ik zag dat Domoticz al standard mijn inverter ondersteunt (SolarMax) en zelfs mijn Nefit Easy. Er is zelfs een scriptje die de data in Domoticz door kan sturen naar PVOutput, dus die kan ik ook blijven gebruiken.
De overgebleven Arduino Mega kan ik dan gaan gebruiken om met RFLink mijn lampen te gaan schakelen.

Maar de eerste stap is foutloos de telegrammen binnenhalen van mijn Sagemcom T210-D. Morgen krijg ik mijn 5V-3.3V level shifter binnen dus ben benieuwd of het gaat lukken!

Gebruikers-avatar
Berichten: 117
Geregistreerd: 10 Jun 2019, 12:16
Woonplaats: Amsterdam

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor master64nl » 20 Jun 2019, 06:12

En dit http://www.esp8266thingies.nl/wp/shop/
De maker hiervan heeft mij geantwoord dat hij het zo kan maken dat de data naar de Arduino gestuurd kan worden.

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor Koepel » 20 Jun 2019, 14:20

Toevallig vind ik millis() en een Finite State Machine leuk, zoals je hier kunt zien: https://github.com/Koepel/Fun_with_millis.

Het vertragen van de bytes van een telegram is typisch iets om met millis() te doen :geek:
Dus heb ik voor de grap een "P1 poort vertrager" gemaakt :shock:
En natuurlijk heb ik daar millis() en een Finite State Machine in gestopt :twisted: :lol:

Je hebt een Arduino Leonardo of Arduino Micro of Arduino Pro Micro nodig die op 16MHz en 5V werkt.
Het maakt niet uit welk merk of welke bootloader er op zit, alleen de hardware seriële poort op pin 0 en pin 1 wordt gebruikt, en eventueel pin 13.
https://www.aliexpress.com/item/Pro-Micro-ATmega32U4-5V-16MHz-Replace-ATmega328-For-arduino-Pro-Mini-With-2-Row-Pin-Header/32957185656.html
https://www.tinytronics.nl/shop/nl/arduino/main-boards/pro-micro-5v-16mhz

Het is niet getest of de vertraagde data ook helpt voor de library van Harold :roll:

cpp code
// P1 poort vertrager
// ------------------
//
// Board
// -----
// Arduino Leonardo/Micro/Pro Micro of een andere ATmega32U4.
// De sketch is niet bedoeld voor een Arduino Uno en zeker niet voor SoftwareSerial.
//
// Werking
// -------
// De 115200 8N1 seriele data wordt ingelezen en vertraagd verstuurd.
// Er wordt niet vaker dan 1 keer per 8 seconden ingelezen.
// Het versturen wordt uitgesmeerd over zo'n 3 seconden.
// Let op: het versturen gaat ook op 115200 baud.
//
// Versies
// -------
// Versie 1, 20 juni 2019
// Eerste versie, het lijkt goed te gaan. Er zullen nog wel fouten in zitten.
//
//
// Aansluitingen
// -------------
// Signaal inverteren en naar pin 0 (RX) van Arduino Leonardo.
// RTS signaal aan pin 13 of aan 5V.
// De sketch is zo geschreven dat RTS ook vast met 5V verbonden mag zijn.
// Pin 1 (TX) gaat verder naar bijvoorbeeld de Arduino Mega 2560.
//
// Benamingen
// ----------
// SerialUSB : de CDC USB poort van de Leonardo. De naam "Serial" mag ook.
// Serial1 : de hardware seriele poort op pin 0 (RX) en pin 1 (TX)
//

// #define ENABLE_DEBUG

const int rtsPin = 13;

enum state_ENUM
{
STATE_IDLE, // niets te doen, maar het versturen gaat gewoon door
STATE_START, // begin met het klaarmaken om een telegram te gaan lezen
STATE_ZOEK_BEGIN, // zoek naar de '/' voor het begin van een telegram
STATE_INLEZEN, // bezig met inlezen van telegram
STATE_CHECKSUM, // inlezen van de checksum (wordt nog niet gecontroleerd).
} state;

byte buffer[1024]; // 1024 zou voldoende moeten zijn voor een telegram
size_t indexIn = 0; // index van de eerste vrije positie
size_t indexOut = 0; // index van het byte dat nog verzonden moet worden.


unsigned long previousMillisSlowIn;
const unsigned long intervalSlowIn = 8000UL; // probeer eens per 8 seconden een telegram in te lezen.

unsigned long previousMillisSlowOut;
const unsigned long intervalSlowOut = 3; // verstuur iedere 3 milliseconden een byte

unsigned long previousMillisTimeout;
const unsigned long intervalTimeout = 1500UL; // timeout voor het inlezen van een telegram


void setup()
{
Serial1.begin( 115200); // Voor de P1 poort. P1 poort -> RX. TX -> Arduino Mega.

pinMode( rtsPin, OUTPUT);

#ifdef ENABLE_DEBUG
SerialUSB.begin( 9600); // voor de seriele monitor op de computer

// Wacht 20 seconden om de seriele monitor te openen
unsigned long effeWachteMillis = millis();
while( millis() - effeWachteMillis < 20000UL)
{
if( SerialUSB) // seriele monitor geopend ?
break;
}

SerialUSB.println(F( "De sketch loopt."));
#endif
}


void loop()
{
unsigned long currentMillis = millis();

// ------------------------------------
// Inlezen van het telegram
// ------------------------------------

if( currentMillis - previousMillisSlowIn >= intervalSlowIn) // activeer het iedere 8 seconden
{
previousMillisSlowIn = currentMillis;
state = STATE_START;
}


switch( state)
{
case STATE_IDLE:
break;

case STATE_START:
// Er kunnen losse stukken van vorige telegrammen in de RX buffer zitten,
while( Serial1.available() > 0)
{
Serial1.read(); // lees byte en gooi het weg
}
digitalWrite( rtsPin, HIGH); // RTS hoog
state = STATE_ZOEK_BEGIN;
break;

case STATE_ZOEK_BEGIN:
if( Serial1.available() > 0)
{
// Hier doe ik een "peek", daarmee blijft de '/' behouden, en die wordt
// dan ook in de buffer opgeslagen en later verstuurd.
byte inChar = (byte) Serial1.peek();
if( inChar != '/')
{
Serial1.read(); // niet het begin, gooi deze byte weg.
}
else
{
state = STATE_INLEZEN;
previousMillisTimeout = currentMillis; // zet de timeout klaar
}
}
break;

case STATE_INLEZEN:
if( Serial1.available() > 0)
{
byte inChar = (byte) Serial1.read();

buffer[indexIn] = inChar;

indexIn = verhoogIndexIn( indexIn);

if( inChar == '!') // einde in zicht ? hierna komt de checksum
{
state = STATE_CHECKSUM;
}
}

if( currentMillis - previousMillisTimeout >= intervalTimeout)
{
// Als er iets fout ging, dan terug naar idle.
// De status van de buffer en variabelen komt bij het volgende telegram weer in orde.
state = STATE_IDLE;
}
break;

case STATE_CHECKSUM:
if( Serial1.available() > 0)
{
byte inChar = (byte) Serial1.read();

buffer[indexIn] = inChar;

indexIn = verhoogIndexIn( indexIn);

if( inChar == '\n') // dit is echt het einde van het telegram ?
{
digitalWrite( rtsPin, LOW); // zet RTS uit
state = STATE_IDLE;
}
}

if( currentMillis - previousMillisTimeout >= intervalTimeout)
{
// Als er iets fout ging, dan terug naar idle.
// De status van de buffer en variabelen komt bij het volgende telegram weer in orde.
state = STATE_IDLE;
}
break;
}


// ------------------------------------
// Vertraagd versturen van het telegram
// ------------------------------------

if( currentMillis - previousMillisSlowOut >= intervalSlowOut) // verstuur iedere 3 ms
{
previousMillisSlowOut = currentMillis;

if( indexOut != indexIn) // zijn er nog bytes om te versturen ?
{
Serial1.write( buffer[indexOut]);

#ifdef ENABLE_DEBUG
SerialUSB.write( buffer[indexOut]);
#endif

indexOut++;
if( indexOut >= sizeof( buffer))
indexOut = 0;
}
}
}


// Kleine hulpfunctie om de index van het inlezen te verhogen,
// zonder te overschrijven wat nog weggeschreven moet worden.
size_t verhoogIndexIn( size_t oud)
{
size_t newIndex = oud + 1;

if( newIndex >= sizeof( buffer))
newIndex = 0;

if( newIndex == indexOut)
{
// Het inlezen heeft het versturen ingehaald. Dat kan niet.
// Misschien was het telegraam te groot, of de buffer te klein,
// of de baudrate verkeerd.
#ifdef ENABLE_DEBUG
SerialUSB.println(F( "Error: Inlezen heeft versturen ingehaald"));
#endif
newIndex = oud; // terug naar de oude index
}

return( newIndex);
}

Gebruikers-avatar
Berichten: 117
Geregistreerd: 10 Jun 2019, 12:16
Woonplaats: Amsterdam

Re: Arduino Mega slimme meter uitlezen met Solarmeter Harold

Berichtdoor master64nl » 20 Jun 2019, 15:02

Ehhh, indrukwekkend maar dat komt omdat ik er niets van snap :D
Printje bovenop de Mega solderen en dan die sketch in het printje schieten via usb. En dan, klaar?

case STATE_CHECKSUM:
if( Serial1.available() > 0)
{
byte inChar = (byte) Serial1.read();

Serial1 zit op pin 19 op de Arduino Mega. Of is dit Serial1 van het nieuwe printje en die zit vast op pin? Serial is meestal pin 0.

VorigeVolgende

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: otboizirovug en 18 gasten