Open FFBoard
Open source force feedback firmware
MotorSimplemotion.h
Go to the documentation of this file.
1/*
2 * MotorSimplemotion.h
3 *
4 * Created on: Jan 9, 2023
5 * Author: Yannick
6 */
7
8#ifndef USEREXTENSIONS_SRC_MOTORSIMPLEMOTION_H_
9#define USEREXTENSIONS_SRC_MOTORSIMPLEMOTION_H_
10
11#include "MotorDriver.h"
12#include "cpp_target_config.h"
13#include "Encoder.h"
14#include "thread.hpp"
15#include "CommandHandler.h"
16#include "PersistentStorage.h"
17#include "UART.h"
18
19#ifdef SIMPLEMOTION
20
24class MotorSimplemotion : public MotorDriver, public Encoder,public CommandHandler,public UARTDevice{
25
26 enum class MotorSimplemotion_commands : uint8_t {
28 };
29
30 enum class MotorSimplemotion_cmdtypes : uint8_t {
31 param32b = 0,param24b = 1,setparamadr = 2,status=3,none = 0xff
32 };
33
34 enum class MotorSimplemotion_param : uint16_t {
35 FBD = 493, FBR = 565,ControlMode = 559,Voltage = 900, Torque = 901,systemcontrol = 554,status = 553,CB1 = 2533,cumstat = 13,faults = 552,devtype = 6020
36 };
37
38 enum class MotorSimplemotion_FBR : uint8_t {
40 };
41
42
45 uint8_t adr = 1;
46 uint16_t val1 = 0;
47 uint16_t val2 = 0;
48 uint8_t crc = 0;
49 } __attribute__((packed));
50
53 uint16_t val1 = 0;
54 uint16_t val2 = 0;
55 uint8_t crc = 0;
56 } __attribute__((packed));
57
58public:
60 virtual ~MotorSimplemotion();
61
63
64 void turn(int16_t power) override;
65 void stopMotor() override;
66 void startMotor() override;
67 Encoder* getEncoder() override;
68 bool hasIntegratedEncoder() {return true;}
69
70
71 int32_t getPos() override;
72 void setPos(int32_t pos) override;
73 EncoderType getEncoderType() override;
74 uint32_t getCpr() override;
75
76 CommandStatus command(const ParsedCommand& cmd,std::vector<CommandReply>& replies) override;
77 void registerCommands();
78 std::string getHelpstring(){return "RS485 Simplemotion interface";};
79
80 void uartRcv(char& buf); //Warning: called by interrupts!
81 void sendFastUpdate(uint16_t val1,uint16_t val2 = 0);
82 void startUartTransfer(UARTPort* port,bool transmit);
83 void endUartTransfer(UARTPort* port,bool transmit);
84 bool sendCommand(uint8_t* buf,uint8_t len,uint8_t adr);
85
86 uint8_t queueCommand(uint8_t* buf, MotorSimplemotion_cmdtypes type,uint32_t data);
87 bool read1Parameter(MotorSimplemotion_param paramId,uint32_t* reply_p,MotorSimplemotion_cmdtypes replylen = MotorSimplemotion_cmdtypes::none); // Check default param length
88 bool set1Parameter(MotorSimplemotion_param paramId,int32_t value,uint32_t* reply_p = nullptr);
89 bool getSettings();
90
91 uint32_t getCumstat();
92
93 bool motorReady();
94
95 int16_t getTorque();
96 int16_t getVoltage();
97
98 void restart();
99
100 static const uint8_t SMCMD_FAST_UPDATE_CYCLE = 2<<3;
101 static const uint8_t SMCMD_FAST_UPDATE_CYCLE_RET = (2<<3) | 1;
102 static const uint8_t SMP_FAST_UPDATE_CYCLE_FORMAT = 17;
103 static const uint8_t SMCMD_INSTANT_CMD = 0x24; // 0x24
104 static const uint8_t SMCMD_INSTANT_CMD_RET = 0x25; // 0x25
105 static const uint8_t SMPCMD_SETPARAMADDR = 2;
106
107protected:
109
110 //CRC
111 static std::array<uint8_t,256> tableCRC8;
112 static std::array<uint16_t,256> tableCRC16;
113 static const uint8_t crcpoly = 0x07;
114 static const uint16_t crcpoly16 = 0x8005;
116 static const uint8_t crc8init = 0x52;
117
118 // Receive buffer
119 static const uint8_t RXBUF_SIZE = 32;
120 volatile char rxbuf[RXBUF_SIZE];
121 volatile uint8_t rxbuf_i = 0;
122
123 // Transmit buffer
124 static const uint8_t TXBUF_SIZE = 32;
126
127 volatile uint8_t replyidx = 0;
128 static const uint8_t REPLYBUF_SIZE = 32;
129 volatile uint32_t replyvalues[REPLYBUF_SIZE]; // can't be vector because filled in isr
130
131 volatile uint32_t crcerrors = 0;
132 int16_t lastTorque = 0;
133 volatile uint32_t lastUpdateTime = 0;
134 volatile uint32_t uarterrors = 0;
135
136private:
137 uint8_t address;
138 void updatePosition(uint16_t value);
139 void updateStatus(uint16_t value);
140
141 uint16_t status;
142 uint16_t devicetype=0;
143
144 int32_t position = 0;
145 int32_t position_offset = 0;
146 uint16_t lastPosRep = 0x7fff;
147 volatile bool waitingFastUpdate = false;
148 volatile bool waitingReply = false;
149 int32_t overflows = 0;
151 volatile uint32_t lastSentTime = 0;
152 volatile uint32_t lastStatusTime = 0;
153
154 static const uint32_t uartErrorTimeout = 10; //ms after a failed transfer to reset the buffer and port status
155 volatile uint32_t lastTimeByteReceived = 0;
156 volatile bool uartErrorOccured = false;
157 void resetBuffer();
158
159 bool prepareUartTransmit();
160
161 bool initialized = false;
162 bool hardfault = false;
163 Error configError = {ErrorCode::externalConfigurationError, ErrorType::critical, "Simplemotion device invalid configuration"};
165
166 static uint16_t calculateCrc16rev(std::array<uint16_t,256> &crctable,uint8_t* buf,uint16_t len,uint16_t crc);
167
172 template<size_t params,size_t replynum>
173 bool readParameter(std::array<MotorSimplemotion_param,params> paramIds,std::array<uint32_t*,replynum> replies,MotorSimplemotion_cmdtypes replylen = MotorSimplemotion_cmdtypes::none,uint32_t timeout_ms = uartErrorTimeout){
174 bool lengthSpecified = replylen != MotorSimplemotion_cmdtypes::none;
175 uint8_t subpacketbuf[lengthSpecified ? (4-((uint8_t)replylen & 0x3)+7) * params : 5*params] = {0};
176 uint8_t requestlen = 0;
177
178 for(MotorSimplemotion_param param : paramIds){
179 if(lengthSpecified){
180 requestlen+=queueCommand(subpacketbuf+requestlen, MotorSimplemotion_cmdtypes::setparamadr, 10); //SMP_RETURN_PARAM_LEN
181 requestlen+=queueCommand(subpacketbuf+requestlen, MotorSimplemotion_cmdtypes::param24b, (uint32_t)replylen); //SMPRET_32B. MUST be 24b at least once!!!
182 }
183 requestlen+=queueCommand(subpacketbuf+requestlen, MotorSimplemotion_cmdtypes::setparamadr, 9); //SMP_RETURN_PARAM_ADDR
184 requestlen+=queueCommand(subpacketbuf+requestlen, MotorSimplemotion_cmdtypes::param24b, (uint32_t)param);
185 }
186
187 if(!sendCommand(subpacketbuf,requestlen,this->address)){
188 uartErrorOccured = true;
189 return false;
190 }
191 uint32_t mstart = HAL_GetTick();
192
193 while((HAL_GetTick()-mstart) < timeout_ms && waitingReply){
194 // Wait...
196 }
197
198 if(waitingReply){
199 uartErrorOccured = true;
200 uarterrors++;
201 //uartport->abortReceive();
202 // resetBuffer();
203
204 waitingReply = false;
205 return false;
206 }
207 for(uint8_t i = 0;i<replynum ; i++){
208 if(lengthSpecified){
209 *replies[i] = replyvalues[(i+1)*3]; // Skip first 3 replies if length is set
210 }else{
211 *replies[i] = replyvalues[(i+1)*2 - 1]; // Skip first reply
212 }
213 }
214
215 return true;
216 }
217
218 template<size_t params,size_t replynum>
219 bool writeParameter(std::array<std::pair<MotorSimplemotion_param,int32_t>,params> paramIds_value,std::array<uint32_t*,replynum> replies,MotorSimplemotion_cmdtypes type,uint32_t timeout_ms = uartErrorTimeout){
220
221 uint8_t packetlen = 4-((uint8_t)type & 0x3);
222 uint8_t subpacketbuf[(packetlen + 2)*params] = {0};
223 uint8_t requestlen = 0;
224
225 for(std::pair<MotorSimplemotion_param,int32_t> param : paramIds_value){
226 requestlen+=queueCommand(subpacketbuf+requestlen, MotorSimplemotion_cmdtypes::setparamadr, (uint32_t)param.first);
227 requestlen+=queueCommand(subpacketbuf+requestlen, type, (uint32_t)param.second);
228 }
229
230 if(!sendCommand(subpacketbuf,requestlen,this->address)){
231 return false;
232 }
233 uint32_t mstart = HAL_GetTick();
234
235 while((HAL_GetTick()-mstart) < timeout_ms && waitingReply){
236 // Wait...
238 }
239
240 if(waitingReply){
241 uartErrorOccured = true;
242 uarterrors++;
243 //uartport->abortReceive();
244 waitingReply = false;
245 return false;
246 }
247 for(uint8_t i = 0;i<replynum ; i++){
248 if(replies[i])
249 *replies[i] = replyvalues[(i+1)*2 - 1]; // Skip first reply
250 }
251
252 return true;
253 }
254};
255
256
257
262private:
263 static bool inUse;
264public:
267 const ClassIdentifier getInfo(){return info;}
269 static bool isCreatable(){return !inUse;}
270
271};
272
277private:
278 static bool inUse;
279public:
282 const ClassIdentifier getInfo(){return info;}
284 static bool isCreatable(){return !inUse;}
285
286};
287#endif
288#endif /* USEREXTENSIONS_SRC_MOTORSIMPLEMOTION_H_ */
CommandStatus
EncoderType
Definition: Encoder.h:27
@ externalConfigurationError
uint16_t val1
uint8_t adr
uint8_t crc
uint16_t val2
static ClassIdentifier info
static bool isCreatable()
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
static bool isCreatable()
const ClassIdentifier getInfo()
Command handlers always have class infos. Works well with ChoosableClass.
static ClassIdentifier info
static const uint8_t SMCMD_INSTANT_CMD_RET
void startMotor() override
volatile uint32_t lastUpdateTime
static const uint8_t TXBUF_SIZE
void uartRcv(char &buf)
static bool crcTableInitialized
void turn(int16_t power) override
volatile bool uartErrorOccured
EncoderType getEncoderType() override
volatile bool waitingReply
void startUartTransfer(UARTPort *port, bool transmit)
volatile uint32_t lastSentTime
static uint16_t calculateCrc16rev(std::array< uint16_t, 256 > &crctable, uint8_t *buf, uint16_t len, uint16_t crc)
const OutputPin & writeEnablePin
volatile uint32_t crcerrors
volatile uint32_t uarterrors
static const uint32_t uartErrorTimeout
volatile uint32_t lastStatusTime
void stopMotor() override
MotorSimplemotion_FBR encodertype
static const uint16_t crcpoly16
volatile uint8_t replyidx
static const uint8_t SMCMD_INSTANT_CMD
static const uint8_t crc8init
static std::array< uint8_t, 256 > tableCRC8
static const uint8_t SMPCMD_SETPARAMADDR
volatile uint32_t replyvalues[REPLYBUF_SIZE]
static const uint8_t SMCMD_FAST_UPDATE_CYCLE
volatile char rxbuf[RXBUF_SIZE]
void updateStatus(uint16_t value)
uint8_t queueCommand(uint8_t *buf, MotorSimplemotion_cmdtypes type, uint32_t data)
char txbuf[TXBUF_SIZE]
volatile uint32_t lastTimeByteReceived
bool writeParameter(std::array< std::pair< MotorSimplemotion_param, int32_t >, params > paramIds_value, std::array< uint32_t *, replynum > replies, MotorSimplemotion_cmdtypes type, uint32_t timeout_ms=uartErrorTimeout)
void sendFastUpdate(uint16_t val1, uint16_t val2=0)
static std::array< uint16_t, 256 > tableCRC16
bool readParameter(std::array< MotorSimplemotion_param, params > paramIds, std::array< uint32_t *, replynum > replies, MotorSimplemotion_cmdtypes replylen=MotorSimplemotion_cmdtypes::none, uint32_t timeout_ms=uartErrorTimeout)
bool read1Parameter(MotorSimplemotion_param paramId, uint32_t *reply_p, MotorSimplemotion_cmdtypes replylen=MotorSimplemotion_cmdtypes::none)
static const uint8_t SMCMD_FAST_UPDATE_CYCLE_RET
static const uint8_t RXBUF_SIZE
void updatePosition(uint16_t value)
const ClassIdentifier getInfo()=0
Command handlers always have class infos. Works well with ChoosableClass.
struct MotorSimplemotion::Sm2FastUpdate __attribute__((packed))
volatile uint8_t rxbuf_i
Encoder * getEncoder() override
MotorSimplemotion(uint8_t instance)
uint32_t getCpr() override
Sm2FastUpdate fastbuffer
bool sendCommand(uint8_t *buf, uint8_t len, uint8_t adr)
void endUartTransfer(UARTPort *port, bool transmit)
static const uint8_t crcpoly
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies) override
int32_t getPos() override
static const uint8_t SMP_FAST_UPDATE_CYCLE_FORMAT
volatile bool waitingFastUpdate
void setPos(int32_t pos) override
static const uint8_t REPLYBUF_SIZE
bool set1Parameter(MotorSimplemotion_param paramId, int32_t value, uint32_t *reply_p=nullptr)
std::string getHelpstring()
Definition: UART.h:26
const OutputPin gpMotor
void refreshWatchdog()
Definition: cppmain.cpp:103
static struct @612 data