forked from SolidGeek/VescUart
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,361 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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=* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
Oops, something went wrong.