20221231 P1 Monitor met ESP32 (NodeMCU)
- under construction
Missie:
We gaan het telegram van de digitale meter ophalen.
Het telegram van de digitale meter (ook wel slimme meter genoemd) wordt via de P1 poort aan de buitenwereld beschikbaar gesteld.
De P1 poort van de digitale meter werkt volgens het zgn. Dutch Smart Meter Requirements protocal, in het kort DSMR.
De versie van 2016 vind je hier.
Hoofdstukken:
Stap 0 - De route van begin tot het eind.
Stap 1 - Een geschikte microprocessor uitzoeken geschikt voor de programmeertaal C.
Stap 2 - Onderzoeken of we de juiste pinnen op de ESP32 benutten.
Stap 3 - Het telegram binnen halen en decoderen.
Stap 0 - De route van begin tot het eind.
- Een geschikte microprocessor uitzoeken geschikt voor de programmeertaal C.
- De juiste pinnen op de ESP32 zoeken.
- Een telegram aanbieden
- Het telegram decoderen met de microprocessor en programmeertaal C.
- Het telegram in het terminal venster zichtbaar maken.
- Een stukje elektronica als buffer in elkaar knutselen.
- De schakeling ontwerpen en bouwen.
- De uitkomsten van het gedecodeerde signaal versturen via MQTT.
- Het MQTT signaal ontvangen op een Raspberry Pi (gebruik NodeRED).
- Met NodeRed het gedecodeerde resultaat naar een InfluxDB database sturen.
- De data die in InfluxDB is opgeslagen, zichtbaar maken op een Grafana dashboard.
Stap 1 - Een geschikte microprocessor uitzoeken geschikt voor de programmeertaal C.
Omdat we een NodeMCU bord al eerder hebben gebruikt, gaan we hiermee beginnen.
Een lijst met meest gebruikte ESP32 varianten vinden we hier.
Blijkt op een later tijdstip dat bijvoorbeeld er onvoldoende geheugen is, dan zitten we in ieder geval op de "Arduino-trein" en hoeven
we niet van voren af aan te beginnen.
De Arduino wordt in C geprogrammeerd. Dat is veel universeler dan bijvoorbeeld Python (waar ik toch al geen fan van ben).
Stap 2 - Onderzoeken of we de juiste pinnen op de ESP32 benutten.
Om te onderzoeken of we de juiste pinnen (voor UART2) op de ESP32 gebruiken gaan we het toestel uit de vorige blog
gebruiken.
Allereerst gaan we de informatie die dan van het Sparkfun bordje komt op de ESP (UART2) binnen brengen en echoëen naar het terminal venster.
Als dat lukt kunnen we de UART2 recieve pin als gevonden beschouwen.
Hier is meer informatie over de pinbezetting van de UARTS op een ESP32 te vinden.
We moeten het volgende doen:
- De pin GND van de Artemis verbinden met de GND pin van de ESP32.
- De TXD pin van de Artemis verbinden met de RXD pin van de ESP32.
Op de Artemis is pin 1 (telling begint bij 0) de Transmit pin, op de ESP is GPIO16 de Recieve pin. - De code uit de vorige blog en het telegram op de Artemis laden.
- Onderstaande code op het ESP32 bord laden.
- Beide bordjes opstarten.
- Het resultaat in CoolTerm bekijken.
P1MonitorTestUART2.ino
#define BAUDRATE0 9600 // Baudrate for the terminal program
#define CONFIG0 SERIAL_8N1 // Configuration for the terminal program
// define UART 2 (see this documentation for the pins)
// https://microcontrollerslab.com/esp32-uart-communication-pins-example/
#define BAUDRATE2 9600 // Baudrate for UART2
#define CONFIG2 SERIAL_7E1 // Configuration for UART2
#define RXD2 16 // RXD pin for UART2 = GPIO16
#define TXD2 17 // TXD pin for UART2 = GPIO17
#define SWVERSION "v0.1" // Software version
// --- Constants will NOT change ----------------------------------------------
// --- Variables will change --------------------------------------------------
uint16_t ledState = LOW; // ledState used to set the LED
uint32_t prevBlinkMillis = 0; // will store last time LED was updated
// === setup ==================================================================
// setup the system
void setup() {
// Initialize LED_BUILTIN and switch it off
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// Start serial0 as terminal
Serial.begin(BAUDRATE0, CONFIG0);
while (!Serial)
{ // wait for serial-0 ready
delay(100);
}
Serial.println("Setup: +--- Terminal window started (UART0).");
Serial.print("Setup: +--- Software version : ");
Serial.println(SWVERSION);
// Start serial2 as input, if the signal is inverterd, set the last parameter on true
Serial2.begin(BAUDRATE2, CONFIG2, RXD2, TXD2, false);
while (!Serial2)
{ // wait for serial2 ready
delay(100);
Serial.println("Setup: +--- Waiting for UART2 to start.");
}
Serial.println("Setup: +--- Serial IO started (UART2).");
} // void setup() ends
//--- void blink() blink the internal LED routine -----------------------------
void blink(uint16_t pinNr, uint16_t interval) {
//--- blinking the LED ------------------------------------------------------
// This is just to see that the program is running
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
uint32_t curBlinkMillis = millis();
// check if blink time elapsed
if (curBlinkMillis - prevBlinkMillis >= interval) {
// save the last time you blinked the LED
prevBlinkMillis = curBlinkMillis;
// if the LED is off turn it on and vice-versa:
ledState = !(digitalRead(pinNr));
digitalWrite(pinNr, ledState);
} // if blink millis elapsed
} // void blink()
// === main ===================================================================
// main program
void loop() {
if (Serial2.available()) {
Serial.println("Loop: === Serial2 is available");
while (Serial2.available()) { // echo Serial2 to Serial0
char ch = Serial2.read();
Serial.print(ch);
}
Serial.println("\n");
}
blink(LED_BUILTIN, 500);
} // void loop() ends
Het CoolTerm vernster ziet er dan uit als hier beneden.
Niet helemaal foutloos, maar we hebben in elk geval de pin voor de juiste UART te pakken.
En nu verder,
Stap 3 - Het telegram binnen halen en decoderen met de microprocessor en programmeertaal C.
3.1 - Opbouw van het telegram.
Zoals te zien in de eerste figuur van deze post heeft het telegram een gedefinieerde opbouw.
Het telegram begint altijd met een forward slash "/" gevolgd door het merk en serienummer van de meter.
Elke regel wordt afgesloten met "\n" en bevat de code, de waarde en de eenheid van de opname.
Het telegram eindigt met een ampersand "!", gevolgd door de CRC16 code.
De opbouw van het telegram is ook in de vorige blog onder TELEGRAM.TXT te zien.
We gaan veel van deze github gebruiken voor het binnenhalen en het decoderen.
De verschillende P1 specificaties zijn hier beneden in tabel vorm opgenomen:
parameter | DSMR 2.0 | DSMR 4.2 | ESMR 5.0 |
---|---|---|---|
Baud rate | 9600 | 115200 | 115200 |
Data bits | 7 | 7 | 8 |
Parity | Even | Even | None |
Stop bits | 1 | 1 | 1 |
Documentatie |
Slimme_meter_DSMR22.pdf |
Slimme_meter_DSMR42.pdf |
Slimme_meter_ESMR50.pdf |