virtuele P1 Kabel

[ 1,928 keer bekeken / views ]

Wat is het

Het is een (héél lang) “verlengsnoer” voor de P1 poort van de Slimme Meter …

… maar dan zonder fysieke kabel!

Door de Virtual P1 Cable kan een DSMR-uitlees apparaat (bijvoorbeeld een DSMR-logger) op afstand de telegrammen van de Slimme Meter lezen.

Waarom

Ik heb een aantal variaties van de DSMR-logger (“Slimme Meter uitlezer”) ontwikkeld en op deze website beschreven. De laatste iteratie is de DSMR-logger32 die als processor een ESP32 gebruikt. Ik heb deze DSMR-logger32 ontwikkeld om meer mogelijkheden (processing power, geheugen, programma grootte en de aansluitingen voor een shield) te hebben. De ESP32 zit gewoon een stuk ruimer “in z’n jasje” dan de voorheen gebruikte ESP8266.

Maar toen de DSMR-logger32 klaar was en ik hem op mijn Slimme Meter aansloot wilde hij niet opstarten. Wat bleek is dat de opstart stroom (inrush current) van de ESP32 vele malen hoger is dan de stroom die de Slimme Meter kan leveren. 

The operating voltage of ESP32 ranges from 2.3 V to 3.6 V. When using a single-power supply, the recommended voltage of the power supply is 3.3 V, and its recommended output current is 500 mA or more.
See here.

De consequentie hiervan is dat je de DSMR-logger32 alleen met een externe voeding kunt gebruiken. Voor veel mensen geen probleem, maar als je geen stopcontact in de meterkast hebt, heb je opeens wél een probleem.

De Virtual P1 Cable is de redder in nood! 

Hij bestaat uit twee delen. Een Zender (Transmitter) en een Ontvanger (Receiver). 

De Zender sluit je via een RJ12 kabeltje aan op de P1 poort van de Slimme Meter. Hij wordt gevoed met pin 1 van de RJ12 connector van de Slimme Meter.

Het DSMR-uitlees apparaat dat je normaal gesproken op de P1 poort van de Slimme Meter aansluit (en dat waarschijnlijk in een andere ruimte staat waar je een stopcontact hebt) sluit je nu via een RJ12 kabeltje op de Ontvanger aan. De Ontvanger wordt gevoed via pin 1 van de RJ12 connector (het “DSMR-uitlees” apparaat moet 5 volt op pin 1 van de RJ12 connector naar buiten voeren). 

De Zender en de Ontvanger zullen nu verbinding met elkaar zoeken. Als dat is gelukt, worden de door de Slimme Meter gegenereerde telegrammen via de virtuele kabel doorgestuurd naar het DSMR-uitlees apparaat.

Ontwerp doelstelling

Het is mijn plan om één ontwerp van een PCB te maken die, door middel van een schakelaar, zowel óf als Zender óf als Ontvanger kan werken. Het PCB moet zo klein mogelijk worden, dus er zal waar mogelijk gebruik gemaakt worden van SMD componenten.

Voor de Micro Processor (MCU) wil ik de AVR128DB28 gaan gebruiken omdat dit een moderne MCU is die ruim in het geheugen zit, meerdere UARTS en voldoende GPIO pinnen heeft terwijl het SSOP-28 formaat nét niet té klein is om handmatig te solderen.

De firmware wil ik in PlatformIO (met de Visual Studio Code IDE) ontwikkelen en niet met de Arduino IDE.

Hoe werkt de Virtual P1 Cable

De virtual P1 Cable maakt gebruik van transceiver (zender en ontvanger) modules van het type NRF2401L+PA/LNA (maar de “gewone” NRF2401L kunnen ook gebruikt worden). 

Dit zijn transceivers die (net als WiFi) op de 2.4 – 2.5GHz ISM band werken. Voor het verzenden en ontvangen van data maken de modules gebruik van GFSK modulatie. 

De NRF24L01 kan pakketjes van maximaal 32 bytes sturen en ontvangen, waarbij de logica om CRC checks en bevestiging van een correct ontvangen pakketje, in de bordjes aanwezig is. Dit zorgt voor een betrouwbare verbinding tot meer dan 800 meter “line of sight” tussen twee NRF24L01 transceivers. De uitgebreidere NRF24L01+AP/LNA kunnen zelfs een afstand van meer dan 1000 meter overbruggen. 

Staan er obstakels tussen de twee transceivers dan wordt de maximaal overbrugbare afstand direct een stuk kleiner. Tijdens het testen heb ik, op maximaal zendvermogen, een betrouwbare verbinding tussen de meterkast en mijn kantoor waarbij de afstand zo’n 12 meter is en het signaal door drie muren heen moet.

Zender

De telegrammen van de Slimme Meter komen binnen op de RJ12 plug waarna deze wordt geïnverteerd en door de MCU wordt ingelezen. Omdat we weten dat ieder telegram begint met een “/“ en eindigt met een “!” is het vrij eenvoudig om een heel telegram in een buffer op te slaan. Omdat je nooit weet waar de Slimme Meter in een telegram zit, als je begint met lezen, leest de Zender alles in een buffer tót hij een ‘!’ tegen komt. Voor DSMR 4+ volgt er nu nog een checksum van 4 characters die we na het ‘!’ nog inlezen en in de buffer stoppen.

Vervolgens kijkt de Zender terug in de buffer tot hij een ‘/‘ tegenkomt. Dát is dus het begín van het telegram.

Nu wordt het complete telegram verstuurd in pakketjes van 20 bytes. Als het hele telegram verstuurd is wordt nog een pakketje met als inhoud “*EOT* verstuurd waarna het proces van voren af aan begint.

Ontvanger

De Ontvanger leest de ontvangen pakketjes in tot hij een pakketje ontvangt waar een ‘/‘ (het begin van een telegram) in zit. Vanaf dat moment plakt hij alle volgende pakketjes achteraan in een buffer tót hij een pakketje ontvangt dat begint met “*EOT*”, wat het einde van de data aangeeft. In de buffer staat nu een volledig telegram die de MCU van de Ontvanger vervolgens geïnverteerd naar de RJ12 plug stuurt en wat uiteindelijk binnen komt bij het DSMR-uitlees apparaat.

De Code uitgelegd (hoofdlijnen)

setup()

In setup() worden één GPIO pin (powerMode) uitgelezen aan de hand waarvan het zendvermogen (LOW of MAX) wordt ingesteld. Vervolgens worden drie GPIO-pinnen uitgelezen die bepalen op welk kanaal de communicatie plaatsvindt (channelNr). Ook de functie van de hardware (Zender of Ontvanger) wordt bepaald aan de hand van de toestand van een GPIO pin (isReceiver). Tenslotte wordt de DSMR standaard bepaald aan de hand van weer een andere GPIO pin (isDSMR_4Plus).

Met deze opzet hoeft er maar één programma geschreven en onderhouden te worden voor zowel de Zender als voor de Ontvanger. In setup() wordt na het lezen van de verschillende GPIO-pinnen  de NRF24L01 geconfigureerd.

Daarna wordt, afhankelijk van de variabele “isReceiver” de functie setupReceiver() of setupTransmitter() aangeroepen waarin voor de taak specifieke instellingen worden gedaan.

//==============================================================
void setup() 
{
  //— set pinMode() for GPIO-Input pinnen 

  Serial.begin(115200);
  while(!Serial) { delay(10); }
  Serial.flush();
  Serial.println("\n\n\nAnd then it begins ....");
  Serial.printf("Firmware version v%s\r\n", _FW_VERSION);

  readSettings();

  //—- set Serial1 to <BAUD>, <BITS ETC> (isDSMR_4Plus)

  //--- now setup radio's ----
  //-- Set Transmitter Power (powerMode)
  //-- Min speed (for better range I presume)
  //-- 8 bits CRC
  //-- Enable dynamic payloads 
  //-- save on transmission time by setting the radio to only transmit the
  //-- number of bytes we need to transmit
  //-- increase the delay between retries and # of retries 
  //-- set Channel
 
  if (isReceiver)
  {
   setupReceiver();
  }
  else  
  {
   setupTransmitter();
  }
  
} //  setup()

loop()

De loop() functie is zo mogelijk nóg eenvoudiger:

//==============================================================
void loop() 
{
  if (isReceiver) loopReceiver();
  else            loopTransmitter();

} //  loop()

loopTransmitter()

In loopTransmitter() wordt de P1-in poort uitgelezen en in een buffer gestopt tot er een ‘!’ (einde telegram) wordt ontvangen.

//-- read until "!" ("!" is not in p1Buffer!!!) --
int len = Serial1.readBytesUntil('!', p1Buffer, (_MAX_P1BUFFER -15));

Het ‘!’ komt niet in de buffer terecht, dus die wordt er “handmatig” aan toegevoegd, waarna er nog een aantal characters worden gelezen (tot de eerste ‘\r’) en achter de buffer geplakt. Als het een DSMR-4+ telegram betreft wordt hierdoor de checksum ingelezen anders is de ‘!’ het laatste teken in het telegram en is het eerstvolgende teken direct al een ‘\r’.

Na een aantal validity checks wordt de functie transmitTelegram() aangeroepen.

transmitTelegram(&p1Buffer[startTelegramPos], p1BuffLen);

transmitTelegram()

Deze functie verstuurt het telegram in blokjes via de NRF24L1 module.

  while(startTelegramPos<telegramLen)
{
memset(payloadBuff, 0, _PAYLOAD_SIZE+10);
for(int i=0; i<_PAYLOAD_SIZE; i++)
{
payloadBuff[i] = telegram[i+startTelegramPos];
}
//---- ending "0" activates autoACK & Retry
errCount = 0;
do
{
transmitOk = radio.write(&payloadBuff, _PAYLOAD_SIZE, 0);
if (!transmitOk) { delay(10); errCount++; }
else
{
if (startTelegramPos==0)
{ delay(50); } //-- give receiver time to check start
else
{ delay(5); }
}
}
while (!transmitOk && (errCount < _MAX_TRANSMIT_ERRORS));
if (!transmitOk)
{
Serial.println("\r\nMax Transmit errors.. Bailout!");
blinkLed(15, 70);
return;
}
startTelegramPos += _PAYLOAD_SIZE;
delay(10);
}

Als het hele telegram is verstuurd wordt er nog een laatste blokje met “end-of-telegram” informatie verstuurd.

  snprintf(payloadBuff, _PAYLOAD_SIZE, "*EOT* %04x", calcCrc);

errCount = 0;
do
{
transmitOk = radio.write(&payloadBuff, _PAYLOAD_SIZE, 0);
if (!transmitOk) { delay(10); errCount++; }
else { delay(5); }
}
while (!transmitOk && (errCount < _MAX_TRANSMIT_ERRORS));

loopReceiver()

In deze functie worden alle binnenkomende berichten van de zender opgevangen. Zodra er een bericht binnenkomt waar een ‘/‘ in staat (het begin van een telegram) …

    radio.read(&payloadBuff, bytesRead);

    int posSlash = findChar(payloadBuff, '/');
    if (posSlash >= 0)
    {
      Serial.println("\r\nFound '/' …”);
	.
	.
    }

… worden de berichten aan een buffer toegevoegd tot er een bericht binnenkomt met de string ‘*EOT*’. Dit bericht geeft aan dat er een compleet telegram is ontvangen.

  while(!foundEOT && (p1BuffPos < (_MAX_P1BUFFER -15)) )
  {
    uint8_t bytesRead = radio.getDynamicPayloadSize();
    radio.read(&payloadBuff, bytesRead);
    if (strncmp(payloadBuff, "*EOT*", 5) == 0)
    {
      foundEOT = true;
      digitalWrite(PIN_LED, LOW); 
    }
    else
    {
      //-- plak payload achteraan telegram
      memcpy(&p1Buffer[p1BuffPos], payloadBuff, bytesRead);
      p1BuffPos += bytesRead;
    }
  }

Vervolgens wordt dit complete telegram naar de P1-out poort verstuurd.

Het schema

Het is niet gelukt om voor de twee taken (Zender en Ontvanger) één schema en uiteindelijk ook één printplaat te ontwerpen. Dat zou alleen mogelijk zijn met een hoop draadbruggen, omdat (bijvoorbeeld) pin 5 van de RJ12 plug in het ene geval een invoer- en in het andere geval een uitvoer- van het DSMR signaal is. Ook de ruimte voor het inverter circuit (transistor schakeling) van de Zender en het inverter circuit (OptoCoupler schakeling) van de Ontvanger nemen beide zoveel ruimte in dat het, samen met benodigde draadbruggen en/of een schakelaar, niet goed past in een “zo klein mogelijk” ontwerp van een PCB.

Het schema is ontworpen in KiCad (7.0.0) en is verdeeld over drie pagina’s. De eerste pagina geeft de links naar pagina 2 (Transmitter) en pagina 3 (Receiver).

Voor de 3v3 spanning-rail voor de NRF24L01 is gekozen voor een RT9080 (SOT23-5). Deze LDO kan 500mA leveren. Ruim voldoende voor de NRF24L01 die tijdens het zenden maximaal 20 á 30mA verbruikt.

De printplaat

Nadat de printplaat is ontworpen moet het ontwerp (in de vorm van Gerben bestanden) naar een PCB fabrikant worden gestuurd. Ik maak graag gebruik van en KiCad heeft een mooie plugin waarmee dit proces geautomatiseerd kan worden. De plugin heet “PCBWay” (hoe kóm je erop). Installatie gaat via de “Plugin and Content Manager” van KiCad:

Na installatie heeft de toolbar van KiCad een nieuwe knop.

Door op deze knop te klikken worden alle, voor PCBWay, benodigde bestanden in een .zip bestand gezet en wordt, via de browser, naar de website van PCBWay gesprongen.

Vervolgens geef je op hoeveel printplaten je van dit ontwerp wil laten maken en hoe je wil dat de printplaat eruit komt te zien (kleur van het soldermask en van het silkscreen).

Na controle door de engineers van kun je de produceer- en verzendkosten betalen. Na ongeveer een week worden je printplaten geleverd en vind je ze in je brievenbus!

Om kosten te sparen zijn de printplaten voor de Zender en Ontvanger tot één printplaat gecombineerd. Deze printplaat moet door midden gezaagd worden om de twee afzonderlijke printplaten te verkrijgen.

Instellingen

Voor de selectie van het kanaal waarop de communicatie plaatsvindt en voor de selectie van het zendvermogen wordt gebruik gemaakt van een DIL-8 4x schuif schakelaar (sw-1,2,3 voor kanaal selectie en sw-4 voor zendvermogen).

Sw 3Sw 2Sw 1Channel
offoffoff12
onoffoff28
offonoff44
ononoff60
offoffon76
onoffon92
offonon108
ononon124
Switch 4Transmit Power
offLOW
onMAX

Voor de selectie van de DSMR-variant is een twee positie pin-header aanwezig. Door hem open te laten wordt DSMR-4+ gebruikt, door er een jumper op te zetten wordt een PréDSMR 4 standaard gebruikt.

Er is een 3 positie pin-header waar een seriële TTL terminal (115200 baud) op kan worden aangesloten waarop debug informatie afgedrukt wordt.

Voor het programmeren is een 3 positie pin-header aanwezig waarmee met een UPDI programmer de firmware naar de MCU geflasht kan worden.

Het schema spreekt verder voor zichzelf. 

De virtuele P1 Kabel afbouwen

Alle relevante documenten staan op github!

Het Lek van Willem

(vrij naar “het lek van elektuur”)

Bij het bedenken van de virtual P1 Cable ben ik teveel uitgegaan van de DSMR-logger32 (dat was immers de aanleiding om deze virtuele kabel te ontwikkelen). Hierdoor vervangt de Ontvanger niet de Slimme Meter in die zin, dat de Slimme Meter 5 volt levert aan de P1 poort waar een aangesloten apparaat mee gevoed kan worden. De Ontvanger zou dus een 5 volt externe aansluiting moeten hebben, zodat de Ontvanger een aangesloten apparaat kan voeden. Nu moet dat “aangesloten apparaat” een eigen (externe) 5 volt voeding hebben, waarmee hij de Ontvanger kan voeden. Een beetje de omgekeerde wereld.

Gelukkig is het niet moeilijk om die externe 5 volt voeding toch op de Ontvanger aan te sluiten. Voor gebruik van de DSMR-logger32 is die aanpassing niet nodig.

This entry was posted in Arduino, AVRxDBx, DSMR-logger, ESP32, Firmware, Hardware, KiCAD. Bookmark the permalink.

15 Responses to virtuele P1 Kabel

  1. Jacques Cardon says:

    Beste Willem,
    ik heb met veel belangstelling uw artikel over de “virtuele P1 kabel” gelezen en die zou misschien de oplossing zijn voor waar ik nu al dagen op aan het zoeken ben.
    Mijn auto staat in de ondergrondse parkeergarage van een appartementsgebouw. De wallbox voor het laden is een “Peblar Home” en als accessoire voor de load balancing zat er een HomeWizard P1 Meter (HWE-P1-C1) bij. Maar lukt niet om deze te laten communiceren met de wallbox, doorheen enkele betonnen muren, en daarom dacht ik om zo’n link te gebruiken. Heb echter geen ervaring, noch gereedschap, om een smd-printplaat te bestukken. Is het mogelijk om een set te bestellen bij u?
    Eventueel kan ik zelf een printplaat maken met through-hole componenten maar dat is wat extra werk.
    Is de virtuele kabel bestelbaar (versie met antennes), en wat moet ie kosten?
    Alvast dank,
    Jacques

    • Willem Aandewiel says:

      Jacques,
      Fijn dat je het artikel interessant vind.
      Ik ben alleen bang dat de Virtuele P1 kabel voor jou geen oplossing zal zijn. Het maakt gebruik van hele zwakke RF zend/ontvangers die in een “normaal” woonhuis prima te gebruiken zijn. In een (gewapend) betonnen appartement verwacht ik niet dat de zender en ontvanger verbinding met elkaar kunnen krijgen.
      Ik kan wel een setje voor je maken maar hou er rekening mee dat dit ongeveer €90,- kost zonder garantie dat het in jouw situatie een oplossing is.

  2. Lars says:

    Hoi Willem, ik ben ook opzoek naar deze oplossing. Heb een slimme meter, en een laadpaal met een P1 poort, (uiteraard voor loadbalancing) maar ja kabel aanleggen is geen optie meer…
    Kan ik setje bij je bestellen?
    Hoor graag van je
    Groeten Lars

  3. Giuseppe Theuws says:

    Hoi, We zijn nu een paar maanden verder dus de vraag opnieuw of deze bestelbaar is . Mijn P1 slimme meter zit ong. 50 meter met meerdere muren van de P1 gebruiker. Ik heb wel overal netwerk dekking. Lukt transmissie via het bestaande netwerk ook?

    mvg Giuseppe

  4. Søren Mikkelsen says:

    Hello
    I have just added some simple shielding to the nrf24 modules.
    This has increased the performance a lot. I can now put the reciever anywhere in my house and still get good reception.
    This is probably one of the most stable DIY solutions i have been using. Has been running for month.

    • Willem Aandewiel says:

      Hi Søren,

      Can you please share some foto’s of the shielding you made?
      (If uploading is a problem, please send them to my eMail address).

      Thanks

      • Søren Mikkelsen says:

        Sure, here it is.
        It is made with common available materiale from the kitchen. Alu-foil and plastic. Performance could probably be better with a proper shielding. But this diy solution is good enough for the setup I have running now.

  5. Søren Mikkelsen says:

    Hello Willem
    This is a great product 🙂
    I am using it now. I ran into lots of issues, however none related to the circuit.
    First a broken RJ12 cable then the smartmeter had to be replaced due to an issue with opening the P1 port. Last one of my nrf24 reciever boards seems to have an issue with the antenna, so the reciever is running without an antenna. But finally I have data. I have modified the case so it fits with an micro USB connector for power. That was easy to do modifying the virtualP1Cable.scad script.
    Thanks a lot for spending the time creating this useful project.
    Best regards
    Søren

  6. Erik says:

    Slimme meter, slimme kabel.

    Ik zal m nodig hebben, want geen wandcontactdoos in mijn meterkast.

    Is ie al bestelbaar?

    • Willem Aandewiel says:

      Erik,

      Ik heb een paar Zender/Ontvangers maar het probleem is dat de gebruikte MCU (AVR128DB28) nergens te krijgen is …

      Ik stuur je een PM

Leave a Reply

Your email address will not be published. Required fields are marked *

The maximum upload file size: 4 MB. You can upload: image, other. Links to YouTube, Facebook, Twitter and other services inserted in the comment text will be automatically embedded. Drop file here

This site uses Akismet to reduce spam. Learn how your comment data is processed.