Skip to content

Commit f8c34be

Browse files
authored
Merge pull request #30 from bcmi-labs/scoped-lock-smart-servo
Use scoped lock for simple & error-free locking within SmartServoClass
2 parents 3093132 + c53ffa9 commit f8c34be

File tree

2 files changed

+86
-94
lines changed

2 files changed

+86
-94
lines changed

src/lib/motors/SmartServo.cpp

Lines changed: 83 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SmartServoClass::SmartServoClass(RS485Class & RS485)
1212
: _RS485{RS485}
1313
, _errors{0}
1414
, _onError{}
15+
, _mtx{}
1516
{
1617

1718
}
@@ -129,8 +130,9 @@ int SmartServoClass::readByteCmd(uint8_t const id, uint8_t const address) {
129130
* PUBLIC MEMBER FUNCTIONS
130131
**************************************************************************************/
131132

132-
int SmartServoClass::ping(uint8_t const id) {
133-
mutex.lock();
133+
int SmartServoClass::ping(uint8_t const id)
134+
{
135+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
134136
writeCmd(id, SmartServoOperation::PING);
135137
// TODO: check return
136138
receiveResponse(6);
@@ -139,11 +141,8 @@ int SmartServoClass::ping(uint8_t const id) {
139141
_rxBuf[1]==0xf5 &&
140142
_rxBuf[2]==id &&
141143
_rxBuf[3]==2) {
142-
143-
mutex.unlock();
144144
return _rxBuf[4];
145145
}
146-
mutex.unlock();
147146
_errors++;
148147
if (_onError) _onError();
149148
return -1;
@@ -152,68 +151,63 @@ int SmartServoClass::ping(uint8_t const id) {
152151
/*
153152
// ATTENTION: RESET also changes the ID of the motor
154153
155-
void SmartServoClass::reset(uint8_t const id) {
156-
mutex.lock();
154+
void SmartServoClass::reset(uint8_t const id)
155+
{
156+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
157157
writeCmd(id, SmartServoOperation::RESET);
158-
mutex.unlock();
159158
}
160159
*/
161160

162-
void SmartServoClass::action(uint8_t const id) {
163-
mutex.lock();
161+
void SmartServoClass::action(uint8_t const id)
162+
{
163+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
164164
writeCmd(id, SmartServoOperation::ACTION);
165-
mutex.unlock();
166-
}
167-
168-
int SmartServoClass::begin() {
169-
if (_RS485) {
170-
_txPacket.header[0] = 0xff;
171-
_txPacket.header[1] = 0xff;
172-
_RS485.begin(115200, 0, 90);
173-
_RS485.receive();
174-
writeByteCmd(BROADCAST, REG(SmartServoRegister::SERVO_MOTOR_MODE), 1);
175-
writeByteCmd(BROADCAST, REG(SmartServoRegister::TORQUE_SWITCH) ,1);
176-
_positionMode = PositionMode::IMMEDIATE;
177-
return 0;
178-
} else {
179-
return -1;
180-
}
165+
}
166+
167+
void SmartServoClass::begin()
168+
{
169+
_txPacket.header[0] = 0xff;
170+
_txPacket.header[1] = 0xff;
171+
_RS485.begin(115200, 0, 90);
172+
_RS485.receive();
173+
writeByteCmd(BROADCAST, REG(SmartServoRegister::SERVO_MOTOR_MODE), 1);
174+
writeByteCmd(BROADCAST, REG(SmartServoRegister::TORQUE_SWITCH) ,1);
175+
_positionMode = PositionMode::IMMEDIATE;
181176
}
182177

183178
void SmartServoClass::setPosition(uint8_t const id, float const angle, uint16_t const speed)
184179
{
185180
if (!isValidAngle(angle))
186181
return;
187182

188-
mutex.lock();
183+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
189184
if (isValidId(id))
190185
{
191-
_targetPosition[id-1] = angleToPosition(angle);
192-
_targetSpeed[id-1] = speed;
186+
_targetPosition[idToArrayIndex(id)] = angleToPosition(angle);
187+
_targetSpeed[idToArrayIndex(id)] = speed;
193188
if (_positionMode==PositionMode::IMMEDIATE) {
194189
writeWordCmd(id, REG(SmartServoRegister::TARGET_POSITION_H), angleToPosition(angle));
195190
}
196191
}
197-
mutex.unlock();
198192
}
199193

200-
float SmartServoClass::getPosition(uint8_t const id) {
201-
mutex.lock();
194+
float SmartServoClass::getPosition(uint8_t const id)
195+
{
196+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
202197
float ret = -1;
203198
if (isValidId(id))
204-
ret = positionToAngle(readWordCmd(id, REG(SmartServoRegister::POSITION_H)));
205-
mutex.unlock();
206-
return ret;
199+
return positionToAngle(readWordCmd(id, REG(SmartServoRegister::POSITION_H)));
207200
}
208201

209-
void SmartServoClass::center(uint8_t const id, uint16_t const position) {
210-
mutex.lock();
202+
void SmartServoClass::center(uint8_t const id, uint16_t const position)
203+
{
204+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
211205
writeWordCmd(id, REG(SmartServoRegister::CENTER_POINT_ADJ_H), position);
212-
mutex.unlock();
213206
}
214207

215-
void SmartServoClass::synchronize() {
216-
mutex.lock();
208+
void SmartServoClass::synchronize()
209+
{
210+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
217211
_txPacket.id = 0xFE;
218212
_txPacket.length = MAX_TX_PAYLOAD_LEN;
219213
_txPacket.instruction = CMD(SmartServoOperation::SYNC_WRITE);
@@ -229,117 +223,116 @@ void SmartServoClass::synchronize() {
229223
_txPacket.payload[index++] = _targetSpeed[idToArrayIndex(i)];
230224
}
231225
sendPacket();
232-
mutex.unlock();
233226
}
234227

235-
void SmartServoClass::setTorque(bool const torque) {
236-
mutex.lock();
228+
void SmartServoClass::setTorque(bool const torque)
229+
{
230+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
237231
writeByteCmd(BROADCAST, REG(SmartServoRegister::TORQUE_SWITCH), torque ? 1 : 0);
238-
mutex.unlock();
239232
}
240233

241-
void SmartServoClass::setTorque(uint8_t const id, bool const torque) {
242-
mutex.lock();
234+
void SmartServoClass::setTorque(uint8_t const id, bool const torque)
235+
{
236+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
243237
writeByteCmd(id, REG(SmartServoRegister::TORQUE_SWITCH), torque ? 1 : 0);
244-
mutex.unlock();
245238
}
246239

247-
void SmartServoClass::setTime(uint8_t const id, uint16_t const time) {
248-
mutex.lock();
240+
void SmartServoClass::setTime(uint8_t const id, uint16_t const time)
241+
{
242+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
249243
writeWordCmd(id, REG(SmartServoRegister::RUN_TIME_H), time);
250-
mutex.unlock();
251244
}
252245

253-
void SmartServoClass::setMaxTorque(uint16_t const torque) {
254-
mutex.lock();
246+
void SmartServoClass::setMaxTorque(uint16_t const torque)
247+
{
248+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
255249
writeWordCmd(BROADCAST, REG(SmartServoRegister::MAX_TORQUE_H), torque);
256-
mutex.unlock();
257250
}
258251

259-
void SmartServoClass::setMaxTorque(uint8_t const id, uint16_t const torque) {
260-
mutex.lock();
252+
void SmartServoClass::setMaxTorque(uint8_t const id, uint16_t const torque)
253+
{
254+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
261255
writeWordCmd(id+1, REG(SmartServoRegister::MAX_TORQUE_H), torque);
262-
mutex.unlock();
263256
}
264257

265-
void SmartServoClass::setID(uint8_t const id) {
266-
mutex.lock();
258+
void SmartServoClass::setID(uint8_t const id)
259+
{
260+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
267261
writeByteCmd(BROADCAST, REG(SmartServoRegister::ID), id);
268-
mutex.unlock();
269262
}
270263

271-
void SmartServoClass::engage(uint8_t const id) {
272-
mutex.lock();
264+
void SmartServoClass::engage(uint8_t const id)
265+
{
266+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
273267
writeByteCmd(id, REG(SmartServoRegister::TORQUE_SWITCH), 0x1);
274-
mutex.unlock();
275268
}
276269

277-
void SmartServoClass::disengage(uint8_t const id) {
278-
mutex.lock();
270+
void SmartServoClass::disengage(uint8_t const id)
271+
{
272+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
279273
writeByteCmd(id, REG(SmartServoRegister::TORQUE_SWITCH), 0);
280-
mutex.unlock();
281274
}
282275

283-
bool SmartServoClass::isEngaged(uint8_t const id) {
284-
mutex.lock();
276+
bool SmartServoClass::isEngaged(uint8_t const id)
277+
{
278+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
285279
int ret = readByteCmd(id, REG(SmartServoRegister::TORQUE_SWITCH));
286-
mutex.unlock();
287280
return ret != 0;
288281
}
289282

290-
void SmartServoClass::setStallProtectionTime(uint8_t const time) {
291-
mutex.lock();
283+
void SmartServoClass::setStallProtectionTime(uint8_t const time)
284+
{
285+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
292286
writeByteCmd(BROADCAST, REG(SmartServoRegister::STALL_PROTECTION_TIME), time);
293-
mutex.unlock();
294287
}
295288

296-
void SmartServoClass::setStallProtectionTime(uint8_t const id, uint8_t const time) {
297-
mutex.lock();
289+
void SmartServoClass::setStallProtectionTime(uint8_t const id, uint8_t const time)
290+
{
291+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
298292
writeByteCmd(id, REG(SmartServoRegister::STALL_PROTECTION_TIME), time);
299-
mutex.unlock();
300293
}
301294

302295
void SmartServoClass::setMinAngle(uint16_t const min_angle)
303296
{
304-
mutex.lock();
297+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
305298
writeWordCmd(BROADCAST, REG(SmartServoRegister::MIN_ANGLE_LIMIT_H), min_angle);
306-
mutex.unlock();
307299
}
308300

309301
void SmartServoClass::setMinAngle(uint8_t const id, uint16_t const min_angle)
310302
{
311-
mutex.lock();
303+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
312304
writeWordCmd(id, REG(SmartServoRegister::MIN_ANGLE_LIMIT_H), min_angle);
313-
mutex.unlock();
314305
}
315306

316307
void SmartServoClass::setMaxAngle(uint16_t const max_angle)
317308
{
318-
mutex.lock();
309+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
319310
writeWordCmd(BROADCAST, REG(SmartServoRegister::MAX_ANGLE_LIMIT_H), max_angle);
320-
mutex.unlock();
321311
}
322312

323313
void SmartServoClass::setMaxAngle(uint8_t const id, uint16_t const max_angle)
324314
{
325-
mutex.lock();
315+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
326316
writeWordCmd(id, REG(SmartServoRegister::MAX_ANGLE_LIMIT_H), max_angle);
327-
mutex.unlock();
328317
}
329318

330-
void SmartServoClass::getInfo(Stream & stream, uint8_t const id) {
319+
void SmartServoClass::getInfo(Stream & stream, uint8_t const id)
320+
{
331321
uint8_t regs[65];
332322
memset(regs, 0x55, sizeof(regs));
333323
int i = 0;
334-
mutex.lock();
335-
while (i < sizeof(regs)) {
336-
if ((i > 29 && i < 40) || (i > 48 && i < 56)) {
337-
i++;
338-
continue;
324+
325+
{
326+
mbed::ScopedLock<rtos::Mutex> lock(_mtx);
327+
while (i < sizeof(regs)) {
328+
if ((i > 29 && i < 40) || (i > 48 && i < 56)) {
329+
i++;
330+
continue;
331+
}
332+
regs[i++] = readByteCmd(id, i);
339333
}
340-
regs[i++] = readByteCmd(id, i);
341334
}
342-
mutex.unlock();
335+
343336
stream.println("regs map:");
344337
for (i = 0; i < sizeof(regs); i++) {
345338
stream.println(String(i, HEX) + " : " + String(regs[i], HEX));

src/lib/motors/SmartServo.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class SmartServoClass
2121

2222
SmartServoClass(RS485Class & RS485);
2323

24-
int begin();
24+
void begin();
2525
void end();
2626

2727
inline void setPositionMode(PositionMode const mode) { _positionMode = mode; }
@@ -86,7 +86,7 @@ class SmartServoClass
8686
static int constexpr MAX_POSITION = 4000;
8787

8888
inline bool isValidAngle(float const angle) { return ((angle >= 0.0f) && (angle <= MAX_ANGLE)); }
89-
inline bool isValidId(int const id) const { return ((id >= MIN_MOTOR_ID) && (id <= MAX_MOTOR_ID)); }
89+
inline bool isValidId(int const id) const { return ((id >= MIN_MOTOR_ID) && (id <= MAX_MOTOR_ID)) || (id == BROADCAST); }
9090

9191
int calcChecksum ();
9292
void sendPacket ();
@@ -106,6 +106,7 @@ class SmartServoClass
106106
RS485Class& _RS485;
107107
int _errors;
108108
mbed::Callback<void()> _onError;
109+
rtos::Mutex _mtx;
109110

110111

111112
struct __attribute__((packed)) {
@@ -121,8 +122,6 @@ class SmartServoClass
121122
uint16_t _targetPosition[NUM_MOTORS];
122123
uint16_t _targetSpeed[NUM_MOTORS];
123124
PositionMode _positionMode;
124-
125-
rtos::Mutex mutex;
126125
};
127126

128127
#endif // _SMARTMOTOR_H_

0 commit comments

Comments
 (0)