For @runger mainly I guess but I thought I’d ask here in case it’s useful for others. Is there any example code? Or could someone help me edit the above file?
I took a quick look, and am a bit confused as to what’s going on…
Are you trying to replace the motor driver, with I2CCommander being used to receive commands, or the central MCU, with I2CCommander sending commands?
Or both, I guess?
To add a basic instance of I2CCommander, once the library is included in the project, you can have code similar to this:
#include "SimpleFOCDrivers.h"
#include "comms/i2c/I2CCommander.h"
// commander instance
uint8_t i2c_addr = 0x60; // can be anything you choose
I2CCommander commander;
// interrupt callbacks
void onReceive(int numBytes) { commander.onReceive(numBytes); }
void onRequest() { commander.onRequest(); }
// ... other variables, like sensor, etc...
BLDCMotor motor = BLDCMotor(POLE_PAIRS);
void setup() {
// ...other setup code
Wire.setClock(400000); // use same speed on controller device
Wire.begin(i2c_addr, true); // initialize i2c in target mode
commander.addMotor(&motor); // add a motor
//commander.addMotor(&motor2); // you could add more than one motor
commander.init(i2c_addr); // initialize commander
Wire.onReceive(onReceive); // connect the interrupt handlers
Wire.onRequest(onRequest);
}
It’s not so hard to use. The integration and initialisation of BLDCMotor and making it all run on SimpleFOC instead of whatever it was using before will be more work I think.
Note that each motor driver needs its own I2C address if they’re to be connected to the same bus…
I didn’t look much into Linobot, but I assume it is supposed to communicate with ROS via serial comm (I can see that the arduino code is reading topics directly).
Linobot MCU receives commands via serial from ROS and commands the motor drivers via pwm.
How exactly are you integrating simplefoc in linobot code?
From my understanding, you just integrated simplefoc in the linobot code to run it all on the same MCU, and I am sorry to say this, but you will most probably have very poor performance if that’s the case (serial comm will mess up your loop timings).
For optimal performance, you would need to run SimpleFoc on a separate MCU. You could send I2C commands to simplefoc mcu via I2C instead of PWM.
In that scenario, you would need to rewrite the part of the code that is sending pwm to motor drivers to send I2C commands to simplefoc instead.
I would do it this way, but it depends on what are you building. A fast RC car commanded from ROS will probably suffer from low speed I2C, but for a slow moving platform, I2C will be enough. Just be careful to stop it if any of the communication protocols fails - or you will crash and destroy whatever you are making.
If you need more reliable and faster communication between main MCU and SimpleFOC, you probably should not go for I2C.
Gotcha! The brain code is actually much simpler. What you’ve got at the moment is the receiving side, so that isn’t right. Sorry I sent the wrong example for your case.
On the sending side on the ESP32, you want something more like this:
#include <SimpleFOC.h>
#include "SimpleFOCDrivers.h"
#include "comms/i2c/I2CCommanderMaster.h"
// our RosmoESC's address...
#define TARGET_I2C_ADDRESS 0x60
// global instance of commander - controller device version
I2CCommanderMaster commander;
void setup() {
// slow start - give RosmoESC a chance to boot up, serial to connect, etc...
delay(1000);
// this is a debug setup so initialize and wait for serial connection
Serial.begin(115200);
while (!Serial);
while (!Wire.begin(21, 22, 100000)) { // standard wire pins for ESP32 PICO Kit v4
Serial.println("I2C failed to initialize");
delay(1000);
}
commander.addI2CMotors(TARGET_I2C_ADDRESS, 1); // only one motor in my test setup
commander.init();
Serial.println("I2C Commander intialized.");
}
Then in your remaining code, you can make calls like:
uint8_t status[4];
int numRead = commander.readRegister(0, REG_STATUS, status, 4); // 0 is the motor number
if (commander.writeRegister(0, REG_TARGET, &targetSpeed, 4)!=4) { // 0 is the motor number
// TODO handle I2C error
}
and things like that.
But you’ll have to consider the control architecture of the robot, its actually not simple. We can have a chat about it sometime.
For the moment you can just get rid of all the motor initialisation stuff, and replace the functions forward() and backward() with implementations that set the target speed via I2C…
I’m currently playing with some code for ESP32 (I2C master) the existing code provides a hotspot & webui for controlling a car using a simple UART protocol
I have it compiling with SimpleFOC using Platformio. In the code I’ve commented out the //original UART code and noted where I need //I2C version:
I sent a pull-request on GitHub - I cleaned it up a bit and fixed the I2CCommander related code, but not knowing the details of the web socket protocol it doesn’t make much sense to me as it is… direction_1 and direction_2 are sent in parallel? What’s the intent? As is, the code would always process direction_2 after direction_1, and whatever comes in direction_2 would effectively set the motors. So as is the options would be L, R and stop, and U and D would just be ignored…