Asked
Resolved Resolved by DJ Sures!

How To Connect Arduino To Ezb With Uart

@DJSures it has been awhile since we discussed my attempt to use Roboclaw library with ESP32 and ARC. But I have made some progress (not real clean, but it does what I need). But now I'm trying to send data from the Roboclaw back to ARC, and can't seem to get the serial comms to work from the ESP32 to ARC. On the ARC side, I have the following EZ-Script code:

$Getbuf = " " #parms: EZB boardindex, UART, RoboClaw CMD UARTWrite(0, 0, $ReadEncoder) #Roboclaw read encoder value

sleep(3000) $x = UartAvailable(0, 0) print("bytes available: " + $x)

This sends a command (ReadEncoder) to the ESP32, sleeps, and then attempts to read data from the ESP32. The ESP32 which correctly recognizes the command it recieved, and then executes the following code on the ESP32:

   char roboCmd       = ' ';
   uint32_t position  = 0;
   roboCmd = ReadByte();
   switch (roboCmd)
   {
   case ReadEncoder:
      position = roboclaw.ReadEncM2(0x80);
      Serial.print("Reading encoder value:");
      Serial.println(position);
      Write32(position);
      break;    

On the Arduino IDE, I can see that the correct value of the encoder is returned, so I know that worked (17:29:19.481 -> Reading encoder value:1125). But on the ARC side, the UartAvailable turns 0 number of bytes in the buffer.
Is there some other function besides Write32() I should be using on the ESP32 side to send data back to the ARC?



ARC Pro

Upgrade to ARC Pro

Don't limit your robot's potential – subscribe to ARC Pro and transform it into a dynamic, intelligent machine.

PRO
Synthiam
#25  

Can you add more detail about what you mean by that?

PRO
USA
#26  

My robot has 2 EZB v4 devices in it at this time. One of them I have setup as the network of the robot (AP Mode, with SSID B9MainDevice). The other EZB (in the brain) is setup with System Name as B9BrainDevice, EZ-B IP Address as xxx.xxx.x.2, and it logs into the B9MainDevice.

On the ARC side, I have the skill EZB Connect by Name, and a Script that connects to the B9BrainDevice by its name - B9BrainDevice.

I need to know/understand what needs to be done in the ESP32 firmware to set the System Name, IP address, and have the name boardcast so the the EZB Connect by Name can use B9BrainDevice instead of an IP address. I set the #define WIFI_AP_SSID to "B9HeadDevice", but EZB Connect by Name does not see it, so I assume since the B9HeadDevice (ESP32) is in Client mode and logging into the B9MainDevice (EZB), that there must be something else to do to boardcast the name when in Client mode.

PRO
Synthiam
#27   — Edited

I'll tell you what I'm thinking, and you can tell me how far off I am from understanding.:)

  1. Your custom firmware is an EZB firmware that extends the protocol with new commands for controlling a servo controller on an ESP32 with wifi

  2. Therefore, you connect to your custom EZB firmware using the Connection robot skill

  3. The connection robot skill accepts either a Serial Port (USB) or IP Address (wifi) of the remote EZB. There can be multiple EZ-B's connected, starting at index 0 (first)

  4. Your custom firmware is wifi. But you also have an EZB v4 wifi. This means you would connect the EZB v4 and ESP32 to Client Mode. That means the two devices connect to the same access point (or router) to which your PC is connected. The access point/router will be assigned a unique address to each of the three devices (PC, ESP32, EZB v4)

  5. The connection robot skill accepts several ControlCommands for connecting and disconnecting from ezbs. You want to connect to the EZBv4 and ESP32 using programmatic control commands.

  6. Let me speculate that the EZB v4 had the IP address 192.168.0.100, and the ESP32 had the IP address 192.168.0.101. Let's also assume you wanted the EZB v4 to be on Index #0 and the ESP32 to be on Index #1. The control commands would be.

ControlCommand("Connection", "Connect0", "192.168.0.100");
ControlCommand("Connection", "Connect0", "192.168.0.101");

You might be asking about the ESP32 broadcasting itself, which can be detected using the EZB Scan Tool. I do not believe the ESP32 does that if that's the case. The firmware could be modified to do it - perhaps in a loop while it waits for a command to send a broadcast every few seconds. If that's something you're thinking of adding, let me know, and I can add some details on how the broadcast works. I recently added a bunch of support for the broadcast to ARCx, so it's fresh in my mind:).

PRO
USA
#29  

We have discussed this before. When an EZB device is in client mode, the IP it gets is assigned by the router/network that the EZB is logging into. This can change, and since my robot will eventually be autonomous, and not have a user interface, ARC must either find out what the EZB device's current IP is (which I don't know how to do without manual/UI intervention), or connect to the EZB by name, which does not change. I already have ARC connecting to the 2 EZBv4 devices via system name (not device name since every EZBv4 device has the same name), and I want to do that with the ESP32.

I have been looking at the Arduino WiFi class methods. Looks like there is a way to force a specific IP for the device. If I can get that to work, that would be another way to go. Then the IP will always be the same, but not sure if that requires changing setup on my router.

PRO
Synthiam
#30   — Edited

Apologies if we had a conversation before. I volunteer some personal time on this forum and help several people, and my day is quite hectic, as you can imagine. I ask you to try to bear with me while I take time to help you get running.:)

  1. hardcoding the IP on the device may be best if the IP changes. If that's going to change, the IP must be on the same IP network within the netmask. I assume your access point/router is part of the robot.

  2. Adding a second USB Wi-Fi adapter to your laptop is the best option. That way, you can have the EZB v4s, and ESP32 connect to it with static IP addresses. They will never change and will remain static moving forward.

  3. If you want to use the broadcast name, you'll have to implement a broadcast feature in the esp32. I'm willing to provide you with the broadcast info if you implement it as I described earlier.

The protocol is UDP on port 4242. You send a packet to the network broadcast, which is the network's broadcast IP. Most likely, your class C with 255 as the last DQN value. For example, 192.168.0.255 or 10.0.0.255, etc. I'm guessing 255.255.255.255 might also work.

The packet is assembled like...

              string broadcast = $"EZ-B {EZBType}||{Environment.MachineName}||{ipAddress}||23";

As an example, a broadcast packet could look like...

EZ-B JSALE ESP32||Some unique name||192.168.0.2||23

In the wait for connection of the esp32... maybe loop and every 2 seconds, send a broadcast packet.

PRO
Synthiam
#31   — Edited

Oh and quick look at the esp32 code you'd do something like this...

#include <WiFi.h>
#include <WiFiUDP.h>

// Create a WiFiUDP object for broadcasting
WiFiUDP udp;

// UDP broadcast address
IPAddress broadcastAddress(255, 255, 255, 255);

// UDP port
uint16_t udpPort = 4242;

// Delay between broadcasts (2 seconds in milliseconds)
unsigned long broadcastInterval = 2000;

// Time tracking for broadcast
unsigned long lastBroadcastTime = 0;

void setup() {
  // WiFi initialization code here
  // ...
  
  // Initialize the UDP object
  udp.begin(udpPort);
}

void loop() {

#ifndef AP_MODE
  if (WiFi.status() != WL_CONNECTED) {
    resetFunc(); 
  }
#endif

  // UDP broadcast every 2 seconds
  unsigned long currentMillis = millis(); // Get current time in milliseconds
  
  if (currentMillis - lastBroadcastTime >= broadcastInterval) {

    lastBroadcastTime = currentMillis;

    // Data to be broadcasted
    String message = "EZ-B JSALE ESP32||Some unique name||" + WiFi.localIP().toString() + "||23";
    
    // Send the UDP packet to the broadcast address
    udp.beginPacket(broadcastAddress, udpPort);
    udp.write(message.c_str());
    udp.endPacket();
  }

  if (_SERVER.hasClient()) {

    _CLIENT = _SERVER.available();

    Serial.print("Client connected from ");
    Serial.println(_CLIENT.remoteIP());

    while (_CLIENT.connected()) 
      doEZProtocol(); 

    Serial.println("Client disconnected");

    _CLIENT.stop();

    Serial.println("Waiting for client...");
  }
}

PRO
Synthiam
#32  

@Athena is there anything you want to add to this conversation that will assist @jsale?