UART Library for VESC

Posted on
  • Hello everyone.

    I really want to get some data from the VESC (Vedders electronic speed control) via UART to a MDBT42Q Official Espruino breakout board. My only issue is that i dont realy know where to begin.

    There are a few libraries already written in C. Im not so familiar with C so its hard to get some useful info out of it;
    STM32F4 C Implementation

    What i do know; the VESC communicates over UART using packets with the following format:

    One Start byte (value 2 for short packets and 3 for long packets)
    One or two bytes specifying the packet length
    The payload of the packet
    Two bytes with a CRC checksum on the payload
    One stop byte (value 3)

    More detailed information here

    I would like some help with where to start basicly, i just want to get data from the VESC with espruino.

    There is a bluetooth module that i can hook on to the VESC aswell that has RX and TX characteristics pre programmed, so there is also a option to communicate via BLEUART.

    VESC Source code
    / G

  • If the ESC continuously sends the data, you can take a look at the GPS or the PMS7003 code.
    "Just" open the serial port, collect the bytes, and process it when you have a full paket.
    Of course looks like you have variable packet length, so it's not trivial...

  • Just moved this to the interfacing forum as I think it makes sense in there.

    But I think you should be fine - connect to the MDBT42Q via Bluetooth (it only has one UART), then do something like:

    Bluetooth.setConsole(1); // force console to Bluetooth so it doesn't interfere when we disconnect
    Serial1.setup(9600,{rx:D14}); // or any pin at all
    var data = "";
    Serial1.on('data', function(d) {
      data += d;
      var match = data.match(/[\x02\x03]....[^\x03]*\x03/)­;
      if (match) {
        data = data.substr(match.index+match[0].length)­;

    That should print out any 6+ byte packet that begins with 2 or 3 and ends with 3 - but it's entirely possible that it might get confused by a packet that contains the byte 3 in the payload, so you may have to be a bit more clever - for instance by detecting pauses in the serial transmission.

    Once you have the packet itself though you can use str.charCodeAt(x) to get the actual character data you need, or can even do E.toUint8Array(str) to get it as an array that you can access normally.

  • Thanks for your answer, no luck sadly. My guess is that i probably need to write some data to get some data.

  • what happens if you just do:

    Serial1.on('data', function(d) {
  • First it complains that i have to define both tx and rx pin, then it just prints undefined once and no data is arriving.

  • Found some useful information

    Reading data is done with getter functions and callback function pointers. For example, to get realtime data from the VESC, first set a callback to your function for handling the data using bldc_interface_set_rx_value_func and then request the data with bldc_interface_get_values.

    // Every time you want to read the realtime data you call the corresponding getter.
    // This will send the get command to the VESC and return. When the data is received
    // the callback will be called from the UART interface.
  • Here is some C code that i think does what im trying to do.

    int VescUart::packSendPayload(uint8_t * payload, int lenPay) {
    	uint16_t crcPayload = crc16(payload, lenPay);
    	int count = 0;
    	uint8_t messageSend[256];
    	if (lenPay <= 256)
    		messageSend[count++] = 2;
    		messageSend[count++] = lenPay;
    		messageSend[count++] = 3;
    		messageSend[count++] = (uint8_t)(lenPay >> 8);
    		messageSend[count++] = (uint8_t)(lenPay & 0xFF);
    	memcpy(&messageSend[count], payload, lenPay);
    	count += lenPay;
    	messageSend[count++] = (uint8_t)(crcPayload >> 8);
    	messageSend[count++] = (uint8_t)(crcPayload & 0xFF);
    	messageSend[count++] = 3;
    	messageSend[count] = '\0';
    		debugPort->print("UART package send: "); serialPrint(messageSend, count);
    	// Sending package
    	serialPort->write(messageSend, count);
    	// Returns number of send bytes
    	return count;
    bool VescUart::getVescValues(uint8_t comm) {
    	uint8_t command[1] = { comm }; // COMM_GET_VALUES or COMM_GET_UNITY_VALUE
    	uint8_t payload[256];
    	packSendPayload(command, 1);
    	// delay(1); //needed, otherwise data is not read
    	int lenPayload = receiveUartMessage(payload);
    	if (lenPayload > 55) {
    		bool read = processReadPacket(payload); //returns true if sucessful
    		return read;
    		return false;
  • First it complains that i have to define both tx and rx pin,

    Try updating your Espruino firmware :)

    Ok, so it might be you have to send some data first to kick it off? If so I guess you'll need to set up a tx pin anyway

  • Yeah. Quiestion is how do i send the correct data ?
    Tested this without good result;

    const packLength =  E.toUint8Array("COMM_GET_VALUES").length­;
    const sendData = E.toUint8Array(2, packLength, "COMM_GET_VALUES", 3);
  • It looks to me like COMM_GET_VALUES is a constant defined somewhere that's just a single byte, rather than the string "COMM_GET_VALUES".

    Also it seems you need to add a 16 bit CRC - so you'll need to find where the crc16 function is defined and copy that.

    OR you could try and compile/run the code on your PC and just print out the data that it's trying to send, and then copy that data as-is to Espruino and send that.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview

UART Library for VESC

Posted by Avatar for Gustav @Gustav