Hello,
I’m successfully sending via Node-Red a MQTT message as a number and successfully subscribing to it in a ESP32 sketch with AsyncMQTTclient, where I wish to use the number to move a Stepper Motor.
Could someone explain to me how I can extract / convert the string in AsyncMQTTclient to a number please?
Regards
Ian
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { String messageTemp; for (int i = 0; i < len; i++) { Serial.print((char)payload[i]); messageTemp += (char)payload[i]; } if (strcmp(topic, "azimuth") == 0) { stepper1.moveTo(????); // MQTT Number should go here stepper1.run(); delay(5); Serial.print("moved to: "); }
Hi Ian.
Can you see if the following works?
https://github.com/knolleary/pubsubclient/issues/105#issuecomment-168538164
I think you can also use the atoi() function to convert a char to an int.
forum.arduino.cc/index.php?topic=82495.0
Let me know if it works.
Regards,
Sara
Hello Sara,
Thanks for your reply.
In the meantime I’ve found out that the problem may not be to convert to a number, more that I get a “no matching function” error when compiling.
I assumed it was trying to read as a number but received it as a string.
no matching function for call to 'AccelStepper::moveTo(String&)'
From this portion of the code:
if (strcmp(topic, "azimuth") == 0) { stepper1.moveTo(messageTemp); stepper1.run(); delay(5); Serial.print("moved to: "); }
I’ve taken and adapted the code from your “learn ESP32” course module 7, ESP32 MQTT
Here’s my code in full if you could maybe point to where I’m going wrong please?
/*
This example uses FreeRTOS softwaretimers as there is no built-in Ticker library
*/
#include WiFi.h
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include AsyncMqttClient.h
#define WIFI_SSID "xxxxxxxx"
#define WIFI_PASSWORD "xxxxxxx"
#define MQTT_HOST IPAddress(192, 168, 0, 3)
//#define MQTT_HOST IPAddress(192, 168, 1, 188)
#define MQTT_PORT 1883
#define A0 36
#define A1 39
#define A2 34
#define A3 35
const int relay1 = 22;
const int relay2 = 23;
const int relay3 = 19;
const int relay4 = 21;
const int pump = 18;
const int fivev = 5;
unsigned long previousMillis0 = 0;
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
const long interval = 5000; // interval at which to publish sensor readings
AsyncMqttClient mqttClient;
TimerHandle_t mqttReconnectTimer;
TimerHandle_t wifiReconnectTimer;
void connectToWifi() {
Serial.println("Connecting to Wi-Fi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}
void connectToMqtt() {
Serial.println("Connecting to MQTT...");
mqttClient.connect();
}
void WiFiEvent(WiFiEvent_t event) {
Serial.printf("[WiFi-event] event: %d\n", event);
switch (event) {
case SYSTEM_EVENT_STA_GOT_IP:
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
connectToMqtt();
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
Serial.println("WiFi lost connection");
xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
xTimerStart(wifiReconnectTimer, 0);
break;
}
}
void onMqttConnect(bool sessionPresent) {
Serial.println("Connected to MQTT.");
Serial.print("Session present: ");
Serial.println(sessionPresent);
uint16_t packetIdSub0 = mqttClient.subscribe("pump", 0);
uint16_t packetIdSub1 = mqttClient.subscribe("relay1", 0);
uint16_t packetIdSub2 = mqttClient.subscribe("relay2", 0);
uint16_t packetIdSub3 = mqttClient.subscribe("relay3", 0);
uint16_t packetIdSub4 = mqttClient.subscribe("relay4", 0);
uint16_t packetIdSub5 = mqttClient.subscribe("fivev", 0);
Serial.print("Subscribing at QoS 0, packetId: ");
Serial.println(packetIdSub0);
Serial.println(packetIdSub5);
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println("Disconnected from MQTT.");
if (WiFi.isConnected()) {
xTimerStart(mqttReconnectTimer, 0);
}
}
void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
//Serial.println("Subscribe acknowledged.");
//Serial.print(" packetId: ");
//Serial.println(packetId);
//Serial.print(" qos: ");
//Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
//Serial.println("Unsubscribe acknowledged.");
//Serial.print(" packetId: ");
//Serial.println(packetId);
}
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
String messageTemp;
for (int i = 0; i < len; i++) {
Serial.print((char)payload[i]);
messageTemp += (char)payload[i];
}
if (strcmp(topic, "fivev") == 0) {
// If the relay is on turn it off (and vice-versa)
if (messageTemp == "fivev-on") {
digitalWrite(fivev, LOW);
} else {
digitalWrite(fivev, HIGH);
}
}
if (strcmp(topic, "relay1") == 0) {
// If the relay is on turn it off (and vice-versa)
if (messageTemp == "relay1-on") {
digitalWrite(relay1, LOW);
} else {
digitalWrite(relay1, HIGH);
}
}
if (strcmp(topic, "relay2") == 0) {
// If the relay is on turn it off (and vice-versa)
if (messageTemp == "relay2-on") {
digitalWrite(relay2, LOW);
} else {
digitalWrite(relay2, HIGH);
}
}
if (strcmp(topic, "relay3") == 0) {
// If the relay is on turn it off (and vice-versa)
if (messageTemp == "relay3-on") {
digitalWrite(relay3, LOW);
} else {
digitalWrite(relay3, HIGH);
}
}
if (strcmp(topic, "relay4") == 0) {
// If the relay is on turn it off (and vice-versa)
if (messageTemp == "relay4-on") {
digitalWrite(relay4, LOW);
} else {
digitalWrite(relay4, HIGH);
}
}
if (strcmp(topic, "pump") == 0) {
// If the relay is on turn it off (and vice-versa)
if (messageTemp == "pump-on") {
digitalWrite(pump, LOW);
} else {
digitalWrite(pump, HIGH);
}
}
Serial.println(" Publish received.");
Serial.print(" topic: ");
//Serial.println(topic);
//Serial.print(" qos: ");
//Serial.println(properties.qos);
//Serial.print(" dup: ");
//Serial.println(properties.dup);
//Serial.print(" retain: ");
//Serial.println(properties.retain);
//Serial.print(" len: ");
//Serial.println(len);
//Serial.print(" index: ");
//erial.println(index);
//Serial.print(" total: ");
//Serial.println(total);
}
void onMqttPublish(uint16_t packetId) {
//Serial.println("Publish acknowledged.");
//Serial.print(" packetId: ");
//Serial.println(packetId);
}
void setup() {
Serial.begin(115200);
Serial.println();
Serial.println();
pinMode(relay1, OUTPUT);
pinMode(relay2, OUTPUT);
pinMode(relay3, OUTPUT);
pinMode(relay4, OUTPUT);
pinMode(pump, OUTPUT);
pinMode(fivev, OUTPUT);
int sMoisture1 = analogRead(A0);
int sMoisture2 = analogRead(A1);
int sMoisture3 = analogRead(A2);
int sMoisture4 = analogRead(A3);
mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast(connectToMqtt));
wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast(connectToWifi));
WiFi.onEvent(WiFiEvent);
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onSubscribe(onMqttSubscribe);
mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onMessage(onMqttMessage);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
connectToWifi();
}
void loop() {
float sMoisture1 = analogRead(A0);
unsigned long currentMillis0 = millis();
// Every X number of seconds (interval = 5 seconds)
// it publishes a new MQTT message on topic sMoisture1
if (currentMillis0 - previousMillis0 >= interval) {
// Save the last time a new reading was published
previousMillis0 = currentMillis0;
uint16_t packetIdPub0 = mqttClient.publish("sMoisture1", 2, true, String(sMoisture1).c_str());
//Serial.print("Publishing on topic sMoisture1 at QoS 2, packetId: ");
//Serial.println(sMoisture1);
}
float sMoisture2 = analogRead(A1);
unsigned long currentMillis1 = millis();
// Every X number of seconds (interval = 5 seconds)
// it publishes a new MQTT message on topic ssMoisture2
if (currentMillis1 - previousMillis1 >= interval) {
// Save the last time a new reading was published
previousMillis1 = currentMillis1;
uint16_t packetIdPub1 = mqttClient.publish("sMoisture2", 2, true, String(sMoisture2).c_str());
//Serial.print("Publishing on topic sMoisture2 at QoS 2, packetId: ");
//Serial.println(sMoisture2);
}
float sMoisture3 = analogRead(A2);
unsigned long currentMillis2 = millis();
// Every X number of seconds (interval = 5 seconds)
// it publishes a new MQTT message on topic ssMoisture3
if (currentMillis2 - previousMillis2 >= interval) {
// Save the last time a new reading was published
previousMillis2 = currentMillis2;
uint16_t packetIdPub2 = mqttClient.publish("sMoisture3", 2, true, String(sMoisture3).c_str());
//Serial.print("Publishing on topic ssMoisture3 at QoS 2, packetId: ");
//Serial.println(sMoisture3);
}
float sMoisture4 = analogRead(A3);
unsigned long currentMillis3 = millis();
// Every X number of seconds (interval = 5 seconds)
// it publishes a new MQTT message on topic ssMoisture4
if (currentMillis3 - previousMillis3 >= interval) {
// Save the last time a new reading was published
previousMillis3 = currentMillis3;
uint16_t packetIdPub3 = mqttClient.publish("sMoisture4", 2, true, String(sMoisture4).c_str());
//Serial.print("Publishing on topic ssMoisture4 at QoS 2, packetId: ");
//Serial.println(sMoisture4);
}
}
Hi Ian.
The code you’ve posted doesn’t include the stepper motor section.
You are using this library, right https://www.airspayce.com/mikem/arduino/AccelStepper/classAccelStepper.html?
The moveTo() function accepts a number as an argument. So, I think you really need to convert it to a number.
It seems that your variable is in String format, so you can use the toInt() function to convert it to a number: https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/toint/
Were you successful controlling the stepper motor without the MQTT code?
Let me know if this helps.
Regards,
Sara
Hello Sara,
I didn’t notice but it seemed when pasting in the code something between < and > gets missed out in visual mode?
#include
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include
#include ;
#include <WiFi.h>
extern "C" {
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
}
#include <AsyncMqttClient.h>
#include <AccelStepper.h>
I’ll give the toint() function a try.
Yes I was successful in controlling the Steppers with a dual stepper example.
Regards
Ian
Hello Sara,
As the value coming from the SunPos node is a float number I’ve tried: moveTo(messageTemp.toFloat())
Which compiles so I’ll flash an ESP32 later when I get home and see what happens.
Thanks for your help so far.
Regards
Ian
Hi.
That was probably an issue with the visual mode. You can paste your code using pastebin for example, so it doesn’t change when you paste it here.
Ok. Then, let me know if it worked.
Regards,
Sara
Hello Sara,
Well I’m reading the MQTT ok using “.toFloat()”, but I can only get the stepper to move if there’s a command in the loop, and I take it I can’t because of freeRTOS?
Would you have any suggestions please?
Hi again.
So, the motor doesn’t move when you receive the message on the topic, is that it? (it is not included in the code you’ve posted).
But the snippet you shared previously seemed to be well implemented, so it should be working. And are the relays working fine? Because they are also controlled when you receive a message on a topic.
What if you add an auxiliary global variable that will tell you whether you received a message on the stepper topic. Save the number and then, in the loop() check if that number has changed and move the motor accordingly? I don’t know if this will work, it is just a suggestion.
Another thing that might help is creating different tasks. But I don’t know if a simple task implementation will solve the problem.
You can take a look at our tutorial about tasks and see if it can be an option: https://randomnerdtutorials.com/esp32-dual-core-arduino-ide/
Regards,
Sara
Hello Sara,
I’m so sorry I posted the wrong code. I am managing to move the motor but only one step, not the full amount it would seem like it need to be in the loop, I’ll take a look at tasks
Regards
Ian
/* This example uses FreeRTOS softwaretimers as there is no built-in Ticker library */ #include <WiFi.h> extern "C" { #include "freertos/FreeRTOS.h" #include "freertos/timers.h" } #include <AsyncMqttClient.h> #include <AccelStepper.h> //#define WIFI_SSID "" //#define WIFI_PASSWORD "" #define WIFI_SSID "" #define WIFI_PASSWORD "" //#define MQTT_HOST IPAddress() #define MQTT_HOST IPAddress() #define MQTT_PORT 1883 // Define two steppers and the pins they will use AccelStepper stepper1(AccelStepper::DRIVER, 32, 33); //AccelStepper stepper2(AccelStepper::DRIVER, 14, 12); int pos1 = 3600; //int pos2 = 5678; AsyncMqttClient mqttClient; TimerHandle_t mqttReconnectTimer; TimerHandle_t wifiReconnectTimer; void connectToWifi() { Serial.println("Connecting to Wi-Fi..."); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } void connectToMqtt() { Serial.println("Connecting to MQTT..."); mqttClient.connect(); } void WiFiEvent(WiFiEvent_t event) { Serial.printf("[WiFi-event] event: %d\n", event); switch (event) { case SYSTEM_EVENT_STA_GOT_IP: Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); connectToMqtt(); break; case SYSTEM_EVENT_STA_DISCONNECTED: Serial.println("WiFi lost connection"); xTimerStop(mqttReconnectTimer, 0); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi xTimerStart(wifiReconnectTimer, 0); break; } } void onMqttConnect(bool sessionPresent) { Serial.println("Connected to MQTT."); Serial.print("Session present: "); Serial.println(sessionPresent); uint16_t packetIdSub0 = mqttClient.subscribe("azimuth", 0); uint16_t packetIdSub1 = mqttClient.subscribe("altitude", 0); Serial.print("Subscribing at QoS 0, packetId: "); Serial.println(packetIdSub0); Serial.println(packetIdSub1); } void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { Serial.println("Disconnected from MQTT."); if (WiFi.isConnected()) { xTimerStart(mqttReconnectTimer, 0); } } void onMqttSubscribe(uint16_t packetId, uint8_t qos) { //Serial.println("Subscribe acknowledged."); //Serial.print(" packetId: "); //Serial.println(packetId); //Serial.print(" qos: "); //Serial.println(qos); } void onMqttUnsubscribe(uint16_t packetId) { //Serial.println("Unsubscribe acknowledged."); //Serial.print(" packetId: "); //Serial.println(packetId); } void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { String messageTemp; for (int i = 0; i < len; i++) { Serial.print((char)payload[i]); messageTemp += (char)payload[i]; } if (strcmp(topic, "azimuth") != 0) { stepper1.moveTo(messageTemp.toFloat()); // stepper1.moveTo(2000); stepper1.run(); //delay(5); Serial.println("moved to: "); Serial.print(messageTemp.toFloat()); Serial.println(stepper1.currentPosition()); //} } // if (strcmp(topic, "altitude") == 0) { // Serial.println("Move Altitude."); // } // if (strcmp(topic, "relay2") == 0) { // If the relay is on turn it off (and vice-versa) // if (messageTemp == "relay2-on") { // digitalWrite(relay2, LOW); // } else { // digitalWrite(relay2, HIGH); // } // } Serial.println(" Publish received."); Serial.print(" topic: "); Serial.println(topic); //Serial.print(" qos: "); //Serial.println(properties.qos); //Serial.print(" dup: "); //Serial.println(properties.dup); //Serial.print(" retain: "); //Serial.println(properties.retain); //Serial.print(" len: "); //Serial.println(len); //Serial.print(" index: "); //Serial.println(index); //Serial.print(" total: "); //Serial.println(total); } void onMqttPublish(uint16_t packetId) { Serial.println("Publish acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); } void setup() { Serial.begin(115200); Serial.println(); stepper1.setCurrentPosition(0); stepper1.setMaxSpeed(1000); stepper1.setAcceleration(1000); //stepper2.setMaxSpeed(2000); //stepper2.setAcceleration(800); stepper1.setEnablePin(26); mqttReconnectTimer = xTimerCreate("mqttTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToMqtt)); wifiReconnectTimer = xTimerCreate("wifiTimer", pdMS_TO_TICKS(2000), pdFALSE, (void*)0, reinterpret_cast<TimerCallbackFunction_t>(connectToWifi)); WiFi.onEvent(WiFiEvent); mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onSubscribe(onMqttSubscribe); mqttClient.onUnsubscribe(onMqttUnsubscribe); mqttClient.onMessage(onMqttMessage); mqttClient.onPublish(onMqttPublish); mqttClient.setServer(MQTT_HOST, MQTT_PORT); connectToWifi(); } void loop() { }
Hi Ian.
The code seems to be well implemented. However I’m not familiar with the library you’re using to control the stepper.
Are you sure you are using the correct methods to move the stepper motor? Because if it moves, it means that that part of the code is running, but the functions to control the stepper motor might not be implemented properly.
Are your relays working fine too?
Then, let me know if you find a solution. Otherwise, I might try taking a look at the stepper motor library as well.
Regards,
Sara