I've been struggling a little bit more with the safe mode problems. Even with the capacitors, the battery simply can't give enough current at startup to handle at the same time the servos twitching, the capacitors charging and the microcontroller requiring that minimum 2.7V. The previous robots worked, because I just happened to use better quality servos that twitched less at startup, but I want this design to work with the crappiest and cheapest servos you can find.
Turns out there have been similar problems with CircuitPython on the SAMD51, and now the bootloader for SAMD51 has a loop that pauses execution until the voltage stabilizes over the required threshold. I could port that to SAMD21 as well, but I found an easier solution, and one that will also improve the life of robot on a single battery — simply lower that threshold. SAMD21 can work with voltage as low as 1.6V. CircuitPython defaults to 2.7V because the boards that use an external flash chip require that voltage for the flash to work properly — but I don't have external flash chip on my robots! So I submitted a pull request that allows to change this threshold in the board definition, and I also lowered it for the #PewPew Standalone and #PewPew M4 boards — they will live longer on battery now!
Testing shows that this solves the problem, so now I have to find another excuse to keep avoiding programming those robots.
I haven't written an update in a while, even though a second version of the PCBs already arrived, and the laser-cut parts work very well. The reason for that is: I was struggling with power problems.
For some reason on the new boards CircuitPython goes into a safe mode due to a power dip, and has to be physically reset to continue operation. This is caused by a "twitch" of servos when they get powered up initially, before they get any signal. This is very surprising to me, because previously I have built robots with exactly the same power distribution and with even more servos, and there was never such a problem. Oh well, so I got to figuring it out.
First, the 3.3V line voltage on switching on looks like this:
You can tell it's not great — it goes up to around 3V, then drops to 2.5V and slowly ramps up to 3.3V. This is probably the twitch of the servo motors overwhelming momentarily the battery. The usual solution to that is a beefy capacitor in parallel to the servos, so let's try that. I think 1000µF will be enough?
This makes the voltage curve look much smoother, but there is this capacitor charging now:
Unfortunately, CircuitPython is still going into safe mode, and I have no idea why — there is code in it that is supposed to wait for the voltage to stabilize before proceeding with booting. So I played a little bit more, tried to swap the LDO with the other, working robot, tried to add more capacitors, tried resistors on the servo signal lines, etc. — all for nothing. I noticed that with just 6 servos it works:
But that's just because the voltage drop is a little bit smaller, so I suppose it goes over the safe mode threshold.
I'm beginning to suspect that there was actually a change in the CircuitPython code handling the safe mode, and that the older robots work just because they use an older version of CircuitPython. That should be easy to verify, actually — let's try older version. The working robot uses 5.0.0, so let's try that...
An nope, still goes into safe mode. So what makes the good robot good? Maybe we can look at its voltage curve? Let's see:
Hmm, so it's the same bad curve from the start, only the voltage doesn't quite dip as low. Probably just better quality servos, I suppose?
Elecrow has made both the PCBs and the laser-cut parts, and they have sent it Monday last week. Unfortunately, it seems that DHL has stopped its operations for some reason, because the package is still in "shipment information received" state after 7 days. Because of that I still have nothing to show, maybe except the photo I got from Elecrow when they sent it:
So I spent the weeked mucking about designing PCBs and throwing new features at them, but if I am supposed to ever finish this project, I need to do some actual work on it. So today I tried to stay focused and do the actual steps that need doing. First, a feather-compatible robot would be great, but it's also complex. At first the only thing I will need is I2C, so let's just make a minimal PCB with just that broken out.
Second, all this is pointless if I can't control the servos. So I need to make sure the pins I connected to servo signals actually can do PWM all at once. The easiest way to do it is to just quickly compile a custom CircuitPython firmware with those pins made available, and try it on a Trinket M0. That's exactly what I did, and of course it didn't work. I had to swap two of the eight pins to make them use different timers, so that they can be used all at once. Of course that made the layout a bit less pretty but that's fine.
Once I have figured out which pins will work, I also fixed the feather-compatible schematic. That took considerably more work, since I didn't have any free pins I could switch to, and there were certain requirements for functions available on certain pins. In the end I think I got it, though, so that PCB is fixed as well.
Finally, I need designs for the leg pieces for that small board. Laser-cutting is considerably cheaper than PCBs, and now that I can order it from Elecrow alongside the PCBs, it doesn't make it much more complex. So I had to re-do the legs, but since I want to use the same code, I wanted to keep the same dimensions. So some reverse-engineering of the PCB designs was necessary:
Once I had all the dimensions and shapes figured out, I just had to arrange all the parts on a 10x10cm sheet:
Now both versions of the robot PCB, the Fluff M0 board and the laser-cut parts are on order — the work will continue in a few weeks when they arrive, and in the mean time maybe I can focus long enough to program the walking code.
I have spent the whole Sunday re-doing the PCB design, and then adding battery protection, charging and a speaker with amplifier. It looks like this now:
And then I realized that the puny SAMD21 is not going to have enough memory to make use of this — at the very least I will need external flash. And I might as well switch to the SAMD51 at this point, since it's not that much more expensive. That also gives me more pins, so I can have a proper feather pinout plus all the servos and plus some extra stuff. However, I will need to completely re-do the design for that, so it will probably wait until the next weekend.
I still have no strength to sit down and program a proper gait, but I keep thinking about the mechanical design and having ideas. One thing I'm going to need is some kind of an expansion socket on the front part of the robot, so that I can connect different kinds of sensors, displays, faces, etc. I could simply just have a pin header with all the unused pins broken out randomly, but that's not very convenient. I could have several headers, to match several of the modules I want to be able to connect, but that gets complex fast. Or I could use some kind of a standard footprint — for example the one for Adafruit Feather, so that I can connect FeatherWings to it. But here is a small problem: the Feather M0 uses a larger SAMD21 chip than I was planning to use — does my chip have enough pins to re-create the pinout?
So I went to Adafruit's website, grabbed the schematic they published, and started working:
The answer is yes, you can do it, with only 7 pins that are not available on this chip, but easily replaced with other pins. And you still have 3 pins free!
Unfortunately, I need at least 8 additional pins to control the servos, and they have to be timer-capable pins to do PWM. So either I switch to a chip with more pins (and at this point it would probably be SAMD51, because I already have it in my drawer), or I use some of the pins that are unlikely to be used by the FeatherWings that I need — in this case that would be the analog pins. I would leave the A0 (because it also has DAC), and re-reoute A1-A5 to the servos, which together with the 3 extra pins should be enough. I would need to do some experimenting to see if all of those pins are PWM-capable, and probably swap some of them around if they are not — something that requires more effort than I am ready to spend right now.
Second thing I was thinking about is the mechanical design. I think I figured out how to best attach the servos to the main body of the robot, without needing to solder loops of paperclip wire to the PCB. See those four slots in the PCB? You just need small horizontal bars that go inside them, with holes for the servo screws. They will push against the outer edge of the slots, and the servos will push against each other, and that should give you a pretty solid attachment.
And the next thing — I originally designed this robot to be just a single piece of PCB, that you just break to get all the parts for the legs and body. This way you don't need access to a laser cutter or a 3D printer. But after my experiences with #PewPew M4 I discovered that it is very easy to order your laser-cut parts together with the PCB, and they are so much cheaper than the PCB is! They also are thicker and look better, so there is really no point in using PCB for construction anymore. That brings me to redesigning the legs and the body to be laser-cut, and the PCB to be as small as possible and attached on top.
After several weeks of severe brain underperformance, I finally managed to get the inverse kinematics code for this robot right — so now I can move its legs properly. This encouraged me to work on it some more, so I went ahead and re-arranged the servos to the configuration I want:
Of course the PCB on top will be re-designed and will take the place of the yellow PCB in between the servos, with the battery on the back, and maybe a sensor and/or some LEDs on the front. The connectors for the servos will be at the bottom, so there will be fewer visible cables as well.
The servos are bolted to loops made out of paperclips soldered into the PCB, but I'm not entirely sure how I will solve this in the final version.
It's been a while since I worked on this — I've been busy with #PewPew M4, though I did update the #SpiderWing and test the battery protection circuit there. But I never finished the SAMD51 version of the PCB for Kubik M4, and it has been on the back burner.
Most recently, however, I realized something: the Kubik M0 PCB doesn't have to be a failure after all. Well, of course, if I wasn't terribly lazy I could write a servo library for the CircuitPython that handles 12 servos with a timer interrupt and use that — the microcontroller is easily fast enough to do it — but that would require effort. But I thought about something else: I have a version of the walking quadruped that doesn't need 12 servos — #Katka, a mammalian robot only needs 8. Sure, turning is a bit of a challenge, but I could totally re-use the Kubik M0 PCB to build a Katka M0. So I went ahead and did it:
The four hip servos went away, and I instead attached the knee servos directly to the PCB, making them the new hips. I think I will try to program it to walk in the configuration shown on the photo, even though it could also easily walk in a more mammal-like posture, with the knees below the hips. But I want it too still look a bit like a spider or insect, so I will go with this.
Of course I can't re-use the code I had for Kubik anymore, so I will also get to re-write the whole walking thing in a cleaner way, possibly using async functions. The inverse kinematics should now be much simplified, and also the cost of the whole device dropped by roughly 1/4 with the removal of the servos. If I can find a reasonable way of turning, then I'm going to go forward with this (re-designing the PCB for easier attaching the servos in this configuration, and adding the battery protection I tested with the Spiderwing).
So I started to work on the new PCB, using a QFN48 foorprint for the SAMD51G. Of course the footprint I made earlier for the IS31FL3733 chip was inexplicably broken — as soon as I started editing the pin descriptions it started doing really weird stuff. So I re-did it, together with a proper schematic image and all that. Then I started with the PCB I re-did recently for the #D1 Mini Tote, only replaced the PCA9685 with the SAMD51G:
Yes, it's a mess for now. Ideally, I will use the same headers as for the D1 Mini, so that I will be able to use all the D1 Mini shields with this robot — including the #Accelerometer Shield for D1 Mini I made recently (that's one reason why I removed the accelerometer from the PCB, actually). However, I still don't know which combination of pins will have the correct set of timers for making all those PWM outputs. But I'm confident that such a set of pins exists, because of an experiment I made with an ItsyBitsy M4:
So yeah, I can have at least 13 PWM outputs — I'm sure I can find a set of pins that will work. Whether they will be easy to route is another question, but I have a lot of space and as many vias, as I need. Also note, that on the current PCB I actually have 16 servo sockets, not 12 — ultimately there will be 4 fewer.
I will probably also add a flash chip and that speaker with an amp — this way I can put all the turret voices from Portal on it.
I compiled a custom CircuitPython firmware with all the pins exposed, and ran a simple program looking for any combination of pins that would give me 12 PWM outputs:
for permutation in permutations(pins):
pwms = 
for pin in permutation:
except (RuntimeError, ValueError):
passif len(pwms) > 10:
for pwm in pwms:
Yes, I know, I could have checked the datasheet for timers instead, but this is easier and makes more more certain.
That's a lot of permutations to check, so it took some time, but ultimately it came up empty. There is no permutation that would give me more than 10 PWM outputs on the SAMD21E18A chip. So what other options do I have now?
I could use a SAMD21G18A that has 38 GPIO pins — I'm sure they come with some extra timers that would enable a few extra PWMs. But the SAMD21E18A costs $2.38 in singles, while SAMD21G18A costs $3.47. That increase in price wouldn't be that bad by itself, however, for $4.01 I can have a SAMD51G19A instead, and a PCA9685 costs a dollar.
So now I have several options:
SAMD21E18A + PCA9685 — $3.38
SAMD21G18A — $3.47
SAMD51G19A — $4.01
But it's not just about the price, is it? The SAMD51 is a massively more powerful microcontroller, with *much* more RAM, faster clock and more flash. Also hardware floating point operations and a bunch of other stuff. And that is for just $2 more. I really think that it's the best option. Besides, I've been wanting to make a board with that microcontroller for a while, but since #µGame Turbo is on hold, I didn't really have a chance. On top of that, I have one already in my drawer, so no need to wait for parts (though I will still need to wait for the PCB).