Arduino Mozzi Wilhelm Exercise

After completing a quick Mozzi exercise, I found a few problems that I wanted to fix in round 2.

The first problem was the use of audio clip from Portal 2. While Valve Software is unlikely to pursue legal action against a hobbyist exercise project for using one short sound from their game, they indisputably own the rights to that sound. If I wanted a short code exercise as any kind of example I can point people to, I should avoid using copyrighted work. Hunting around for a sound that would be recognizably popular but less unencumbered by copyright restrictions, I settled on the famous stock sound effect known as the Wilhelm scream. Information about this effect — as well as the sound clip itself — is found all over, making it a much better candidate.

The second problem was audible noise even when not playing sampled audio. Reading through Mozzi sound code and under-the-hood diagram I don’t understand why this noise is coming through. I explicitly wrote code to emit zero when there’s no sound, which I thought meant silence, but something else was happening that I don’t understand yet.

As a workaround, I will call stopMozzi() when playback ends, and when the button is pressed, I’ll call startMozzi(). The upside is that the noise between playback disappears, the downside is that I now have two very loud pops, one each at the start and end of playback. If connected to a powerful audio amplifier, this sudden impulse can destroy speakers. But I’ll be using it with a small battery-powered amplifier chip, so the destruction might not be as immediate. I would prefer to have neither the noise nor the pop, but until I figure out how, I would have to choose one of them. The decision today is for quick pops rather than ongoing noise.

This improved Arduino Mozzi exercise is publicly available on Github.

Arduino Mozzi Space Core Exercise

Temporarily stymied in my Teensy adventures, I dropped back to Arduino for a Mozzi exercise. I’ve helped Emily through bits and pieces of putting sampled audio on an Arduino using Mozzi, but I had yet to run through the whole process myself.

The hardware side was kept as simple as possible: there’s only a single switch wired to be normally open and momentarily closed. For audio output, I used the wire salvaged from the Project MC2 Pixel Purse(*) that was briefly a hacker darling due to its clearance-sale price. (As of this writing, the price is up to $39.58, far above the $6 – $8 leading to its “buy to take it apart” fame.) Since this cable was designed to be plugged into a cell phone, it had a TRRS plug that I rewired into an imitation of a monophonic TS plug by using the T wire and connecting RRS together into another wire.

With hardware sorted out, I dived into the software tasks. There were more than a few annoyances that make this task not very beginner-friendly. The Huffman audio compression utility audio2huff.py had dependencies listed only in a comment block easily overlooked by beginners. They didn’t all install in the same way (purehuff required a download and install, while the others were installed via pip.) And since they are a few years old and not actively maintained, they were all written for Python 2.

This will become more and more of a problem as we go, since Python 2 support has just officially ended at the start of 2020. Older Linux distributions would launch Python 2 when the user runs python at the command line, and those that want to use Python 3 would need to run python3. This is getting flipped around and some environments now launch Python 3 when the user runs python and those that need the old stuff has to run python2.

What happens when we run these utilities under Python 3? It’d be nice if the error message is “Hey, this needs Python 2” but that’s not the reality. It is more likely to be something like “foobar is not iterable” completely bewildering to beginners.

To be fair, none of these are problems specific to Mozzi, there’s a large body of work online that were written for Python 2 and waiting for someone motivated enough to bring them up to date.

Anyway, after those problems are sorted out, I got my Arduino to play a sound when the button is pressed. My test sound clip was from the game Portal 2: the ecstatic “SPAAACE!” emitted by the corrupted Space Core when it finally got its wish to go flying through space.

This Arduino Mozzi exercise is publicly available on Github.

[UPDATE]: “Wilhelm” exercise (round 2) has some improvements.


(*) Disclosure: As an Amazon Associate I earn from qualifying purchases. But you shouldn’t buy a Pixel Purse until it drops back down to clearance prices.

Examining Composite Video Signal Generated By Microcontrollers

There was a several-years-long period of my life when I spent money to build a home theater. This was sometime after DVD became popular, because the motivation was my realization of how much superior DVD picture quality was over VHS. With movies on VHS, noisy visual artifacts were a limitation of the analog magnetic medium. With movies on DVD, the media-imposed limitations were gone and now there are all these other limitations I could remove by spending money, lots of it, to do things like upgrade from composite video to S-Video connections.

Eventually home theater moved to all digital HDMI, and I stopped spending big money because even the cheapest flat panels could completely eliminate classic CRT problems like color convergence. (My personal peeve.) I thought I have left the era of CRT and composite video behind, but throwing out my pile of analog interconnects and video equipment turned out to be premature.

Now I’ve found an interest in old school video again, because they are accessible for the electronics hobbyist. It is much easier to build something to output a composite video signal rather than HDMI. Local fellow maker and tinkerer Emily likes the old school tech for aesthetics reasons in addition to accessibility. So one day we got together at one of our regular SGVTech meets to dig a little deeper into this world.

Emily brought an old portable TV with composite video input, and two candidate Arduino sketches each purporting to generate composite video. (arduino-tvout and one other whose name I can’t remember now.) I brought my ESP32 dev module running Bitluni’s composite video demo. For reference Emily had an actual composite video camera, the composite video Wikipedia page and the reference document used by Bitluni for his demo.

All three were able to get the little TV to show a picture. However, they looked very different under the oscilloscope. The [name will be filled in once I remember] sketch had the wildest waveform whose oscilloscope trace didn’t look anything like a composite video signal, but the proof is in the fact an animated 3D vector graphic cube showed up on the TV anyway. The waveform generated by arduino-tvout was a little rougher than expected, but unlike the previous, it was clearly recognizable as a composite video waveform on the oscilloscope and accepted by the TV. Waveform generated by Bitluni is the best fit with we expected to see, and matched most closely with output generated by the composite video camera.

Knowledge from tonight’s investigation will inform several of our project candidates.

 

Optical Drive Carriage, The Sequel

During my learning and exploration of stepper motor control, I managed to destroy an optical carriage I salvaged from a laptop drive. In order to continue experimentation I need another stepper motor linear actuator of some kind. I rummaged in my pile of parts and came up empty-handed, but I am fortunate to have another local resource: Emily‘s pile of parts. My request was granted with an assembly that had an intact motor, drive screw, and linear carriage. The optical assembly in that carriage had been torn apart, but that is irrelevant for the purposes of this project.

Unlike the previous two stepper motors I played with, this one has exposed pads on the flexible control cable so I tried to solder to them. Given my experience soldering fine pitched parts, I knew it’s problematic to solder one at a time: they are so close together heat from one pad will melt solder on an adjacent pad. My best bet is to set things up so all the wires are soldered at the same time.

Emily salvaged stepper motor wiringThere is slightly less solder than I would have preferred on each of these joints, but several efforts to add solder created solder bridges across pins. Requiring removal by solder sucker, which reduced the amount of solder even more. Since there was enough for electrical conductivity, I left it as is to continue my experiments.


Unrelated to stepper motors or Grbl:

While I was taking the above picture to document my work, I noticed I was being watched and took a picture of the watcher. This little beauty was surveying my workbench perched on top of a cardboard box of M3 fasteners from McMaster-Carr. The spider was only about 5mm long overall including legs. Unfortunately at the time of this shot I had set it for shallow depth of field to photograph the above solder joint. I adjusted my camera to bring more into focus, but this little one was camera shy and jumped away before I could take a better shot. Still, I’m quite pleased with my camera’s macro lens.

Spider on McMaster Carr box

Panasonic UJ-867 Optical Carriage (Briefly) Under A4988 Control

Once I extracted the optical assembly carriage of a Panasonic UJ-867 optical drive, the next step is to interface it with a Pololu A4988 driver board. And just as with the previous optical drive stepper motor, there are four visible pins indicating a bipolar motor suitable for control via A4988. However, this motor is far smaller as befitting a laptop computer component.

Panasonic UJ-867 70 stepper motor connector

The existing motor control cable actually passed through the spindle motor, meaning there were no convenient place to solder new wires on the flexible connector. So the cable was removed and new wires soldered in its place.

Panasonic UJ-867 80 stepper motor new wires

Given the fine pitch of these pins it was very difficult to avoid solder bridges. But it appeared to run standalone so I reinstalled into the carriage. Where it still ran – but was very weak. Hardly any power at all. When I tilted it up so the axis of travel is vertical, the carriage couldn’t win its fight against gravity. Since the job is only to move an optical assembly, I didn’t expect these carriages exert a great deal of force. But I’ve seen vertically mounted slot loading optical drives. I thought it should at least be able to fight against gravity.

A Dell laptop charger delivers 19.2V. I’m not sure how many volts this motor intended to run at, but 12V seemed reasonable. Then I increased current beyond the 50mA of the previous motor. Increasing both voltage and amperage seemed to help with more power, but it remained too weak to overcome gravity.

As I’m tilting the metal carriage assembly in my hand, I started noticing it was warming. Oh no! The motor! I checked the temperature with my finger, which was a mistake as it was hot enough to be painful to human skin. I shut down my test program but it was too late, the carriage never moved again.

Lessons learned: don’t get too overzealous with power and check temperature more frequently.

And if I want to continue these experiments, I’ll need another stepper motor assembly.

Resuming Pololu Stepper Driver Adventures with Arduino and A4988

By the time I got around to playing with homing switches on a salvaged industrial XY stage, it was getting late. I only had a few minutes to perform one experiment: connect the normally open homing switch to X_LIMIT_PIN (GPIO02 as per cpu_map.h), set HOMING_CYCLE_0 to X_AXIS in config.h, and sent command to home X-axis. The motor moved right past the switch into the hard stops, so I turned off the ESP32 marking an unsatisfying end to the work session.

I wanted to be able continue learning Grbl while at home, away from the salvaged hardware, so I dug up the A4988 motor control board I’ve played with briefly. It’s time to get a little further in depth with this thing. Motivated by my current state in the XY stage project, the first goal is to get a stepper motor to activate a homing switch. If I could get that far, I’ll think about other projects. People have done some pretty creative things with little stepper motors controlled by Grbl, I could join that fun.

Rummaging through my pile of parts, the first stepper motor I retrieved was one pulled from an optical drive. This particular stepper motor had only the drive screw, the carriage has been lost. But with four exposed pins in two groups of two, it is a bipolar motor suitable for an A4988 motor control board. I just had to solder some wires to make it usable with a breadboard.

Since this stepper motor was a lot smaller than the one used in my previous A4988 stepper motor experience, I thought this was a good opportunity to learn how to tune the current limits on these modules by following instructions published by Pololu and using an Arduino as a test controller running code published on this page. I started with a limit of 100mA, but the motor got quite toasty at that level after running for a minute. I turned it down to 50mA, and it no longer got hot to the touch running that Arduino sketch.

This is a good start, but a motor with just a drive shaft is not useful for motion control. The next step is to find something that could push on a limit switch. I don’t seem to have anything handy, so it’s time to start digging into salvaged hardware.

Evaluate Retired Melzi Board for XY Stage

In an effort to put a salvaged industrial XY table back to work, the Arduino AccelStepper was used as a quick test to see if the motors and controllers still respond to input signals. Things moved, which is a good sign, but the high precision of the Parker ZETA4 controller demanded step pulses at a far higher frequency than what AccelStepper could deliver.

The search then moved on to something that could generate the pulses required. I’m confident the hardware is capable of more, as AccelStepper topped out at less than 5 kHz signal on a 8 MHz chip. Pulsing a pin isn’t a task that requires over 1,000 instruction cycles. Given familiarity with the 3D printer world, I started looking at Marlin which runs on Arduino hardware.

The problem with running Marlin on my Arduino Nano is that I would have none of the associated accessories. No control panel, no SD reader, etc. However, I do have a full control board retired from one of my 3D printers. This board called itself a Melzi Ardentissimo and a search led to the Melzi page of RepRap wiki. Thanks to the open nature of this design, I could trace through its PCB layout. Much to my disappointment, the step and direction signals connected straight from the tiny pin on the main processor to the motor driver without surfacing in an easily tapped fashion. The intent of this board is integration and it’ll be quite some work to defeat that intent in order to decouple the processor from its integrated stepper driver.

Fortunately, I’m not limited to the world of AVR ATmega chips, nor Marlin software. There’s another very capable processor on hand waiting for such project… an ESP32 running Grbl software.

Arduino AccelStepper Under The Scope

The standard Arduino library includes a stepper motor control library. The external AccelStepper library adds the capability for acceleration and deceleration curves. I thought that would be important for driving industrial equipment as the large pieces of metal impart far more momentum than what I’m familiar with in a 3D printer.

As it turns out, I was worrying about the wrong thing. I connected my bargain oscilloscope to the output pins of my (knockoff) Arduino Nano and watched the pulses go by as I issue different commands to AccelStepper. As I issued commands for faster and faster speeds, I could see those pulses come closer and closer together until they were almost but not quite 0.2 ms apart. Running a test program in a tight loop, an Arduino running AccelStepper is indeed failing to reach 5 kHz pulse speed.

A little web search indicated this is roughly comparable to what others are saying online. AccelStepper is good for roughly 3-4 kHz and things get dicey beyond that. For the ZETA4 controller, configured to 25,000 microsteps per revolution, this is simply not fast enough to get decent speed out of the box.

How does this happen? Further web search indicated this is because all the timing for AccelStepper is done in software. Perhaps for the goal of leaving the very precious hardware timer resources for other user programs? That’s merely speculation of the design decisions involved. But one thing is certain – AccelStepper limits meant it is not sufficient for generating high frequency pulses required to drive this particular salvaged XY motion control table. I’ll have to look at something more specific for motion control, possibly a 3D printer control board.

Old Industrial XY Stage Moves Again On Arduino AccelStepper

A decades-old piece of industrial equipment has failed and been retired, but its motion control table was still good and salvaged for a potential future project. It is a far cry from the kind of motion control equipment I see on a hobbyist 3D printer. Much more rigid chassis, more precise linear guides, finer pitch thread, far beefier motor, under the command of a much more capable control box. One example: the A4988 stepper motor popular in 3D printers features the capability to generate up to 16 microsteps in between whole steps of a stepper motor. In contrast this Parker ZETA4 unit features up to 255 microsteps.

Pulling from the electronic hobbyist world, I set up my Arduino to run the AccelStepper library generating stepper motor direction and pulse signals. It was connected to one axis of the XY stage for the first test. It was exciting when the motor started turning, but it was very very loud! I doubted it was supposed to sound like that. A bit of examination found two problems: the ZETA4 was configured to take whole steps — no microsteps — which is always noisy. And I amplified this mistake by accidentally choosing a speed that caused a resonance.

Once the ZETA4 was configured to its default of 125 microsteps, things were much quieter and smoother. It also slowed down significantly, because each pulse on the step pin moved 1/125 as far as it did before. (And a full revolution of the motor was only 200 steps.) The obvious answer was to increase frequency of those pulses, but I seemed to top out at around 5,000 pulses per second. This surprised me: The ATmega328 chip on board an Arduino is running at 8MHz. I would have expected it to easily generate pulses faster than 5 kHz. Time to put this guy under the oscilloscope and see what we see.

Arduino Accelerometer Success On Second Try: Mozzi + MMA7660

When we left off earlier, Emily and I determined that getting her MMA7660 I2C accelerometer breakout board to work with Mozzi on an Arduino will require more work than it looked at first glance, and probably not worth the trouble. Emily has since moved on to a different accelerometer module, one which communicates via analog voltage values. But I had a harder time letting go. Some helpful comments on Twitter plus Randy Glenn’s comment on the previous blog post motivated me to take another run with different objectives.

The first change was a reduction in problem scope: I originally thought I’d update the MMA7660 library using fragments from Mozzi’s non-blocking I2C example. This time I’m going the other way: I’m modifying Mozzi’s non-blocking I2C example by pulling fragments from the MMA7660 library. This is a tiny subset of capability and coding. Notably absent are any sort of error-handling… not even that wacky use of goto that make seasoned programmer eyes twitch.

The second change was a change in attitude: I see a lot of violations of good coding conventions, and I wanted to fix them all. Especially problems horrible for code robustness such as poor error-handling. But talking with others who have played with Arduino longer than I have, I learned code quality has not exactly been a barrier for people putting Arduino code online. As I’m starting with a piece of Mozzi example code, all I had to do is make sure I don’t make that code worse, and I should be good to go.

Easing those two constraints (a.k.a. lowering expectations) made for a much easier task, one which was ultimately successful! The Mozzi example chirped at one of three different pitches depending on if the ADXL345 reported X, Y, Z value over half of its range. (And stays silent if none of them were.) Now it chirps in response to MMA7660 data instead. Here’s the short demonstration video I tweeted. (Be sure to turn on sound.)

There was one technical challenge in capturing that video clip: I didn’t have an audio amplifier on hand, so the tiny speaker was powered directly by the Arduino Nano and thus extremely quiet. To capture the chirps, I plugged in a wired earbud headphone with mic to my cell phone for filming. Its microphone module was placed next to the quietly chirping speaker and visible in the picture/video. I prefer not to have such items in the field of view, but it’s what I had to do.

It turns out the MMA7660 is not appropriate for what Emily had in mind anyway. This module was designed for detecting portrait/landscape orientation and had very poor resolution: 5 bits, or values from zero to 63 to cover a range +/- 1.5G. Moving through an 180 degree arc under normal gravity, we see about 40 out of those 64 values. This translates to one tick every ~4.5 degrees. A gently swinging pendulum like what Emily had in mind would only ever see four or five different values through its entire range of motion and not nearly enough to make interesting sounds.

But that’s OK, I’m sure it’ll be useful for something else in the future. I’ve made my modified Mozzi example available on Github in case Emily or I or anyone else decide to put the MMA7660 accelerometer in a Mozzi sketch. And if someone is less interested in that specific module but more curious about how to adapt from one I2C peripheral to another, they can look at this commit to see every line I changed.

Aborted Attempt At Arduino Accelerometer: Mozzi + MMA7660

Every tool has its use, and for quick prototype of electronic ideas, it’s hard to beat an Arduino. A huge community of users has generated an equally huge selection of libraries to get any hardware up and running quickly. The downside is that there’s no way to ensure they all work together. Playing with a single library is easy, but getting more than one to play nicely together is a hit-or-miss affair. Today’s story is a miss.

Mozzi is an Arduino library for sound synthesis. It allows Arduino creations to audibly react to external input, and is the brains behind the Rackety Raccoon project. Its inputs were potentiometers connected to an Arduino’s analog pins. To follow up that project, Rackety Raccoon creator Emily wanted to use an accelerometer chip as input.

The device Emily had on hand was a small breakout board for the MMA7660FC. It communicates via I2C and there’s an Arduino library available. But when it was added into a Mozzi sketch, verification fails with the following error:

libraries/Wire/utility/twi.c.o (symbol from plugin): In function `twi_init':
(.text+0x0): multiple definition of `__vector_24'
libraries/Mozzi/twi_nonblock.cpp.o (symbol from plugin):(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
exit status 1

This error message is spectacularly unhelpful even though it is technically correct on all counts. There is indeed a collision in defining interrupt vector table entries, but Arduino’s target user demographic would have no idea what that means. At a higher level, the problem is that we have two chunks of code both trying to perform I2C communication. MMA7660 sample code uses the standard Arduino Wire library, Mozzi has its own I2C communication library. They both use the same hardware resources and hence the collision. Only one of them may exist in an Arduino sketch.

Why would Mozzi have its own I2C library? The hint comes from the name: “twi_nonblock“. Mozzi is an audio library and it is critically important for Mozzi to run nonstop. Any interruptions would become audible glitches! This is a problem for receiving I2C data using the Wire library because it would wait (“block”) for the I2C peripheral (accelerometer in this case) to respond.

Mozzi can’t wait, hence the twi_nonblock I2C communication library as a replacement for Arduino’s standard Wire library. In order to use MMA7660 with Mozzi on an Arduino, the portions dependent on Wire library must be replaced with counterparts in Mozzi’s twi_nonblock. Mozzi includes sample code to communicate with another I2C accelerometer, the ADXL345.

Examining the sample, we see it is a straightforward line-by-line replacement when sending I2C data. The sample function acc_writeTo() includes comments explaining the Wire equivalent for each line.

// Writes val to address register on device
void acc_writeTo(byte address, byte val) {
  // Wire.beginTransmission(ADXL345_DEVICE); // start transmission to device
  twowire_beginTransmission(ADXL345_DEVICE); // start transmission to device
  // Wire.send(address); // send register address
  twowire_send( address );
  // Wire.send(val); // send value to write
  twowire_send( val );
  // Wire.endTransmission(); // end transmission
  twowire_endTransmission();
}

Which would serve as an excellent guide to rewrite MMA7660::write() from its current Wire format.

void MMA7660::write(uint8_t _register, uint8_t _data) {
  Wire.begin();
  Wire.beginTransmission(MMA7660_ADDR);
  Wire.write(_register);
  Wire.write(_data);
  Wire.endTransmission();
}

In contrast, receiving I2C data would not be a trivial line-by-line replacement. The nature of twi_nonblock meant we have to change a lot more code in order to convert it from a simple synchronous blocking procedure to an asynchronous non-blocking process. If the MMA7660 module and associated library were well-executed, it would not be technically challenging, just time-consuming. And it might be something good we can do to contribute back to the Arduino community.

MMA7660 demo code says it is bad and uses goto

Sadly it was not a shining example of excellence. A comment saying “it is bad” raised warning flags about weird behavior from the chip. Then a few lines later, we see a goto statement as an ugly hack around the chip’s behavior. This is when we decided to “Nope!” out of there and abort this particular investigation.

UPDATE: A week later I took another look, and the second try was successful.

Sawppy Roving With Wired Handheld Controller

I now have a basic Arduino sketch for driving Sawppy using a joystick, I’ve built a handheld controller using an Arduino Nano and a joystick, and an input jack for interfacing with Sawppy. It’s time to put it all together for a system integration test.

Good news: Sawppy is rolling with the new wired controller! Now if there’s too much electromagnetic interference with Sawppy’s standard WiFi control system, we have a backup wired control option. This was the most important upgrade to get in place before attending Maker Faire Bay Area. As the flagship event, I expect plenty of wireless technology in close proximity at San Mateo and wanted this wired backup as an available option.

This successful test says we’re in good shape electrically and mechanically, at least in terms of working as expected. However, a part of “working as expected” also included very twitchy movement due to super sensitive joystick module used. There is very little range of physical joystick movement that maps to entire range of electrical values. In practice this means it is very difficult to drive Sawppy gently when using this controller.

At the very minimum, it doesn’t look very good for Sawppy’s to be seen as jittery and twitchy. Sharp motions also place stresses on Sawppy’s mechanical structure. I’m not worried about suspension parts breakage, but I am worried about the servos. Steering servo are under a lot of stress and couplers may break. And it’s all too easy to command a max-throttle drag racing start, whose sudden surge of current flow may blow the fuse.

I had wanted to keep the Arduino sketch simple, which meant it directly mapped joystick movement to Sawppy motion. But it looks like translating the sensitive joystick’s motion directly to overeager Sawppy is not a good way to go. I need to add more code to smooth out movement for the sake of Sawppy’s health.

Sawppy Wired Controller Enclosure

I now have an assembly of circuit boards that has all the electronics I needed to create a wired controller for Sawppy the Rover. Now I need an enclosure to make it easy to hold, protecting both my skin against punctures by header pins and also protecting the soldered wires from damage.

The first task is to measure dimensions and iterate through design of how I would hold the assembly using 3D printed plastic. It evolved into two separate pieces that mate up with left and right sides of my prototype circuit board.

The next step is to design and print two small parts to hold on to the wire. The idea is to have it take some stress so tugs on the wire do not rip my 4-pin JST-XH connector from my circuit board. And finally, an exterior shell to wrap all of the components.

Sawppy handheld controller unassembled

The exterior shell was an opportunity to play with creating smooth comfortable hand-conforming organic shapes. Designing this in Onshape was a bit of an square peg in round hole situation: standard engineering CAD is tailored for precision and accuracy, not designing organic shapes. That’s the domain of 3D sculpting tools, but I made do with what I had available in Onshape.

Given a bit more time I could probably incorporate all the design lessons into a single 3D printed piece instead of five separate pieces, but time is short and this will suffice for Maker Faire Bay Area 2019.

Now that I have one end of my wired serial communication cable, it’s time to look at the other end.

Sawppy handheld controller assembled

Arduino Nano Forms Core Of Sawppy Wired Controller

At this point in the project, I have an Arduino sketch that reads an analog joystick’s position and calculates speed and position for Sawppy’s ten serial bus servos to execute that command. Now I turn my attention back to the hardware, which up until this point is a collection of parts connected by jumper wires. Good for experimental prototyping, not good for actually using in the field.

The biggest switch is from using an Arduino Uno clone to an Arduino Nano clone (*). The latter is far smaller and would allow me to package everything inside a single hand-held assembly. Both Arduino are based on the same ATmega328 chip and offers all the input and output I need for this project. Typically, beginners like to start with an Uno because of its selection of compatible Arduino Shields, but that is not a concern here.

This specific Arduino Nano will be mounted on a prototype perforated and plated circuit board. It is placed on one end of the board in order to keep its USB port accessible. Two other components were soldered to the same prototype board: a 4-pin JST-XH connector for power and serial communications, and an analog joystick module.

My mess of jumper wires were then replaced by short segments of wire that are soldered in place for greater reliability. This is a relatively simple project so there aren’t very many wire connections, and they all easily fit on the back.

Arduino nano with joystick on PCB back

In theory the Arduino sketch can be seamlessly switched over to this board. In practice I saw bootloader errors when I plugged in this board. It turns out, for this particular clone, I needed to select the “Tools” / “Processor” / “ATmega328P (Old Bootloader)” option in Arduino IDE. As a beginner I’m not completely sure what this meant, but I noticed sketch upload speed is significantly slower relative to the Uno. My source code was unchanged and it all still worked. A few test drive sessions verified this little hand held assembly could drive Sawppy as designed.

Next step: an enclosure.


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

Prototype Arduino Wired Controller For Sawppy

Once I had basic control of LewanSoul LX-16A serial bus servo via analog joystick with an Arduino Uno, it was time to write code to perform trigonometry math necessary to calculate Ackerman steering angle and speed for each of Sawppy’s six wheels. Conceptually this is a port of code I wrote for the SGVHAK Rover project. However, that had the benefit Python, a high level friendly language.

The first concern came from reviewing Arduino Language Reference page. Under Trigonometry section it lists cosine, sine, and tangent functions but I didn’t see their counterparts arccosine, arcsine, and arctangent which I needed. I was never worried that I might have to reimplement my own math library: surely one would exist! They’re too useful and the Arduino ecosystem is too large for them not to.

It turned out I didn’t have to go very far in my search: underneath all the beginner-friendliness the board still runs an ATmega328 chip of the AVR microcontroller product line. And Arduino has not deviated from core language for programming that chip, so I could pull in the standard AVR <math.h> library to gain acos(), asin() and atan() functions.

I only had to duplicate the math for an Arduino counterpart, I didn’t try to replicate all the features of my Python code since some of them relied on the nature of Python for their flexibility. Still, even with the simplifications (or possibly because of them?) the code was different enough for some bugs to slip in. I ended up retracing through my steps using pen and paper to debug a few problems.

Once debugged, I had a crude wired controller for Sawppy. An analog joystick connected to my Arduino Uno with jumper wires provides user input. My freshly written code translates the joystick position to four corner steering angles and six wheel velocities, and sends out commands to all ten LewanSoul serial bus servos using Arduino’s UART TX pin connected to LewanSoul BusLinker via another pair of jumper wires.

Next task: make this Arduino wired controller more compact and more reliable with soldered wire connections to replace these jumper wires.

(Code for this project is publicly available in the arduino_sawppy subdirectory of Sawppy Rover’s Github repository.)

Arduino Control Of LewanSoul LX-16A Servo Via Joystick Commands

Once I climbed a few early steps on the Arduino IDE learning curve, I was off and running writing code. Fortunately the underlying code for programming an Arduino is still the C++ I’m familiar with. I picked up where I left off earlier with the analog joystick tutorial, now shuffled off to its own C++ class. I then looked over the sample code released by LewanSoul for controlling LX-16A servos in the form of a single flat Arduino sketch file. All with the goal of controlling these LX-16A servos. (*)

I don’t plan on using most of the functionality of that sketch, but I thought it was easiest to lift the code wholesale rather than putting time into extracting just the parts I wanted to use. The code was written as flat top-level APIs, but it wasn’t difficult to write a small class that exposed a few methods which called into the two API I cared about. One to make a LX-16A move to a specific position, the other to make it rotate continuously.

There were a few rounds of experimentation on how exactly to communicate intent across this API. Using values as directly dictated by LewanSoul would have worked fine for this one case, but I didn’t want to be tied to one specific servo. Like my SGVHAK Rover software project, I wanted this code to be adaptable to multiple motor implementations which meant a more general description of motor action.

I tried percentages for both, ranging from -100% to +100%. For position servo, this would mean -100% is full deflection left, 0 is center, and +100% is full deflection right. And for continuous rotation, -100% is full speed reverse, 0 is stopped, and +100% is full speed forward.

Speed worked well but position did not: different servo will have different ranges of motion, so full deflection would mean different angles for different servos. So that was changed to angle in degrees. In the case of LewanSoul, -120 degree to +120 degree.

This was enough to let me control two servos with an Arduino, based on position of the connected analog joystick. This is sufficient control for my standard “rover wheel on a stick” test case, a good milestone before proceeding onwards.

(Code for this project is publicly available in the arduino_sawppy subdirectory of Sawppy Rover’s Github repository.)


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

Additional Source Code In Arduino Sketches Are Tabs Not Files

Being an electronics hardware tinkerer, there was no way for me to be ignorant about Arduino, but it never quite seemed to fit what I needed for a project: if I wanted computing power I used a Raspberry Pi, and if I wanted inexpensive low-level microcontroller I used a PIC. But I wanted to make Sawppy friendlier to beginners, and that was my motivation to finally start learning about the Arduino ecosystem.

I understand Arduino’s success is largely credited to how its creators underwent a clean-sheet examination at physical computing with the specific goal of making things easy for beginners to get started. A clean-sheet approach meant that tenure was meaningless. If the creators felt it was not helpful to beginners, it was gone regardless of whether it was a long standing tradition. I read this philosophy repeatedly as I was learning about Arduino, one example among many was this statement from Arduino API design style guide:

Some of these run counter to professional programming practice. We’re aware of that, but it’s what’s made it possible for so many beginners to get started with Arduino easily.

After I felt I had done enough reading to feel like I was properly oriented, I embarked on my project to started writing code for driving Sawppy using an Arduino. It didn’t even take 5 minutes before my well-worn habits ran into a collision with The Arduino Way. I wanted to put joystick tutorial code in its own header (*.h) and source (*.cpp) files instead of putting it in the top level sketch (*.ino) file… and I couldn’t do it.

I selected “File”/”New” in the Arduino IDE, but that created a new Arduino sketch (*.ino). I poked around in various options on the file creation dialog, hoping to see a “create new header file” or similar, but saw nothing dealing with file types. I could see how file types might be confusing to beginners, so it’s Arduino design in practice: avoid file types even if it disorients long time computer programmers.

And I was definitely disoriented. I was so stuck in my old ways I couldn’t figure out what might have replaced it in Arduino IDE. I eventually found my answer by downloading an existing Arduino project with multiple source files and opening it in the IDE: additional source files are tabs! In the Arduino IDE, a “document” is a complete sketch with all its parts. If source code is spread across multiple files on disk, they are represented as tabs when the document was opened.

So in order to create a separate set of files for my joystick code, I need to select “New Tab” and give it the filenames I intended. One tab for joydrive.h and one for joydrive.cpp.

My relationship with Arduino is off to a rocky start, but I’m sure we’ll work it out.

 

Learning How To Write Arduino Libraries and Tutorials

For small software projects like a typical beginner Arduino sketch, we can get away with putting everything in a single *.ino file. This was the way LewanSoul served up their Arduino sample code for controlling LX-16A serial bus servos. But as a software project grows in size, proper organization of software modules become more important.

While I don’t intend to tackle the task of writing a big Arduino sketch, I did want to get an idea of how to write my Arduino code in a way that can be reused in their own installable Arduino library. That’s a powerful part of Arduino’s software ecosystem, but I don’t want to just consume other libraries… I want to get a little practice in so I have the option to write my own libraries later.

I started by reading about the mechanics of creating an Arduino library. As expected of the world of low power microcontrollers, programming is done in C and a library has, at a minimum, a *.h header file and a *.cpp implementation file. This was all in order, an Arduino-specific twist is the IDE integration with keywords.txt. That I didn’t expect. Everything is packed in a ZIP file.

Next I moved on to Arduino’s API design style guide. This is less about the mechanical details, and more about how to structure an Arduino API. This passage caught my attention:

Some of these run counter to professional programming practice. We’re aware of that, but it’s what’s made it possible for so many beginners to get started with Arduino easily.

This might be what caused some of my irritation with Arduino code – design decisions that ran counter to my professional practice, but now I understand there’s a well-meaning reason for it.

From there reading moved to the Arduino style guide for how to structure tutorials that accompany code, then I went back to see the analog joystick tutorial I had referenced earlier, this time as an example of Arduino tutorial style.

Examining LewanSoul Arduino Library

When I first built Sawppy using LewanSoul LX-16A serial bus servos (*), I was not interested in using their PC software which was tailored to running pre-scripted sequences of motion. At the time I was not using an Arduino, either, so I wrote my own serial communication driver in Python based on LewanSoul’s PDF documenting their serial communication protocol.

This time around, I am using an Arduino and eager to take advantage of already prebuilt software to cut down on development time. In the same Dropbox where I found my LewanSoul Bus Servo Communication Protocol.pdf reference document, there was a file LSC series communication routines of controller.zip. Now that I’ve seen Arduino libraries packaged in a zip file, I looked inside to verify the structure of having *.cpp and *.h source files. It turns out they were packaged inside that zip file as another file LobotServoController.zip. This zip file within a zip file looked like an Arduino library, with LobotServoController.h header file and LobotServoController.cpp source, a keywords.txt for Arduino IDE syntax highlighting, and a few *.ino sketch files inside an example directory.

It all looked very promising at first glance but a closer look deflated the initial enthusiasm. The API only had commands for servo position, nothing for continuous rotation mode which is how Sawppy’s six wheels roll on the ground. And looking under the hood inside the code, the serial communication header is in the wrong format. The first two bytes are LewanSoul identifiers 0x55 0x55 as expected, but the third byte is length, not servo ID.

Digging a little deeper, I realized despite its location in the LX-16A Bus Servo subdirectory of LewanSoul’s Dropbox, this Arduino library was not for controlling LX-16A devices. They are, as the file name stated (but I overlooked) intended for their LSC line of controller boards for standard RC servos, not the serial bus servos.

Sadly, this promising-looking Arduino library will not help me.

Code for LX-16A servos actually lived in a different folder: bus servo communication routines held Arduino sketches matching the expected protocol. However, they were written as individual one big flat *.ino file, and not written as an Arduino library.

This is fine for sample code, but not well suited to be part of a larger project. It looks like I’ll need to learn to how to write an Arduino library after all, either to convert this LewanSoul sample code into a library or create my own from scratch (again).


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

Taking An Arduino Crash Course

Now that I’ve got the first few basic experiments up and running on my Arduino compatible board, I should invest a little time into learning what I’m dealing with here. Fortunately there is no shortage of informative pages on the web to take me beyond the simplistic “Hello World” blinking LED demo for an Arduino Uno. At the end of that tutorial, Arduino point the user towards to either further practice with the desktop IDE or go browse the project hub. I found the former lacking in technical information I desire and the latter was mostly irrelevant to the project idea I have on hand.

I then turned to one of my favorite resources: Adafruit’s extensive tutorials. Specifically their Arduino learning center. To get a grounding on what’s actually on an Arduino Uno board, “Lesson #0” orientation is a great start. For a little more advanced information on Arduino Uno hardware (and how it has evolved since the initial release) their hardware tips, tricks, and techniques was quite informative.

But the computing hardware was never the core strength of the Arduino platform, it was the extensive ecosystem of code libraries. These libraries allow users to assemble code modules together like LEGO pieces to build projects. People don’t have to know every nut and bolt of how to write software for everything, because it has already been done and available as an Arduino library.

The selection of Arduino libraries has grown enough there’s a dedicated library manager to keep things under control, and of course Adafruit has a walkthrough for the library manager as well. At this point I already saw how to interface with a simple potentiometer joystick, and I knew there exists a servo library for controlling standard RC servos. I also saw LewanSoul offers Arduino library to control the LX-16A servos. In theory, these code libraries should let me build an Arduino-based Sawppy controller with minimal coding. Let’s find out if the theory matches practice…