DIY I²C motor driver with Arduino

Community-Firmware (cfw), Selbstbaucontroller (TX-Pi, ftduino, usw.), usw.
Forumsregeln
Bitte beachte die Forumsregeln!
Benutzeravatar
rubem
Beiträge: 112
Registriert: 10 Feb 2014, 17:45
Wohnort: Porto Alegre, RS, Brasil

Re: DIY I²C motor driver with Arduino

Beitrag von rubem » 09 Mai 2021, 18:04

Off-topic here:
rubem hat geschrieben:
09 Mai 2021, 17:42
I suspect the forum shrinks files above a certain size. For some unknown reason it does not accept WEBPs (way smaller than PNGs) or SVGs (vector format).
For comparison, here are various files as exported from Fritzing, all with the same schematic. The WEBP was exported as a lossless image from the PNG, I used IrfanView for it. As you can see, the smaller ones are the SVG and WEBP, but unfortunately they are not allowed.

explorer_2021-05-09_13-02-41.png
explorer_2021-05-09_13-02-41.png (7.2 KiB) 529 mal betrachtet

Enough off-topic for me today :)

Benutzeravatar
rubem
Beiträge: 112
Registriert: 10 Feb 2014, 17:45
Wohnort: Porto Alegre, RS, Brasil

Re: DIY I²C motor driver with Arduino

Beitrag von rubem » 20 Mai 2021, 19:14

Hi everyone,

Here's my second version of the motor driver prototype on a perfboard. I gave up on the first version, I was planning a 45 x 30 form factor with a "sandwich" layout where the Arduino and the driver would go under the connector board. But it wouldn't work, the assembly was too complicated and error-prone. With 60 x 45 I have more room and soldering is kept simple.

Prototype.jpg
Prototype.jpg (153.53 KiB) 406 mal betrachtet

It's still under construction, I've just wired the power lines... and then realized my layout is potentially destructive: The Arduino has many contact points, and an energized 9V ft plug would fry it at once. At least before I build a housing (and protect the outputs), I'll certainly remove the two 2.5 mm jacks near the LEDs and use only the pin headers to power the unit. Better safe then sorry. I'm not worried about fischertechnik compatibility, and it seems I'm in good company.

Best regards from (chilly) Southern Brazil,

Rubem

juh
Beiträge: 572
Registriert: 23 Jan 2012, 13:48

Re: DIY I²C motor driver with Arduino

Beitrag von juh » 23 Mai 2021, 23:50

Deutsch: Ich stelle eine firmware in Entwicklung vor, die für unterschiedliche Microcontroller und Hardware-Kombinationen genutzt werden kann, um (z.B. per I2C, WiFi, BT etc.) ferngesteuerte Motorcontroller mit Drehwertgeber/Encoder und Endstops zu realisieren, die autonom und mit PID-Regelung Aufgaben wie 'fahre bis X', 'fahre mit Geschwindigkeit Y' etc. erledigen können. Die firmware ist flexibel nutzbar, soll aber natürlich vor allem in ft Lösungen zum Einsatz kommen. Kommentare sind willkommen.

Hi all,

@rubem, your new PCB looks very neat! And I understand only too well why you went for a non sandwiched design. I used one in the (unpublished) Adafruit V2 motor controller shown above, and also here, and things tend to become very complex and tangled up soon with these designs.

A bit of an update on my own progress. After having finished my hardware tests, I've been working on the firmware the last couple of weeks.

The discussion we've had here and my prior attempts at this issue tell me that the general idea (µC + encoder + motor driver + endstops + remote control) is quite a universal one. So I realized I'd find it unsatisfactory to develop one specific solution for one specific hardware setup.

Wouldn't it be nice to have a firmware framework that could be adapted to different microprocessors, motor drivers, rotary encoder, endstop setups, and interfaces?

This is the concept that emerged under the acronym "QPID". The goal is to have a generic, adaptable firmware prototype which provides
  • up to 16 "QPID" units,
  • with each QPID unit consisting of one motor driver, one rotary sensor, and up to two endstops,
  • with each QPID unit being able to autonomously perform PID controlled tasks like running to a given position, running at a given speed for some time or until told otherwise, finding endstops, self-calibration etc.,
  • generic way of remote access usable by any kind of interface (I2C, ISP, ESP-now, Bluetooth...)
  • flexible configuration of pin assignments, hardware setup etc. via interface
Problem is, this idea calls for an objective oriented design, which led my to overcome my frustration with c++ and have another look on how it's done there (and yes, I still think that it's a mess of a programming language, and still oftentimes struggle with its cluttered design).

My approach is to have a class library which abstracts all of the above features into base classes, from which classes representing specific hardware have to be derived. Most of the work is already done, with very little testing yet. And the communication aspect is still in an early stage of development, I chose CBOR encoding to make it as flexible and future proof as possible, too.

This for example is the abstract definition for the most trivial class, the endstop class:

Code: Alles auswählen

class QPID_Endstop : public QPID_Object {
  public:
    virtual bool isOn();  ///< true if switch currently activated
    virtual bool processMessage(uint8_t *m);
};
All it defines is an abstracted access to the endstop's state (on or off).

This is its derived class "QPID_Digital_Endstop" which implements the simple case that each endswitch has its own input pin:

Code: Alles auswählen

class QPID_Endstop_Digital : public QPID_Endstop {
  public:
    bool isOn() override;
    bool processMessage(uint8_t *m) override;
    void init(int8_t switchPin, bool useInternalPullup, bool activeHigh);
  private:
    int8_t pin;
    bool activeLow;
};
As we don't want to hardcode the configuration into the firmware and leave it up to the master to tell the system what setup to use, all configuration will usually be done after the object's creation via the message system. That's why I don't use constructors, but an init() method for initial configuration. The message system is implemented by the processMessage() method that interprets messages handed down by the main system locally at the subclass level.

The object oriented design allows to easily add other endstop types, e.g. pinshared analog or hooked up to an I2C port expander. It could also be used to implement debouncing, hysteresis etc. without having to tinker with the overall system. Motor drivers and rotary encoders follow the same pattern. This enables maximum flexibility hardwarewise.

As I feel it is too early to share the code, I uploaded the doxygen documentation here. This is the current class diagram with two kinds of motor drivers, two kinds of encoders, and two kinds of endstops already implemented:

Bild

The QPID-Unit is where to main work is happening. It bundles one motor driver, one encoder and up to two endstops objects and is internally controlled by a state machine which performs the currrent task it has received by a command either by a direct function call or via communication interface:

Bild

This is my first serious effort in programming a larger project in more than 25 years, so I invite everyone for comments. Particularly I'd be interested if I overlooked some possible use cases in designing the overall system, e.g. in the above commands and states offered by the system.

Best
Jan
Meine fischertechnik Designs für den 3D-Druck: https://www.thingiverse.com/juh/designs

Benutzeravatar
rubem
Beiträge: 112
Registriert: 10 Feb 2014, 17:45
Wohnort: Porto Alegre, RS, Brasil

Re: DIY I²C motor driver with Arduino

Beitrag von rubem » 26 Mai 2021, 16:35

Hi Jan,

Wow, you are really into object-oriented programming now. I pretty much undserstand your frustration with C++, I don't like it either. Fortunately for me, most Arduino code is in fact C, without the OO features. On the other hand there is C#, which is a wonderful language / environment in my opinion, but I don't have a clue if a compiler exists for your platform.

Nevertheless it seems we have somewhat similar goals with our projects, but yours is obviously more ambitious in terms of scope and precision. For example, I've been testing the break function with the ft encoder motors. MoG was right! For the same speed, the motors always stop at the same position, generally only 2-3 extra pulses. The consequence is that I don't need fine speed control or PID, at least for now.

I have been looking at the state diagram you provided and it makes a lot of sense. I'm thinking if there is something I could incorporate in my commands, I'm still working on them. At least you inspired me to update my table which was already obsolete. I know it's hard to read, but not impossible:

chrome_2021-05-26_11-31-41.png
chrome_2021-05-26_11-31-41.png (146.28 KiB) 291 mal betrachtet

Please keep posting your progress here, it's great to see that similar projects are being developed.

Greetings,

Rubem
Zuletzt geändert von rubem am 26 Mai 2021, 16:56, insgesamt 1-mal geändert.

Benutzeravatar
rubem
Beiträge: 112
Registriert: 10 Feb 2014, 17:45
Wohnort: Porto Alegre, RS, Brasil

Re: DIY I²C motor driver with Arduino

Beitrag von rubem » 26 Mai 2021, 16:54

I've converted the table from Google to to .ods. The file is in the repo now:

https://github.com/leosdad/fischertechn ... /main/docs

And here is the direct link to it (OneDrive account required):

https://1drv.ms/x/s!AoEOnU-XO9iY1ssr99u ... Q?e=oYoeLL

Regards,

Rubem

Benutzeravatar
steffalk
ft:pedia-Herausgeber
Beiträge: 1491
Registriert: 01 Nov 2010, 16:41
Wohnort: Karlsruhe
Kontaktdaten:

Re: DIY I²C motor driver with Arduino

Beitrag von steffalk » 26 Mai 2021, 18:26

Hello everybody,

for C# fans wanting to use it on micro controllers: Have a look at https://nanoframework.net/!

Regards,
Stefan

juh
Beiträge: 572
Registriert: 23 Jan 2012, 13:48

Re: DIY I²C motor driver with Arduino

Beitrag von juh » 31 Mai 2021, 17:42

Hi rubem and Stefan,

I decided many years ago that my quality of life has a direct and inverse proportional relationship with the amount of Microsoft I have to suffer, and since I'm doing this in my free time, i fear that C# is neither in provenience nor practice an option for me. :D My hope is that TinyGo will gain traction in the near future, unfortunately ESP support is still very incomplete at the moment.

Rubem, your table is interesting to see (BTW: you can link github downloads directly). Do I understand your idea about the Learn/slot commands correctly? Do you want your controller to run a list of movements independently from memory? I haven't thought about that yet, but of course it would be a nice feature e.g. for exhibition models.

In my project I did some testing of the subunits developed so far. This setup shows a working QPID system with two seperately controlled QPID units:
resized_DSC_3782.JPG
resized_DSC_3782.JPG (106.69 KiB) 204 mal betrachtet
On the right is the geared motor with hall sensor and ESP32 hardware encoder that you already know. On the left is a fischertechnik XS motor and a quadrature encoder with ft switches and "Impulszahnrad". It is driven by an Adafruit MotorshieldV2 via I2C, the encoder could be evaluated with another EPS32 hardware encoder, but for testing it uses a polled quadrature encoder library which could also work on a plain Arduino. Everything works within the QPID framework, which shows that the subunits are in fact completely interchangeable, so for example you could easily update the motor driver to a more powerful one by just adding a new derived MotorDriver class to the system.

PID, in fact, would be overkill for a slow and clumsy unit like the ft one. So I'll probably add motion ramps as an alternative to the PIDs at a later stage. However, PIDs even here could be useful if not positioning, but running at a constant speed is what you need.

Apart from that I'm working on the interface, which proves to be a bit more complex than the previous steps. I abstracted two very different protocols, I2C and ESPnow, into a common callback system, so things look quite promising, too. Ressources could become a problem though. The ESP32 still has ample flash and RAM left, but to run on an Arduino the system will probably need to be much more optimized, sth I don't have a lot of experience atm.

Cheers
Jan
Meine fischertechnik Designs für den 3D-Druck: https://www.thingiverse.com/juh/designs

Benutzeravatar
rubem
Beiträge: 112
Registriert: 10 Feb 2014, 17:45
Wohnort: Porto Alegre, RS, Brasil

Re: DIY I²C motor driver with Arduino

Beitrag von rubem » 01 Jun 2021, 23:01

Hi Jan,
juh hat geschrieben:
31 Mai 2021, 17:42
Do I understand your idea about the Learn/slot commands correctly? Do you want your controller to run a list of movements independently from memory? I haven't thought about that yet, but of course it would be a nice feature e.g. for exhibition models.
The idea here is to store up to eight positions per encoder motor. I want the motor driver to keep track of the current position for each motor so that the main controller (e.g. micro:bit) will be able to use only high-level commands like GoToNextPosition or GoToPosition, for example. I admit there is currently some confusion between the terms slot, position and index, but I'll eventually address this. The main controller is still responsible for consuming events and issuing commands to the motor driver.
In my project I did some testing of the subunits developed so far. This setup shows a working QPID system with two seperately controlled QPID units...
Great! I don't have much to say, but it's nice to see things are evolving well on your side. And now I see PID is also not needed for my project.
Apart from that I'm working on the interface, which proves to be a bit more complex than the previous steps...
Arduino code can be quite compact, but optimization requires time. Ambitious goals require more complexity :) Anyway I'm assuming you'll not be using Arduinos, so lack of resources shouldn't be a problem for you...

Greetings,

Rubem

Antworten