Code issues with Node-Red and ESP-01

So I had someone write me some Arduino sketches, ESP-01 code, and a Node Red interface. I need to change a few things, but I want to make sure I don't completely screw this up. There are 6 motor/motor controller/AS5600 combos that will be acting a servo's. I need to be able to select the angle of an individual 'servo'. The nodes list everything as speed, and the slider range is -255 to 255. The change nodes aren't something I have dealt with, so I don't understand exactly what they are doing.
Any clarification on this would be great, thank you!!

JSON

[{"id":"3427a35b48d703b8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"dd186bbed581f701","type":"mqtt out","z":"3427a35b48d703b8","name":"test","topic":"test","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"288a79fc1071de7a","x":830,"y":440,"wires":[]},{"id":"f9351e44aea91086","type":"ui_slider","z":"3427a35b48d703b8","name":"","label":"Motor 1 Speed","tooltip":"","group":"1775db9907ecb428","order":7,"width":3,"height":3,"passthru":false,"outs":"end","topic":"test","topicType":"msg","min":"-255","max":"255","step":1,"x":180,"y":340,"wires":[["1da20c308ebfbbc1"]]},{"id":"1da20c308ebfbbc1","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Motor1Speed","pt":"global","to":"0.0,q","tot":"str"},{"t":"change","p":"Motor1Speed","pt":"global","from":"q","fromt":"str","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"Motor1Speed","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":340,"wires":[[]]},{"id":"5987fb834bc6ee59","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":18,"width":3,"height":1,"passthru":false,"label":"Confirm","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Motor1Speed","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":340,"wires":[["dd186bbed581f701"]]},{"id":"ee4dcfedacda15c5","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":13,"width":3,"height":1,"passthru":false,"label":"Confirm","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Motor2Speed","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":380,"wires":[["dd186bbed581f701"]]},{"id":"156e8555a4db1783","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":14,"width":3,"height":1,"passthru":false,"label":"Confirm","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Motor3Speed","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":420,"wires":[["dd186bbed581f701"]]},{"id":"244e6ba1f0f3caab","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":15,"width":3,"height":1,"passthru":false,"label":"Confirm","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Motor4Speed","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":460,"wires":[["dd186bbed581f701"]]},{"id":"780f11cd0e6bae30","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":16,"width":3,"height":1,"passthru":false,"label":"Confirm","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Motor5Speed","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":500,"wires":[["dd186bbed581f701"]]},{"id":"02b1efc54d992596","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":17,"width":3,"height":1,"passthru":false,"label":"Confirm","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Motor6Speed","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":540,"wires":[["dd186bbed581f701"]]},{"id":"255f2f02da7aa735","type":"comment","z":"3427a35b48d703b8","name":"Motor Speed Confirmations","info":"","x":590,"y":280,"wires":[]},{"id":"3c5ee43067f49bff","type":"ui_slider","z":"3427a35b48d703b8","name":"","label":"Motor 2 Speed","tooltip":"","group":"1775db9907ecb428","order":8,"width":3,"height":3,"passthru":false,"outs":"end","topic":"test","topicType":"msg","min":"-255","max":"255","step":1,"x":180,"y":380,"wires":[["cfc7f324c4c43787"]]},{"id":"cfc7f324c4c43787","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Motor2Speed","pt":"global","to":"0.1,q","tot":"str"},{"t":"change","p":"Motor2Speed","pt":"global","from":"q","fromt":"str","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"Motor2Speed","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":380,"wires":[[]]},{"id":"d0932abefc911e17","type":"ui_slider","z":"3427a35b48d703b8","name":"","label":"Motor 3 Speed","tooltip":"","group":"1775db9907ecb428","order":9,"width":3,"height":3,"passthru":false,"outs":"end","topic":"test","topicType":"msg","min":"-255","max":"255","step":1,"x":180,"y":420,"wires":[["40aea0d1a0397abe"]]},{"id":"40aea0d1a0397abe","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Motor3Speed","pt":"global","to":"0.2,q","tot":"str"},{"t":"change","p":"Motor3Speed","pt":"global","from":"q","fromt":"str","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"Motor3Speed","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":420,"wires":[[]]},{"id":"aa62d84d06cfcfac","type":"ui_slider","z":"3427a35b48d703b8","name":"","label":"Motor 4 Speed","tooltip":"","group":"1775db9907ecb428","order":10,"width":3,"height":3,"passthru":false,"outs":"end","topic":"test","topicType":"msg","min":"-255","max":"255","step":1,"x":180,"y":460,"wires":[["d4c75faf6744d70e"]]},{"id":"d4c75faf6744d70e","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Motor4Speed","pt":"global","to":"0.3,q","tot":"str"},{"t":"change","p":"Motor4Speed","pt":"global","from":"q","fromt":"str","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"Motor4Speed","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":460,"wires":[[]]},{"id":"9b925ad0c98825b7","type":"ui_slider","z":"3427a35b48d703b8","name":"","label":"Motor 5 Speed","tooltip":"","group":"1775db9907ecb428","order":11,"width":3,"height":3,"passthru":false,"outs":"end","topic":"test","topicType":"msg","min":"-255","max":"255","step":1,"x":180,"y":500,"wires":[["da23639bead70940"]]},{"id":"da23639bead70940","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Motor5Speed","pt":"global","to":"0.4,q","tot":"str"},{"t":"change","p":"Motor5Speed","pt":"global","from":"q","fromt":"str","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"Motor5Speed","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":500,"wires":[[]]},{"id":"20c76a184d291c06","type":"ui_slider","z":"3427a35b48d703b8","name":"","label":"Motor 6 Speed","tooltip":"","group":"1775db9907ecb428","order":12,"width":3,"height":3,"passthru":false,"outs":"end","topic":"test","topicType":"msg","min":"-255","max":"255","step":1,"x":180,"y":540,"wires":[["1df7403fb2ddfca1"]]},{"id":"1df7403fb2ddfca1","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Motor6Speed","pt":"global","to":"0.5,q","tot":"str"},{"t":"change","p":"Motor6Speed","pt":"global","from":"q","fromt":"str","to":"payload","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"Motor6Speed","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":540,"wires":[[]]},{"id":"6232f850775f52ca","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":20,"width":14,"height":1,"passthru":false,"label":"Tune","tooltip":"","color":"","bgcolor":"","icon":"","payload":"2.0","payloadType":"str","topic":"topic","topicType":"msg","x":610,"y":600,"wires":[["dd186bbed581f701"]]},{"id":"eb955bd089da5cfb","type":"ui_dropdown","z":"3427a35b48d703b8","name":"","label":"Servos","tooltip":"","place":"Select option","group":"1775db9907ecb428","order":2,"width":14,"height":1,"passthru":true,"multiple":false,"options":[{"label":"Servo 1","value":"1","type":"str"},{"label":"Servo 2","value":"2","type":"str"},{"label":"Servo 3","value":"3","type":"str"},{"label":"Servo 4","value":"4","type":"str"},{"label":"Servo 5","value":"5","type":"str"},{"label":"Servo 6","value":"6","type":"str"},{"label":"Servo 7","value":"7","type":"str"},{"label":"Servo 8","value":"8","type":"str"},{"label":"Servo 9","value":"9","type":"str"},{"label":"Servo 10","value":"10","type":"str"},{"label":"Servo 11","value":"11","type":"str"},{"label":"Servo 12","value":"12","type":"str"},{"label":"Servo 13","value":"13","type":"str"},{"label":"Servo 14","value":"14","type":"str"},{"label":"Servo 15","value":"15","type":"str"},{"label":"Servo 16","value":"16","type":"str"}],"payload":"","topic":"ServoNum","topicType":"global","x":220,"y":680,"wires":[["3af8dc949403d411"]]},{"id":"53a888bd4ad1c5da","type":"ui_numeric","z":"3427a35b48d703b8","name":"","label":"Servo Degree","tooltip":"","group":"1775db9907ecb428","order":5,"width":14,"height":1,"wrap":true,"passthru":true,"topic":"ServoDeg","topicType":"global","format":"{{value}}","min":0,"max":"360","step":1,"x":180,"y":600,"wires":[["b91509241361502f"]]},{"id":"b91509241361502f","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"Servo","pt":"global","to":"1.q,w","tot":"str"},{"t":"change","p":"Servo","pt":"global","from":"w","fromt":"str","to":"payload","tot":"msg"},{"t":"change","p":"Servo","pt":"global","from":"q","fromt":"str","to":"ServoNum","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":600,"wires":[[]]},{"id":"ec2ae6d52ce9271c","type":"ui_button","z":"3427a35b48d703b8","name":"","group":"1775db9907ecb428","order":23,"width":14,"height":1,"passthru":false,"label":"Update","tooltip":"","color":"","bgcolor":"","icon":"","payload":"Servo","payloadType":"global","topic":"topic","topicType":"msg","x":600,"y":680,"wires":[["dd186bbed581f701"]]},{"id":"3af8dc949403d411","type":"change","z":"3427a35b48d703b8","name":"","rules":[{"t":"set","p":"ServoNum","pt":"global","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":680,"wires":[[]]},{"id":"288a79fc1071de7a","type":"mqtt-broker","name":"","broker":"localhost ","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""},{"id":"1775db9907ecb428","type":"ui_group","name":"Servos","tab":"78741e0a6481a2f3","order":5,"disp":false,"width":"18","collapse":false},{"id":"78741e0a6481a2f3","type":"ui_tab","name":"Servo Control","icon":"dashboard","disabled":false,"hidden":false}]

Here is the ESP-01 code. SSID and PW changed for security

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include "Arduino.h"

const char* ssid = "XXXXXX";
const char* password = "XXXXXXXXXX";
const IPAddress mqttServerIP(192,168,254,14);
const int httpPort = 1883;
const char* deviceID = "ESP8266";

WiFiClient wifiClient;
PubSubClient MQTTClient(wifiClient);
long lastMsgTime = 0;
char msg[64];
char topic[32];
int pulseCount = 0;

/*
 * Code for MQTT reseves
 * 0.{number of motor},{speed}
 * 1.{number of servo},{degree}
 */
void mqttCallback(char* topic, byte* payload, unsigned int length){
  memcpy(msg, payload,length);
  msg[length] = '\0';
  
  String message(msg); 
  int comma = message.indexOf(',');
  int period = message.indexOf('.');
  
  if(message.charAt(0) == '0'){
    int motor_num = message.substring(period+1, comma).toInt();
    String speed = message.substring(comma+1);
    if(motor_num<6){
      Serial.println("0."+String(motor_num)+","+speed);
    }else{
      Serial.println("0."+String(motor_num));
    }
  }else if(message.charAt(0) == '1'){
    String servo_num = message.substring(period+1, comma);
    String degree = message.substring(comma+1);
    Serial.println("1."+servo_num+","+degree);
  }

  /*
  Serial.print("Message recived in topic [");
  Serial.print(topic);
  Serial.print("]  ");
  Serial.println(msg);
  */

  //Here is where to put stuff to act when somthing is recived
}

void wifiSetup(){
   delay(10);
  // We start by connecting to a WiFi network
  /*
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  */

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    //Serial.print(".");
  }
/*
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP()); 
  */
}

void mqttSetup(){
  MQTTClient.setServer(mqttServerIP, 1883);
  MQTTClient.setCallback(mqttCallback);  
}

void setup() {
  Serial.begin(9600);
  wifiSetup();
  mqttSetup();
}

void mqttLoop(){
  while(!MQTTClient.connected()){
    /*
    Serial.print("Attempting to connect to MQTT broker at ");
    Serial.println(mqttServerIP);
*/
    if(MQTTClient.connect(deviceID)){
      //Serial.println("Connected to MQTT broker");
/*
      snprintf(topic,32,"ToHost/%s", deviceID);
      snprintf(msg, 64, "CONNECT", deviceID);
      MQTT.publish(topic,msg);

      snprintf(topic, 32, "ToDevice/%s", deviceID);
      MQTTClient.subscribe(topic);
*/
      MQTTClient.subscribe("test");
      
    }else{
      Serial.print("Connection Failed");
      delay(5000);
    }
  }
  MQTTClient.loop(); 
}

void publish(char* message){
  snprintf(topic, 32, "test", deviceID);
  MQTTClient.publish(topic, message);
}

void loop() {
  mqttLoop();
  /*
  if(Serial.available()>0){
    String data = Serial.readString();
    char temptopic[32];
    data.toCharArray(temptopic, 32);
    publish(temptopic);
  }
  */
}

The way your flow is coded it can handle 6 motors and 12 servos. To deal with a servo you need to:

1 - select a Servo
2 - set the Servo Degree
3 - press the UDATE SETVO button (spelling error?)

The 'TUNE SERVO' button sends a hard coded payload of '2.0' but the Arduino code has nothing to handle that.

In addition, thre is no code in Arduino code to actually do anything with the MQTT messages it receives. If you look in the code you will see:

  //Here is where to put stuff to act when somthing is recived

that needs to be fleshed out and this part is not a Node-RED issue.

The servo section is workable. The motor section has me wondering. The way it is set up, what value is the motor speed
slider sending? The change nodes have me confused. Thank you for the reply. I'm working in the Arduino forums to try and fix the other code.

First off, change the Label' in each of the button nodes so identify what motor it controls. So for the first button change the label to 'Confirm 1' the second to 'Confirm 2' etc.

Next move one of the motor sliders and then go refersh the 'global' context to see what is in the variable OR you could add a debug node to the output of the change nodes to see what it has generated.

1 Like

If I just want to have the slider control the position directly, instead of using the "Confirm" buttons, what do I need to do with the Confirm button, and the Change nodes?
Also, if possible is there a simple way to explain what the change node are doing? The 'set and change' data isn't familiar to me.

Have you opened a button and looked at it’s configuration and read the Help tab about it? If so, tell me what you think it does and if not, open it and read the ``Help` and tell me what you think it does.

The button config is straight forward. The button will send the payload when pressed. So I deleted one button, and connected the change nodes to the 'MQTT Out' and Debug nodes directly. It seems like that is doing the same thing without having to press the 'confirm'. I can move the slider and watch the payload values change.
In the change nodes, the set and change functions use 0.0,q and q. The output according to debug is in this format "0.1,-58" How does that output correlate to a position on the other side? Or, is there a simpler way to format this to be read by an Arduino for positional output?
Thank you for all the help!

It sounds like you are confusing the motors with the servos. If you look at the bit of Arduino code you supplied is has this

/*
 * Code for MQTT reseves
 * 0.{number of motor},{speed}
 * 1.{number of servo},{degree}
 */

so if the first character is a 0, it deals with motors. If it is a 1 it deals with servos.

For '0.1.-58' the '0.1,-58' indicates it is for a motor, the '0.1,-58' indicatees it is for motor number one and the '0.1,-58' is for the speed of the motor. I would guess it is telling the motor to go in reverse at that speed.

When talking about 'positional output' I would assume you are talking about a servo. The servo has a range it can turn and you have specified (in the node) a range from 0 to 360. So you won't see negative numbers from the servo node.

That is exactly what I needed! Thank you! The motors will be set up with position sensors and motor controllers to turn them into a PID controlled servo. So the range set in the slider node will be whatever range of values each setup needs. The lightbulb is on! At least it makes sense now.

1 Like

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