Hi, I’ve got two Inventor HAT Minis connected to four N20 motors via JST SH cables. I’ve changed the I2C address on one to 0x16 and disabled the User and I2C pins on the second to avoid GPIO conflicts. All four motors work as expected in both example scripts and my own code when setting their speed.
When using an example script like velocity_control.py with an encoder and PID controller (that’s just using the one default HAT), the motors move but no ticks seem to register on the encoders. Printing a Capture result is all zeros. Adding a print statement to the __take_reading() method in ioexpander/encoder.py returns zeros for raw_count, raw_change, and self.local_count.
So while the motor is moving my print outputs look like this:
I have two of those motors, with encoders, but mine are connected to an Inventor 2040 W (Pico W Aboard). It’s been a while since I’ve tinkered with it, but I do remember struggling with the encoders. @ZodiusInfuser helped me get it all sorted out and working. Lets see what he has to say.
Thanks, yes, I saw your earlier post in the Forum and was trying to glean any details, especially given that most of the implementation for the Inventor HAT Mini is actually within the IOE library.
I did find one strange thing I thought to mention: if I instantiate the InventorHATMini from within the script that starts the process, things work as expected. I tried embedding that same declaration within my own MotorController class and it no longer worked. I.e., there were no errors, but neither did the motors move. My solution was to declare the object and pass it into the MotorController’s constructor, which works. I find that rather hard to fathom, and it may be related to the encoder issue, no idea (since I can’t explain the above).
You lost me with that info. I was happy enough to get mine working the way I wanted. Even though I didn’t, and still don’t, understand how it does it. ;)
I usually understand the electronics, but get lost in the code.
Sorry, my target here are the Pimoroni developers of the library, who clearly understand what I’m talking about.
But in brief, the Inventor HAT Mini is based around the same Nuvoton MS51 chip that’s in the IO Expander, so it utilitises the IO Expander’s library, which also serves as a foundation for other MS51-based products like their Weather HAT, RGB Potentiometer and RGB Encoder.
In fact, I was somewhat surprised to learn that the support classes for things like Motor and Encoder for the Inventor HAT Mini aren’t in its library but in the IO Expander’s library. The justification is that people might use things like motors from these other MS51-based Pimoroni products.
FYI, the MS51 (AKA MCS-51) is an 8051-compatible 8 bit microcontroller, an architecture that was originally designed back in 1980 but is still (with performance and many other improvements) still being actively used a lot in industry, and someone at Pimoroni clearly saw its value.
Now, the RP2040 is being used by Pimoroni in a similar fashion such as the Inventor 2040 or the Yukon, but their support libraries aren’t based on the IO Expander given they’re not using an MS51 chip (i.e., the IOE library is CPython for the Pi, whereas the RP2040 is a microcontroller whose libraries are C/C++ and MicroPython).
From your descriptions, nothing immediately comes across as incorrect with the code. Did you try the read_encoders.py example and get the same results?
If values are not changing with that example, it could be a hardware problem or incompatibility. Have you got any scoping tools you can hook up to your encoders to confirm they are producing a signal? I know you’re using Pololu encoders rather than our MMME, so perhaps they require pull-ups / pull-downs on the signal lines to produce a pulse (which our MMME’s do not)? Or it could be that the magnet is too far away from the encoders for a signal to be picked up.
If the encoders are absolutely producing a signal then that either means the signal is not getting to the IHM or it is a code issue (but again, nothing seems incorrect there).
You’re correct that I’m using Pololu N20 motors (#5197) with the encoders already attached (and under a small black plastic shell). Pimoroni and Sparkfun both have their board connections reversed from what Pololu use, so I had to take a sharp object and de-pin all of the JST SH cables to reverse the wires at one end. But from the schematics it seems that they’re simply a direct swap so this should not be the issue. Given the motors actually work is hopefully proof of this.
I ran read_encoders.pyand spun the wheels by hand, but did not see any evidence of the encoders reading any ticks. In my instrumented copy of the library I’m still seeing:
__take_reading: raw count: 0; change: 0; local_count: 0
Given the motors are brand new and the encoders were installed by Pololu I’m not thinking this is a hardware problem, more likely some kind of incompatibility. I couldn’t find anything about whether pull-ups or pull-downs are required, though from the Encoder schematic diagram on page 3 it appears they have a 10K pullup.
I’m sure resolving this would be helpful for everyone else using Pololu N20 motors, which are very popular in the hobby market.
At this point I would start re-checking your assumptions. Yes, you can drive the motor, but that has no relation to whether the encoder is powered and working. They’re completely separate circuits.
If I was personally encountering this issue I would assess the following:
Does the Pololu motor work in isolation? I.e. if I provide 3v3 and GND to the encoder, do I see the voltage of A and B change as I turn the motor slowly, if I probe it with a Multimeter
Did I actually swap the wiring correctly? I’d post pictures for other people to see too, as they may be able to spot something I have not.
Do I see signals on A and B when plugged in and powered by the Inventor HAT Mini, if I probe it with a Multimeter via the exposed pins on the rear of IHM’s connectors (can be difficult)
Are all my motors affected or is it just one? Are all the IHM ports affected or just one?
If I was able to answer all of those favourably, then that confirms its either a software or hardware issue with the Inventor HAT Mini, and I’d reach out to support@pimoroni.com for help or a replacement, explaining the diagnosing I had just done.
Yes, I understand there are effectively two separate circuits, the motor (M+ and M-) and the pair of encoders (Vcc, GND, A and B).
The reason I’m certain that the motors working proves the base assumption of the wiring being okay is as follows. After reversing the cables, comparing the wires this is how they match:
Pololu IHMini
Red: M1 MP
Black: M2 MN
Blue: Vcc 3V3
Yellow: A A
White: B B
Green: GND GND
This is as according to the respective schematics from Pololu (as already posted above) and Pimoroni’s Inventor HAT schematic.
I have confirmed that I swapped the wires exactly as reversed, on all four motors (I have a pair of Inventor HATs on this robot). I was particularly meticulous about this when I de-pinned and re-pinned the cables as I knew once the robot was assembled it would be really difficult to gain access to them, since the motors are underneath everything else. The ones on the front of the robot are at least visible:
The order of the wires is: red-black-blue-yellow-white-green at one end, and the exact reverse of that at the other. Attached are photos at each end. You can see the motor side is reversed (i.e., the motors have some visible markings on them and the wire colors are backwards, e.g., green is now M1/M+ rather than GND).
The big problem with these JST SH cables is it’s pretty much impossible to intercept signals between the connector on the HAT and the motor unless I were to cut the wires, and unfortunately the HAT only provides Dupont connectors for M1 and M2, not the encoders. I do have the wiring harnesses from before I swapped out some older motors for these newer, more powerful ones so I may be able to rig up a harness with some kind of intercept in the middle.
I’ve tried this on all four motors and they’re all the same.
I’ve not tried your first bullet point yet, so I’ll try to wire up a test rig. I may be able to do this without dissembling the robot, which at this point is a lot of time. I can provide Vcc and GND and then wire A and B either to GPIO pins or to the scope and then spin the motors.
Thanks for your input on this. Hopefully I can sort out what’s going on here.
Well, I’ve rigged up a direct connection between the encoder A and B pins to two GPIO pins on the Pi, and when manually spinning the motor I can see the pulses on those pins. So I’ve confirmed that there’s no issue with the encoders: if they’re provided with power they will return pulses as expected.
I’ve then reconnected the Inventor HAT Mini to the motors and ran a modified read_encoders.py script that turns on the motors, and I’m just not seeing any ticks from the encoders at all. I’ve confirmed that the GND and Vcc wires from the motors are connected to the correct pins on the HAT (pins 1 and 4, green and blue resp.), with A (pin 3, yellow) and B (pin 2, white) as per the photo I posted.
It would really help if someone could clarify (for once) what exactly is the pinout, not on the schematic, but as the pins appear on the HAT when viewed from above:
Interesting! Thank you for testing that. So the encoders are fine (yes I know you said that before but this is actual evidence), but there’s still unknowns whether the signals are not getting to the IHM or if the IHM firmware/software is not behaving correctly.
Unless I missed it (quite likely!), I don’t believe you specifically asked for a picture of the physical pinout before. Anyway, here you go:
If that works, then that points to the firmware/software of IHM being correct, but there being an electrical issue between the motors and IHM (either in the cable, or in the PCB itself)
If that does not work, then that is certainly a firmware/software issue, though I honestly could not tell you what would be failing there if the program is not returning any error. Incorrectly flashed at our factory?? I don’t know.
That would be a case of reach out to support for a replacement, and to return your current units so I can test them personally. It may also be worth getting our cables bundled in at the same time too.
Thanks, that clarifies I am at least using the right pins. This will clearly take a bit more time to debug. I’ve ordered some Delrin plastic to replace the lower 3mm plate on the robot with a 5mm plate, so that will require deconstructing much of the robot, which will be a good time to isolate a single Inventor HAT Mini.
Before the plastic arrives I was trying out hooking a TinyFX to an IO Expander via the former’s Qwiik connector (something I’ve done on a previous robot), and I noted that the IOE constructor that was called for that is not the same one as for the Inventor HAT Mini (I’d added print statements to each so I could tell).
Given the strange behaviour of the board needing to be created in the starting script rather than in a class (which I’ve described before, i.e., I pass board into the class as a workaround), I’m wondering if there’s some clue there. The Encoders are clearly getting created and I can see the loop running, but there just isn’t anything happening in terms of the A/B signals actually getting read. I’m just wondering if there’s some weirdness where the actual instances of the class I’m calling aren’t the instances being created and used. Or something strange like that…
I’ll hopefully in the next few days get the plastic and can try an isolated experiment with a fresh SD card, a Pi Zero and just a single Inventor HAT Mini.