Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
SolidGeek committed Aug 19, 2018
1 parent 3b46681 commit 9fce8e1
Show file tree
Hide file tree
Showing 10 changed files with 1,361 additions and 0 deletions.
45 changes: 45 additions & 0 deletions examples/getVescValues/getVescValues.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Name: getVescValues.ino
Created: 19-08-2018
Author: SolidGeek
Description: This example is made using a Arduino Micro (Atmega32u4) that has a HardwareSerial port (Serial1) seperated from the Serial port.
A Arduino Nano or Uno that only has one Serial port will not be able to display the data returned.
*/

#include <VescUart.h>

/** Initiate VescUart class */
VescUart UART;

void setup() {

/** Setup Serial port to display data */
Serial.begin(9600);

/** Setup UART port (Serial1 on Atmega32u4) */
Serial1.begin(19200);

while (!Serial) {;}

/** Define which ports to use as UART */
UART.setSerialPort(&Serial1);
}

void loop() {

/** Call the function getVescValues() to acquire data from VESC */
if ( UART.getVescValues() ) {

Serial.println(UART.data.rpm);
Serial.println(UART.data.inpVoltage);
Serial.println(UART.data.ampHours);
Serial.println(UART.data.tachometerAbs);

}
else
{
Serial.println("Failed to get data!");
}

delay(50);
}
19 changes: 19 additions & 0 deletions keywords.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#######################################
# Syntax Coloring Map For vescUart
#######################################

#######################################
# Datatypes (KEYWORD1)
#######################################

VescUart KEYWORD1

#######################################
# Methods and Functions (KEYWORD2)
#######################################
setSerialPort
setDebugPort
getVescValues KEYWORD2
printVescValues KEYWORD2
setNunchuckValues
printVescValues
9 changes: 9 additions & 0 deletions library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=VescUart
version=1.0.0
author=SolidGeek
maintainer=SolidGeek
sentence=Library offering UART communication for VESC
paragraph=VESC UART library
category=Device Control
url=https://solidgeek.dk
architectures=*
280 changes: 280 additions & 0 deletions src/VescUart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
#include "VescUart.h"
#include <HardwareSerial.h>


VescUart::VescUart(void){
nunchuck.valXJoy = 127;
nunchuck.valYJoy = 127;
nunchuck.valLowerButton = false;
nunchuck.valLowerButton = false;
}

void VescUart::setSerialPort(HardwareSerial* _serialPort)
{
serialPort = _serialPort;
}

void VescUart::setDebugPort(Stream* _debugPort)
{
debugPort = _debugPort;
}

int VescUart::receiveUartMessage(uint8_t * payloadReceived) {

// Messages <= 255 starts with "2", 2nd byte is length
// Messages > 255 starts with "3" 2nd and 3rd byte is length combined with 1st >>8 and then &0xFF

unsigned int counter = 0;
unsigned int endMessage = 256;
bool messageRead = false;
uint8_t messageReceived[256];
unsigned int lenPayload = 0;

unsigned long timeout = 0;
timeout = millis() + 100;

while ( millis() < timeout && messageRead == false) {

while (serialPort->available()) {

messageReceived[counter++] = serialPort->read();

if (counter == 2) {

switch (messageReceived[0])
{
case 2:
endMessage = messageReceived[1] + 5; //Payload size + 2 for sice + 3 for SRC and End.
lenPayload = messageReceived[1];
break;

case 3:
// ToDo: Add Message Handling > 255 (starting with 3)
break;

default:
if( debugPort != NULL ){
debugPort->println("No start bit");
}
break;
}
}

if (counter >= sizeof(messageReceived)) {
break;
}

if (counter == endMessage && messageReceived[endMessage - 1] == 3) {
messageReceived[endMessage] = 0;
if (debugPort != NULL) {
debugPort->println("End of message reached!");
}
messageRead = true;
break; //Exit if end of message is reached, even if there is still more data in buffer.
}
}
}

if(messageRead == false && debugPort != NULL ) {
debugPort->println("Timeout");
}

bool unpacked = false;
if (messageRead) {
unpacked = unpackPayload(messageReceived, endMessage, payloadReceived);
}

if (unpacked) {
// Message was read
return lenPayload;
}
else {
// No Message Read
return 0;
}
}


bool VescUart::unpackPayload(uint8_t * message, int lenMes, uint8_t * payload) {

uint16_t crcMessage = 0;
uint16_t crcPayload = 0;

// Rebuild crc:
crcMessage = message[lenMes - 3] << 8;
crcMessage &= 0xFF00;
crcMessage += message[lenMes - 2];

if(debugPort!=NULL){
debugPort->print("SRC received: "); debugPort->println(crcMessage);
}

// Extract payload:
memcpy(payload, &message[2], message[1]);

crcPayload = crc16(payload, message[1]);

if( debugPort != NULL ){
debugPort->print("SRC calc: "); debugPort->println(crcPayload);
}

if (crcPayload == crcMessage) {
if( debugPort != NULL ) {
debugPort->print("Received: ");
serialPrint(message, lenMes); debugPort->println();

debugPort->print("Payload : ");
serialPrint(payload, message[1] - 1); debugPort->println();
}

return true;
}else{
return false;
}
}


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;
}
else
{
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';

if(debugPort!=NULL){
debugPort->print("UART package send: "); serialPrint(messageSend, count);
}

// Sending package
serialPort->write(messageSend, count);

// Returns number of send bytes
return count;
}


bool VescUart::processReadPacket(uint8_t * message) {

COMM_PACKET_ID packetId;
int32_t ind = 0;

packetId = (COMM_PACKET_ID)message[0];
message++; // Removes the packetId from the actual message (payload)

switch (packetId){
case COMM_GET_VALUES:

ind = 4; // Skip the first 4 bytes
data.avgMotorCurrent = buffer_get_float32(message, 100.0, &ind);
data.avgInputCurrent = buffer_get_float32(message, 100.0, &ind);
ind += 8; // Skip the next 8 bytes
data.dutyCycleNow = buffer_get_float16(message, 1000.0, &ind);
data.rpm = buffer_get_int32(message, &ind);
data.inpVoltage = buffer_get_float16(message, 10.0, &ind);
data.ampHours = buffer_get_float32(message, 10000.0, &ind);
data.ampHoursCharged = buffer_get_float32(message, 10000.0, &ind);
ind += 8; // Skip the next 8 bytes
data.tachometer = buffer_get_int32(message, &ind);
data.tachometerAbs = buffer_get_int32(message, &ind);
return true;

break;

default:
return false;
break;
}
}

bool VescUart::getVescValues(void) {

uint8_t command[1] = { COMM_GET_VALUES };
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;
}
else
{
return false;
}
}

void VescUart::setNunchuckValues() {
int32_t ind = 0;
uint8_t payload[11];

payload[ind++] = COMM_SET_CHUCK_DATA;
payload[ind++] = nunchuck.valXJoy;
payload[ind++] = nunchuck.valYJoy;
buffer_append_bool(payload, nunchuck.valLowerButton, &ind);
buffer_append_bool(payload, nunchuck.valUpperButton, &ind);

// Acceleration Data. Not used, Int16 (2 byte)
payload[ind++] = 0;
payload[ind++] = 0;
payload[ind++] = 0;
payload[ind++] = 0;
payload[ind++] = 0;
payload[ind++] = 0;

if(debugPort != NULL){
debugPort->println("Data reached at setNunchuckValues:");
debugPort->print("valXJoy = "); debugPort->print(nunchuck.valXJoy); debugPort->print(" valYJoy = "); debugPort->println(nunchuck.valYJoy);
debugPort->print("LowerButton = "); debugPort->print(nunchuck.valLowerButton); debugPort->print(" UpperButton = "); debugPort->println(nunchuck.valUpperButton);
}

packSendPayload(payload, 11);
}

void VescUart::serialPrint(uint8_t * data, int len) {
if(debugPort != NULL){
for (int i = 0; i <= len; i++)
{
debugPort->print(data[i]);
debugPort->print(" ");
}

debugPort->println("");
}
}


void VescUart::printVescValues() {
if(debugPort != NULL){
debugPort->print("avgMotorCurrent: "); debugPort->println(data.avgMotorCurrent);
debugPort->print("avgInputCurrent: "); debugPort->println(data.avgInputCurrent);
debugPort->print("dutyCycleNow: "); debugPort->println(data.dutyCycleNow);
debugPort->print("rpm: "); debugPort->println(data.rpm);
debugPort->print("inputVoltage: "); debugPort->println(data.inpVoltage);
debugPort->print("ampHours: "); debugPort->println(data.ampHours);
debugPort->print("ampHoursCharges: "); debugPort->println(data.ampHoursCharged);
debugPort->print("tachometer: "); debugPort->println(data.tachometer);
debugPort->print("tachometerAbs: "); debugPort->println(data.tachometerAbs);
}
}
Loading

0 comments on commit 9fce8e1

Please sign in to comment.