Open FFBoard
Open source force feedback firmware
VescCAN.cpp
Go to the documentation of this file.
1/*
2 * VescCAN.cpp
3 *
4 * Created on: Aug 08, 2021
5 * Author: Vincent Manoukian (manoukianv@gmail.com)
6 */
7#include "target_constants.h"
8#ifdef VESC
9#include <VescCAN.h>
10#include "ClassIDs.h"
11#include "CRC.h"
12
14std::array<uint16_t,256> VescCAN::crc16_tab __attribute__((section (CCRAM_SEC))); // Generate in ram to save some flash (512B)
15
16// ***** static initializer for the VESC_1 instance (extend VESC_CAN) *****
17
18bool VESC_1::inUse = false;
19
21 .name = "VESC 1" ,
22 .id=CLSID_MOT_VESC0
23};
24
26 return !VESC_1::inUse;
27}
28
30 return info;
31}
32
33// ***** static initializer for the VESC_2 instance (extend VESC_CAN) *****
34
35bool VESC_2::inUse = false;
36
38 .name = "VESC 2" ,
39 .id=CLSID_MOT_VESC1
40};
41
43 return !VESC_2::inUse;
44}
45
47 return info;
48}
49
50// ***** VESC_CAN *****
51
52VescCAN::VescCAN(uint8_t address) :
53 CommandHandler("vesc", CLSID_MOT_VESC0, address), Thread("VESC", VESC_THREAD_MEM,
54 VESC_THREAD_PRIO) {
55
56 if(!crcTableInitialized){ // Generate a CRC16 table the first time a vesc instance is created
59 }
60
61 setAddress(address);
63
64 // Set up a filter to receive vesc commands
65 CAN_filter filterConf;
66 filterConf.extid = true;
67 filterConf.buffer = 0;
68 filterConf.filter_id = 0;
69 filterConf.filter_mask = 0;
70 this->filterId = this->port->addCanFilter(filterConf); // Receive all
71
72 if(port->getSpeedPreset() < 3){
73 port->setSpeedPreset(3); // Minimum 250k
74 }
75 this->port->takePort();
76
78 this->Start();
79
80}
81
83 this->stopMotor();
84 this->port->freePort();
86}
87
88void VescCAN::setAddress(uint8_t address) {
89 if (address == 0) {
90 this->flashAddrs = VescFlashAddrs( { ADR_VESC1_CANID, ADR_VESC1_DATA, ADR_VESC1_OFFSET });
91 } else if (address == 1) {
92 this->flashAddrs = VescFlashAddrs( { ADR_VESC2_CANID, ADR_VESC2_DATA, ADR_VESC2_OFFSET });
93 } else if (address == 2) {
94 this->flashAddrs = VescFlashAddrs( { ADR_VESC3_CANID, ADR_VESC3_DATA, ADR_VESC3_OFFSET });
95 }
96}
97
98void VescCAN::turn(int16_t power) {
99 float torque = ((float) power / (float) 0x7fff);
101 this->setTorque(torque);
102}
103
105 this->setTorque(0.0);
106 activeMotor = false;
107}
108
110 activeMotor = true;
111}
112
114 if (useEncoder)
115 return static_cast<Encoder*>(this);
116 else
118}
119
121 return useEncoder;
122}
123
125 if (useEncoder)
127 else
129}
130
133}
134
136 uint16_t dataFlash = 0;
137
138 if (Flash_Read(flashAddrs.canId, &dataFlash)) {
139 this->OFFB_can_Id = dataFlash & 0xFF;
140 this->VESC_can_Id = (dataFlash >> 8) & 0xFF;
141 }
142
143 if (Flash_Read(flashAddrs.data, &dataFlash)) {
144
145 //uint8_t canspd = dataFlash & 0b111;
146 //this->baudrate = canspd;
147
148 this->useEncoder = (dataFlash >> 3) & 0x1;
149 }
150
151 if (Flash_Read(flashAddrs.offset, &dataFlash)) {
152 this->posOffset = (float) ((int16_t) dataFlash / 10000.0);
153
154 this->posOffset = this->posOffset - (int) this->posOffset; // Remove the multi-turn value
155 bool moreThanHalfTurn = fabs(this->posOffset) > 0.5 ? 1 : 0;
156 if (moreThanHalfTurn) {
157 // if delta is neg, turn is CCW, decrement multi turn pos... else increment it
158 this->posOffset += (this->posOffset > 0) ? -1.0 : 1.0;
159 }
160 }
161
162}
163
165 uint16_t dataFlash = 0;
166
167 // save the OpenFFBoard Can Id in 0..7 and the Vesc_can_id in the 8..15
168 dataFlash = (this->VESC_can_Id << 8) | this->OFFB_can_Id;
169 Flash_Write(flashAddrs.canId, dataFlash);
170
171 dataFlash = 0;
172 //dataFlash |= (this->baudrate & 0b111); // set the baudrate in 0..2 bit
173 dataFlash |= (this->useEncoder & 0x1) << 3; // set the encoder use in bit 3
174 Flash_Write(flashAddrs.data, dataFlash);
175
177}
178
180
181 // store the -180°/180°offset
182 float storedOffset = this->posOffset - (int) this->posOffset; // Remove the multi-turn value
183 bool moreThanHalfTurn = fabs(storedOffset) > 0.5 ? 1 : 0;
184 if (moreThanHalfTurn) {
185 // if delta is neg, turn is CCW, decrement multi turn pos... else increment it
186 storedOffset += (storedOffset > 0) ? -1.0 : 1.0;
187 }
188
189 uint16_t dataFlash = ((int16_t) (storedOffset * 10000) & 0xFFFF);
190 Flash_Write(flashAddrs.offset, dataFlash);
191
192}
193
197void VescCAN::setPos(int32_t pos) {
198 // Only change encoder count internally as offset
199 posOffset = lastPos - ((float) pos / (float) getCpr());
200
201 saveFlashOffset(); // save the new offset for next restart
202}
203
206 this->askPositionEncoder();
207 }
208 return lastPos - posOffset;
209}
210
212 return getCpr() * getPos_f();
213}
214
215uint32_t VescCAN::getCpr() {
216 return 0xFFFF;
217}
218
221 registerCommand("offbcanid", VescCAN_commands::offbcanid, "CAN id of OpenFFBoard Axis", CMDFLAG_GET | CMDFLAG_SET);
222 registerCommand("vesccanid", VescCAN_commands::vesccanid, "CAN id of VESC", CMDFLAG_GET | CMDFLAG_SET);
223 registerCommand("canspd", VescCAN_commands::canspd, "CAN baud ! for info", CMDFLAG_GET | CMDFLAG_SET); // Kept for backwards compatibility. Remove in the future
224 registerCommand("errorflags", VescCAN_commands::errorflags, "VESC error state", CMDFLAG_GET);
225 registerCommand("vescstate", VescCAN_commands::vescstate, "VESC state", CMDFLAG_GET);
226 registerCommand("voltage", VescCAN_commands::voltage, "VESC supply voltage (mV)", CMDFLAG_GET);
227 registerCommand("encrate", VescCAN_commands::encrate, "Encoder update rate", CMDFLAG_GET);
228 registerCommand("pos", VescCAN_commands::pos, "VESC position", CMDFLAG_GET);
229 registerCommand("torque", VescCAN_commands::torque, "Current VESC torque", CMDFLAG_GET);
230 registerCommand("forceposread", VescCAN_commands::forcePosRead, "Force a position update", CMDFLAG_GET);
231 registerCommand("useencoder", VescCAN_commands::useEncoder, "Enable VESC encoder", CMDFLAG_GET | CMDFLAG_SET);
232 registerCommand("offset", VescCAN_commands::offset, "Get or set encoder offset", CMDFLAG_GET | CMDFLAG_SET);
233}
234
236 std::vector<CommandReply> &replies) {
237
238 switch (static_cast<VescCAN_commands>(cmd.cmdId)) {
239
241 return handleGetSet(cmd, replies, this->OFFB_can_Id);
243 return handleGetSet(cmd, replies, this->VESC_can_Id);
245 if (cmd.type == CMDtype::get)
246 replies.emplace_back(vescErrorFlag);
247 break;
249 if (cmd.type == CMDtype::get) {
250 replies.emplace_back(port->getSpeedPreset());
251 } else if (cmd.type == CMDtype::set) {
252 port->setSpeedPreset(std::max<uint8_t>(3,cmd.val));
253 }
254 break;
256 if (cmd.type == CMDtype::get)
257 replies.emplace_back((uint32_t) this->state);
258 break;
260 if (cmd.type == CMDtype::get)
261 replies.emplace_back((uint32_t) this->encRate);
262 break;
264 if (cmd.type == CMDtype::get) {
265 replies.push_back(
267 (int32_t) ((lastPos - posOffset) * 1000000000)));
268 }
269 break;
271 if (cmd.type == CMDtype::get) {
272 replies.emplace_back((int32_t) (lastTorque * 10000));
273 }
274 break;
276 this->askPositionEncoder();
277 break;
279 if (cmd.type == CMDtype::get) {
280 replies.emplace_back(useEncoder ? 1 : 0);
281 } else if (cmd.type == CMDtype::set) {
282 useEncoder = cmd.val != 0;
283 }
284 break;
286 if (cmd.type == CMDtype::get) {
287 replies.emplace_back((int32_t) (posOffset * 10000));
288 } else if (cmd.type == CMDtype::set) {
289 posOffset = (float) cmd.val / 10000.0;
290 this->saveFlashOffset(); // Really save to flash?
291 }
292 }
293 break;
295 if (cmd.type == CMDtype::get)
296 replies.emplace_back(voltage * 1000);
297 break;
298
299 default:
301 }
302
303 return CommandStatus::OK;
304}
305
306/*
307 * state = VESC_UNKOWN => ping until the state go to PONG
308 * = VESC_PONG => call a status message
309 * = VESC_ERROR => call a status message
310 *
311 * if error => state = VESC_ERROR
312 * else=> state = VESC_RESPOND
313 *
314 * if RespondVescTime > 100 => VESC_NOT_RESPOND
315 *
316 */
318
319 while (true) {
320 Delay(500);
321 // if status is UNKNOW, ask firmware info and wait next 500ms
323 this->getFirmwareInfo();
324 // the return of getFirmwareInfo change the state to COMPATIBLE/INCOMPATIBLE
325 // skip the follow control if we don't change from unknown state
326 continue;
327 }
328
329 // if vesc is compatible, ready or in error => check the status
331 this->askGetValue();
332 // the return of askGetValue put the state in READY or ERROR is vesc respond to status
333 }
334
335 // test is a ready/error vesc is always respond
336 uint32_t period = HAL_GetTick() - lastVescResponse;
338 || state == VescState::VESC_STATE_ERROR) && period > 1000) {
340 }
341
342 // when motor is active we call vesc each 500ms, to disable the vesc watchdog
343 // (if vesc not received message in 1sec, it cut off motor)
344 if (lastTorque != 0.0 && activeMotor
346 this->setTorque(lastTorque);
347 }
348
349 // compute encoderRate each second
350 period = HAL_GetTick() - encStartPeriod;
351 if (period > 1000) {
352 encRate = encCount / (period / 1000.0);
353 encCount = 0;
354 encStartPeriod = HAL_GetTick();
355 }
356
357 }
358}
359
360/************************************************************************************************
361 *
362 * CAN SECTION
363 */
364
365
370 uint8_t msg[3];
371 msg[0] = this->OFFB_can_Id;
372 msg[1] = 0x00; // ask vesc to process the msg
373 msg[2] = (uint8_t) VescCmd::COMM_FW_VERSION;// sub action is to get FW version
374
376 sizeof(msg));
377}
378
383 uint8_t buffer[1];
384 buffer[0] = this->OFFB_can_Id;
385
387 sizeof(buffer));
388}
389
394void VescCAN::setTorque(float torque) {
395
396 // Check if vesc CAN is ok, if it is, send a message
397 if (!this->motorReady() || !activeMotor)
398 return;
399
400 uint8_t buffer[4];
401 int32_t send_index = 0;
402 this->buffer_append_float32(buffer, torque, 1e5, &send_index);
403
405 sizeof(buffer));
406
407}
408
409/*
410 * Get the telemetry : Status & Value
411 */
413 uint8_t msg[8];
414 msg[0] = this->OFFB_can_Id;
415 msg[1] = 0x00; // ask vesc to process the msg
416 msg[2] = (uint8_t) VescCmd::COMM_GET_VALUES_SELECTIVE;// sub action is COMM_GET_VALUES_SELECTIVE : ask wanted data
417 uint32_t request = ((uint32_t) 1 << 15); // bit 15 = ask vesc status (1byte)
418 request |= ((uint32_t) 1 << 8); // bit 8 = ask voltage (2byte)
419
420 int32_t index = 3;
421 this->buffer_append_uint32(msg, request, &index);
422
424 sizeof(msg));
425}
426
432 this->sendMsg((uint8_t) VescCANMsg::CAN_PACKET_POLL_ROTOR_POS, nullptr, 0);
433}
434
435/*
436 * Compute the new position (laspos) value from data received by vesc:
437 * newPos is a 0-360° angle position
438 * if delta with previous and new position is > 180° then we count 1 turn
439 * at 1kz, more than 180° mean 30000rpm, not admissible in simracing
440 */
441void VescCAN::decodeEncoderPosition(const float newPos) {
442 float delta = newPos - prevPos360; // Compute the delta position
443
444 bool moreThanHalfTurn = fabs(delta) > 180.0 ? 1 : 0;
445 if (moreThanHalfTurn) {
446 // if delta is neg, turn is CCW, decrement multi turn pos... else increment it
447 mtPos += (delta > 0) ? -1.0 : 1.0;
448 }
449
450 lastPos = (newPos / 360.0) + mtPos; // normalize the position
451 prevPos360 = newPos;
452
453 encCount++;
454}
455
459void VescCAN::sendMsg(uint8_t cmd, uint8_t *buffer, uint8_t len) {
460 CAN_tx_msg msg;
461 memcpy(&msg.data, buffer, len);
462 msg.header.rtr = false;
463 msg.header.length = len;
464 msg.header.extId = true;
465 msg.header.id = this->VESC_can_Id | (cmd << 8);
466 port->sendMessage(msg);
467}
468
469void VescCAN::decode_buffer(uint8_t *buffer, uint8_t len) {
470
471 if (!len) {
472 return;
473 }
474
475 VescCmd command = (VescCmd) (buffer[0] & 0xFF);
476 buffer++;
477 len--;
478
479 switch (command) {
480
482 int32_t ind = 0;
483 uint8_t fw_major = buffer[ind++];
484 uint8_t fw_min = buffer[ind++];
485
486 std::string test((char*) buffer + ind);
487 ind += test.length() + 1;
488
489 uint8_t uuid[12] = { 0 };
490 memcpy(buffer + ind, uuid, 12);
491 ind += 12;
492
493 //bool isPaired = buffer[ind++];
494 uint8_t isTestFw = buffer[ind++];
495
496 //uint8_t hwType = buffer[ind++]; // Comment because unused
497 //uint8_t customConfig = buffer[ind++]; // Comment because unused
498
499 // bool hasPhaseFilters = buffer[ind++]; // Comment because unused
500
501 bool compatible = false;
502 if (!isTestFw)
503 compatible = ((fw_major << 8) | fw_min) >= (FW_MIN_RELEASE >> 8);
504 else
505 compatible = ((fw_major << 16) | (fw_min << 8) | isTestFw)
506 >= FW_MIN_RELEASE;
507
508 if (compatible) {
510 } else {
512 }
513
514 break;
515 }
516
518 int32_t ind = 0;
519 uint32_t mask = this->buffer_get_uint32(buffer, &ind);
520
521 if (mask & ((uint32_t) 1 << 8)) {
522 voltage = this->buffer_get_float16(buffer, 1e1, &ind);
523 }
524 if (mask & ((uint32_t) 1 << 15)) {
525 vescErrorFlag = buffer[ind++];
526
527 // if the vesc respond but with an error, we put the vesc in error flag
528 if (vescErrorFlag) {
530 } else {
532 }
533
534 }
535 if (mask & ((uint32_t) 1 << 16)) {
536 float pos = this->buffer_get_float32(buffer, 1e6, &ind);
537 this->decodeEncoderPosition(pos);
538 }
539 break;
540
541 }
542
543 default:
544 break;
545
546 }
547
548}
549
550/*
551 * Process the received message on the CAN bus.
552 * Message have several struct, depends on message type, check the comm_can.c and
553 * command.c in the vesc source project to identify the struct format.
554 *
555 * Quick tips :
556 * Msg struct for CAN_PACKET_PROCESS_RX_BUFFER and CAN_PACKET_PROCESS_SHORT_BUFFER :
557 * uint8_t[0] => can_emitter_id (vesc id)
558 * uint8_t[1] => send bool
559 * uint8_t[2] => COMM_PACKET_ID command
560 * uint8_t[3] -> uint8_t[7] => DATA (5 bytes)
561 *
562 * Msg struct for CAN_PACKET_POLL_ROTOR_POS
563 * uint8_t[0]..uint8_t[3] : uint32 f_pos / 10000
564 *
565 */
567
568 // we record the last time respond to check if vesc is OK
569 lastVescResponse = HAL_GetTick();
570
571 // Check if message is for the openFFBoard
572 uint16_t destCanID = msg.header.id & 0xFF;
573 uint8_t *rxBuf = msg.data;
574
575 // Extract the command encoded in the ExtId
576 VescCANMsg cmd = (VescCANMsg) (msg.header.id >> 8);
577
578 bool messageIsForThisVescAxis = destCanID == this->OFFB_can_Id;
579 messageIsForThisVescAxis |= (cmd == VescCANMsg::CAN_PACKET_POLL_ROTOR_POS) && // if it's a encoder position message
580 (this->VESC_can_Id == 0xFF); // and the vescCanId is not the default one
581 messageIsForThisVescAxis |= (cmd == VescCANMsg::CAN_PACKET_POLL_ROTOR_POS)
582 && // if it's a encoder position message
583 (this->VESC_can_Id != 0xFF) && // and the vescCanId is not the default one
584 (destCanID == this->VESC_can_Id); // we check that emiterId is the vescId for this axis
585
586 if (!messageIsForThisVescAxis)
587 return;
588
589 // Process the CAN message received
590 switch (cmd) {
591
593 memcpy(buffer_rx + rxBuf[0], rxBuf + 1, msg.header.length - 1);
594 break;
595 }
596
598 uint32_t rxbuf_ind = (unsigned int) rxBuf[0] << 8;
599 rxbuf_ind |= rxBuf[1];
600 if (rxbuf_ind < BUFFER_RX_SIZE) {
601 memcpy(buffer_rx + rxbuf_ind, rxBuf + 2, msg.header.length - 2);
602 }
603 break;
604 }
605
607
608 // remove 2 first byte to exclude "can emitter id" and the "send bool" flag from buffer
609 int32_t index = 2;
610
611 uint32_t rxbuf_length = (uint32_t) rxBuf[index++] << 8;
612 rxbuf_length |= (uint32_t) rxBuf[index++];
613
614 if (rxbuf_length > BUFFER_RX_SIZE) {
615 break;
616 }
617
618 uint8_t crc_high = rxBuf[index++];
619 uint8_t crc_low = rxBuf[index++];
620
621 if(calculateCrc16_8(crc16_tab,buffer_rx,rxbuf_length)
622 //if (crc16(buffer_rx, rxbuf_length)
623 == ((uint8_t) crc_high << 8 | (uint8_t) crc_low)) {
624
625 this->decode_buffer(buffer_rx, rxbuf_length);
626
627 }
628
629 break;
630 }
632
633 // remove 2 first byte to exclude "can emitter id" and the "send bool" flag from buffer
634 this->decode_buffer(rxBuf + 2, msg.header.length - 2);
635
636 break;
637 }
638
641 break;
642
643 case VescCANMsg::CAN_PACKET_POLL_ROTOR_POS: { // decode encoder data
644 int32_t index = 0;
645 float pos = this->buffer_get_int32(rxBuf, &index) / 100000.0; // extract the 0-360 float position
646 this->decodeEncoderPosition(pos);
647 break;
648 }
649
650 default:
651 break;
652 }
653
654}
655
656void VescCAN::buffer_append_float32(uint8_t *buffer, float number, float scale,
657 int32_t *index) {
658 this->buffer_append_int32(buffer, (int32_t) (number * scale), index);
659}
660
661void VescCAN::buffer_append_int32(uint8_t *buffer, int32_t number,
662 int32_t *index) {
663 buffer[(*index)++] = number >> 24;
664 buffer[(*index)++] = number >> 16;
665 buffer[(*index)++] = number >> 8;
666 buffer[(*index)++] = number;
667}
668
669void VescCAN::buffer_append_uint32(uint8_t *buffer, uint32_t number,
670 int32_t *index) {
671 buffer[(*index)++] = number >> 24;
672 buffer[(*index)++] = number >> 16;
673 buffer[(*index)++] = number >> 8;
674 buffer[(*index)++] = number;
675}
676
677uint32_t VescCAN::buffer_get_uint32(const uint8_t *buffer, int32_t *index) {
678 uint32_t res = ((uint32_t) buffer[*index]) << 24
679 | ((uint32_t) buffer[*index + 1]) << 16
680 | ((uint32_t) buffer[*index + 2]) << 8
681 | ((uint32_t) buffer[*index + 3]);
682 *index += 4;
683 return res;
684}
685
686int32_t VescCAN::buffer_get_int32(const uint8_t *buffer, int32_t *index) {
687 int32_t res = ((uint32_t) buffer[*index]) << 24
688 | ((uint32_t) buffer[*index + 1]) << 16
689 | ((uint32_t) buffer[*index + 2]) << 8
690 | ((uint32_t) buffer[*index + 3]);
691 *index += 4;
692 return res;
693}
694
695int16_t VescCAN::buffer_get_int16(const uint8_t *buffer, int32_t *index) {
696 int16_t res = ((uint16_t) buffer[*index]) << 8
697 | ((uint16_t) buffer[*index + 1]);
698 *index += 2;
699 return res;
700}
701
702float VescCAN::buffer_get_float32(const uint8_t *buffer, float scale,
703 int32_t *index) {
704 return (float) buffer_get_int32(buffer, index) / scale;
705}
706
707float VescCAN::buffer_get_float16(const uint8_t *buffer, float scale,
708 int32_t *index) {
709 return (float) buffer_get_int16(buffer, index) / scale;
710}
711
712#endif
void makeCrcTable(std::array< T, LEN > &table, const T crcpoly, const uint8_t bits, const bool refin=false, const bool refout=false)
Definition: CRC.h:36
uint16_t calculateCrc16_8(std::array< uint16_t, 256 > &crctable, uint8_t *buf, uint16_t len, uint16_t crc=0)
Definition: CRC.cpp:23
CommandStatus
EncoderType
Definition: Encoder.h:27
std::array< uint16_t, 256 > VescCAN::crc16_tab __attribute__((section(CCRAM_SEC)))
@ VESC_STATE_READY
@ VESC_STATE_INCOMPATIBLE
@ VESC_STATE_COMPATIBLE
@ VESC_STATE_UNKNOWN
@ VESC_STATE_ERROR
VescCAN_commands
Definition: VescCAN.h:57
VescCANMsg
Definition: VescCAN.h:37
@ CAN_PACKET_FILL_RX_BUFFER
@ CAN_PACKET_PROCESS_RX_BUFFER
@ CAN_PACKET_SET_CURRENT_REL
@ CAN_PACKET_POLL_ROTOR_POS
@ CAN_PACKET_PROCESS_SHORT_BUFFER
@ CAN_PACKET_FILL_RX_BUFFER_LONG
VescCmd
Definition: VescCAN.h:48
@ COMM_FW_VERSION
@ COMM_GET_VALUES_SELECTIVE
uint32_t id
Definition: CAN.h:70
uint32_t length
Definition: CAN.h:71
Definition: CAN.h:119
virtual void freePort()
Definition: CAN.h:164
virtual uint8_t getSpeedPreset()=0
virtual void takePort()
Definition: CAN.h:159
virtual void setSpeedPreset(uint8_t preset)=0
virtual int32_t addCanFilter(CAN_filter filter)=0
virtual bool sendMessage(CAN_tx_msg &msg)=0
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
virtual EncoderType getEncoderType()
Definition: Encoder.cpp:29
virtual Encoder * getEncoder()
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
Definition: VescCAN.cpp:29
static ClassIdentifier info
Definition: VescCAN.h:174
static bool isCreatable()
Definition: VescCAN.cpp:25
static bool inUse
Definition: VescCAN.h:175
static bool isCreatable()
Definition: VescCAN.cpp:42
static ClassIdentifier info
Definition: VescCAN.h:187
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
Definition: VescCAN.cpp:46
static bool inUse
Definition: VescCAN.h:188
float buffer_get_float16(const uint8_t *buffer, float scale, int32_t *index)
Definition: VescCAN.cpp:707
uint8_t buffer_rx[BUFFER_RX_SIZE]
Definition: VescCAN.h:140
void getFirmwareInfo()
Definition: VescCAN.cpp:369
bool motorReady() override
Definition: VescCAN.cpp:131
volatile VescState state
Definition: VescCAN.h:114
void decodeEncoderPosition(float newPos)
Definition: VescCAN.cpp:441
volatile uint8_t vescErrorFlag
Definition: VescCAN.h:115
int32_t getPos() override
Definition: VescCAN.cpp:211
void buffer_append_int32(uint8_t *buffer, int32_t number, int32_t *index)
Definition: VescCAN.cpp:661
uint8_t OFFB_can_Id
Definition: VescCAN.h:138
bool activeMotor
Definition: VescCAN.h:116
float lastTorque
Definition: VescCAN.h:117
void setTorque(float torque)
Definition: VescCAN.cpp:394
float posOffset
Definition: VescCAN.h:126
int32_t buffer_get_int32(const uint8_t *buffer, int32_t *index)
Definition: VescCAN.cpp:686
uint32_t getCpr() override
Definition: VescCAN.cpp:215
void askPositionEncoder()
Definition: VescCAN.cpp:431
VescFlashAddrs flashAddrs
Definition: VescCAN.h:113
void stopMotor() override
Definition: VescCAN.cpp:104
void askGetValue()
Definition: VescCAN.cpp:412
volatile uint32_t encCount
Definition: VescCAN.h:127
volatile uint32_t lastVescResponse
Definition: VescCAN.h:130
void decode_buffer(uint8_t *buffer, uint8_t len)
Definition: VescCAN.cpp:469
float lastPos
Definition: VescCAN.h:123
void Run()
Definition: VescCAN.cpp:317
void turn(int16_t power) override
Definition: VescCAN.cpp:98
int16_t buffer_get_int16(const uint8_t *buffer, int32_t *index)
Definition: VescCAN.cpp:695
virtual ~VescCAN()
Definition: VescCAN.cpp:82
uint32_t buffer_get_uint32(const uint8_t *buffer, int32_t *index)
Definition: VescCAN.cpp:677
volatile float encRate
Definition: VescCAN.h:129
float buffer_get_float32(const uint8_t *buffer, float scale, int32_t *index)
Definition: VescCAN.cpp:702
float getPos_f() override
Definition: VescCAN.cpp:204
void buffer_append_uint32(uint8_t *buffer, uint32_t number, int32_t *index)
Definition: VescCAN.cpp:669
void sendMsg(uint8_t cmd, uint8_t *buffer, uint8_t len)
Definition: VescCAN.cpp:459
float voltage
Definition: VescCAN.h:118
void saveFlashOffset()
Definition: VescCAN.cpp:179
static bool crcTableInitialized
Definition: VescCAN.h:164
float prevPos360
Definition: VescCAN.h:125
static const uint16_t crcpoly
Definition: VescCAN.h:163
uint8_t VESC_can_Id
Definition: VescCAN.h:139
void saveFlash() override
Definition: VescCAN.cpp:164
bool hasIntegratedEncoder() override
Definition: VescCAN.cpp:120
static std::array< uint16_t, 256 > crc16_tab
Definition: VescCAN.h:162
void startMotor() override
Definition: VescCAN.cpp:109
void restoreFlash() override
Definition: VescCAN.cpp:135
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
Definition: VescCAN.cpp:235
float mtPos
Definition: VescCAN.h:124
void sendPing()
Definition: VescCAN.cpp:382
int32_t filterId
Definition: VescCAN.h:137
bool useEncoder
Definition: VescCAN.h:122
void registerCommands()
Definition: VescCAN.cpp:219
void setPos(int32_t pos) override
Definition: VescCAN.cpp:197
void buffer_append_float32(uint8_t *buffer, float number, float scale, int32_t *index)
Definition: VescCAN.cpp:656
VescCAN(uint8_t address)
Definition: VescCAN.cpp:52
Encoder * getEncoder() override
Definition: VescCAN.cpp:113
EncoderType getEncoderType() override
Definition: VescCAN.cpp:124
CANPort * port
Definition: VescCAN.h:136
volatile uint32_t encStartPeriod
Definition: VescCAN.h:128
void canRxPendCallback(CANPort *port, CAN_rx_msg &msg) override
Definition: VescCAN.cpp:566
void setAddress(uint8_t address)
Definition: VescCAN.cpp:88
void Delay(const TickType_t Delay)
Definition: thread.hpp:352
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
uint8_t const * buffer
Definition: midi_device.h:100
static void * memcpy(void *dst, const void *src, size_t n)
Definition: ringbuffer.c:8
bool extid
Definition: CAN.h:112
uint32_t buffer
Definition: CAN.h:110
uint32_t filter_mask
Definition: CAN.h:109
uint32_t filter_id
Definition: CAN.h:108
bool extId
Definition: CAN.h:62
bool rtr
Definition: CAN.h:63
uint32_t id
Definition: CAN.h:60
uint32_t length
Definition: CAN.h:61
Definition: CAN.h:96
uint8_t data[CAN_MSGBUFSIZE]
Definition: CAN.h:97
CAN_msg_header_rx header
Definition: CAN.h:99
Definition: CAN.h:89
CAN_msg_header_tx header
Definition: CAN.h:92
uint8_t data[CAN_MSGBUFSIZE]
Definition: CAN.h:90
const char * name
uint32_t cmdId
uint16_t offset
Definition: VescCAN.h:64
uint16_t data
Definition: VescCAN.h:63
uint16_t canId
Definition: VescCAN.h:62