Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
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
65
66 if(port->getSpeedPreset() < 3){
67 port->setSpeedPreset(3); // Minimum 250k
68 }
69 this->port->takePort();
70
72 this->Start();
73
74}
75
77 this->stopMotor();
78 this->port->freePort();
80 this->port->removeCanFilter(filterId);
81 this->port->removeCanFilter(filterIdVesc);
82}
83
84void VescCAN::setAddress(uint8_t address) {
85 if (address == 0) {
86 this->flashAddrs = VescFlashAddrs( { ADR_VESC1_CANID, ADR_VESC1_DATA, ADR_VESC1_OFFSET });
87 } else if (address == 1) {
88 this->flashAddrs = VescFlashAddrs( { ADR_VESC2_CANID, ADR_VESC2_DATA, ADR_VESC2_OFFSET });
89 } else if (address == 2) {
90 this->flashAddrs = VescFlashAddrs( { ADR_VESC3_CANID, ADR_VESC3_DATA, ADR_VESC3_OFFSET });
91 }
92}
93
95 if(filterId != -1){
96 port->removeCanFilter(filterId);
97 filterId = -1;
98 }
99 // Set up a filter to receive vesc commands
100 CAN_filter filterConf;
101 filterConf.extid = true;
102 filterConf.buffer = 0;
103 filterConf.filter_id = this->OFFB_can_Id;
104 filterConf.filter_mask = 0xff;
105 this->filterId = this->port->addCanFilter(filterConf); // Receive messages for this id
106
107 if(filterIdVesc != -1){
108 filterIdVesc = -1;
109 port->removeCanFilter(filterIdVesc);
110 }
111
112 if(this->filterIdVesc == -1){
113 filterConf.extid = true;
114 filterConf.buffer = 0;
115 filterConf.filter_id = VESC_can_Id == 0xff ? ((uint8_t)VescCANMsg::CAN_PACKET_POLL_ROTOR_POS) << 8 : VESC_can_Id;
116 filterConf.filter_mask = VESC_can_Id == 0xff ? 0xff00 : 0xff; // Filter pos update or vesc id
117 this->filterIdVesc = this->port->addCanFilter(filterConf);
118 }
119
120 return this->filterId != -1 && this->filterIdVesc != -1;
121}
122
123void VescCAN::turn(int16_t power) {
124 float torque = ((float) power / (float) 0x7fff);
125 if(fabs(torque-lastTorque) > 0.01){
126 pulseErrLed();
127 }
129 this->setTorque(torque);
130}
131
133 this->setTorque(0.0);
134 activeMotor = false;
135}
136
138 activeMotor = true;
139}
140
142 if (useEncoder)
143 return static_cast<Encoder*>(this);
144 else
146}
147
151
158
162
164 uint16_t dataFlash = 0;
165
166 if (Flash_Read(flashAddrs.canId, &dataFlash)) {
167 this->OFFB_can_Id = dataFlash & 0xFF;
168 this->VESC_can_Id = (dataFlash >> 8) & 0xFF;
169 }
170
171 if (Flash_Read(flashAddrs.data, &dataFlash)) {
172
173 //uint8_t canspd = dataFlash & 0b111;
174 //this->baudrate = canspd;
175
176 this->useEncoder = (dataFlash >> 3) & 0x1;
177 }
178
179 if (Flash_Read(flashAddrs.offset, &dataFlash)) {
180 this->posOffset = (float) ((int16_t) dataFlash / 10000.0);
181
182 this->posOffset = this->posOffset - (int) this->posOffset; // Remove the multi-turn value
183 bool moreThanHalfTurn = fabs(this->posOffset) > 0.5 ? 1 : 0;
184 if (moreThanHalfTurn) {
185 // if delta is neg, turn is CCW, decrement multi turn pos... else increment it
186 this->posOffset += (this->posOffset > 0) ? -1.0 : 1.0;
187 }
188 }
189
190}
191
193 uint16_t dataFlash = 0;
194
195 // save the OpenFFBoard Can Id in 0..7 and the Vesc_can_id in the 8..15
196 dataFlash = (this->VESC_can_Id << 8) | this->OFFB_can_Id;
197 Flash_Write(flashAddrs.canId, dataFlash);
198
199 dataFlash = 0;
200 //dataFlash |= (this->baudrate & 0b111); // set the baudrate in 0..2 bit
201 dataFlash |= (this->useEncoder & 0x1) << 3; // set the encoder use in bit 3
202 Flash_Write(flashAddrs.data, dataFlash);
203
205}
206
208
209 // store the -180°/180°offset
210 float storedOffset = this->posOffset - (int) this->posOffset; // Remove the multi-turn value
211 bool moreThanHalfTurn = fabs(storedOffset) > 0.5 ? 1 : 0;
212 if (moreThanHalfTurn) {
213 // if delta is neg, turn is CCW, decrement multi turn pos... else increment it
214 storedOffset += (storedOffset > 0) ? -1.0 : 1.0;
215 }
216
217 uint16_t dataFlash = ((int16_t) (storedOffset * 10000) & 0xFFFF);
218 Flash_Write(flashAddrs.offset, dataFlash);
219
220}
221
225void VescCAN::setPos(int32_t pos) {
226 // Only change encoder count internally as offset
227 posOffset = lastPos - ((float) pos / (float) getCpr());
228
229 saveFlashOffset(); // save the new offset for next restart
230}
231
234 this->askPositionEncoder();
235 }
236 return lastPos - posOffset;
237}
238
240 return getCpr() * getPos_f();
241}
242
243uint32_t VescCAN::getCpr() {
244 return 0xFFFF;
245}
246
249 registerCommand("offbcanid", VescCAN_commands::offbcanid, "CAN id of OpenFFBoard Axis", CMDFLAG_GET | CMDFLAG_SET);
250 registerCommand("vesccanid", VescCAN_commands::vesccanid, "CAN id of VESC", CMDFLAG_GET | CMDFLAG_SET);
251 registerCommand("canspd", VescCAN_commands::canspd, "CAN baud ! for info", CMDFLAG_GET | CMDFLAG_SET); // Kept for backwards compatibility. Remove in the future
252 registerCommand("errorflags", VescCAN_commands::errorflags, "VESC error state", CMDFLAG_GET);
253 registerCommand("vescstate", VescCAN_commands::vescstate, "VESC state", CMDFLAG_GET);
254 registerCommand("voltage", VescCAN_commands::voltage, "VESC supply voltage (mV)", CMDFLAG_GET);
255 registerCommand("encrate", VescCAN_commands::encrate, "Encoder update rate", CMDFLAG_GET);
256 registerCommand("pos", VescCAN_commands::pos, "VESC position", CMDFLAG_GET);
257 registerCommand("torque", VescCAN_commands::torque, "Current VESC torque", CMDFLAG_GET);
258 registerCommand("forceposread", VescCAN_commands::forcePosRead, "Force a position update", CMDFLAG_GET);
259 registerCommand("useencoder", VescCAN_commands::useEncoder, "Enable VESC encoder", CMDFLAG_GET | CMDFLAG_SET);
260 registerCommand("offset", VescCAN_commands::offset, "Get or set encoder offset", CMDFLAG_GET | CMDFLAG_SET);
261}
262
264 std::vector<CommandReply> &replies) {
265
266 switch (static_cast<VescCAN_commands>(cmd.cmdId)) {
267
269 {
270 CommandStatus status = handleGetSet(cmd, replies, this->OFFB_can_Id);
271 if(!setCanFilter()) status = CommandStatus::ERR;
272 return status;
273 }
275 {
276 CommandStatus status = handleGetSet(cmd, replies, this->VESC_can_Id);
277 if(!setCanFilter()) status = CommandStatus::ERR;
278 return status;
279 }
281 if (cmd.type == CMDtype::get)
282 replies.emplace_back(vescErrorFlag);
283 break;
285 if (cmd.type == CMDtype::get) {
286 replies.emplace_back(port->getSpeedPreset());
287 } else if (cmd.type == CMDtype::set) {
288 port->setSpeedPreset(std::max<uint8_t>(3,cmd.val));
289 }
290 break;
292 if (cmd.type == CMDtype::get)
293 replies.emplace_back((uint32_t) this->state);
294 break;
296 if (cmd.type == CMDtype::get)
297 replies.emplace_back((uint32_t) this->encRate);
298 break;
300 if (cmd.type == CMDtype::get) {
301 replies.push_back(
303 (int32_t) ((lastPos - posOffset) * 1000000000)));
304 }
305 break;
307 if (cmd.type == CMDtype::get) {
308 replies.emplace_back((int32_t) (lastTorque * 10000));
309 }
310 break;
312 this->askPositionEncoder();
313 break;
315 if (cmd.type == CMDtype::get) {
316 replies.emplace_back(useEncoder ? 1 : 0);
317 } else if (cmd.type == CMDtype::set) {
318 useEncoder = cmd.val != 0;
319 }
320 break;
322 if (cmd.type == CMDtype::get) {
323 replies.emplace_back((int32_t) (posOffset * 10000));
324 } else if (cmd.type == CMDtype::set) {
325 posOffset = (float) cmd.val / 10000.0;
326 this->saveFlashOffset(); // Really save to flash?
327 }
328 }
329 break;
331 if (cmd.type == CMDtype::get)
332 replies.emplace_back(voltage * 1000);
333 break;
334
335 default:
337 }
338
339 return CommandStatus::OK;
340}
341
342/*
343 * state = VESC_UNKOWN => ping until the state go to PONG
344 * = VESC_PONG => call a status message
345 * = VESC_ERROR => call a status message
346 *
347 * if error => state = VESC_ERROR
348 * else=> state = VESC_RESPOND
349 *
350 * if RespondVescTime > 100 => VESC_NOT_RESPOND
351 *
352 */
354
355 while (true) {
356 Delay(500);
357 // if status is UNKNOW, ask firmware info and wait next 500ms
359 this->getFirmwareInfo();
360 // the return of getFirmwareInfo change the state to COMPATIBLE/INCOMPATIBLE
361 // skip the follow control if we don't change from unknown state
362 continue;
363 }
364
365 // if vesc is compatible, ready or in error => check the status
366 if (state >= VescState::VESC_STATE_COMPATIBLE && !port->isWaiting()) {
367 this->askGetValue();
368 // the return of askGetValue put the state in READY or ERROR is vesc respond to status
369 }
370
371 // test is a ready/error vesc is always respond
372 uint32_t period = HAL_GetTick() - lastVescResponse;
374 || state == VescState::VESC_STATE_ERROR) && period > 1000) {
376 }
377
378 // when motor is active we call vesc each 500ms, to disable the vesc watchdog
379 // (if vesc not received message in 1sec, it cut off motor)
380 if (lastTorque != 0.0 && activeMotor
381 && state == VescState::VESC_STATE_READY && !port->isWaiting()) {
382 this->setTorque(lastTorque);
383 }
384
385 // compute encoderRate each second
386 period = HAL_GetTick() - encStartPeriod;
387 if (period > 1000) {
388 encRate = encCount / (period / 1000.0);
389 encCount = 0;
390 encStartPeriod = HAL_GetTick();
391 }
392
393 }
394}
395
396/************************************************************************************************
397 *
398 * CAN SECTION
399 */
400
401
406 uint8_t msg[3];
407 msg[0] = this->OFFB_can_Id;
408 msg[1] = 0x00; // ask vesc to process the msg
409 msg[2] = (uint8_t) VescCmd::COMM_FW_VERSION;// sub action is to get FW version
410
412 sizeof(msg));
413}
414
419 uint8_t buffer[1];
420 buffer[0] = this->OFFB_can_Id;
421
423 sizeof(buffer));
424}
425
431
432 // Check if vesc CAN is ok, if it is, send a message
433 if (!this->motorReady() || !activeMotor)
434 return;
435
436 uint8_t buffer[4];
437 int32_t send_index = 0;
438 this->buffer_append_float32(buffer, torque, 1e5, &send_index);
439
441 sizeof(buffer));
442
443}
444
445/*
446 * Get the telemetry : Status & Value
447 */
449 uint8_t msg[8];
450 msg[0] = this->OFFB_can_Id;
451 msg[1] = 0x00; // ask vesc to process the msg
452 msg[2] = (uint8_t) VescCmd::COMM_GET_VALUES_SELECTIVE;// sub action is COMM_GET_VALUES_SELECTIVE : ask wanted data
453 uint32_t request = ((uint32_t) 1 << 15); // bit 15 = ask vesc status (1byte)
454 request |= ((uint32_t) 1 << 8); // bit 8 = ask voltage (2byte)
455
456 int32_t index = 3;
457 this->buffer_append_uint32(msg, request, &index);
458
460 sizeof(msg));
461}
462
468 this->sendMsg((uint8_t) VescCANMsg::CAN_PACKET_POLL_ROTOR_POS, nullptr, 0);
469}
470
471/*
472 * Compute the new position (laspos) value from data received by vesc:
473 * newPos is a 0-360° angle position
474 * if delta with previous and new position is > 180° then we count 1 turn
475 * at 1kz, more than 180° mean 30000rpm, not admissible in simracing
476 */
477void VescCAN::decodeEncoderPosition(const float newPos) {
478 float delta = newPos - prevPos360; // Compute the delta position
479
480 bool moreThanHalfTurn = fabs(delta) > 180.0 ? 1 : 0;
481 if (moreThanHalfTurn) {
482 // if delta is neg, turn is CCW, decrement multi turn pos... else increment it
483 mtPos += (delta > 0) ? -1.0 : 1.0;
484 }
485
486 lastPos = (newPos / 360.0) + mtPos; // normalize the position
487 prevPos360 = newPos;
488
489 encCount++;
490}
491
495void VescCAN::sendMsg(uint8_t cmd, uint8_t *buffer, uint8_t len) {
496 CAN_tx_msg msg;
497 memcpy(&msg.data, buffer, len);
498 msg.header.rtr = false;
499 msg.header.length = len;
500 msg.header.extId = true;
501 msg.header.id = this->VESC_can_Id | (cmd << 8);
502 port->sendMessage(msg);
503}
504
505void VescCAN::decode_buffer(uint8_t *buffer, uint8_t len) {
506
507 if (!len) {
508 return;
509 }
510
511 VescCmd command = (VescCmd) (buffer[0] & 0xFF);
512 buffer++;
513 len--;
514
515 switch (command) {
516
518 int32_t ind = 0;
519 uint8_t fw_major = buffer[ind++];
520 uint8_t fw_min = buffer[ind++];
521
522 std::string test((char*) buffer + ind);
523 ind += test.length() + 1;
524
525 uint8_t uuid[12] = { 0 };
526 memcpy(buffer + ind, uuid, 12);
527 ind += 12;
528
529 //bool isPaired = buffer[ind++];
530 uint8_t isTestFw = buffer[ind++];
531
532 //uint8_t hwType = buffer[ind++]; // Comment because unused
533 //uint8_t customConfig = buffer[ind++]; // Comment because unused
534
535 // bool hasPhaseFilters = buffer[ind++]; // Comment because unused
536
537 bool compatible = false;
538 if (!isTestFw)
539 compatible = ((fw_major << 8) | fw_min) >= (FW_MIN_RELEASE >> 8);
540 else
541 compatible = ((fw_major << 16) | (fw_min << 8) | isTestFw)
542 >= FW_MIN_RELEASE;
543
544 if (compatible) {
546 } else {
548 }
549
550 break;
551 }
552
554 int32_t ind = 0;
555 uint32_t mask = this->buffer_get_uint32(buffer, &ind);
556
557 if (mask & ((uint32_t) 1 << 8)) {
558 voltage = this->buffer_get_float16(buffer, 1e1, &ind);
559 }
560 if (mask & ((uint32_t) 1 << 15)) {
561 vescErrorFlag = buffer[ind++];
562
563 // if the vesc respond but with an error, we put the vesc in error flag
564 if (vescErrorFlag) {
566 } else {
568 }
569
570 }
571 if (mask & ((uint32_t) 1 << 16)) {
572 float pos = this->buffer_get_float32(buffer, 1e6, &ind);
573 this->decodeEncoderPosition(pos);
574 }
575 break;
576
577 }
578
579 default:
580 break;
581
582 }
583
584}
585
586/*
587 * Process the received message on the CAN bus.
588 * Message have several struct, depends on message type, check the comm_can.c and
589 * command.c in the vesc source project to identify the struct format.
590 *
591 * Quick tips :
592 * Msg struct for CAN_PACKET_PROCESS_RX_BUFFER and CAN_PACKET_PROCESS_SHORT_BUFFER :
593 * uint8_t[0] => can_emitter_id (vesc id)
594 * uint8_t[1] => send bool
595 * uint8_t[2] => COMM_PACKET_ID command
596 * uint8_t[3] -> uint8_t[7] => DATA (5 bytes)
597 *
598 * Msg struct for CAN_PACKET_POLL_ROTOR_POS
599 * uint8_t[0]..uint8_t[3] : uint32 f_pos / 10000
600 *
601 */
603
604 // we record the last time respond to check if vesc is OK
605 lastVescResponse = HAL_GetTick();
606
607 // Check if message is for the openFFBoard
608 uint16_t destCanID = msg.header.id & 0xFF;
609 uint8_t *rxBuf = msg.data;
610
611 // Extract the command encoded in the ExtId
612 VescCANMsg cmd = (VescCANMsg) (msg.header.id >> 8);
613
614 bool messageIsForThisVescAxis = destCanID == this->OFFB_can_Id;
615 messageIsForThisVescAxis |= (cmd == VescCANMsg::CAN_PACKET_POLL_ROTOR_POS) && // if it's a encoder position message
616 (this->VESC_can_Id == 0xFF); // and the vescCanId is not the default one
617 messageIsForThisVescAxis |= (cmd == VescCANMsg::CAN_PACKET_POLL_ROTOR_POS)
618 && // if it's a encoder position message
619 (this->VESC_can_Id != 0xFF) && // and the vescCanId is not the default one
620 (destCanID == this->VESC_can_Id); // we check that emiterId is the vescId for this axis
621
622 if (!messageIsForThisVescAxis){
623 return;
624 }
625
626 // Process the CAN message received
627 switch (cmd) {
628
630 memcpy(buffer_rx + rxBuf[0], rxBuf + 1, msg.header.length - 1);
631 break;
632 }
633
635 uint32_t rxbuf_ind = (unsigned int) rxBuf[0] << 8;
636 rxbuf_ind |= rxBuf[1];
637 if (rxbuf_ind < BUFFER_RX_SIZE) {
638 memcpy(buffer_rx + rxbuf_ind, rxBuf + 2, msg.header.length - 2);
639 }
640 break;
641 }
642
644
645 // remove 2 first byte to exclude "can emitter id" and the "send bool" flag from buffer
646 int32_t index = 2;
647
648 uint32_t rxbuf_length = (uint32_t) rxBuf[index++] << 8;
649 rxbuf_length |= (uint32_t) rxBuf[index++];
650
651 if (rxbuf_length > BUFFER_RX_SIZE) {
652 break;
653 }
654
655 uint8_t crc_high = rxBuf[index++];
656 uint8_t crc_low = rxBuf[index++];
657
658 if(calculateCrc16_8(crc16_tab,buffer_rx,rxbuf_length)
659 //if (crc16(buffer_rx, rxbuf_length)
660 == ((uint8_t) crc_high << 8 | (uint8_t) crc_low)) {
661
662 this->decode_buffer(buffer_rx, rxbuf_length);
663
664 }
665
666 break;
667 }
669
670 // remove 2 first byte to exclude "can emitter id" and the "send bool" flag from buffer
671 this->decode_buffer(rxBuf + 2, msg.header.length - 2);
672
673 break;
674 }
675
678 break;
679
680 case VescCANMsg::CAN_PACKET_POLL_ROTOR_POS: { // decode encoder data
681 int32_t index = 0;
682 float pos = this->buffer_get_int32(rxBuf, &index) / 100000.0; // extract the 0-360 float position
683 this->decodeEncoderPosition(pos);
684 break;
685 }
686
687 default:
688 break;
689 }
690
691}
692
693void VescCAN::buffer_append_float32(uint8_t *buffer, float number, float scale,
694 int32_t *index) {
695 this->buffer_append_int32(buffer, (int32_t) (number * scale), index);
696}
697
698void VescCAN::buffer_append_int32(uint8_t *buffer, int32_t number,
699 int32_t *index) {
700 buffer[(*index)++] = number >> 24;
701 buffer[(*index)++] = number >> 16;
702 buffer[(*index)++] = number >> 8;
703 buffer[(*index)++] = number;
704}
705
706void VescCAN::buffer_append_uint32(uint8_t *buffer, uint32_t number,
707 int32_t *index) {
708 buffer[(*index)++] = number >> 24;
709 buffer[(*index)++] = number >> 16;
710 buffer[(*index)++] = number >> 8;
711 buffer[(*index)++] = number;
712}
713
714uint32_t VescCAN::buffer_get_uint32(const uint8_t *buffer, int32_t *index) {
715 uint32_t res = ((uint32_t) buffer[*index]) << 24
716 | ((uint32_t) buffer[*index + 1]) << 16
717 | ((uint32_t) buffer[*index + 2]) << 8
718 | ((uint32_t) buffer[*index + 3]);
719 *index += 4;
720 return res;
721}
722
723int32_t VescCAN::buffer_get_int32(const uint8_t *buffer, int32_t *index) {
724 int32_t res = ((uint32_t) buffer[*index]) << 24
725 | ((uint32_t) buffer[*index + 1]) << 16
726 | ((uint32_t) buffer[*index + 2]) << 8
727 | ((uint32_t) buffer[*index + 3]);
728 *index += 4;
729 return res;
730}
731
732int16_t VescCAN::buffer_get_int16(const uint8_t *buffer, int32_t *index) {
733 int16_t res = ((uint16_t) buffer[*index]) << 8
734 | ((uint16_t) buffer[*index + 1]);
735 *index += 2;
736 return res;
737}
738
739float VescCAN::buffer_get_float32(const uint8_t *buffer, float scale,
740 int32_t *index) {
741 return (float) buffer_get_int32(buffer, index) / scale;
742}
743
744float VescCAN::buffer_get_float16(const uint8_t *buffer, float scale,
745 int32_t *index) {
746 return (float) buffer_get_int16(buffer, index) / scale;
747}
748
749#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
Definition VescCAN.h:32
@ VESC_STATE_INCOMPATIBLE
Definition VescCAN.h:29
@ VESC_STATE_COMPATIBLE
Definition VescCAN.h:31
@ VESC_STATE_PONG
Definition VescCAN.h:30
@ VESC_STATE_UNKNOWN
Definition VescCAN.h:28
@ VESC_STATE_ERROR
Definition VescCAN.h:33
VescCAN_commands
Definition VescCAN.h:57
VescCANMsg
Definition VescCAN.h:37
@ CAN_PACKET_PING
Definition VescCAN.h:43
@ CAN_PACKET_PONG
Definition VescCAN.h:44
@ CAN_PACKET_FILL_RX_BUFFER
Definition VescCAN.h:38
@ CAN_PACKET_PROCESS_RX_BUFFER
Definition VescCAN.h:40
@ CAN_PACKET_SET_CURRENT_REL
Definition VescCAN.h:42
@ CAN_PACKET_POLL_ROTOR_POS
Definition VescCAN.h:45
@ CAN_PACKET_PROCESS_SHORT_BUFFER
Definition VescCAN.h:41
@ CAN_PACKET_FILL_RX_BUFFER_LONG
Definition VescCAN.h:39
VescCmd
Definition VescCAN.h:48
@ COMM_FW_VERSION
Definition VescCAN.h:49
@ COMM_GET_VALUES_SELECTIVE
Definition VescCAN.h:51
uint32_t id
Definition CAN.h:72
uint32_t length
Definition CAN.h:73
Definition CAN.h:121
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)
CommandHandler(const char *clsname, uint16_t clsid, uint8_t instance=0)
virtual EncoderType getEncoderType()
Definition Encoder.cpp:29
Encoder()
Definition Encoder.cpp:18
virtual Encoder * getEncoder()
const ClassIdentifier getInfo()
Definition VescCAN.cpp:29
static ClassIdentifier info
Definition VescCAN.h:20
static bool isCreatable()
Definition VescCAN.cpp:25
static bool inUse
Definition VescCAN.h:178
static bool isCreatable()
Definition VescCAN.cpp:42
static ClassIdentifier info
Definition VescCAN.h:37
const ClassIdentifier getInfo()
Definition VescCAN.cpp:46
static bool inUse
Definition VescCAN.h:191
float buffer_get_float16(const uint8_t *buffer, float scale, int32_t *index)
Definition VescCAN.cpp:744
uint8_t buffer_rx[BUFFER_RX_SIZE]
Definition VescCAN.h:143
void getFirmwareInfo()
Definition VescCAN.cpp:405
bool motorReady() override
Definition VescCAN.cpp:159
volatile VescState state
Definition VescCAN.h:116
void decodeEncoderPosition(float newPos)
Definition VescCAN.cpp:477
volatile uint8_t vescErrorFlag
Definition VescCAN.h:117
int32_t getPos() override
Definition VescCAN.cpp:239
void buffer_append_int32(uint8_t *buffer, int32_t number, int32_t *index)
Definition VescCAN.cpp:698
uint8_t OFFB_can_Id
Definition VescCAN.h:141
bool activeMotor
Definition VescCAN.h:118
float lastTorque
Definition VescCAN.h:119
void setTorque(float torque)
Definition VescCAN.cpp:430
float posOffset
Definition VescCAN.h:128
int32_t buffer_get_int32(const uint8_t *buffer, int32_t *index)
Definition VescCAN.cpp:723
uint32_t getCpr() override
Definition VescCAN.cpp:243
void askPositionEncoder()
Definition VescCAN.cpp:467
VescFlashAddrs flashAddrs
Definition VescCAN.h:115
void stopMotor() override
Definition VescCAN.cpp:132
void askGetValue()
Definition VescCAN.cpp:448
volatile uint32_t encCount
Definition VescCAN.h:129
volatile uint32_t lastVescResponse
Definition VescCAN.h:132
void decode_buffer(uint8_t *buffer, uint8_t len)
Definition VescCAN.cpp:505
float lastPos
Definition VescCAN.h:125
void Run()
Definition VescCAN.cpp:353
int32_t filterIdVesc
Definition VescCAN.h:140
void turn(int16_t power) override
Definition VescCAN.cpp:123
int16_t buffer_get_int16(const uint8_t *buffer, int32_t *index)
Definition VescCAN.cpp:732
virtual ~VescCAN()
Definition VescCAN.cpp:76
uint32_t buffer_get_uint32(const uint8_t *buffer, int32_t *index)
Definition VescCAN.cpp:714
volatile float encRate
Definition VescCAN.h:131
float buffer_get_float32(const uint8_t *buffer, float scale, int32_t *index)
Definition VescCAN.cpp:739
float getPos_f() override
Definition VescCAN.cpp:232
void buffer_append_uint32(uint8_t *buffer, uint32_t number, int32_t *index)
Definition VescCAN.cpp:706
void sendMsg(uint8_t cmd, uint8_t *buffer, uint8_t len)
Definition VescCAN.cpp:495
float voltage
Definition VescCAN.h:120
void saveFlashOffset()
Definition VescCAN.cpp:207
static bool crcTableInitialized
Definition VescCAN.h:167
float prevPos360
Definition VescCAN.h:127
static const uint16_t crcpoly
Definition VescCAN.h:166
uint8_t VESC_can_Id
Definition VescCAN.h:142
void saveFlash() override
Definition VescCAN.cpp:192
bool hasIntegratedEncoder() override
Definition VescCAN.cpp:148
static std::array< uint16_t, 256 > crc16_tab
Definition VescCAN.h:165
void startMotor() override
Definition VescCAN.cpp:137
void restoreFlash() override
Definition VescCAN.cpp:163
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
Definition VescCAN.cpp:263
float mtPos
Definition VescCAN.h:126
void sendPing()
Definition VescCAN.cpp:418
int32_t filterId
Definition VescCAN.h:139
bool useEncoder
Definition VescCAN.h:124
void registerCommands()
Definition VescCAN.cpp:247
void setPos(int32_t pos) override
Definition VescCAN.cpp:225
void buffer_append_float32(uint8_t *buffer, float number, float scale, int32_t *index)
Definition VescCAN.cpp:693
VescCAN(uint8_t address)
Definition VescCAN.cpp:52
Encoder * getEncoder() override
Definition VescCAN.cpp:141
EncoderType getEncoderType() override
Definition VescCAN.cpp:152
CANPort * port
Definition VescCAN.h:138
volatile uint32_t encStartPeriod
Definition VescCAN.h:130
void canRxPendCallback(CANPort *port, CAN_rx_msg &msg) override
Definition VescCAN.cpp:602
void setAddress(uint8_t address)
Definition VescCAN.cpp:84
bool setCanFilter()
Definition VescCAN.cpp:94
void Delay(const TickType_t Delay)
Definition thread.hpp:352
Thread(const std::string Name, uint16_t StackDepth, UBaseType_t Priority)
Definition cthread.cpp:56
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
void pulseErrLed()
uint8_t const * buffer
static void * memcpy(void *dst, const void *src, size_t n)
Definition ringbuffer.c:8
bool extid
Definition CAN.h:114
uint32_t buffer
Definition CAN.h:112
uint32_t filter_mask
Definition CAN.h:111
uint32_t filter_id
Definition CAN.h:110
uint32_t id
Definition CAN.h:62
uint32_t length
Definition CAN.h:63
uint8_t data[CAN_MSGBUFSIZE]
Definition CAN.h:99
CAN_msg_header_rx header
Definition CAN.h:101
CAN_msg_header_tx header
Definition CAN.h:94
uint8_t data[CAN_MSGBUFSIZE]
Definition CAN.h:92
CFG_TUH_MEM_ALIGN tusb_control_request_t request
Definition usbh.c:259