Uart bridge

FluidNC runs the UART at 1Mbps by default.

Yes, but opposite what you’re suggesting.

I believe the ESP-32 bit-bangs the UART, so when you’re transmitting data you’re hanging out in an ISR. That’s fine if you are sending a byte or two and the system is pretty much idle. It’s not fine if you have significant data flow and the system is otherwise pretty busy.

You want to get into and out of the ISR as friggin fast as you can to save the processor to handle the real work (running the motion control and many KHz of stepper driver pulse train I2S bit-banging)

Going to 1990s bit rates can be the difference from a non-viable system at the legacy rates vs one that runs correctly.

Completely suspect. See above.

1Mbps isn’t even that fast these days. Look at SERDES or even something simple like the HDMI or DisplayPort cable that you find in your monitors or TVs. Multi-gigabit signal interfaces over ‘junk’ copper.

Edit to add: The pendants are not presently capable of being gcode senders. They speak a FluidNC (possibly shared with GrblHAL) protocol for sending commands and status reports back and forth.

When using these for jogging or starting a job or probing, We’re not using gcode sending of job commands. just things like (paraphrasing) “FluidNC status is [blah], my position is [xyzabc]” etc.

The things you see in the FluidDial app like position displays are all perioidically sent from FluidNC and the pendant displays them.

This also means that the pendant interface doesn’t have to be reliable for status. If the pendant misses a status update from FluidNC, it recovers on the next packet of data in the protocol stream.

Similarly, if you send a jog command and the pendant doesn’t get the [Ack?], the pendant sends it again.

Reliability is in the protocol layer, not down in the physical layer. As is the general practice for high speed ineterfaces over junk copper.

The CYD does have a storage card slot, so if we ever decife to use sender code we would then use the command/ack protocol to achieve reliability. It’s more of the same where you want to rip through sending the gcode sentences as blindingly fast as you can so you get the heck out of the ISR processing the receive and get back to the business of running the machine.

The sender doesn’t send the next line before it gets the ACK, and likely FluidNC wouldn’t send the ACK until the motion and control elements were ready to receive a new line.

Edit2: some references for review, in case any of my understanding is BS. “Jim is a moron” is always the first branch on the bad understanding fishbone.

GrblParser:

Sample Applications:

1 Like

To see if it works!

Lower baud rates work too, with marginally more lag for things like getting file lists.

Once it’s going if there’s still weird behaviour I’ll start dropping the BAUD bit at a time.

I have no clue how fast the serial link needs to be but as has been pointed out unless it’s streaming gcode missed packets aren’t an issue.

1 Like

And Bing-go was his name-o!

I’ll have to edit the first post,everything in it is wrong now, the code and the hardware. :grin:

I also noticed when I had a lipo battery connected it powered the CYD but there didn’t seem to be 5v going out to the esp32 serial sender. But with USB power plugged in there was.

As an aside I did try some Bluetooth code. I didn’t test a lot but initial observations were there was a few seconds needed to pair each time.

I’m waiting on a couple new esp32 boards coming. Next steps will be soldering the wiring with connectors.

I think I’d like to keep trying with the esp32-c3 boards, or I think I have a s3 somewhere.

2 Likes

I stand corrected. Thanks for clearing that up for me.

1 Like

I just re-read my wall of text from last night. Text is a terrible medium because it can’t convey tone. Re-reading it this morning, it comes across as professorial or grumpy. Not my intent at all. Intent is more “excited to share some experience with the forum.”

I’m sorry if it didn’t read the way I intended it.

I should elaborate on this a bit more. Jeff is completely right that from a data flow point of view, these low bit rates are indeed sufficient to move the data we need to move, it’s just the weird nuances of the embedded hardware and software that make this a difficult problem to analyze.

A part of my professional activities include commanding and telemetring things that have transport and turnaround times measured in hours, and maximum bit rates measured in single digit bits per second. I live in weird edge conditions like this and seldom get to spout off about these edge cases. That adds to the loquatiousnes.

:grinning:

4 Likes

I was just trying to watch out. Making sure we weren’t trying to eek out a max number for the hell of it. But it makes sense if it is pausing for bit banging that higher baud rates would spend less time in the routine (especially if that is all waiting inside an ISR).

I dunno, I’m making this up as I go. If someone has a recommendation for the best BAUD to use I’ll not argue.

If you have 921600 working reliably, my advise is to leave it there.

Now that you have it working, how does someone replicate your setup?

1 Like

I’ll need to tidy up the hardware, replace all the jumper wires with proper connections but in essence:

Board 1 - connects to the CYD using the 4 wires that would go to the connector:

Board 2 connects to the Jackpot expansion slot the same way - in each case matching TX to RX. strong text

This is the code for both boards - you need the mac address of the boards you’re using then one is defined and Board 1, the other as Board 2

If you using normal 32 or 38 pin esp32 then Pins 1 and 3 are used. I’m still trying with the esp32c3

In the code below debug has been commented out as it interfered with the pendant display. you can reenable it for testing and if you open a serial connection over usb you can confirm messages being sent and received.

This is the code for both boards, define them as 1 or 2. It also doesn’t matter which goes on what end.

/*********************************************************************************
 * ESP-Now-Serial-Bridge
 *
 * ESP32 based serial bridge for transmitting serial data between two boards
 *
 * The primary purpose of this sketch was to enable a MAVLink serial connection,
 *   which I successfully tested at 57600 bps.  In theory, much faster buad rates
 *   should work fine, but I have not tested faster than 115200.
 *
 * Range is easily better than regular WiFi, however an external antenna may be
 *   required for truly long range messaging, to combat obstacles/walls, and/or
 *   to achieve success in an area saturated with 2.4GHz traffic.
 * 
 * I made heavy use of compiler macros to keep the sketch compact/efficient.
 *
 * To find the MAC address of each board, uncomment the #define DEBUG line, 
 *   and monitor serial output on boot.  Set the OPPOSITE board's IP address
 *   as the value for RECVR_MAC in the macros at the top of the sketch.
 *   
 * The BLINK_ON_* macros should be somewhat self-explanatory.  If your board has a built-in
 *   LED (or you choose to wire an external one), it can indicate ESP-Now activity as
 *   defined by the macros you choose to enable.
 *
 * When uploading the sketch, be sure to define BOARD1 or BOARD2 as appropriate
 *   before compiling.
 *
 * -- Yuri - Sep 2021
 *
 * Based this example - https://randomnerdtutorials.com/esp-now-two-way-communication-esp32/
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files.
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
*********************************************************************************/

#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>

#define BOARD2 // BOARD1 or BOARD2

#ifdef BOARD2 //Long Board
#define RECVR_MAC {0x64, 0xE8, 0x33, 0x86, 0x46, 0x5C}  //Esp32C3 Board 1
//#define BLINK_ON_SEND
//#define BLINK_ON_SEND_SUCCESS
#define BLINK_ON_RECV
#else
#define RECVR_MAC {0x64, 0xE8, 0x33, 0x86, 0x62, 0x60}   // //Esp32C3 Board 2
//#define BLINK_ON_SEND
#define BLINK_ON_SEND_SUCCESS
//#define BLINK_ON_RECV
#endif

#define WIFI_CHAN  11 // 12-13 only legal in US in lower power mode, do not use 14
#define BAUD_RATE  921600
#define TX_PIN     21 // default UART0 is pin 1 (shared by USB)
#define RX_PIN     20 // default UART0 is pin 3 (shared by USB)
#define SER_PARAMS SERIAL_8N1 // SERIAL_8N1: start/stop bits, no parity
//#define DEBUG
#define BUFFER_SIZE 250 // max of 250 bytes
//#define DEBUG // for additional serial messages (may interfere with other messages)

#ifndef LED_BUILTIN
#define LED_BUILTIN 2  // some boards don't have an LED or have it connected elsewhere
#endif

const uint8_t broadcastAddress[] = RECVR_MAC;
// wait for double the time between bytes at this serial baud rate before sending a packet
// this *should* allow for complete packet forming when using packetized serial comms
const uint32_t timeout_micros = (int)(1.0 / BAUD_RATE * 1E6) * 20;

uint8_t buf_recv[BUFFER_SIZE];
uint8_t buf_send[BUFFER_SIZE]; 
uint8_t buf_size = 0;
uint32_t send_timeout = 0;

esp_now_peer_info_t peerInfo;  // scope workaround for arduino-esp32 v2.0.1

#if defined(DEBUG) || defined(BLINK_ON_SEND_SUCCESS)
uint8_t led_status = 0;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  #ifdef DEBUG
  if (status == ESP_NOW_SEND_SUCCESS) {
    Serial.println("Send success");
  } else {
  Serial.println("Send failed");
  }
  #endif

  #ifdef BLINK_ON_SEND_SUCCESS
  if (status == ESP_NOW_SEND_SUCCESS) {
    led_status = ~led_status;
    // this function happens too fast to register a blink
    // instead, we latch on/off as data is successfully sent
    digitalWrite(LED_BUILTIN, led_status);
    return;
  }
  // turn off the LED if send fails
  led_status = 0;
  digitalWrite(LED_BUILTIN, led_status);
  #endif
}
#endif

void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  #ifdef BLINK_ON_RECV
  digitalWrite(LED_BUILTIN, HIGH);
  #endif
  memcpy(&buf_recv, incomingData, sizeof(buf_recv));
  Serial.write(buf_recv, len);
  #ifdef BLINK_ON_RECV
  digitalWrite(LED_BUILTIN, LOW);
  #endif
  #ifdef DEBUG
  Serial.print("\n Bytes received: ");
  Serial.println(len);
  #endif
}
 
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  // XIAO ESP32C3 uses USB CDC Serial which doesn't support pin configuration
  Serial.begin(BAUD_RATE);
  Serial.println(send_timeout);
  WiFi.mode(WIFI_STA);

  #ifdef DEBUG
  Serial.print("ESP32 MAC Address: ");
  Serial.println(WiFi.macAddress());
  #endif
  
  if (esp_wifi_set_channel(WIFI_CHAN, WIFI_SECOND_CHAN_NONE) != ESP_OK) {
    #ifdef DEBUG
    Serial.println("Error changing WiFi channel");
    #endif
    return;
  }

  if (esp_now_init() != ESP_OK) {
    #ifdef DEBUG
    Serial.println("Error initializing ESP-NOW");
    #endif
    return;
  }

  #if defined(DEBUG) || defined(BLINK_ON_SEND_SUCCESS)
  esp_now_register_send_cb(OnDataSent);
  #endif
  
  // esp_now_peer_info_t peerInfo;  // scope workaround for arduino-esp32 v2.0.1
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = WIFI_CHAN;  
  peerInfo.encrypt = false;

  if (esp_now_add_peer(&peerInfo) != ESP_OK){
    #ifdef DEBUG
    Serial.println("Failed to add peer");
    #endif
    return;
  }

  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {

  // read up to BUFFER_SIZE from serial port
  if (Serial.available()) {
    while (Serial.available() && buf_size < BUFFER_SIZE) {
      buf_send[buf_size] = Serial.read();
      send_timeout = micros() + timeout_micros;
      buf_size++;
    }
  }

  // send buffer contents when full or timeout has elapsed
  if (buf_size == BUFFER_SIZE || (buf_size > 0 && micros() >= send_timeout)) {
    #ifdef BLINK_ON_SEND
    digitalWrite(LED_BUILTIN, HIGH);
    #endif
    esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &buf_send, buf_size);
    buf_size = 0;
    #ifdef DEBUG
    if (result == ESP_OK) {
      Serial.println("Sent!");
    }
    else {
      Serial.println("Send error");
    }
    #endif
    #ifdef BLINK_ON_SEND
    digitalWrite(LED_BUILTIN, LOW);
    #endif
  }

}

For the pendant you have to upload the firmware using platformio - there is a build flag that sets the BAUD rate, I’m not at my home compter but its easy to find.

I currently have one of these attached to the pendant but the 18650 isn’t charging (its been in a drawer for a looooog time). with a modified case it’d be a neat power solution.

Or you can use a power bank into the usbc connector of the CYD

Interesting that PiBot seems to be doing something like this. There’s a video in the description.

Very interesting indeed, as it showa it is fluidnc! Wonder what they are connecting to

Oh they have their own fluidnc board!

Wonder what the 2 knurled knobs arw for!

I edited 3 times. Time for new reply. Here is an interesting idea! Would you be able to make the controller, everything, into a pendant? Would the cords be too long? Would they lose amperage over the distance?

The cyd pendant looks good, only 3 buttons (could use more) m5 dial (too small of a screen). I use big screens windows tablets and a 15" touch monitor all fixed to the tables.
I guess im ok with that.

I will try the pendant in one of the machines and see how it goes but i doubt it will change my preference over the table tab in webui

I am soooo sorry i just drifted your topic. Would you like me to delete my comments! I thought i was on another topic!

Ah? Dont erase anything, i like that +1k pendant on the picture

Some things I’m toying with-

Can an ESP-01S work for the bridge? Dirt cheap and I have a pile of them.

Since the CYD and the M5 have an ESP-32 on them… Could we merge the ESP-NOW functionality with the pendant firmware and not need any other external components at all?

I wonder if an LiFEPO4 battery works with the onboard CYD connector. How cool would it be to have an all-in-one wireless battery powered pendant.???

1 Like

Well this pendant thing is really getting interesting now.

3 Likes

Funny I was thinking today if an wemos d1 mini would work but I haven’t tried it.

It would absolutely make sense to me to use the CYD’s own esp32 chip - it’s not really doing anything else - I had a look though the firmware when I downloaded it to change the baud and it’s way beyond my comprehension to add.

As a concept though I like the idea of a pair of boards that plug into the jackpot expansion port and the CYD, or m5Dial in place of the RJ11 breakouts. I noodled it over with an LLm that suggested it would be possible to have them spin up an AP and webpage to configure the paired MAC but that seems excessive, you should only need to configure the matching MAC addresses once.

That’s the territory of our real software engineers. Fortunately, we have a few knocking around here.

I’m sort of thinking the ideal would be a pre-packaged deal where you open the box, plug in all the parts, and it works. People could still build their own (like we’re doing), but that would not be worth the hassle for most folks who just want to drive their machine.

2 Likes