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.

Window Shopping Chirp For Arduino… Actually, ESP32

Lately local fellow maker Emily has been tinkering with the Mozzi sound synthesis library for building an Arduino-based noise making contraption. I pitched in occasionally on the software side of her project, picking up bits and pieces of Mozzi along the way. Naturally I started thinking about how I might use Mozzi in a project of my own. I floated the idea of using Mozzi to create a synthetic robotic voice for Sawppy, similar to the voices created for silver screen robots R2-D2, WALL-E, and BB-8.

“That’d be neat,” she said, “but there’s this other thing you should look into.”

I was shown a YouTube video by Alex of Hackster.io. (Also embedded below.) Where a system was prototyped to create a voice for her robot companion Archimedes. And Archie’s candidate new voice isn’t just a set of noises for fun’s sake, they encode data and thus an actual sensible verbal language for a robot.

This “acoustic data transmission” magic is the core offering of Chirp.io, which was created for purposes completely unrelated to cute robot voices. The idea is to allow communication of short bursts of data without the overhead of joining a WiFi network or pairing Bluetooth devices. Almost every modern device — laptop, phone, or tablet — already has a microphone and a speaker for Chirp.io to leverage. Their developer portal lists a wide variety of platforms with Chirp.io SDK support.

Companion robot owls and motorized Mars rovers models weren’t part of the original set of target platforms, but that is fine. We’re makers and we can make it work. I was encouraged when I saw a link for the Chirp for Arduino SDK. Then a scan through documentation of the current release revealed it would be more accurately called the Chirp for Espressif ESP32 SDK as it doesn’t support original genuine Arduino boards. The target platform is actually the ESP32 hardware (connected to audio input and output peripherals) running in its Arduino IDE compatible mode. It didn’t matter to me, ESP32 is the platform I’ve been meaning to gain some proficiency at anyway, but might be annoying to someone who actually wanted to use it on other Arduino and compatible boards.

Getting Chirp.io on an ESP32 up and running sounds like fun, and it’s free to start experimenting. So thanks to Emily, I now have another project for my to-do list.