MQTT publishing to node red

Having problems with converting the analog voltage to a string and then to char so I can read a chart in node red.
I am using an ESP 32. On the debug screen in node red the word voltage appears. In the serial port window I am getting the correct voltage readings (watts) readings.
Have tried all sorts of combinations of analog conversions from the internet without success
Have you any suggestions?
I have also installed a temp probe for my water heater using a ESP8266 and it is working in node red.

#include <WiFi.h>
#include <PubSubClient.h>

// Change the credentials below
// so your ESP32 connects to your router
const char* ssid = "xxxxxxxxxx";
const char* password = "xxxxxxxxxY";
// Change the variable to your Raspberry Pi IP address
// so it connects to your MQTT broker
const char* mqtt_server = "test.mosquitto.org";

// Initializes the espClient.
WiFiClient esp32;
PubSubClient client(esp32);

// This connects your ESP32 to your router
void setup_wifi() {
delay(10);
Serial.begin(115200);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("WiFi connected - ESP IP address: ");
Serial.println(WiFi.localIP());

}

void readSensors() {
// read the input on analog pin solarpin, c/t 30 amp with output of 1volt
const int solarPin = 39;//Analog pin
int solarValue;// do not change
solarValue = analogRead (solarPin);
float voltage = 0; // do not change
voltage = (1 / 4095.0 * 30 * 240) * solarValue;// converts to watts
Serial.print(voltage);
Serial.println(" Watts");
delay(500);
}

// This reconnects your ESP32 to your MQTT broker
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("esp32")) {
Serial.println("connected");
// Subscribe or resubscribe to a topic
// You can subscribe to more topics
client.subscribe("home/solar/power");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
//Turn off wifi access point
WiFi.mode(WIFI_STA);
}
// ensures that you esp32 is connected to wifi and mqtt broker
void loop() {

//connect wifi if not connected
if (WiFi.status() != WL_CONNECTED) {
delay(1);
setup_wifi();
return;
}
if (!client.connected()) {
reconnect();

if (!client.loop())
client.connect("esp32");
}
readSensors();

client.publish("home/solar/power","voltage");
delay(2000);

}

Thanks
Peter Fitzgerald

Messy code

You try
client.publish("home/solar/power","voltage");]
but get no worky thingy.

Here is some ESP32 code to publish that works

void DoTheBME680Thing( void *pvParameters )
{
  SPI.begin(); // initialize the SPI library
  vTaskDelay( 10 );
  if (!bme.begin()) {
    log_i("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }
  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms
  //wait for a mqtt connection
  while ( !MQTTclient.connected() )
  {
    vTaskDelay( 250 );
  }
  xEventGroupSetBits( eg, evtWaitForBME );
  TickType_t xLastWakeTime    = xTaskGetTickCount();
  const TickType_t xFrequency = 1000 * 15; //delay for mS
  int sendLRDataTrigger       = 240; // 1 hour-ish = 240
  int sendLRdataCount         = sendLRDataTrigger - 1; //send linear regression data when count is reached
  for (;;)
  {
    x_eData.Temperature  = bme.readTemperature();
    x_eData.Temperature  = ( x_eData.Temperature * 1.8f ) + 32.0f; // (Celsius x 1.8) + 32
    x_eData.Pressure     = bme.readPressure();
    x_eData.Pressure     = x_eData.Pressure / 133.3223684f; //converts to mmHg
    sendLRdataCount++;
    if ( sendLRdataCount >= sendLRDataTrigger )
    {
      xQueueOverwrite( xQ_lrData, (void *) &x_eData.Pressure ); // send to trends
      sendLRdataCount    = 0;
    }
    x_eData.Humidity     = bme.readHumidity();
    x_eData.IAQ          = fCalulate_IAQ_Index( bme.readGas(), x_eData.Humidity );
    //log_i( " temperature % f, Pressure % f, Humidity % f IAQ % f", x_eData.Temperature, x_eData.Pressure, x_eData.Humidity, x_eData.IAQ);
    xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY );
    if ( MQTTclient.connected() )
    {
      MQTTclient.publish( topicInsideTemp, String(x_eData.Temperature).c_str() );
      vTaskDelay( 3 ); // gives the Raspberry Pi 4 time to receive the message and process
      MQTTclient.publish( topicInsideHumidity, String(x_eData.Humidity).c_str() );
      vTaskDelay( 3 ); // delay for RPi
      MQTTclient.publish( topicInsidePressure, String(x_eData.Pressure).c_str() );
      vTaskDelay( 3 ); // delay for RPi
      MQTTclient.publish( topicInsideIAQ, String(x_eData.IAQ).c_str() );
    }
    xSemaphoreGive( sema_MQTT_KeepAlive );
    xSemaphoreGive( sema_PublishPM ); // release publish of dust density
    xSemaphoreTake( sema_mqttOK, portMAX_DELAY );
    mqttOK ++;
    xSemaphoreGive( sema_mqttOK );
    xQueueOverwrite( xQ_eData, (void *) &x_eData );// send data to display
    //
    xLastWakeTime = xTaskGetTickCount();
    vTaskDelayUntil( &xLastWakeTime, xFrequency );
    // log_i( "DoTheBME280Thing high watermark % d",  uxTaskGetStackHighWaterMark( NULL ) );
  }
  vTaskDelete ( NULL );
}
////

Perhaps you get clue as to what you do wrong.

Declare topics like this:

const char* topic_SunLampOn          = "Home/SunLampOn";

Code below in 2 parts is a complete working ESP32 program that publishes and subscribes.

#include <WiFi.h>
#include <PubSubClient.h>
#include "certs.h"
#include "sdkconfig.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/event_groups.h"
#include "time.h"
#include <ESP32Time.h>
//
ESP32Time rtc;
//
hw_timer_t * timer = NULL;
EventGroupHandle_t eg;
#define evtDoDisplay ( 1 << 1 )
#define evtDoTheMQTT_Watch   ( 1 << 2 )
#define evtParseMQTT ( 1 << 5 )
#define evtDoTheSunLampThing ( 1 << 10 )
//
int SunLampManual = 0; // manual on or off
int SunLampAuto = 1;// auto mode
int mqttOK = 0;
////
WiFiClient wifiClient;
PubSubClient MQTTclient( mqtt_server, mqtt_port, wifiClient );
////
String str_eTopic;
char strPayload [300] = { '\0' };
////
SemaphoreHandle_t sema_MQTT_Parser; //if parsing is in progress hold up callback a moment to let parsing finish before sending a new things to parse
SemaphoreHandle_t sema_MQTT_KeepAlive;
SemaphoreHandle_t sema_mqttOK;
////
volatile bool TimeSet = false;
volatile int iDoTheThing = 0;
////
void IRAM_ATTR onTimer()
{
 BaseType_t xHigherPriorityTaskWoken;
 iDoTheThing++;
 if ( iDoTheThing == 60000 )
 {
   xEventGroupSetBitsFromISR( eg, evtDoTheSunLampThing, &xHigherPriorityTaskWoken );
   iDoTheThing = 0;
 }
}
////
void IRAM_ATTR mqttCallback(char* topic, byte * payload, unsigned int length)
{
 xSemaphoreTake( sema_MQTT_Parser, portMAX_DELAY); //if parsing is in progress hold up a moment to let parsing finish before sending a new things to parse
 str_eTopic = topic + '\0';
 int i = 0;
 for ( i; i < length; i++) {
   strPayload[i] = ((char)payload[i]);
 }
 strPayload[i] = '\0';
 xSemaphoreGive ( sema_MQTT_Parser );
 xEventGroupSetBits( eg, evtParseMQTT ); // trigger tasks
} // void mqttCallback(char* topic, byte* payload, unsigned int length)
////
void setup()
{
 //
 gpio_config_t io_cfg = {};
 io_cfg.mode = GPIO_MODE_OUTPUT;
 //bit mask of the pins to set
 io_cfg.pin_bit_mask = ( (1ULL << GPIO_NUM_15) );
 //  //configure GPIO with the given settings
 gpio_config(&io_cfg);
 REG_WRITE(GPIO_OUT_W1TC_REG, BIT15); // sunlamp
 //
 /* Use 4th timer of 4.
   1 tick 1/(80MHZ/80) = 1us set divider 80 and count up.
   Attach onTimer function to timer
   Set alarm to call timer ISR, every 1000uS and repeat / reset ISR (true) after each alarm
   Start an timer alarm
 */
 timer = timerBegin( 3, 80, true );
 timerAttachInterrupt( timer, &onTimer, true );
 timerAlarmWrite(timer, 1000, true);
 timerAlarmEnable(timer);
 //
 str_eTopic.reserve(300);
 //
 eg = xEventGroupCreate();
 //
 sema_MQTT_Parser = xSemaphoreCreateBinary();
 sema_MQTT_KeepAlive = xSemaphoreCreateBinary();
 sema_mqttOK    =  xSemaphoreCreateBinary();
 xSemaphoreGive( sema_mqttOK );
 xSemaphoreGive( sema_MQTT_KeepAlive ); // found keep alive can mess with a publish, stop keep alive during publish
 ////
 xTaskCreatePinnedToCore( fparseMQTT, "fparseMQTT", 7000, NULL, 5, NULL, 1 ); // assign all to core 1, WiFi in use.
 xTaskCreatePinnedToCore( MQTTkeepalive, "MQTTkeepalive", 7000, NULL, 2, NULL, 1 ); //this task makes a WiFi and MQTT connection.
 xTaskCreatePinnedToCore( fDoTheSunLampThing, "fDoTheSunLampThing", 2000, NULL, 3, NULL, 1 );
 xTaskCreatePinnedToCore( fmqttWatchDog, "fmqttWatchDog", 2000, NULL, 3, NULL, 1 );
 ////
} //setup() END
////
///
void fmqttWatchDog( void * paramater )
{
 int UpdateImeTrigger = 86400; //seconds in a day
 int UpdateTimeInterval = 86300; // 1st time update in 100 counts
 int maxNonMQTTresponse = 60;
 for (;;)
 {
   vTaskDelay( 1000 );
   xSemaphoreTake( sema_mqttOK, portMAX_DELAY );
   if ( mqttOK >= maxNonMQTTresponse )
   {
     ESP.restart();
   }
   mqttOK++;
   UpdateTimeInterval++; // trigger new time get
   if ( UpdateTimeInterval >= UpdateImeTrigger )
   {
     TimeSet = false; // sets doneTime to false to get an updated time after a days count of seconds
     UpdateTimeInterval = 0;
   }
   //log_i( "mqttOK %d", mqttOK );
   xSemaphoreGive( sema_mqttOK );
 }
 vTaskDelete( NULL );
}
////
void fDoTheSunLampThing( void * parameter )
{
 int _hour = rtc.getHour(true);
 // SunLampManual = sunlamp on manual mode, automatic mode off for manual mode to work
 // SunLampAuto = sun lamp enable automatic mode
 for (;;)
 {
   xEventGroupWaitBits (eg, evtDoTheSunLampThing, pdTRUE, pdTRUE, portMAX_DELAY );
   // sun lamp auto mode of operation
   //log_i( "SunLampManualOnOff %d SunLampAuto %d",  SunLampManual, SunLampAuto  );
   if ( SunLampAuto )
   {
     // run in automated mode
     _hour = rtc.getHour(true); // get hour in 24 hours format
     //log_i( "get hour %d", _hour );
     if ( (_hour >= 7) && (_hour <= 17) )
     {
       REG_WRITE(GPIO_OUT_W1TS_REG, BIT15);
     }
     if ( (_hour < 7) || (_hour > 16) )
     {
       REG_WRITE(GPIO_OUT_W1TC_REG, BIT15);
     }
   } else {
     // manual mode off/on
     if ( (SunLampManual == 1)  )
     {
       REG_WRITE(GPIO_OUT_W1TS_REG, BIT15);
     } else {
       REG_WRITE(GPIO_OUT_W1TC_REG, BIT15);
     }
   }
   //log_i( " AlreadyOn = %d", AlreadyOn );
   xSemaphoreGive( sema_MQTT_KeepAlive );
   //log_i( "fDoTheSunLampThing high watermark %d",  uxTaskGetStackHighWaterMark( NULL ) );
 }
 vTaskDelete( NULL );
} // void fDoTheSunLampThing( void * parameter )
////
/*
   Important to not set vtaskDelay to less then 10. Errors begin to develop with the MQTT and network connection.
   makes the initial wifi/mqtt connection and works to keeps those connections open.
*/
void MQTTkeepalive( void *pvParameters )
{
 // setting must be set before a mqtt connection is made
 MQTTclient.setKeepAlive( 90 ); // setting keep alive to 90 seconds makes for a very reliable connection, must be set before the 1st connection is made.
 for (;;)
 {
   //check for a is-connected and if the WiFi 'thinks' its connected, found checking on both is more realible than just a single check
   if ( (wifiClient.connected()) && (WiFi.status() == WL_CONNECTED) )
   {
     xSemaphoreTake( sema_MQTT_KeepAlive, portMAX_DELAY ); // whiles MQTTlient.loop() is running no other mqtt operations should be in process
     MQTTclient.loop();
     xSemaphoreGive( sema_MQTT_KeepAlive );
   }
   else {
     log_i( "MQTT keep alive found MQTT status %s WiFi status %s", String(wifiClient.connected()), String(WiFi.status()) );
     if ( !(WiFi.status() == WL_CONNECTED) )
     {
       connectToWiFi();
     }
     connectToMQTT();
   }
   vTaskDelay( 250 ); //task runs approx every 250 mS
 }
 vTaskDelete ( NULL );
}
////
void connectToMQTT()
{
 // create client ID from mac address
 byte mac[5];
 WiFi.macAddress(mac);
 log_i( "mac address %d.%d.%d.%d.%d", mac[0], mac[1], mac[2], mac[3], mac[4] );
 String clientID = String(mac[0]) + String(mac[4]) ;
 log_i( "connect to mqtt as client %s", clientID );
 while ( !MQTTclient.connected() )
 {
   MQTTclient.connect( clientID.c_str(), mqtt_username, mqtt_password );
   log_i( "connecting to MQTT" );
   vTaskDelay( 250 );
 }
 log_i("MQTT Connected");
 MQTTclient.setCallback( mqttCallback );
 MQTTclient.subscribe( topic_SunLampOn );
 MQTTclient.subscribe( topic_SunLampEnable );
 MQTTclient.subscribe( topicOK );
}
//
void connectToWiFi()
{
 while ( WiFi.status() != WL_CONNECTED )
 {
   WiFi.disconnect();
   WiFi.begin( SSID, PASSWORD );
   vTaskDelay( 4000 );
 }
 WiFi.onEvent( WiFiEvent );
}
////
void fparseMQTT( void *pvParameters )
{
 xSemaphoreGive ( sema_MQTT_Parser );
 for (;;)
 {
   xEventGroupWaitBits ( eg, evtParseMQTT, pdTRUE, pdTRUE, portMAX_DELAY ); //
   xSemaphoreTake( sema_MQTT_Parser, portMAX_DELAY );
   if ( String(str_eTopic) == topic_SunLampOn )
   {
     SunLampManual = String(strPayload).toInt();
   }
   if ( String(str_eTopic) == topic_SunLampEnable )
   {
     SunLampAuto = String(strPayload).toInt();
   }
   // parse the time from the OK message and update MCU time
   if ( String(str_eTopic) == topicOK )
   {
     if ( !TimeSet)
     {
       String temp = "";
       temp = strPayload[0];
       temp += strPayload[1];
       temp += strPayload[2];
       temp += strPayload[3];
       int year =  temp.toInt();
       temp = "";
       temp = strPayload[5];
       temp += strPayload[6];
       int month =  temp.toInt();
       temp = "";
       temp = strPayload[8];
       temp += strPayload[9];
       int day =  temp.toInt();
       temp = "";
       temp = strPayload[11];
       temp += strPayload[12];
       int hour =  temp.toInt();
       temp = "";
       temp = strPayload[14];
       temp += strPayload[15];
       int min =  temp.toInt();
       rtc.setTime( 0, min, hour, day, month, year );
       log_i( "%s   rtc  %s ", strPayload, rtc.getTime() );
       TimeSet = true;
     }
   }
   // clear pointer locations
   memset( strPayload, '\0', 300 );
   str_eTopic = ""; //clear string buffer
   xSemaphoreGive( sema_MQTT_Parser );
   xEventGroupSetBits( eg, evtDoTheSunLampThing );
   xSemaphoreTake( sema_mqttOK, portMAX_DELAY );
   mqttOK = 0;
   xSemaphoreGive( sema_mqttOK );
 }
} // void fparseMQTT( void *pvParameters )
////
// great trouble shooting tool when uncommented
////
void WiFiEvent(WiFiEvent_t event)
{
 // log_i( "[WiFi-event] event: %d\n", event );
 switch (event) {
   //    case SYSTEM_EVENT_WIFI_READY:
   //      log_i("WiFi interface ready");
   //      break;
   //    case SYSTEM_EVENT_SCAN_DONE:
   //      log_i("Completed scan for access points");
   //      break;
   //    case SYSTEM_EVENT_STA_START:
   //      log_i("WiFi client started");
   //      break;
   //    case SYSTEM_EVENT_STA_STOP:
   //      log_i("WiFi clients stopped");
   //      break;
   case SYSTEM_EVENT_STA_CONNECTED:
     log_i("Connected to access point");
     break;
   case SYSTEM_EVENT_STA_DISCONNECTED:
     log_i("Disconnected from WiFi access point");
     break;
   //    case SYSTEM_EVENT_STA_AUTHMODE_CHANGE:
   //      log_i("Authentication mode of access point has changed");
   //      break;
   //    case SYSTEM_EVENT_STA_GOT_IP:
   //      log_i ("Obtained IP address: %s",  WiFi.localIP() );
   //      break;
   //    case SYSTEM_EVENT_STA_LOST_IP:
   //      log_i("Lost IP address and IP address is reset to 0");
   //      //      vTaskDelay( 5000 );
   //      //      ESP.restart();
   //      break;
   //    case SYSTEM_EVENT_STA_WPS_ER_SUCCESS:
   //      log_i("WiFi Protected Setup (WPS): succeeded in enrollee mode");
   //      break;
   //    case SYSTEM_EVENT_STA_WPS_ER_FAILED:
   //      log_i("WiFi Protected Setup (WPS): failed in enrollee mode");
   //      //      ESP.restart();
   //      break;
   //    case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT:
   //      log_i("WiFi Protected Setup (WPS): timeout in enrollee mode");
   //      break;
   //    case SYSTEM_EVENT_STA_WPS_ER_PIN:
   //      log_i("WiFi Protected Setup (WPS): pin code in enrollee mode");
   //      break;
   //    case SYSTEM_EVENT_AP_START:
   //      log_i("WiFi access point started");
   //      break;
   //    case SYSTEM_EVENT_AP_STOP:
   //      log_i("WiFi access point  stopped");
   //      //      WiFi.mode( WIFI_OFF);
   //      //      esp_sleep_enable_timer_wakeup( 1000000 * 2 ); // 1 second times how many seconds wanted
   //      //      esp_deep_sleep_start();
   //      break;
   //    case SYSTEM_EVENT_AP_STACONNECTED:
   //      log_i("Client connected");
   //      break;
   case SYSTEM_EVENT_AP_STADISCONNECTED:
     log_i("WiFi client disconnected");
     break;
   //    case SYSTEM_EVENT_AP_STAIPASSIGNED:
   //      log_i("Assigned IP address to client");
   //      break;
   //    case SYSTEM_EVENT_AP_PROBEREQRECVED:
   //      log_i("Received probe request");
   //      break;
   //    case SYSTEM_EVENT_GOT_IP6:
   //      log_i("IPv6 is preferred");
   //      break;
   //    case SYSTEM_EVENT_ETH_GOT_IP:
   //      log_i("Obtained IP address");
   //      break;
   default: break;
 }
}
////
void loop() { }

Important for good operations.

BEFORE connection to WiFI use wifi.disconnect().

WiFI.disconnect() does 2 things.

A) Disconnects from WiFi if connected.

AND the most important thing is.

B) Resets the WiFI stack to its default values.

Corrupted stack is the biggest reasons WiFi fails.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.