Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
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
24class MotorSimplemotion : public MotorDriver, public Encoder,public CommandHandler,public UARTDevice{
29
30 enum class MotorSimplemotion_cmdtypes : uint8_t {
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
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:
266 static ClassIdentifier info;
267 const ClassIdentifier getInfo(){return info;}
269 static bool isCreatable(){return !inUse;}
270
271};
272
277private:
278 static bool inUse;
279public:
281 static ClassIdentifier info;
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
CommandHandler(const char *clsname, uint16_t clsid, uint8_t instance=0)
Encoder()
Definition Encoder.cpp:18
static ClassIdentifier info
static bool isCreatable()
const ClassIdentifier getInfo()
static bool isCreatable()
const ClassIdentifier getInfo()
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
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()
UARTDevice()
Definition UART.cpp:212
const OutputPin gpMotor
void refreshWatchdog()
Definition cppmain.cpp:103
static struct @024127060247016123033304002117326322243354210111 data