@@ -23,21 +23,6 @@ void I2CCommander::addMotor(FOCMotor* motor){
2323
2424
2525
26- I2CCommander_Motor_Status I2CCommander::getMotorStatus (uint8_t motorNum){
27- if (motorNum<numMotors){
28- if (motors[motorNum]->zero_electric_angle ==NOT_SET) // TODO detect open-loop uninitialized state!
29- return I2CCommander_Motor_Status::MOT_UNINITIALIZED;
30- if (motors[motorNum]->enabled ==0 )
31- return I2CCommander_Motor_Status::MOT_DISABLED;
32- if (motors[motorNum]->shaft_velocity >= I2CCOMMANDER_MIN_VELOCITY_FOR_MOTOR_MOVING)
33- return I2CCommander_Motor_Status::MOT_MOVING;
34- return I2CCommander_Motor_Status::MOT_IDLE;
35- }
36- return I2CCommander_Motor_Status::MOT_UNKNOWN;
37- };
38-
39-
40-
4126
4227bool I2CCommander::readBytes (void * valueToSet, uint8_t numBytes){
4328 if (_wire->available ()>=numBytes){
@@ -85,7 +70,17 @@ void I2CCommander::onRequest(){
8570
8671
8772
73+ /*
74+ Reads values from I2C bus and updates the motor's values.
75+
76+ Currently this isn't really thread-safe, but works ok in practice on 32-bit MCUs.
8877
78+ Do not use on 8-bit architectures where the 32 bit writes may not be atomic!
79+
80+ Plan to make this safe: the writes should be buffered, and not actually executed
81+ until in the main loop by calling commander->run();
82+ the run() method disables interrupts while the updates happen.
83+ */
8984bool I2CCommander::receiveRegister (uint8_t motorNum, uint8_t registerNum, int numBytes) {
9085 int val;
9186 float floatval;
@@ -230,7 +225,23 @@ bool I2CCommander::receiveRegister(uint8_t motorNum, uint8_t registerNum, int nu
230225
231226
232227
228+ /*
229+ Reads values from motor/sensor and writes them to I2C bus. Intended to be run
230+ from the Wire.onRequest interrupt.
231+
232+ Assumes atomic 32 bit reads. On 8-bit arduino this assumption does not hold and this
233+ code is not safe on those platforms. You might read "half-written" floats.
234+
235+ A solution might be to maintain a complete set of shadow registers in the commander
236+ class, and update them in the run() method (which runs with interrupts off). Not sure
237+ of the performance impact of all those 32 bit read/writes though. In any case, since
238+ I use only 32 bit MCUs I'll leave it as an excercise to the one who needs it. ;-)
233239
240+ On 32 bit platforms the implication is that reads will occur atomically, so data will
241+ be intact, but they can occur at any time during motor updates, so different values might
242+ not be in a fully consistent state (i.e. phase A current might be from the current iteration
243+ but phase B current from the previous iteration).
244+ */
234245bool I2CCommander::sendRegister (uint8_t motorNum, uint8_t registerNum) {
235246 // read the current register
236247 switch (registerNum) {
@@ -239,8 +250,7 @@ bool I2CCommander::sendRegister(uint8_t motorNum, uint8_t registerNum) {
239250 _wire->write ((uint8_t )lastcommandregister);
240251 _wire->write ((uint8_t )lastcommanderror+1 );
241252 for (int i=0 ;(i<numMotors && i<28 ); i++) { // at most 28 motors, so we can fit in one packet
242- uint8_t status = (uint8_t )getMotorStatus (i);
243- _wire->write (status);
253+ _wire->write (motors[motorNum]->motor_status );
244254 }
245255 break ;
246256 case REG_MOTOR_ADDRESS:
0 commit comments