MQTT char array naar variabele conversie ?

Projecten die niet passen in bovenstaande onderwerpen
Berichten: 37
Geregistreerd: 16 Jun 2016, 21:23

MQTT char array naar variabele conversie ?

Berichtdoor john33 » 30 Jan 2023, 20:20

Beste forumleden,

via een Raspberry Pi, aangesloten op mijn slimme meter stuur ik dmv P1monitor de meterdata van het verbruik naar een MQTT broker.

Met een ESP8266 heb ik succesvol verbinding kunnen maken met de broker, en kan ik het verbruik uitlezen op een LCD display via i2c aangesloten op de ESP8266.

War gaat het mis?
De data die ik ontvang is met 3 cijfers achter de komma.
Bijvoorbeeld, op dit moment verbruik ik 0,187kW/h volgens het display.

Ik wil met deze waardes een boiler gaan aansturen, als ik de conversie goed heb verander ik het MQTT topic naar "teruglevering".
Maar wat mij tot nu toe nog niet lukt is om die waarde van 0,187 (char* omgezet naar string) om daar een variabele van te maken.
Getest met toInt, maar als resultaat krijg ik een 0, of een 1 bij een verbruik van +1000watt.

Hoe kan ik de string die ik heb omzetten naar een waarde van x,000 naar xxxx (1200 of zo iets) want daarmee kan ik wel sturen.

Code waar MQTT bericht mee ontvangen wordt:
Code: Alles selecteren
//MQTT data ontvangen en op LCD weergev
  Serial.print("Message arrived in topic: ");
  //Serial.println(topic);
  Serial.print("Message:");
  for (int i = 0; i < length; i++) {
  //Serial.print((char) payload[i]);

  //weergave op LCD scherm
  lcd.clear();
  payload[length] = '\0';
  String strPayload = String((char*)payload);
  int Val10 = Serial.read();                             //Val10 leest de serieele poort uit en slaat deze op als variabele
    if (isDigit(Val10)) {
      strPayload + - (char)Val10;

    }
    if (strPayload.toInt() <= 0, 000) {              //test stukje om cursor te laten knipperen bij aktieve boiler
      //Serial.println("BOILER");
      lcd.setCursor(15, 1);
      lcd.blink();
    }
    else
    {
      lcd.setCursor(15, 1);
      lcd.noBlink();
    }
    lcd.setCursor(0, 0);
    lcd.print("Consumption: ");
    lcd.setCursor(0, 1);
    lcd.print(strPayload);             //strPayload = de naar string geconverteerde char*
    lcd.print(" kW");
    Serial.println(strPayload);        //deze Serial.print geeft de juiste waarde weer

Advertisement

Berichten: 180
Geregistreerd: 26 Aug 2015, 11:57

Re: MQTT char array naar variabele conversie ?

Berichtdoor Frits1956 » 30 Jan 2023, 22:46

Een int kan alleen hele getallen bevatten. Probeer het eens met een float

Berichten: 80
Geregistreerd: 02 Nov 2022, 13:03

Re: MQTT char array naar variabele conversie ?

Berichtdoor ThHe » 31 Jan 2023, 01:44

Een oplossing bij 3 cijfers achter de ,

String s = "0,184";

Serial.begin(9600);
int v = 0;
for (int i = 0; i < s.length(); i++)
{
if (s.charAt(i) != ',') v = v *10 + (s.charAt(i) - '0');
}
Serial.println(v);
Serial.println(v / 1000., 3);

Berichten: 37
Geregistreerd: 16 Jun 2016, 21:23

Re: MQTT char array naar variabele conversie ?

Berichtdoor john33 » 01 Feb 2023, 20:26

Omzetten naar float, dat was de truuk .
Daarna een variabele aangemaakt die de float x 1000 vermenigvuldigd en het werkt.

Hiermee kan ik verder.
Bedankt.

Berichten: 37
Geregistreerd: 16 Jun 2016, 21:23

Re: MQTT char array naar variabele conversie ?

Berichtdoor john33 » 05 Feb 2023, 22:29

Nu toch weer iets raars waar ik niet uit kom,

Mijn sketch loopt tot en met de weergave op het lcd scerm prima.
Maar zodra ik extra functionaliteit toevoeg, iets aansturen op basis van de waarde op het lcd scherm dan blijft de eerste ontvangen waarde op het scherm staan en wordt niet meer ververst.
dit is de sketch die werkt:
Code: Alles selecteren
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

//Global variables
LiquidCrystal_I2C lcd(0x27, 16, 2);    // set the LCD address to 0x27 for a 16 chars and 2 line display
int temppin = A0;                      //TMP36 temperatuur sensor op A0
//int buttonPin = 4;
int PWM_Output = 2;                    //=D4 pwm output naar KEMO kastje
//int minimumWatts = 250;                //minimaal verbruik huis
int val = 0;                           //variabele om watts op te slaan
int val1 = 0;                          //variabele om vermogen naar boiler op te slaan
int val2 = 0;                          //variabele om ontvangen gegevens op te slaan
int val3 = 0;
//const int LED = 6;                     //Led knippert sneller naar gelang er meer power naar de boiler gaat
int Relais = 4;                        //D2 Relais om 230 volt echt af te sluiten als het zonvermogen te laag is of boiler op temperatuur
//int BoilerLed = 8;                     // led om status van boiler aan te geven
int i = 0;

//drukknop
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;
unsigned long previousMillis = 0;      // slaat de tijd op
const long interval = 500;             // interval tussen meetmomenten
   

// WiFi
const char *ssid = "*********"; // Enter your WiFi name
const char *password = "********";  // Enter WiFi password

// MQTT Broker
const char *mqtt_broker = "broker.******.com";
const char *topic = "p1monitor/smartmeter/consumption_kw";
const int mqtt_port = 1883;

WiFiClient espClient;
PubSubClient client(espClient);

//end of global variables

void setup() {
  // Set software serial baud to 115200;
  Serial.begin(115200);
  lcd.init();
  lcd.backlight();
 
  //pinMode(buttonPin, INPUT);
  //pinMode(LED, OUTPUT);
  pinMode (2, OUTPUT);                  //uitgang naar KEMO kastje
  //pinMode (6, OUTPUT);                  //uitgang voor LED
  pinMode (4, OUTPUT);                  //uitgang voor Relais
  //pinMode (8, OUTPUT);                  //uitgang voor boilerled status
  lcd.setCursor(1, 0);
  lcd.print("Solar Diverter");
  lcd.setCursor(3, 1);
  lcd.print("by JG TECH");
  delay(5000);
  lcd.clear();
  //lcd.print("druk op knop");

 // End of setup
 
  // connecting to a WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      lcd.setCursor(0, 0);
      lcd.print("connecting...");
      Serial.println("Connecting to WiFi..");
  }
  Serial.println("Connected to the WiFi network");
  //connecting to a mqtt broker
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);
  while (!client.connected()) {
      String client_id = "esp8266-client-";
      client_id += String(WiFi.macAddress());
      Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
      if (client.connect(client_id.c_str())) {
          Serial.println("Public ****** mqtt broker connected");
      } else {
          Serial.print("failed with state ");
          Serial.print(client.state());
          delay(2000);
      }
  }
  // publish and subscribe
  client.publish(topic, "p1monitor/smartmeter/consumption_kw");
  client.subscribe(topic);
}

//In deze loop moet alles plaatsvinden:
 
void callback(char *topic, byte *payload, unsigned int length) {            //unsigned int kan geen negatieve getallen opslaan
  //temperatuurmeter van boiler uitlezen
  int reading = analogRead(temppin);
  float voltage = reading * (1100 / 1024.0); //converteer de uitlezing in voltage
  // Converteer het voltage in temperatuur in Celsius:
  float temperature = voltage / 12;
  // Print de temperatuur in de Serial Monitor:
  //Serial.println("boilertemp");
  Serial.println(temperature);
 
  //MQTT data ontvangen en op LCD weergeven
   
  Serial.print("Message arrived in topic: ");
  //Serial.println(topic);
  //Serial.print("Message:");
  for (int i = 0; i < length; i++) {
  //Serial.print((char) payload[i]);
     
  //weergave op LCD scherm
      lcd.clear();
      payload[length] = '\0';
      String strPayload = String((char*)payload);
      int Val10 = Serial.read();                     //Val10 wat doet die?
      if (isDigit(Val10)){
        strPayload +- (char)Val10;
      }
      lcd.setCursor(0, 0);
      lcd.print("Consumption: ");
      lcd.setCursor(0, 1);
      lcd.print(strPayload);             //strPayload = de naar string geconverteerde char*
      //lcd.print(val3);                   //testje
      lcd.print(" kW");
      //Serial.println(strPayload);     //deze Serial.print geeft de juiste waarde weer
      //--------------------------------------------------------------------------------------------
      // Boiler aansturen
    float num = strPayload.toFloat();            //converteer de payload naar een float met de naam num
    Serial.println(num);
    val3 = (num *1000);                          //variabele val3 is float num x 1000, om hele watt`s te krijgen
    Serial.println (val3);                           //print de waarde val3 in de serieele monitor
    //if (val3 > 1){
    //digitalWrite(Relais, HIGH);                  //Schakel 230 volt in naar KEMO kastje
    //digitalWrite(BoilerLed, HIGH);               //laat de LED voor boiler status branden
    //val2 = (val3 / 8,62);                        //val2 is maximaal 2000(watt output) 2000/8.62 = 255, max uitstuurwaarde
    //analogWrite(PWM_Output, val2);                        //stuur pin 5 met PWM uit
    //Serial.println(val2);                        //laat de uitstuurwaarde zien in de serieele monitor
    //}
    //-------------------------------------------------------------------------------------------------
    //boiler aansturing met voorwaardes
   
    //if (val3 < 1){                              //als er geen terug lvering is
    //digitalWrite(Relais, LOW);                  //Schakel 230 volt uit naar KEMO kastje
    //digitalWrite(BoilerLed, LOW);               //laat de LED voor boiler status uit
    //}
    //voorwaarde scheppen om boiler af te schakelen bij bereiken max temperatuur
    //if (temperature >= 50) {                     //als de boilertemperatuur groter of gelijk dan 50 graden is
    //analogWrite(PWM_Output, 0);                         //pin 5 mag niets meer uitsturen
    //Serial.println("boiler uit");
    //digitalWrite(Relais, LOW);                 //Schakel 230 volt uit naar KEMO kastje
    //digitalWrite(BoilerLed, LOW);              //laat de LED voor boiler status uit
    //}
    //else
    //{
    //analogWrite(PWM_Output, val3);                      //in andere gevallen wel
   
   // }
 
      }
 
  Serial.println();
  Serial.println("-----------------------");
}

void loop() {
  client.loop();

}


Als is ik vanaf //if (val3 > 1){ de // weg haal of die functies aan te zetten dan wordt het display niet meer geupdate, de eerst ontvangen waarde blijft in het scherm staan.
In de serieele monitor zie ik wel keurig de nieuwe waardes binnen komen, dat dan weer wel.
Waar ga ik verkeerd ? ik heb de lcd code al op verschillende plaatsen neergezet zonder resultaat.

Berichten: 180
Geregistreerd: 26 Aug 2015, 11:57

Re: MQTT char array naar variabele conversie ?

Berichtdoor Frits1956 » 06 Feb 2023, 01:25

Voor zover ik kan zien is er geen functie client.loop() die in de main wordt aangeroepen.
Bedoel je niet callback() ???

Berichten: 37
Geregistreerd: 16 Jun 2016, 21:23

Re: MQTT char array naar variabele conversie ?

Berichtdoor john33 » 12 Feb 2023, 11:36

De code zoals afgebeeld werkt.
Echter stom stom stom, nog maar eens naar de hardware gekeken.....

Ik moet nog wennen aan dat ik met een ESP8266 werk, de pin namen zijn net even anders als bij een Arduino.
En daar ging het mis, het "relais" had ik op pin 4 staan, maar daar zit de SDA al op van het I2C deel voor het display.
Nooit aangedacht.

Ik heb wel een stukje code herschreven, maar nu werkt het zoals ik het wil.
Ik heb een extra void aangemaakt, void boilercontrol en in de main loop alle sturing laten plaatsvinden in plaats van het Callback gedeelte.

Berichten: 37
Geregistreerd: 16 Jun 2016, 21:23

Re: MQTT char array naar variabele conversie ?

Berichtdoor john33 » 02 Sep 2023, 19:16

Het kastje dat ik gemaakt heb werkt.
Alleen zit er nog wel bug in die ik er nog niet uit krijg.

Ik "meet" hoeveel vermogen ik teruglever naar het net, via P1 monitor en mqtt, dat gaat goed.

Mijn idee is om dit overschot naar een boiler te sturen, proportioneel, dus bij 100 watt overschot, deze 100 watt naar de boiler sturen, en hetzelfde als er 2kW overschot is.
In de code die hier staat lukt dit, ik map 2000 watt naar een uitstuur waarde tussen 0 en 255.
Een Kemo thyristor module met puls sturing stuurt de belasting aan.

Als ik een badkamer ventilator (1000/2000 watt) aansluit gaat dit in de 1000 watt modus prima
Ik zie het overschot afnemen met de belasting.
Dus meer dan 2kW overschot, 1kW belasting, er gaat nog 1kW en een beetje het net in, hoera!!!
Wat is dan de bug?
Als ik de belasting op 2kW zet en er is net iets meer dan 2 kW opwek dan is het resultaat zo goed als 0, er is bijna tot geen teruglevering meer dus de uitstuur waarde daalt naar 0, en het systeem gooit de boiler uit, maar ondertussen heb ik wel 2kW opwek.... Het systeem ziet vervolgens dat er 2kw overschot is en de boiler springt weer bij, teruglevering gaat naar 0, uitstuur stopt weer enz enz, het systeem pendelt.

Daar zit mijn probleem, eigenlijk wil ik dat het systeem bij 2kW opwek, ook 2kW uitstuurt, waarbij de invoer naar het net dus zo goed als 0 is.
Hoe kan ik zo iets voor elkaar krijgen?

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: MQTT char array naar variabele conversie ?

Berichtdoor shooter » 03 Sep 2023, 10:22

dat komt omdat je maar op 1 plek meet en dus moet je de waarde van je boiler optellen bij je zonnepanelen dus je opbrengst is wat je teruglevert plus de boiler
paul deelen
shooter@home.nl

Berichten: 4067
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: MQTT char array naar variabele conversie ?

Berichtdoor shooter » 03 Sep 2023, 12:10

en als er een wolkje verschijnt dan kan het ook maar eens negatief worden dus een beetje filteren is een oplossing
paul deelen
shooter@home.nl

Volgende

Terug naar Overige projecten

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 2 gasten