ESP32 FreeRTOS Practice Project Controls L298

After deciding I should learn to use FreeRTOS as part of my ESP32 projects toolbox, I read through the free e-Book PDF. I don’t understand all of it yet, but it built a foundation. Enough for me to start a practice project using some basic FreeRTOS features. What’s the first thing I did? What we always do in embedded hardware: blink a LED!

I’ve used this particular ESP32, mounted on this pink breadboard, for several projects. I had a few external LEDs configured on this pink breadboard for experimentation, and that was because I somehow never noticed that there was a second LED available for direct use on my ESP32 dev module. I knew there was a red one to indicate power, but I didn’t notice the blue one until this project. Apparently this particular ESP32 development board (*) is not a direct clone of Espressif’s official ESP32 DevKitC, because that had only one red LED to indicate power. I have no idea how popular this particular two-LED layout is among ESP32 development boards, I’ll have to keep an eye out as I buy more.

Anyway, this board has a blue LED wired to GPIO2, who still got routed to the same pin as the Espressif module. The LED is wired in parallel and should not interfere with using that pin as output. Though it might affect the signal if I use it as input. I spun up a FreeRTOS task purely for the task of blinking the LED at regular intervals, just to verify I could. My first effort put the ESP32 in an infinite reset loop, and I eventually figured out it was caused by insufficient memory allocated to task stack. I was very surprised that a simple LED blinker needed more than one kilobyte of stack, but it’s not the most important thing right now so I’ll look into it later.

After I successfully created a FreeRTOS task and see it running blinking the onboard blue LED, I proceeded to set up my first message queue. Queues are the simplest way for FreeRTOS tasks to pass data to each other. I copied code from my earlier ADC experiment to read position of an analog joystick, and queued the joystick position message for retrieval by another task. First run of the reader task simply dequeued the joystick position and printed to serial terminal, but that was enough to verify I had the queue running correctly.

With those basic pieces established, I then wrote two more tasks. One reads the joystick position and puts motor control commands into yet another queue, and finally a task that reads motor control commands and adjusts MCPWM control signal for the L298N motor driver accordingly.

This exercise was a good test run to verify I could get the advantages I hoped to get by adopting FreeRTOS.

  • By writing individual subareas as tasks, I could test them individually. In this case, I could smoke test the ADC task by writing another task to read the data it queued.
  • Each task could be in charge of its own ESP32 configuration. ADC configuration is handled by the joystick reading task, separate from the other tasks. And likewise MCPWM configuration is handled by the L298N output task.
  • Tasks are run independently from each other, and more importantly, can be modified independently. I found the blue LED was obnoxiously bright and went into my LED blinking task to reduce the on time to a brief flash and extend the time between flashes, and doing so did not affect timing of other tasks. Reading the joystick and sending motor control signals do not necessarily have to run in sync, I could update motor speed more often than reading the joystick, which would be useful if I wanted to add motor acceleration logic.

That last item is especially important. If I learn enough to design my interfaces (FreeRTOS queues) right, I could swap out FreeRTOS tasks without worrying that I would interfere with other tasks. I want this design to scale from micro Sawppy to regular size Sawppy V2 by swapping out different modules written for different motor controllers. By similar token, it should be easier to do quick hacks like swap out a single steering motor as SGVHAK rover had to do. I also want different control input options, from simple wired joystick to web UI to ROS messages, each of which would be a different task module but they could all use the same message queue format to communicate with the rest of the rover.

Knowing how to set up FreeRTOS tasks and queues aren’t nearly the whole picture of using FreeRTOS, but it gave me a good introduction and built confidence for continuing forward.

[Source code for this project is publicly available on GitHub]

(*) Disclosure: As an Amazon Associate I earn from qualifying purchases.

ESP32 Exercise: Stepper Motor Pulses With LEDC PWM

After successfully installing PlatformIO’s ESP-IDF support (and a sigh of relief nothing else seems broken on my computer) I resumed practicing writing code for ESP32. The next exercise was motivated by Emily’s optical audio decoder project where we traded a few e-mail about generating stepper motor signals. For her project she used an Arduino and the AccelStepper library, but it has a maximum speed of roughly four thousand steps per second on classic Arduinos. I was confident the ESP32 can do far better than that, and decided to try it myself.

It was also an opportunity to play with a Trinamic TMC2208 breakout board sometimes called the SilentStepStick. I think this board might be a Trinamic original design, but there’s a slight chance they just hosted materials on their website since it was such a popular use of their chip. Either way, there are a lot of Amazon vendors selling these in affordable multi-packs(*) targeting the 3D printer market. Mostly for people who are unhappy with the high-pitched whine of many inexpensive 3D printers, because TMC2208 is a good choice for helping a printer run much silently than they would on the very popular A4988 driver chip that helped start the current wave consumer 3D printers. My own 3D printers had A4988 drivers soldered on the board so I couldn’t use these modules to upgrade, but I foresee these modules becoming useful in other projects.

In the current Sawppy rover context, these drivers may become useful if I investigate using stepper motors in a future rover iteration. I’ve already received requests to drive and steer Sawppy wheels with NEMA17 style stepper motors commonly used in 3D printers, and there’s always that mythical robot arm that my rover is still patiently waiting for. Commodity NEMA17 motors typically have far less torque than LX-16A serial bus servos, but I’m not sure it is a critical difference for a rover and the best way to find out would be to build one.

But for now I’m just looking at the stepper motor driver, which is commanded by two signal pins: one signifying direction, and another that signals a step for the stepper motor. Direction pin is fairly trivial, it’s the signal pin that presents a challenge. Generic portable code like AccelStepper couldn’t reliable pulse the step pin at high speeds, that requires coding to the hardware as GRBL did for the ATmega328.

For the ESP32, my experiment used the ADC peripheral to read the position of a potentiometer and the LED control hardware PWM module to generate step pulses. This module is optimized for dynamic adjustment of pulse width duty cycle during application execution, but stepper motor control is a bit of a off-label use where I left the duty cycle at 50% and changed the PWM frequency at runtime in response to knob position.

According to LEDC peripheral documentation, it is theoretically capable of up to 40MHz pulses at 50% duty cycle. However, for any given configuration, the ESP32 is constrained to a subset of the total range of speed possible. I’m not sure how feasible it is to reconfigure the LEDC peripheral at runtime, but such tricks will be required for anyone with ambition to generate a wider range of pulse frequencies. In my exercise it is limited to a range of 32 Hz to 32.5kHz, which is plenty for today as proof we can surpass the 4kHz limit of AccelStepper on a ATmega328. A stepper motor’s torque diminishes as the speed rises, so I expect the stepper motors will run into mechanical problems well before becoming limited by ESP32 PWM frequency range up to 40MHz.

Once I got this exercise up and running, I started eyeing a desirable luxury advertised by PlatformIO: source-level JTAG debugging.

Code and schematic for this practice exercise is publicly available on GitHub.

(*) Disclosure: As an Amazon Associate I earn from qualifying purchases.

Using PlatformIO For ESP-IDF Development

Based on my limited experience, the installation script for ESP-IDF (Espressif IoT Development Framework) made some assumptions about an ESP-IDF developer’s computer, including the all-too-common assumption that nothing else will be on the computer. This is problematic for several reasons, but the one that made me pull back was Python. Python is infamous for its problems keeping track of different version and their associated code libraries. It’s such a common problem there are tools made specifically to help developers keep Python ancillaries organized. I’ve had first experience with venv and conda and I understand there are many others. In the absence of such isolation in the default installation script, I went online looking for others who have taken a stab at keeping ESP-IDF from messing up the rest of my computer.

I found a few blog posts and GitHub repos, but what made me happy was a reminder that I already have experience with one solution to this problem: PlatformIO has support for ESP-IDF development. I encountered PlatformIO earlier in the context of HX711 strain gauges interface with an Arduino Nano, so my computer already had PlatformIO on board configured for Arduino on classic ATmega328. I can switch it to Arduino on ESP32, but right now I’m more interested in PlatformIO’s promise to make ESP-IDF easy to install, isolate, and eventually uninstall.

There are a few downsides to this approach. First is the fact I’m no longer using ESP-IDF directly, and thereby adding the possibility that a problem might be caused by PlatformIO instead of Espressif or myself. I would also have to switch over to PlatformIO project structure which is not the same as the ESP-IDF application template. This had greater repercussion than I initially thought, because it’s not just a matter of where the source files were placed. While those source files are still calling the ESP-IDF API I can read in Espressif documentation, the portions of documentation about project configuration may or may not apply. When working directly in ESP-IDF, a lot of project configuration is done by running menuconfig and that’s not necessarily the case anymore. The people who work on PlatformIO ESP32 support recently added some sort of compatibility in response to user requests, so that’s something I’ll have to look into later.

I’m willing to accept some limitations in exchange for PlatformIO’s ability to keep ESP-IDF Python separate from anybody else’s Python on my computer. As long as I can figure out how to do what I want to do on an ESP32… which means it’s time for more ESP32 programming exercises!

ESP-IDF Up And Running on Ubuntu

Since I decided to learn to write code for ESP32 using Espressif’s own tool ESP-IDF for the sake of following official instructions, I went straight to the official directions for installing ESP-IDF and saw it was the “run this one script to install everything” type of instruction. This is not itself a problem, but when I saw that ESP-IDF had a lot of Python scripts, that made me suck air through my teeth. Automated scripts doing unknown things to Python (without mentioning any kind of environment isolation like venv or conda) sets off many alarms. Hesitant to run ESP-IDF installation script on my main computer, I tentatively dipped in my toes by using a computer running Ubuntu I could dedicate to this experiment. A long but uneventful installation process enabled me to compile the ESP-IDF project template and I proceeded to do a few introductory projects on this test machine.

After the trivial blinking light exercise, I moved on to the ADC (analog-to-digital converter) peripheral. When I built a wired handheld controller for Sawppy V1 with an Arduino Nano, its joystick position was read using an ADC and I expect I’ll need something similar again for micro Sawppy running on ESP32. The unexpected twist I had to learn was the attenuation parameter for ESP32 ADC input. Most microcontrollers ADC can read the range from zero volts to input voltage level. (For an Arduino Nano, 0V to 5V.) So I expected the ESP32 to read from 0V to 3.3V. But by default it only reads up to a much lower level and, even with maximum configurable attenuation, it only reads from 0V to roughly 2.6V. Meaning the joystick potentiometer’s center point will not map to the middle of the allowable range of values. But I was able to take Espressif’s sample ADC project and simplifying it for my needs. I removed all the parts that dealt with calibration and conversion to an accurate voltage reading. Such efforts are largely wasted on a low-quality joystick anyway, they drift far more than the ESP32 will.

The next exercise was to take that ADC data and do something with it. I expect to use ESP32 MCPWM peripheral to control micro Sawppy’s six rolling wheels, so I started learning how to use the LEDC peripheral to generate control signals for micro Sawppy’s four corner steering servos. When an Arduino ESP32 project implements the servo() command, they usually turn to LEDC and I decided to follow suit. Generating a one-to-two millisecond signal every twenty milliseconds is well within the capabilities of the LEDC peripheral, and at the end I had a simple ESP32 servo tester generating servo control signals based on the position of a potentiometer.

So far so good. Out of all operating systems at my disposal, Ubuntu was the least problematic one and I’m glad it passed the first few tests. But this was a test computer, with nothing else on it to break. Certainly no other critical Python dependencies. In contrast, Apple Mac OS X is infamously temperamental about its integrated Python and woe to anyone who messes with it.

Windows lies somewhere in between, with no hard system dependencies to fatally break, but still a complicated relationship with Python. Still wary, I whipped up a Windows test computer and ran the ESP-IDF installer. According to ESP-IDF Windows setup page, it was supposed to install associated dependencies including Python 3.7. But when I launched I got a Python 2.7 error.

error while loading shared libraries: cannot open shared object file: No such file or directory

Ugh, what a mess. Now I’m very glad I had used test computers for these experiments. I shall proceed to wipe them clean and consider alternate options.

[Practice projects described in this post are publicly available on GitHub]

Evaluating My Options for ESP32 Development

Once I decided I could use ESP32 as a micro Sawppy rover brain, the next decision is how I intend to write my code to run on an ESP32. Since it’s such a popular microcontroller, I have many options that I’ve narrowed down to top three candidates: ESP-IDF, Arduino, and MicroPython.

The lowest level option is ESP-IDF: Espressif IoT Development Framework. This is the software development kit released by the same people who made the ESP32 hardware. All sample code in Espressif documentation will be targeted to ESP-IDF, so this is the best option if I’m working from the official reference sources. This is important when working with less-popular features like the MCPWM module designed for motor control: I can be confident the feature will be supported.

The mid-level option is Arduino adapted for the ESP32 hardware. Setting up the Arduino IDE for ESP32 development is a very simple process compared to the setup procedures for ESP-IDF. It also allows access to the huge catalog of Arduino libraries that exist out there. Or at least the subset that don’t have hardware dependencies. Code that is hard-coded for ATmega328P won’t run on an ESP32, but that problem is shared with other non-AVR Arduino compatibles like Teensy or even the newer Arduino boards. Architecturally this is a translation layer on top of ESP-IDF, so non-ATmega328P features like MCPWM can be accessible as long as the proper header declarations are in place. Which, in the case of MCPWM, they appear to be.

The high-level option is MicroPython for ESP32. Where the user doesn’t even really need to install anything on their computer: anything that can open a serial terminal will do. The Python language itself is much more beginner friendly than the C language used by Arduino and ESP-IDF. However, a search for MCPWM support found that it is currently a work-in-progress, eliminating it from consideration for this project.

With that elimination my choices are between using ESP-IDF directly versus the Arduino translation layer, I favor direct usage because I saw it as eliminating a variable. When my code doesn’t work, I won’t have to wonder if it’s a bug in my code or in ESP32 Arduino core. While not a huge concern in the well-trodden paths, it is a worry when I venture to less popular sections like MCPWM. And since I’m using an ESP32-specific peripheral, this code won’t run on any other Arduino-compatible boards anyway. Might as well go straight to the source.

Micro Rover ESP32 Brain Is Feasible

I was a little disappointed when I learned that the ESP32 can only use a tiny fraction of its vast peripheral interface capabilities due to the fact there are only a few physical I/O pins to be allocated among them. But to be honest, roughly 20 is a fair number in terms of controllers in this price range. It’s only “few” when compared to literally hundreds of possible uses for those pins. It also makes sense when we think about the target market for the ESP32: it was derived from the ESP8266, and they are both intended to act as a WiFi interface to some device, not to be in charge of a large complex thing. So does my little rover qualify as a small focused-purpose device that needs a WiFi interface? I think so, but it’s a tight fit.

I originally intended to drive L298N by digitally setting the direction on its two input pins and put a PWM signal on the enable pin to control velocity. The straightforward implementation of this would require 3 pins per wheel. Six wheels mean 18 pins, and I still need four more. One for each of the four corner steering servos. I don’t think I can get 22 output pins on the ESP32 dev board I have. Fortunately it isn’t quite that bad, because all three wheels on one side of the rover are always rotating in the same direction, so they can share the same direction control pins. Two pins to control all left wheels, two more to control all right wheels, and one pin for each of the six wheels for PWM add up to ten pins, plus four more for corner steering servos add up to fourteen pins. This will work.

Alternatively, I can implement the control scheme used by Espressif’s sample program for controlling a L298N motor controller using ESP32 MCPWM peripheral. I’m skeptical of this one, though. It wants the enable pin to be tied high, and controls speed by using PWM signal on the direction pins. As per my understanding of L298 data sheet, this toggles between powered state and brake state. Which sounds like an extremely inefficient way to control velocity. Nevertheless, doing this would require 2 PWM pins for each of the six wheels. Plus the four corner steering pins for sixteen output pins. Even though there are only fifteen easy to use output pins, I can probably make one of the caveat-encumbered pins work for the sixteenth.

The final consideration: what would happen if I decide I don’t want to use the L298, and want to use a different motor controller instead? I haven’t studied them as much as I’ve studied the L298, but the few I’ve glanced at appear to use one of the two above control schemes. Perhaps the L298 is established enough that most newer DC motor controller offer drop-in compatibility with L298 control signals? Even if not, I believe a mini rover using another DC motor controller would still be feasible to implement on an ESP32. And the best way to know for sure is to start writing some code.

Notes on ESP32 PWM Peripherals

Now that we’ve celebrated the success of Perseverance rover’s arrival on Mars, I resume working on my little rovers. I was happy to discover that I’m less intimidated by the ESP32 than I was over two years ago. I now have a basic understanding of its capabilities and the ecosystem that has grown up around it. Enough to figure out where to start if I have a problem to solve. And the problem of the day is to determine if micro Sawppy can use an ESP32 as its brain.

The reason I started looking at the ESP32 is because of its WiFi capability and its low cost. I liked the idea of web browser-based UI like what I wrote for SGVHAK rover and adapted for Sawppy. But that ran on a Raspberry Pi which, even in its lowest-cost Pi Zero form, is far more expensive than an ESP32. My experience with other ESP32 projects like Ben Hencke’s Pixelblaze and Bart Dring’s Grbl port taught me the ESP32 is quite capable of serving up HTML user interfaces. So the next thing to do is to verify an ESP32 can generate all the control signals for a Sawppy rover, which means investigating its PWM capabilities.

PWM (Pulse Width Modulation) is a tool that can be used to solve many problems in a microcontroller. For micro Sawppy I need PWM capability to control four steering micro servos and the six wheel drive motors. It doesn’t matter if they are micro servos modified for continuous rotation or a real DC motor driver like the L298N, they all need PWM signals. And what I found was that no only can ESP32 generate PWM signals, it has separate interfaces dedicated to specific problem someone might want to solve with PWM.

First up is LEDC, the Light Emitting Diode Control module. I bring this up first because our first project with any new piece of electronics is to blink a LED, and in many tutorials the next step is learning how to vary the brightness of a LED via PWM. LEDC is designed with the intent of controlling intensity of up to 16 LEDs via PWM.

Another problem commonly solved with PWM is to convert a digital signal into an analog one. This is sort of like controlling the brightness level of a LED, but some applications are sensitive to the sharp pulse transitions of a PWM signal. One example is for generating sounds, which needs a smoother output. And here the ESP32 delivers a dedicated DAC (digital-analog converter) peripheral. Anticipating that this would be used for audio, Espressif provisioned it to interface with I2S which is popular with audio applications. This may be fun to look at later, but it is not critical for driving a little rover.

And finally, I was surprised to find there is a dedicated Motor Control PWM module for generating PWM signals sent to motor driver modules like the L298N. It included many motor-specific features absent from LEDC, but they are mostly aimed at controlling brushless motors which usually have three coils each requiring independent control. ESP32’s MCPWM is set up to control two brushless motors, which means controlling six coils. But it is not required to control brushless motors, each of those coil control an be used to control a single DC brushed motor.

So the ESP32 MCPWM peripherals can control six brushed DC motors, which is a perfect fit for a six-wheel-drive little rover. I should be able to use four channels of LEDC to generate PWM to control four steering servos. This first pass over the spec sheet supports the idea of using ESP32 as little rover brain, though there is a potential problem in assigning control signals.

ESP32 Feels Less Disorienting This Time

Seeing all the interesting projects built with an ESP32 has made me interested in learning more about the popular platform, but it wouldn’t be real until I dedicate the time and focus to build some projects of my own. My micro Sawppy project might be the motivation I needed to get down to business.

Querying in this blog’s history, I was embarrassed to realize that it’s been over two years since I first thought I would build something with an ESP32. My first exposure to the fire hose of information online was overwhelming. But I returned occasionally to pick off little bite-sized pieces to digest. Reading documentation on some specific aspect on the ESP32 at a time, usually in response to seeing someone’s project making cool use of that particular aspect. I wanted to see how it was done!

During this incremental learning, I picked up on the fact something is coordinating the works to keep all the plates up in the air. Eventually learning that the default ESP32 runtime environment includes a minimalist operating system for embedded hardware: FreeRTOS. Which was a world onto itself! There is a tutorial e-Book to help get people up to speed but again, it is a lot of information that I had to digest a little bit at a time. I’ll write more about FreeRTOS later.

And though I hadn’t reached the point of writing my own ESP32 code, I did start getting a bit of hands-on experience working with an ESP32 developer board. Which was more full featured than the minimalist mesh networking Supercon hack that was my first introduction to the hardware. Even though I was only running other people’s code (like Bart Dring’s ESP32 Grbl port) and not my own code, it was valuable familiarization of the ESP32 landscape.

All of these individual pieces built up a comfort level that was absent from my first time facing the avalanche of information available for ESP32 over two years ago. Now I can look at the page like and have a much better understanding why things are organized the way they were, and which pieces of information are relevant to others. This knowledge map is important as I do some basic due diligence to see if it’s feasible to build a micro Sawppy brain from an ESP32. Before I get any further on my little rovers, though, there’s a big event for a big rover.

Thoughts on Micro Sawppy Brain

My diversion to learn a bit of Unity 3D was a good change of pace, but now I will set that aside and return to rover work. My latest little rover Micro Sawppy Beta 3 (MSB3) had a few interesting features that I reviewed before taking this Unity break, most recently a few notes on MSB3’s living hinge differential link. MSB3 was built around the TT gearbox, which requires DC motor drivers commanded by some kind of rover brain.

I have the option of using the same brain I used for MSB1 and MSB2, which was adapted from Sawppy V1 and allowed me to control everything with servo PWM control signals. This worked for MSB1 and MSB2 because they were all micro servos. Four in their original form for steering, and six modified to continuous rotation to drive the wheels. But now that I’ve converted rover locomotion to DC gear motors, I’ll have to switch to something else.

My current generation of rover software was originally written for SGVHAK rover, which had DC motors in its wheels and used RoboClaw motor controllers. Those are nice, but far too expensive for my micro Sawppy price target. Or I could continue controlling via PWM by using forward/reverse brushed DC motor controllers(*) from the world of remote control hobbies. These are far less expensive than RoboClaw controllers but also less capable. Unfortunately they are still too expensive to meet my price target. Motivation to find a cheap commodity was why I investigated commodity L298N driver boards earlier.

But I’ve always known I couldn’t keep using a Raspberry Pi. In order to meet my price target, I have to swap it out for something more affordable. For MSB1 I chose to use the Pi as a known quantity, because the rest of the rover was all new and I wanted to reduce the number of unknowns for the first prototype. After several revisions I’m at MSB3 and I’ve decided it’s fine if a baseline micro Sawppy didn’t have the computing power of a Raspberry Pi as long as there are provisions for people to upgrade if they wish. So any microcontroller capable of generating the required PWM control signals (for servos and for L298N motor drivers) would suffice. The classic Arduino is always the first candidate I consider for a project, but ATmega328P based Arduinos only have 6 PWM channels. That’s not enough here so I have to move upscale.

Classic ATmega328P-based Arduino are also missing another very important feature: WiFi. SGVHAK rover’s Raspberry Pi based brain served up a web browser-based rover control interface. Controlling Sawppy from my touchscreen phone was very useful. Not just because of convenience but also because I didn’t need to worry about building a separate device to act as handheld controller. Which, in a bit of cheat, also meant I did not counted the cost of controller phone in micro Sawppy budget. I justified this by saying many people today have old web-capable touchscreen phone or two sitting around collecting dust. Maybe a stretch, but I’m going with it!

If I want something more powerful than a classic ATmega328P-based Arduino, but more affordable than a Raspberry Pi, and can handle web-based network traffic over WiFi, the top candidate is pretty obvious: ESP32, we meet again.

(*) Disclosure: As an Amazon Associate I earn from qualifying purchases.

Micro Sawppy Beta 3 Differential Link

Several design changes in Micro Sawppy Beta 3 (MSB3) allowed me to experiment with different suspension rocker designs: the multi-piece rocker with deployment pivot and the single-piece rocker for straightforward assembly. One of those enabling changes was a rework of the link between the rocker and the differential, continuing the experiment started with MSB1 and MSB2 of using 3D printed living hinges for this critical linkage.

Enabling a single-piece rocker was not an explicitly goal of this rework, that was just a convenient side effect that I took advantage of. The real focus of this iteration was to make the living hinge itself a small disposable component that can be easily replaced. Because micro Sawppy is targeted for an audience with entry-level printers, I can’t assume rover builders can print with flexible filament like TPU. So if I want to use living hinge in my design, I have to account for the fact that beginner-friendly 3D printing materials like PLA will fatigue and break with some regularity.

If the living hinges of MSB1 and MSB2 should break, it would mean reprinting and replacing some very large parts. In contrast, MSB3 hinge is a tiny little part that clips into larger surrounding rigid parts. Furthermore, it is the same part at all four joints. We would only need to keep one style on hand in replacement inventory, which can be used to fix any of the four joints that might break.

An associated benefit is that we can print the hinge with different settings to find the best tradeoff between flexibility and durability. Looking at the hinge in the orientation on the 3D printer bed, it is easy to scale the design’s print height and test how a particular batch of filament behaves. I printed these at heights varying from 2mm to 6mm and I tried the 2mm first. It would be the most flexible, and I wanted to see how long it would last.

The answer: less than 30 seconds! Oh well, at least now I know. For this particular type of material (MatterHackers Build Series PLA) 2mm was too fragile. 6mm was overly rigid and interfered with proper rocker-bogie operation. 4mm seems to be sufficiently durable but it was still too stiff to let the rocker-bogie operate as smoothly as I like. Even though these data points weren’t terribly encouraging, I’m glad MSB3 made it really easy to adjust this particular parameter for experimentation.

But at this point I’m suffering from rover fatigue and need a break. I’ll return to micro Sawppy later (UPDATE: it is later) but right now I’m going to go play with Unity 3D for about a week.

Micro Sawppy Beta 3 Suspension Rocker With Deploy Pivot

One of the main project goals of Micro Sawppy Beta 3 (MSB3) is making a 3D-printed rover design that is easier to build than Sawppy V1. Reducing the number of parts is one way to support that goal, and that’s why making the suspension rocker as a single 3D printed piece was a good thing to try and something to keep as a strong candidate for the final design.

But I’m a tinkerer, and it’s hard to resist the temptation of doing more. Especially for features that are tempting and have a good chance of being actually useful. The Rocker Deploy Pivot (RDP) is one such feature, a hinge on the suspension rocker that lets Curiosity and Perseverance fold up for their trip to Mars. I thought replicating the RDP on my own rover would help make it more portable in addition to the nerd cred factor. If so, that might be a worthwhile gain in exchange for increased parts count and assembly complexity.

Since MSB1 and MSB2 suspension rocker had to be a multi-piece design anyway, I started exploring the idea of building a RDP but it was never functional for those rovers. MSB3 is the first iteration that can practically fold up for transport. Collapsing the suspension like this does not change the length or width by much, but it cuts height by almost half. In this form, MSB3 can conceivably be small enough to be carried in a backpack.

Like many of the mechanisms that are newly designed for MSB3, it is probably bulkier than it needs to be. It added two more M3 screws In addition to the screw holding the rocker bearing. This is plenty strong so I have margin to cut back on the structure, maybe eliminating one of those extra screws and move the remaining screw closer to the pivot point. Both will help reduce bulk and reduce load on its link to the differential.

Micro Sawppy Beta 3 Suspension Rocker (Single Piece)

My rover Micro Sawppy Beta 3 (MSB3)’s suspension bogie attaches to its rocker assembly. Just for the sake of experiment, I designed and printed a single-piece rover suspension rocker. Rovers MSB1 and MSB2 had a complex multi-piece rocker design because its many mounting points were not coplanar and I couldn’t figure out how to align everything along 3D printing layers for maximum strength.

I redesigned the steering servo and rotational bearing mounting mechanisms for MSB3. As a result, it was almost possible to get everything lined up. The lone exception was that the front corner was still not easily aligned with the rest, but it could be a long sloping shape that spreads its load across a large surface area of print layers. It still won’t be as strong as if everything were lined up on the same layer, but it should not be an immediate structural disaster. It will, however, require printing with supports and accepting the rough surface that results.

I could help hide this poor surface finish, by aligning the print so it is on the inner surface of the suspension member. It’s not out of sight, however, since the front corner wheel stick out the front and thus this surface is always visible.

Every 3D printing slicer handles supports slightly differently. This particular test piece was sliced with MatterControl on default PLA settings and auto-generated supports. The flat portions (near steering servo and joint) had a rough surface but at least that section separated cleanly. The angled section (between steering joint and rocker pivot bearing) was a mess. That section of support did not separate at all, the surface visible here is a combination of forcibly tearing plastic apart and cutting the remainder free with a blade. I would not call this a complete success. Nevertheless the result does appear structurally sound. I would be confident using it in a rover design as there’s enough surface area across the diagonal section to hold together well, except under gross abuse.

This experiment proved that a single-piece suspension rocker is feasible. Practical, even. But I was not content to leave it at that and built a multi-piece suspension rocker in an effort to improve rover portability.

Micro Sawppy Beta 3 Suspension Bogie

A quick strength test of SG90 micro servo found that it was pretty fragile, but before I worry too much about mitigating that problem I wanted to get more real world runtime on Micro Sawppy Beta 3 (MSB3) to see if such work is even necessary. In order to get that real world runtime, I should focus on continuing design work on the rest of the rover. Next stop: the suspension bogie.

Most of changes to MSB3 bogie reflects the switch to using TT gearmotors to drive the middle wheel. Compared to those changes, work to accommodate new steering joint and servo mount were relatively minor. The final change was mechanically simple but has a big impact: following the precedent set by steering bearings of MSB3, the bogie bearings mount were also changed around. Now, instead of a M3 fastener running through the center of bearings as a rotational axle, the M3 fastener now securely bolts down the center to be static relative to the bogie and the motion is around the outside.

Again the major advantage is making this rover much easier to build and maintain. We no longer have to worry about the amount of torque used, as it no longer affects smoothness of bearing motion. A rover builder can torqued down these M3 fasteners to their heart’s content and it wouldn’t affect rover behavior.

As part of this change, the C-shaped bracket to prevent bogie over-rotation is no longer a simple clip-on piece of plastic as it was on MSB1 and MSB2. It is now a structurally important part of the rocker-bogie joint, supporting the weight of outer bogie bearing. There’s a good chance this bracket on MSB3 is bulkier than necessary, but I wanted to verify the idea works before slimming it down. It’s already taken way more effort than I thought it would take to get this point.

I need to sit down and simplify the bracket’s geometry. Its shape is dictated by the bogie’s allowable rotational range of motion, and I think that math got away from me. There are far too many numbers and guide lines in the CAD sketch. It took several small test samples to work through this geometry and my mechanical intuition says there should be an easier way. Fortunately the bracket is small and quick to print making iterations fast. Hopefully that mythical “easier way” will come to reality once I dedicate some time to stew on the problem for a bit. For right now, I’m content to use this design for attachment to MSB3’s suspension rocker, starting with the single-piece version.

SG90 Micro Servo Strength Test

The weakest point in my Sawppy V1 rover were its shaft couplers, but that bug also became an accidental feature: when the system is abused, being the weakest link meant it is a sacrificial element to break before anything more expensive would. I am now designing the servo steering mechanism for Micro Sawppy Beta 3 (MSB3) and wanted to know: do I also have an (accidental) abuse-absorbing feature on the little rover?

This was something fairly easy to test and, thanks to the low cost of SG90 plastic gear micro servos, I was willing to sacrifice one for this knowledge. I put together a MSB3 prototype steering assembly and wired the servo to power and control signal, telling to hold straight center. If I wanted to be scientific I would use a torque wrench or something to quantify the forces as I test, but I didn’t have the proper equipment so I just used my hand.

The answer is no, nothing else in this steering assembly for MSB3 will step up and absorb abuse on behalf of the steering servos. It took surprisingly little force from my wrist before I heard something snap. I disassembled the gearbox to see not one but two failures: A tooth is bent (but still attached) on the final output gear, and another tooth has broken off from the adjacent meshing gear.

Since I didn’t use an instrument to quantify the breaking force, I don’t have objective numbers to post here. Subjectively I felt the breaking point was beyond what I would reasonably expect from a little rover in normal roaming, which is good for rovers rolling along minding their own business. But I want micro Sawppy to be something a teacher can introduce to their class, and I didn’t think the breaking point was beyond the capabilities of curious/destructive children, and so the fragility worries me.

I’m sure MG90 metal gear servos would fare better, but would they be strong enough? I’ve already sacrificed a few MG90s to experimentation and I’ll want to set up proper instrumentation before I sacrifice another. And obviously a MG90 is more expensive than a SG90. Is it better to use affordable SG90 servos and replace them as needed? Or is it better to go straight to MG90 for higher durability? Answering this question definitively would require real world usage data. See how often SG90s require replacement, and whether the replacement rate is greater or less than the up front-cost increase of using MG90 servos. In order to obtain this real world usage data, I’ll have to keep working on the rest of the rover.

Micro Sawppy Beta 3 Steering Trim

Getting a pair of bearings aligned with the wheel contact patch is a feature on all Sawppy rovers, so that in itself wasn’t new. But Micro Sawppy Beta 3 (MSB3) did try a new way to mount bearings, and I’m optimistic it’ll make future Sawppy designs easier to build. On top of that steering joint, I’ve also modified the servo attachment for another feature I wanted to put on my rover designs: mechanical steering trim adjustment.

Sawppy V1 had a software-based trim adjustment system, where the center point of each steering servo could be adjusted by modifying a value in a text file. I though it was something that I could set once and forget but I was wrong. The potentiometers used to sense position inside a servo motor drifts over time (and temperature, and humidity, and phase of the moon…) so in reality steering trim had to be adjusted fairly frequently.

For MSB3 the servo horn bundled with a micro servo is mounted on a 3D-printed piece with an arched hook in the front. I could then fasten it to my steering assembly with a single screw. Steering trim adjustment becomes a matter of loosening that screw, sliding to a different point within that arc, and tightening the screw back down.

Another advantage of this design is that, unlike MSB1 and MSB2, the servo is freed from handling any structural loads. It is now responsible solely for steering just as servos were for Sawppy V1. It is a feature I’m glad I could bring to a smaller scale. I thought about going one step further on ease of assembly, and tried a few clip-on servo mounting brackets for tool-less assembly and replacement. (Pictured.) But even though these little servos assert little torque, there is enough to distort 3D-printed plastic and affect steering accuracy so I returned to the concept of a screw-down servo bracket.

But the experience did remind me of one thing about Sawppy V1: I didn’t like using heat-set inserts on shaft couplings because they would slip and break. However, that slippage and breakage did have an advantage when Sawppy is stressed beyond design limits. When a child decided to break my rover, the coupler broke before that abuse was transmitted into the servo. What would happen to this little rover servo?

Micro Sawppy Beta 3 Steering Bearings

The third revision of my little rover prototypes, Micro Sawppy Beta 3 (MSB3), uses TT gear motors and matching wheels for the six-wheel-drive aspect of its rover suspension. Using commodity components solves a lot of problems, but now I have to integrate them. The starting point is a rectangular bracket that bolts onto two top mounting points of a TT gearbox, and angles over the wheel to a hole for a bearing that is aligned with where the wheel touches the ground. (“Contact patch”) This alignment is necessary in order for the wheel to pivot in place. If the rotational axis of the bearing is not aligned, then any rotation would drag the wheel across an arc instead of pivoting on the axis of rotation.

Sawppy V1 had the same steering axis alignment requirement, and I used 8mm shafts running through the center of 608 bearings. For MSB3 I’ve turned that design around: instead of transmitting the rotational force through the center of the bearing, now the bearing center remains static while steering forces are transmitted around it. M3 fasteners bolt a pair of bearings to the front end of the suspension rocker, one top and one bottom. The steering mechanism takes the general shape of a C holding above and below this pair of bearings.

MSB1 and MSB2 ran M3 screw through the center of bearings in their suspension members, but that used the M3 fastener as a rotational axle much like how Sawppy V1 used 8mm shafts. This meant the smoothness of the rotation is sensitive to how tightly the fastener was torqued down. Too loosely, and it rattles. Too tightly, and the fastener would cause the bearings to bind up. Which defeats the purpose of using ball bearings to begin with! I had a few other ideas on how to address these problems, but I decided to try this one first. Inverting the roles was less dependent on 3D printer precision and hence easier to build.

Part of making micro Sawppy easier to build is to avoid similar looking parts that are not interchangeable. For MSB3 I designed the two parts of this steering C-shaped assembly so it can be used on all four corners. That is to say, a builder will print four copies of the same design. Rather than Sawppy V1 which had distinct front-left, front-right, rear-left, and rear-right corner steering components people might (and did) inadvertently swap causing confusion. This is something I wanted to mitigate by stamping reference numbers on parts, but it’s better to design so the user doesn’t have to squint to make out part numbers at all.

In order to make a part usable in multiple directions, it is symmetric front-back as well as side-to-side. Adding provisions to allow the parts to be attached in multiple directions also added unnecessary bulk, and I haven’t made up my mind whether the tradeoff is worthwhile. Clever designers know how to design parts so they are clearly unambiguous, I might want to tackle that as a challenge instead. In the meantime I’ll leave this as-is and proceed to steering servo installation and associated adjustment.

Micro Sawppy Beta 3 Wheel

The major motivation to build Micro Sawppy Beta 3 (MSB3), leaving MSB2 behind, was the increasing complexity of MSB2 wheels and I wanted a rover that is simple to build. Switching to using commodity TT gearmotor plus its associated wheels for the rover’s six wheels goes a long way. By using a gearbox that is already designed to support and drive a matching wheel, we eliminate custom modification and any worries about robustness of said modifications.

When I looked inside a TT gearbox I didn’t see any ball bearings, but I did see support structure that should suffice for a rover at this scale. At a very minimum, the rover would be as robust as every other robot design that use these wheels.

But like everything in design and engineering, there are tradeoffs. The biggest disappointment (and why I was reluctant to use these things to begin with) is that poor ground clearance. Comparing MSB3 against MSB2 and MSB1, we see ground clearance has degraded with iteration. There were good reasons to take each of these steps but it’s not the direction I wanted to go. Even with feedback that this feature isn’t ranked highly on many other people’s rover builds. Fortunately(?) I think this is as far as I have to compromise on this topic, at the moment I don’t know of anything that might further degrade clearance for future rovers.

Another problem is the fact these wheels don’t much resemble real Mars rover wheels. I was really proud of Sawppy’s wheel design and how I was able to scaled down for MSB1 and MSB2, but now I’m leaving them behind. While there’s the possibility to replace these generic wheels with 3D printed rover wheels, it would only be cosmetic. Given the geometry here, I don’t see a good way to restore functional ground clearance. But at least these wheels come with rubber tires, which was one of the biggest non-Mars-authentic feature requests for Sawppy.

A TT gearbox offers three attachment points. Two near the motor and one at the opposite end. While it would be most robust to use all three points, for MSB3 I decided on simplicity and used only the two close to its motor. The mounting bracket is angled to meet up with the steering axis, which is aligned with the middle of the wheel so the wheel could pivot in place.

Micro Sawppy Beta 3

Gaining a basic understanding of how to use the L298N module to control DC motors was an important confidence booster for modifying my little rover plans: Switch the rover’s six-wheel drive from micro servos modified for continuous rotation to a different approach: TT gearmotors that are designed from the start to drive wheels. They even come with one of the most frequent Sawppy requests: soft rubber wheels that are expected to have better traction on earthly surfaces. Steering the little rover’s four corner wheels remain the duty of micro servos, which would be doing their designed job of rotational position actuators.

The first rover chassis to emerge from this new plan is Micro Sawppy Beta 3 (MSB3) shown here next to its predecessors MSB1 and MSB2. Changing the wheel drive mechanism has a huge impact on the overall design, as this family portrait shows. A new rocker-bogie suspension implementation is the focus here, relegating the body back to a simple box as it was on MSB1.

The next few posts will cover some of the highlights of mechanical design changes for MSB3. Changing the wheel drive motor required a completely new steering knuckle design for the corner wheels. Which became an opportunity to design a multi-piece mechanism that would allow me to quickly adjust steering trim at mechanical level. Increasing the number of parts does make the mechanism more complex, but I am optimistic it would actually prove to be easier to build. MSB3 also represented a new way to use 623 bearings that hopefully eliminates the sensitivity to tightening torque. And the revamped rocker features an improved adaptation of the real rover’s rocker deploy pivot allowing the rover to fold up for transport. And finally, the differential linkage is a further evolution of using 3D printing to avoid having to scour remote control hobby catalogues for an adjustable suspension turnbuckle.

This tour of MSB3 starts at the same place as its predecessors, from the wheels. Then we’ll work our way up.

Circuit Schematic of Generic L298N Driver Board

As a learning exercise, I decided to generate my own documentation for commodity L298N motor driver modules available wherever hobbyist electronics are sold. The first step was to catalogue all the components mounted on board, and now I analyze the circuit board layout to see how they are connected together. And as much as I like to do things digitally, for projects like this I really appreciate the flexibility and immediacy of a sheet of paper to scribble on.

I could probably do it with the actual device in hand and a blank sheet of paper, but this time around I decided to create my own visual guide. I took photos that are as directly square-on as I could front and back. I scaled them to the same size, and printed them side by side on a sheet of paper leaving room for me to write notes. Once printed, I folded the paper in half while holding it up to a light source so I could line up the front and the back. Then I started following copper traces and scribbling my notes.

Fortunately this was a relatively simple circuit that mostly followed data sheet recommendations. I quickly confirmed the eight diodes were present to dump excess power into the +12V and GND planes. The two electrolytic capacitors are there for the +12V and +5V power planes respectively. IN1 through IN4 and OUT1 through OUT4 are straightforward direct routes. I also confirmed the optional current sensing resistors were absent, those pins were tied directly to ground. Furthermore, there was no provision to make adding current sensing resistors easy. People who want to perform current sensing are probably better off using another module.

A few traces were buried under components so their paths had to be teased out via probing with a continuity meter. The jumpers on ENA and ENB do indeed tie them high to the +5V power plane. The third jumper enable/disable the onboard 78M05 regulator. When the jumper is in place, it connects the +12V power plane to the input pin of 78M05. Which can then supply 500mA of current to +5V plane. Since the L298 itself draws less than 100mA, the remainder capacity can be tapped via the +5V screw terminal to perhaps drive a microcontroller. When the jumper is removed, regulator input is disconnected from the +12V plane and the +5V screw terminal becomes an input port to accept external power. The LED and current-limiting resistor is connected to the +5V plane and will illuminate when +5V power is present.

Aside from the silkscreened text proclaiming +12V, I found nothing to limit motor power supply to +12V. As far as I can tell it can be anywhere from 7 to 35V when using the onboard 78M05 regulator. If the regulator jumper is removed and L298N is running on external logic power, the lower limit is dictated by the L298N which can function with as low as 4V. The upper limit of a L298N is 45V with peaks of 50V, but the capacitors and 78M05 used on this module are listed with 35V maximums. Personally I’m unlikely to use anything higher than two 12V lead-acid batteries in series, which would be 28.8V fully charged and comfortably under that limit.

As a part of this self-assigned exercise, I also practiced drawing a schematic using the electronics design component of Autodesk Fusion 360. I think I’ve captured all of the information above, though I’m sure this schematic violates a bunch of conventions and make electronic engineer eyes twitch. (I’ve had to read software code written by electrical engineers so I have some idea what the mirror image is like.) And while I try to put lots of comments into my software source code, I haven’t learned how to best document a schematic. Until I learn more about that world, this blog post represents my best effort for this round.

Armed with this knowledge, I felt confident enough to embark on designing a micro rover to use TT gearbox with its DC motor, leading to Micro Sawppy Beta 3.

Components of Generic L298N Motor Driver Module

The internet is a great resource, but sometimes I want the experience of doing something on my own. This is why after buying a batch of generic L298N motor driver modules, I decided to sit down and understand what I have on hand instead of just downloading someone else’s documentation.

The main attraction with the big heat sink is the L298 itself, specifically the L298N variant. Flanking it, four on each side, are small modules labelled “M7”. Since the datasheet said an array of four diodes each are required for A and B sides, seeing eight of something on the board makes them candidates for those diodes. A search for “M7 Diode” indicates they are 1N4007 diodes.

A single rectangular package is etched with ST logo and designation 78M05. Its datasheet describes it as a voltage regulator delivering 5V at nominal 500mA. Input voltage can be up to 35V, but must be at least 7V. Two cylindrical assemblies are likely electrolytic capacitors. The numbers indicate 220uF at up to 35V, matching the maximum limit of 78M05. L298 datasheet required a capacitor between motor voltage supply and ground, and another capacitor between logic voltage supply and ground, so that fits.

Two blue screw terminal blocks on either side are motor output connections. They are labeled OUT1 and OUT2 on one side and OUT3 and OUT4 on the other, designations straight from the L298N data sheet. Also straight from the data sheet are control signals IN1, IN2, IN3, and IN4. There are jumpers on ENA and ENB. My hypothesis is that they are tied to +5V to stay in the enabled state by default, allowing motor direction control going full speed forward, full speed reverse, and brake stop. If an application wants control over enabled state, we can remove jumpers and connect the enable lines for PWM speed control.

The third screw terminal block has three posts labeled +5V, GND, and +12V. GND is obvious enough, and given the presence of 78M05, my first guess is that the +5V terminal gives the option of tapping its output to drive our microcontroller. But it is also possible it is a +5V input to bypass the 78M05. There is a jumper nearby to disconnect something, possibly the 78M05? A small surface mount LED and accompanying current limiting resistor probably indicate power on one of the power rails. Finally the +12V label is mysterious, since everything I see with a voltage limit can go up to +35V and I see no reason to constrain it to +12V.

Looking over the list of expected components, I am left with two missing: there are no candidates for current sense resistors. Time to trace through this circuit and see if I can find them.