For those interested in controlling stepper motors (and servos) remotely over I2C, you might be interested in hearing that I just released the AccelStepperI2C library at https://github.com/ftjuh/AccelStepperI2C.
From the readme:
This is an I2C wrapper for Mike McCauley's AccelStepper library with support for two end stops per stepper and optional servo support. It consists of an Arduino-based firmware for one or more I2C-slaves, and corresponding Arduino libraries for the I2C-master. Think of it as a more accessible and more flexible replacement for dedicated I2C stepper motor controller ICs like AMIS-30622, PCA9629 or TMC223 with some extra bells and whistles. Use it with your own hardware or with a plain stepper driver shield like the Protoneer CNC GRBL shield (recent V3.51 or V3.00 clone).
The firmware has been tested on ATmega328 Arduino (Uno, Nano etc.), ESP8266 and ESP32 platforms.
The firmware uses a state machine, i.e. it runs AccelStepper locally, so that the I2C bus is kept free from constant polling traffic needed in other solutions.
This is my first major peace of software released to the public and I am neither an experienced nor avid c++ programmer, so I welcome any feedback.
The I2C bus is weak, it often fails when motors are involved.
There is a delay of 50 ms before the next I2C sessions starts ? Did you try it with 1 ms ?
This will fail during a rollover:
now = millis();
if (now > then)
Have you seen the source code of millis() and what its return is ? That is a "unsigned long", yet you use "uint32_t". I suggest to stick to the documentation.
"### needed?" No, you don't need to clear the I2C buffers. The Wire library uses packages of data, it is not a stream. I call clearing buffers: common problem #4
In the loop(), the ProcessMessage() is called, which could call WriteOutputBuffer() which could call Wire.slaveWrite(). I'm not sure what is going no, but that should not happen.
-1-
There are a number of projects with the I2C bus and motors lately on the forum that have a hard time with the weak I2C bus. I thought I just mention that the I2C bus is weak.
-6-
I think the Wire.slaveWrite() should only be used in the onRequest handlers.
But I have to admit that I did not carefully check your code. I saw the Wire.slaveWrite() and I noticed a path from the loop() to that function.
I did not encounter any problems that I'd attribute to that during my tests. I'm sure, though, that I didn't do them under particularly stressful conditions.
Far from an expert here, but I assume that a proper electrical design should be able to alleviate a lot of these kind of problems.
You are right about the path, but note that I did that only for the ESP32 code. It's slave implementation, which has been added only recently to the Arduino code base, is different. It needs the buffer prefilled before the request happens, at least that's what I deducted from Expressif's slightly unclear documentation and my own tests.
Added pin control support (PinI2C.h and PinI2C.cpp) for reading and writing unused slave pins.
Restructured folder layout to prepare for submission as third party library to the Arduino library manager.
fixed I2Cdelay, which would not work correctly with debugging disabled. Also, shortened the default I2C delay to 10 ms (which still is a conservative default)
I filed a removal pull request today, so that I expect it to be removed from the Arduino library manager soon.
AccelStepperI2C has been replaced by the more powerful and versatile the I2Cwrapper project (see this thread). AccelStepperI2C and ServoI2C are still available as modules in the new project, so any transition should be seamless.