Posts with «hackaday columns» label

KIM-1 to COSMAC Elf Conversion — Sort Of

In the mid-1970s, if you had your own computer, you probably built it. If you had a lot of money and considerable building skill, you could make an Altair 8800 for about $395 — better than the $650 to have it built. However, cheaper alternatives were not far behind.

In 1976, Popular Electronics published plans for a computer called the COSMAC Elf which you could build for under $100, and much less if you had a good junk box. The design was simple enough that you could build it on a piece of perf board or using wire wrap. We featured the online archive of the entire Popular Electronics collection, but hit up page 33 of this PDF if you want to jump right to the article that started it all. The COSMAC Elf is a great little machine built around a 40-pin RCA 1802 processor, and for many was the first computer they owned. I lost my original 1802 computer in a storm and my recent rebuild in another completely different kind of storm. But there is a way to reclaim those glory days without starting from scratch.  I’m going to repurpose another retro-computing recreation; the KIM-1.

I’ll admit it, Rewiring a real KIM-1 to take an 1802 CPU would be difficult and unnecessary and that’s not what this article is about. However, I did have a KIM UNO — [Oscar’s] respin of the classic computer using an Arduino mini pro. Looking at the keyboard, it occurred to me that the Arduino could just as easily simulate an 1802 as it could a 6502. Heck, that’s only two digits different, right?

The result is pretty pleasing. A “real” Elf had 8 toggle switches, but there were several variations that did have keypads, so it isn’t that far off. Most Elf computers had 256 bytes of memory (without an upgrade) but the 1802 UNO (as I’m calling it) has 1K. There’s also a host of other features, including a ROM and a monitor for loading and debugging programs that doesn’t require any space in the emulated 1802.

Repurpose

The KIM UNO has 24 switches. There are 16 for the hex digits, of course. The top two rows mimic functions from the original KIM-1. A real Elf had a way to input a byte (usually 8 toggle switches), a load switch, a run switch, a memory protect switch, and a push button wired to a CPU pin. That means the hardware has more than enough switches.

On the display side, a normal Elf had a single-byte hex display although some clones had more. There was also the Q LED that a program could light or extinguish. The KIM UNO hardware has many 7-segment displays so it is possible to put those digits to use like an Elf clone. There isn’t an LED, however, except for the Arduino’s built in LED which is not normally visible in operation. However, the digital displays have decimal points and they are connected to the Arduino. So if you don’t mind using those, you have plenty of LEDs, too.

The hardware is open source and easy to duplicate. [Oscar] sometimes has kits as well and they are very inexpensive (about $20).

The KIM UNO software is open source, so I started there. I first stripped all the code out of the main file other than the parts that drove the display and the keyboard, then built up everything need to suppot 1802 emulation. You can find all the code in my 1802UNO GitHub repository.

Inside the 1802

The 1802 instruction set is very regular and quite simple. Most instructions use the top 4 bits as an op code and the bottom 4 bits to select one of sixteen 16-bit registers. So 0x12 increments register 2 and 0x15 increments register 5. There are only a handful of op codes that don’t follow this pattern. There’s also an 8-bit accumulator called “D” (not to be confused with register D).

One unique feature in the 1802 architecture is the program counter. There isn’t one. Well, more precisely, there are up to 16. Any of the registers can be the program counter and a subroutine call can be as simple as switching the program counter. Unfortunately, that isn’t very reentrant (or good for recursion). If you want a proper subroutine call, you had to code it yourself. RCA provided the “standard call and return technique” that had the unfortunate downside of destroying the accumulator.

With so few instructions, the emulator turns out to be a few switch statements and some pretty simple code. Although it is made to run with the KIM UNO hardware, like the KIM UNO, you should be able to use it with just about any Arduino via the serial port. It isn’t quite as fun as having the real hardware, but it is simpler.

Unreal

The emulator is reasonably accurate except it doesn’t simulate interrupts (since there is no source of them). However, it doesn’t faithfully reproduce the 1802’s load mode which used DMA. Instead, load mode is just completely custom code that enters data into memory. It does not simulate the cycle and register manipulations that go on in a real 1802 using DMA in load mode.

In addition to loading a program with the ersatz load mode, you can also move RAM back and forth to EEPROM or a PC via the serial port.

Serial and Push Buttons

The serial port is just the usual Arduino serial port set for 9600 baud. By default, the serial input will mimic the hardware keys. However, you can use the pipe character (‘|’) to shift the serial port into terminal mode. Then the 1802 code can read data from the serial port. You lose the front panel functions and there’s no way to go back until you cycle the power unless you make the 1802 code release the port.

A few of the push buttons have special functions if you hold them down for more than one second. For example, the AD button writes the EEPROM data into RAM. This is useful for storing a self-contained demo, for example.

You can find a summary of the keyboard and serial commands on the GitHub site. The serial port can do things you can’t do from the front panel, like set a trace mode, dump the CPU registers, and more.

Building

The hardware doesn’t require any changes to the stock KIM UNO kit. There’s a lot to solder and once you solder the displays on, it would be hard to get the Arduino back off the board.

You could probably build the software using the Arduino IDE, but I used Platform IO. That lets me use the editor of my choice, but you ought to be able to get the code to work in the IDE, as well. There is enough memory to make the RAM slightly bigger, but I didn’t do it. Since one way to save and load the RAM is to EEPROM, I didn’t want the RAM to be larger than the EEPROM. In addition, the RAM “maps” like a real Elf (that is, RAM at location 0x0 also appears at 0x4000, 0x8000, etc). This would be more difficult if you added a little bit more than 1K of RAM.

There are a few other options at the top of 1802config.h. You can select how often the screen and keyboard refresh. Higher values are slower to refresh but faster to execute code. You can change the I/O ports associated with the keyboard, displays, and serial port. You can also change the serial escape character.

Examples

There are some examples provided that blink the LEDs and manipulate the serial port. If you look around, there’s a lot of 1802 code on the web. However, be aware that most 1802s don’t have a hardware UART. They emulate serial ports using the Q output and one of the EF inputs. That’s fine for a real device even though it takes lots of code, but for this virtual device, it isn’t practical. You’ll need to rip out any code that does serial I/O and replace it with single I/O instructions.

If you have a binary file (or a format you can convert to binary) I have a converter written in C included on GitHub. You can compile it on nearly any platform and use it to convert. It always assumes address. If that’s not right, you can always open the output in a text editor and adjust.

In addition, there are three ROMs included that you can try. By default, there is a simple high-low game. There are also two monitors, one for use with the built-in keyboard and another for use with a serial port. To select a ROM, edit 1802rom.h and change the comments so the ROM you want is not commented and the others are.

Practical?

Emulators are fun, but as the song goes, there’s nothing like the real thing. If that’s not authentic enough for you, it is possible to build a very authentic looking Elf, even today. The reason real 1802s are still around is they had several desirable characteristics, namely low power consumption and resistance to radiation.

The Arduino simulation has neither of those features. However, it is a fun retrocomputing toy, inexpensive, and a great learning tool. The CPU is simple enough to program directly in machine code and the portability is better than most other old school computers.

If you want to learn more about the 1802 there are several sites dedicated to it and a very helpful Yahoo group. One site has a very prolific software author, but most of the code won’t fit in the 1802 UNO’s 1K RAM. Maybe a version with more memory is in the future.


Filed under: Arduino Hacks, classic hacks, computer hacks, Hackaday Columns

First Look at ABC: Basic Connections

[Alberto Piganti], aka [pighixxx] has been making circuit diagram art for a few years now, and has just come out with a book that’s available on Kickstarter. He sent us a copy to review, and we spent an hour or so with a refreshing beverage and a binder full of beautiful circuit diagrams. It doesn’t get better than that!

[pighixxx] started out making very pretty and functional pinout diagrams for a number of microcontrollers, and then branched out to modules and development boards like the Arduino and ESP8266. They’re great, and we’ll admit to having a printout of his SMD ATMega328 and the ESP-12 on our wall. His graphical style has been widely copied, which truly is the sincerest form of flattery.

But after pinouts, what’s next? Fully elaborated circuit diagrams, done in the same style, of course. “ABC: Basic Connections” started out life as a compendium of frequently used sub-circuits in Arduino projects. But you can take “Arduino” with a grain of salt — these are all useful for generic microcontroller-based projects. So whether you want to drive a 12 V solenoid from a low-voltage microcontroller, drive many LEDs with shift registers, or decode a rotary encoder, there is a circuit snippet here for you.

One of the things that we like most about the graphics in “ABC” is that they’re not dumbed down — they’re fundamentally just well-done circuit diagrams, but with graphic touches and extra detail where it actually helps to clarify things. This is a middle ground between the kind of schematic you use in a PCB layout program and the kind of diagram you get from Fritzing. In the former, every part has a symbol but multifunction parts like microcontrollers are just represented as squares bristling with pin numbers. In the latter, wiring up an IC is easy because the parts and pins are represented graphically, but you quickly run out of colors for the different wires, and the “breadboard” turns into a rat’s nest with a circuit of any complexity.

“ABC” takes the middle road, using standard circuit diagram style overall, but also the nice graphic representations of the ICs and modules that [pighixxx] is good at. Is a 2N2222 pinned EBC or BCE? You don’t have to look that up, because it’s sketched out for you here. We’d guess that this attractive, but information-rich, style is a great fit for the target audience — people with some electronics experience who do not yet have their favorite transistor symbol tattooed on their forearm. [pighixxx]’s diagrams are simple, easy to understand, easy to use, and pretty to boot.

There is a planned online counterpart to the book, with further elaborations of all of the circuit setups. They’re not finished yet, but they have a lot more of the flavor of the Fritzing-style, this-wire-goes-to-that-hole diagrams. This style does work better in an online format than in a physical book, because you can build up the rat’s nest in bite-sized steps, none of which are too overwhelming. But honestly, for an advanced beginner or intermediate electronics hacker, the book can be treated as stand-alone. The web content may help the rank newbie when they get stuck.

Tee-hee.

The breadth of circuits in “ABC” is fairly wide, covering most of the microcontroller-interfacing problems that we’ve ever encountered. None of the circuits are revolutionary — they’re the tried-and-true, correct solutions to the various problems, rather than anything too hacky or clever. We weren’t surprised by any of the circuits, but we didn’t find anything that we wouldn’t use ourselves either. These are basic connections after all, and a darn solid collection of them.

To sum up, “ABC” is an attractive book in a handy binder format that would make a great collection of solutions for anyone who’s just getting started in the whole “Arduino” scene but who gets hung up on interfacing the chips with the real world. It’s a handy reference for the pinouts of a number of frequently used parts, combined with the resistors, flyback diodes, level-shifting circuits, and whatever else that you’d need to make them work. It’s what we wish our simple circuit diagrams looked like. We like it.


Filed under: Hackaday Columns, reviews

Friday Hack Chat: Tenaya Hurst From Arduino

Join us this Friday at noon PDT for a Hack Chat with Tenaya Hurst of Arduino. If you’ve been one of the big Maker Faires over the last few years (or innumerable other live events) and stopped by the Arduino area you’ve probably met Tenaya. She is the Education Accounts Manager for Arduino and loves working with wearable electronics.

Come and discuss maker education and the role Arduino is playing in getting our students excited about electronics, and STEAM education in general. Tenaya will also be discussing a new wearable tech kit she’s been working on. We hope to see the gear in person at Bay Area Maker Faire next week.

Here’s How To Take Part:

Our Hack Chats are live community events on the Hackaday.io Hack Chat group messaging.

Log into Hackaday.io, visit that page, and look for the ‘Join this Project’ Button. Once you’re part of the project, the button will change to ‘Team Messaging’, which takes you directly to the Hack Chat.

You don’t have to wait until Friday; join whenever you want and you can see what the community is talking about.


Filed under: Arduino Hacks, Hackaday Columns, wearable hacks

PlatformIO and Visual Studio Take over the World

In a recent post, I talked about using the “Blue Pill” STM32 module with the Arduino IDE. I’m not a big fan of the Arduino IDE, but I will admit it is simple to use which makes it good for simple things.

I’m not a big fan of integrated development environments (IDE), in general. I’ve used plenty of them, especially when they are tightly tied to the tool I’m trying to use at the time. But when I’m not doing anything special, I tend to just write my code in emacs. Thinking about it, I suppose I really don’t mind an IDE if it has tools that actually help me. But if it is just a text editor and launches a few commands, I can do that from emacs or another editor of my choice. The chances that your favorite IDE is going to have as much editing capability and customization as emacs are close to zero. Even if you don’t like emacs, why learn another editor if there isn’t a clear benefit in doing so?

There are ways, of course, to use other tools with the Arduino and other frameworks and I decided to start looking at them. After all, how hard can it be to build Arduino code? If you want to jump straight to the punch line, you can check out the video, below.

Turns Out…

It turns out, the Arduino IDE does a lot more than providing a bare-bones editor and launching a few command line tools. It also manages a very convoluted build process. The build process joins a lot of your files together, adds headers based on what it thinks you are doing, and generally compiles one big file, unless you’ve expressly included .cpp or .c files in your build.

That means just copying your normal Arduino code (I hate to say sketch) doesn’t give you anything you can build with a normal compiler. While there are plenty of makefile-based solutions, there’s also a tool called PlatformIO that purports to be a general-purpose solution for building on lots of embedded platforms, including Arduino.

About PlatformIO

Although PlatformIO claims to be an IDE, it really is a plugin for the open source Atom editor. However, it also has plugins for a lot of other IDEs. Interestingly enough, it even supports emacs. I know not everyone appreciates emacs, so I decided to investigate some of the other options. I’m not talking about VIM, either.

I wound up experimenting with two IDEs: Atom and Microsoft Visual Studio Code. Since PlatformIO has their 2.0 version in preview, I decided to try it. You might be surprised that I’m using Microsoft’s Code tool. Surprisingly, it runs on Linux and supports many things through plugins, including an Arduino module and, of course, PlatformIO. It is even available as source under an MIT license. The two editors actually look a lot alike, as you can see.

PlatformIO supports a staggering number of boards ranging from Arduino to ESP82666 to mBed boards to Raspberry Pi. It also supports different frameworks and IDEs. If you are like me and just like to be at the command line, you can use PlatformIO Core which is command line-driven.

In fact, that’s one of the things you first notice about PlatformIO is that it can’t decide if it is a GUI tool or a command line tool. I suspect some of that is in the IDE choice, too. For example, with Code, you have to run the projection initialization tool in a shell prompt. Granted, you can open a shell inside Code, but it is still a command line. Even on the PlatformIO IDE (actually, Atom), changing the Blue Pill framework from Arduino to mBed requires opening an INI file and changing it. Setting the upload path for an FRDM-KL46 required the same sort of change.

Is it Easy?

Don’t get me wrong. I personally don’t mind editing a file or issuing a command from a prompt. However, it seems like this kind of tool will mostly appeal to someone who does. I like that the command line tools exist. But it does make it seem odd when some changes are done in a GUI and some are done from the command line.

That’s fixable, of course. However, I do have another complaint that I feel bad for voicing because I don’t have a better solution. PlatformIO does too much. In theory, that’s the strength of it. I can write my code and not care how the mBed libraries or written or the Arduino tools munge my source code. I don’t even have to set up a tool chain because PlatformIO downloads everything I need the first time I use it.

When that works it is really great. The problem is when it doesn’t. For example, on the older version of PlatformIO, I had trouble getting the mBed libraries to build for a different target. I dug around and found the issue but it wasn’t easy. Had I built the toolchain and been in control of the process, I would have known better how to troubleshoot.

In the end, too, you will have to troubleshoot. PlatformIO aims at moving targets. Every time the Arduino IDE or the mBed frameworks or anything else changes, there is a good chance it will break something. When it does, you are going to have to work to fix it until the developers fix it for you. If you can do that, it is a cost in time. But I suspect the people who will be most interested in PlatformIO will be least able to fix it when it breaks.

Bottom Line

If you want to experiment with a different way of building programs — and more importantly, a single way to create and build — you should give PlatformIO a spin. When it works, it works well. Here are a few links to get you started:

Bottom line, when it works, it works great. When it doesn’t it is painful. Should you use it? It is handy, there’s no doubt about that. The integration with Code is pretty minimal. The Atom integration — while not perfect — is much more seamless. However, if you learn to use the command line tools, it almost doesn’t matter. Use whatever editor you like, and I do like that. If you do use it, just hope it doesn’t break and maybe have a backup plan if it does.


Filed under: Arduino Hacks, ARM, Hackaday Columns, reviews, Skills

My DIY BB-8: Problems, Solutions, Lessons Learned

Imagine trying to make a ball-shaped robot that rolls in any direction but with a head that stays on. When I saw the BB-8 droid doing just that in the first Star Wars: The Force Awakens trailer, it was an interesting engineering challenge that I couldn’t resist. All the details for how I made it would fill a book, so here are the highlights: the problems I ran into, how I solved them and what I learned.

The Design Criteria: Portable and Inexpensive

Carrying BB-8

I had two design criteria in mind. The first was to keep it low-cost. Some spend $1000 to $1500 on their BB-8s. I wanted to spend as little as I could, so as many parts as possible had to come from my existing stock and from online classifieds and thrift stores. Not counting the parts that were discarded along the way, the cost came in just shy of $300.

The second design criteria was to make it portable. It had to be something I could take on the bus or carry while walking a reasonable distance (I once carried it twenty-five minutes to a nearby school).

Both of these criteria meant that it had to be smaller than full size. A full size ball is 20″ in diameter. Mine has a 12″ ball which makes it 3/5 scale. Also, the larger it is, the more powerful and costly the motors, batteries, motor controllers, magnets, and so on.

Version One: Quick And Easy

First I tried a minimalist approach. For the ball, I found my 12″ cardboard globe on kijiji.ca. I bought an RC toy truck at a yard sale and attached a pole to it for holding magnets near the top of the globe. I then made a head with corresponding magnets under it. The head magnets attract to the pole magnets, keeping the head on. Meanwhile, the truck rolling inside the ball makes the ball move.

Making the ball roll around was easy. Making it roll around while keeping the head on was very hard. The magnets at the top of the pole attract the magnets under the head, pulling them down hard onto the surface of the globe. That essentially glues the truck to the top of the globe.

To overcome that the truck needs sufficient traction. That also means the truck needs to be heavy. And lastly, the truck’s motor needs to be powerful enough to overcome its own weight and the grip of the magnets on the ball. The alternative is to make the magnetic attraction weaker, but if it’s too weak the head falls off. It’s a tricky balancing act, in both senses of the word.

But the most dome-like head I could make stay on was just a cardboard skeleton. Anything more filled out would be heavier and require a stronger magnetic attraction. The toy truck’s motor would not be up to it.

Version Two: Drill Motors And Drill Batteries

Batteries and motors in Blender

For more powerful motors and more mass I figured I could kill two birds with one stone by going with drill motors and drill batteries in a hamster drive configuration. Using drill parts kept costs down as the batteries and one drill came from yard sales while the other drill was free through freecycle.org. Meanwhile, both are heavy.

To make sure it all fit, I drew up a 3D model in Blender, the free 3D modelling and animation software that I use a lot. In fact, finding out how to make the batteries and motors fit was the first step. They had to be as low as possible. Their large mass low down is what keeps the droid vertical, with the much lighter head at the highest point.

Batteries Velcroed and a connector

The drill batteries had to be easily removable for recharging. To hold them under the drive plate I simply used Velcro. Meanwhile, the drill battery stems went up through a hole in the drive plate. I made a connector to electrically connect to the battery terminals. It is a plastic rectangle with thin copper sheet metal for the contacts. Once the battery was Velcroed in place, this plastic and metal piece was lowered down onto the stem, the copper metal making contact with the battery terminals.

The Electronics

For the brains I used an Arduino UNO. To drive the motors I had all the parts for making two H-bridge driver boards, with the exception of 4 MOSFETs and some fuses. The Arduino does pulse width modulation (PWM) to the driver boards for speed control, as well as playing sounds at certain times when the motors are turned on.

For remote control, I hacked the RC receiver from the toy truck and added an extra set of AA batteries in parallel for more runtime. A problem I ran into right away though, was that the RC receiver put out voltages of both polarities based on which direction the motors should rotate, whereas the Arduino’s pins take only positive voltages. To solve that I came up with a converter board to go between them.

Getting all that to work reliably took a while. Before I added fuses, I burned a few MOSFETs. At one point I’d put an N-type MOSFET where a P-type should have gone and vice versa. That resulting problem alone took a few days of spare time to figure out.

The wheels were old Rollerblade wheels — I keep a small bucket of these in my shop. I decided I wanted the ball to roll at around 1 foot per second and doing the math, that meant the wheels would have to rotate at around 2 rotations per second or 120 RPM. I found a PWM value that would give something close to that and started blowing fuses. I started with 1 amp fuses, then 2, 5, and finally settled on 10 amp fuses.

My final hurdle was that the motors would behave oddly when the motors were told to turn in opposite directions but were fine when they were told to turn in the same direction. This turned out to be a bad assumption on my part about how the RC receiver was wired internally — none of the output wires were common inside. After some changes to the circuit, I now had stable electronics.

I had basically been treating the RC receiver as a black box, but when I asked for help about my converter board here on Hackaday, it was pointed out that the receiver likely contained H bridges. Opening it up, that’s exactly what I found. The converter board works fine for now, but in the near further I’ll use one of the suggestions from that Hackaday post to eliminate the board altogether. I might even try all of the suggestions, just for fun.

The Drive System

The drive system

The motors were too long to fit in line between the wheels and so had to be mounted off to the sides. To transfer rotation to the wheels, I drew up some gears in Blender and 3D printed them at our local University of Ottawa Makerspace. In the print settings I used 2 shells and only 50% infill. The gears are held firmly onto the shafts solely using nuts and washers on either side. They’ve held up amazingly well, even with slipping and grinding during development.

For the bearings for the center gears and the wheels I used an old trick of making bearing blocks from hardwood.

Putting Loctite and screwing gear to motor shaft

I wanted to keep as much room as possible on the drive plate available for adding things later and so initially I’d mounted the motors at only three points. But this allowed the motors to move a little causing the gears to slip. To fix that I later added a fourth mounting point and haven’t had any slipping since.

At the end of the shaft for the drill motors is a hole that a screw goes into. That’s part of how the chuck is kept on a drill motor, and that’s how one gear was kept on. However, this screw had a tendency to get loose. Putting a little Loctite on the threads fixed that.

Stability

Rearranging BB-8’s internals

Given that I was trying to fit a lot in a small droid, I had to mount some things higher than I’d have liked to. When the droid stops, mass high up causes the droid to wobble. In the BB-8 droid used for promotional events they’ve gone to a great extent to keep the majority of the mass as low as possible. Originally I had the Arduino batteries and the RC receiver with its extra batteries fairly high up. I later mounted them much lower. When holding the internals in my hands I could tell the difference but it didn’t make a noticeable difference with the wobble.

Instead, for that I added Adafruit’s BNO055 inertial measurement unit (IMU) board. With it I could tell what angle the droid was at when stopping and experimented with PID loops and other algorithms of my own to minimize wobble. That helped.

The Ball

As I said, I used a 12″ cardboard globe. To increase the traction of the wheels inside the globe I sprayed the globe’s interior with an anti-slip spray from a hardware store. This made a huge difference. However, over time the anti-slip coating vanished, and so I’m looking for another, more permanent coating, perhaps urethane or something. If anyone has any suggestions, please let me know in the comments. It also has to stop off-gassing eventually. The anti-slip spray had an odor for a long time.

Sealing globes – cardboard and fiberglass

But the main problem with the cardboard globe was its thinness. With the huge weight of the internals pushing down on it where the wheels are, it warped significantly and required a lot of effort and a copious amount of tape to keep the two hemispheres together. This large amount of tape also made an uneven ridge for the head to slide over, making it get stuck. At that point either the drive system continued to move while the head fell off or the drive system couldn’t move at all.

The solution was to carefully coat a new globe in three layers of fiberglass. I took my time doing this, over a month and a half, applying one piece at a time and then sanding before putting the next piece. The result was a fantastic improvement. It no longer deformed and now it takes a minimal effort to attach the two hemispheres with only eight narrow strips of transparent duct tape.

The Never-ending Saga

My DIY BB-8 in action

My BB-8 is now at the point that I can call it finished. At least it’s finished as far as all the engineering is concerned, and that’s usually where I call it quits.

While the paint job worked out well, up close you can see that the details are painted on. It’d be nice to have at least the lines on the head be actual grooves. Also, these drill motors are brushed motors and I’ve since learned that doing high frequency PWM to brushed motors damages them over time. I’d like to replace them with brushless motors. And as anyone who’s use cordless drills a lot knows, drill batteries don’t last long, and so it’d be great to switch to LiPos.

But for now, the reactions I get from both kids and adults is beyond my wildest expectations. Kids threat it like a friend while adults have petted it and called to it like it was a baby or a dog wagging its tail. I’d call that a success.


Filed under: Hackaday Columns, robots hacks

My Life in the Connector Zoo

“The great thing about standards is that there are so many to choose from.” Truer words were never spoken, and this goes double for the hobbyist world of hardware hacking. It seems that every module, every company, and every individual hacker has a favorite way of putting the same pins in a row.

We have an entire drawer full of adapters that just go from one pinout to another, or one programmer to many different target boards. We’ll be the first to admit that it’s often our own darn fault — we decided to swap the reset and ground lines because it was convenient for one design, and now we have two adapters. But imagine a world where there was only a handful of distinct pinouts — that drawer would be only half full and many projects would simply snap together. “You may say I’m a dreamer…”

This article is about connectors and standards. We’ll try not to whine and complain, although we will editorialize. We’re going to work through some of the design tradeoffs and requirements, and maybe you’ll even find that there’s already a standard pinout that’s “close enough” for your next project. And if you’ve got a frequently used pinout or use case that we’ve missed, we encourage you to share the connector pinouts in the comments, along with its pros and cons. Let’s see if we can’t make sense of this mess.

FTDI TTL Serial

The de-facto standard for a hacker’s TTL serial pinout is definitely the layout that FTDI uses for their USB/TTL serial cables. Said cable is just so handy to have on hand that you’d be silly to use any other pinout for the job. And the good news is that the rest of the world has basically joined in. From the Chinese “Pro Mini” cloneduinos to the Hackaday Edition Huzzah ESP8266 board, and from Adafruit’s FTDI Friend to Modern Device’s USB-BUB, almost everyone uses this pinout. A victory for the common man!

There is one slight point of contention, however, and that’s whether pin 6 is DTR or RTS#. We never use either, so we couldn’t care less, but if you’re counting on your programmer sending the DTR signal to enter programming mode on the device (we’re looking at you Arduino!) then you’ll want DTR on pin 6, and the original FTDI cable, ironically, has the “wrong” pinout. Perhaps that’s why Sparkfun avoided the whole debacle and went their own way, breaking out every signal off the FTDI chip into their own unique configuration.

If you’re only going to break out TTL serial lines, you’d be a fool to use any other pinout.

Modules and Other Communications

Unlike the case with simple serial, connecting various kinds of modules to mainboards is a difficult problem. Creating a single pinout or connector specification for many potential protocols or arbitrary signals is a Herculean task. Surprisingly, it’s been done a few times over. Here are some notables.

Pmod

Digilent makes a wide range of FPGA demo boards, and they needed an in-house standard pinout that they could use to plug into various add-on peripheral modules that they sell. Thus Pmod was born. It has since become a full-fledged, and trademarked, open standard that you can use in your designs. Here’s the PDF version of the specification for you to print out, so you know they mean business.

There are a few aspects of Pmod that we think are particularly clever. First, the number of pins involved is “just right” at six, and it’s easily expandable. They use standard 0.1″ pitch pins and headers. Two lines carry power and ground, leaving four free pins for SPI, UART, or whatever else. The specification is that all power and signal voltages are 3.3 V because they’re designed for FPGAs after all. You can mix and match if you know what you’re doing, but they won’t let you call it Pmod(tm).

Eric Brombaugh’s iceRadio FPGA SDR, plugged together with Pmods

If you need more than four signals, there’s a twelve-pin version which is just two six-pin Pmods stacked into a double-row header. The extra power and ground are redundant, but it makes a twelve-pin output very flexible, because nothing stops it from being used as two sixes. The standard also says that the twelve-pin headers are to be spaced at 0.9″ center-to-center, so you can even connect two of them together when you need sixteen board-to-board signal connections. We like the modularity and expandability.

Pmod connectors are multi-protocol, but for each protocol there is a single pinout. So there’s an SPI Pmod and an I2C Pmod, and the pins are always in the same place. There isn’t a Pmod standard for every conceivable application, of course, so there’s a GPIO pinout that gives you free rein over what goes where. We think that it would be nice if some additional notable protocols (I2S? one-wire? servos? analog stereo audio?) were included in the specs, but the community can also handle these lower-level details.

In our eyes, Pmod is nearly perfect. It uses cheap hardware, is easily expandable, and the smallest incarnations are small enough to fit on all four sides of a one-inch-square board. If you’re willing to pay the brand-name premium, Digilent makes an incredible range of modules. We want to see more hackers outside of the FPGA scene get on it.

mikroBUS

What Digilent is to development boards in the US, MikroElektronika is in Europe. While Pmod aims to be capable of doing anything, Mikro-E’s mikroBUS connector wants to do everything, which is to say it has I2C, SPI, UART, two voltages, and even a few extra signals all on the same pinout. Physically, it’s two single rows of eight pins, spaced 0.9″ apart side-to-side, which means it fits into a breadboard nicely. Here’s the spec in PDF.

The tradeoff here, relative to Pmod, is that a lot of pins go unused on any given design. With (only) one “analog” channel, you wouldn’t choose mikroBUS to send stereo audio, whereas nothing stops you from calling the Pmod’s GPIO lines analog and sending four channels of sound. But that mikroBUS gains is fool-proofness. (Well, they could have also made it asymmetric…) There’s no chance of a newbie plugging an SPI module in where an I2C module is expected and scratching their heads. With mikroBus, it should just work.

Microchip has added a mikroBus port to their Curiosity boards, and MikroElektronika makes a ton of modules. If your audience consists of beginners, and one footprint for all protocols, it’s worth considering.

Seeed’s Grove

Meanwhile in China, Seeed Studios makes open-source modules, and makes them cheap. Their Grove connector uses only four pins, with power and ground among them. The have standard pinouts for UART, I2C, and for servo motors. Sensors and other analog peripherals are allocated one “primary” pin and one “secondary” and it’s assumed that you know what you’re doing. The idea behind their system is that you add a shield to your microcontroller board, and they break out the relevant pins into these four-pin Grove headers.

This is great for small things and I2C devices, which is Seeed’s catalog, but there just aren’t enough signal pins to run SPI or an analog RGB LED, for instance. But because of the small number of pins, they use very inexpensive polarized cables and shrouds that you can’t plug in the wrong way, and that take up relatively little board space. That’s Grove’s design trade-off.

Servo Motor control

One of these things is not like the others…

Hobby servo motors need three wires: voltage, ground, and a signal to tell them where to point. There are three distinct ways to arrange these wires, but Futaba, HiTec, Tower, GWS, and JR servos all chose to put them in SVG (or GVS) order, and there’s no reason to buck the trend. (Airtronics, what were you thinking?!)

SVG is also a handy pinout to use for all sorts of one-signal sensors or actuators where space is a premium, and we’ve seen this in a few designs (here and here, for instance). But we’re torn. Relative to the Grove, for instance, you’re just saving one pin. Even the Pmod would work with only three pins’ overhead. Is that worth complicating your life with another pinout? If you need a lot of powered one-signal devices, or servos, it probably is, and you can hardly beat SVG or GVS, whichever way you look at it.

Arduino

Viewed in the light of any of the other module interconnection systems, the Arduino is the worst of all worlds. It’s monolithic like mikroBUS, but it’s gigantic — you have to build a 55×73 mm board and accommodate 30 pins and pass-throughs if you’d like it to be stackable. The pins have a funny spacing (that gap!), that doesn’t fit any normal protoboard. Nobody goes through the trouble of building a shield just for an I2C connection. No wonder most Arduino projects look like a breadboard hedgehog. About the only good thing we can say about it is that it’s hard to plug one in backwards.

There’s also the tiny little factor that there’s a million Arduino shields out there, a huge community built around them, and widespread support for them. Which turns out to trump all of the reasonable design concerns. (Shakes head.)

Miscellany

Of course, there are other very specific pinouts that one might encounter, like the old ESP-01 module, or the XBee, or the nRF24. Adapting modules to fit boards is always going to be a pain, because the manufacturers will pick whatever suits them on that day. Programmer pinouts for specific microcontrollers are a similar story, as is JTAG, which is a beautiful standard with a dogs’ breakfast of pinout possibilities. (We could do a whole column!)

Faced with this inevitability, and the need for many one-off adapters, what can you do? What we do is buy a lot of those cheap “Dupont” female-to-female cables, get the connections working and tested, and then tape them permanently together and label them. It’s not as pretty as a dedicated PCB adapter, but it’s quick and easy and gets you moving on to what you wanted to do in the first place.

Wrapup and Recommendations

The goal of connectors, and their standards, is putting parts together. If you’re designing a sensor module with more than a couple components, and you want it to be maximally easy for yourself and others to hook up to whatever mainboard they’ve got, this is no easy task. The end result is a proliferation of translators, adapter boards, hats, shields, capes, or whatever else. We have a drawer and a half full, and we bet you do too.

Yes, I do see what I’m suggesting here. [source: xkcd 927]
We’d be happy to see the world settle on Pmod for most needs, honestly, and we’d even throw away our beloved FTDI serial pinout in the name of standardization (or make an adapter). We can also see the need for exceptions like SVG / servo connectors when small sensors or multiples are in play. There will always be the need for dedicated on-board connectors as well, of course. Nobody said hardware was easy.

What’s your solution to the ultimate connector conundrum? Are there important connector systems that we’ve left out? What are their design tradeoffs? How stoked would you be if things could just plug together? Let us know!

Thumbnail image courtesy of [Raspberry Pi Controller].


Filed under: Engineering, Hackaday Columns, hardware, rants

3D Printering: Trinamic TMC2130 Stepper Motor Drivers

Adjust the phase current, crank up the microstepping, and forget about it — that’s what most people want out of a stepper motor driver IC. Although they power most of our CNC machines and 3D printers, as monolithic solutions to “make it spin”, we don’t often pay much attention to them.

In this article, I’ll be looking at the Trinamic TMC2130 stepper motor driver, one that comes with more bells and whistles than you might ever need. On the one hand, this driver can be configured through its SPI interface to suit virtually any application that employs a stepper motor. On the other hand, you can also write directly to the coil current registers and expand the scope of applicability far beyond motors.

The TMC2130 SilentStepStick’s top side with SPI headers and heatsink.

Last month, we took a closer look at microstepping on common stepper driver ICs, but left out the ones that we actually want to use: the smart ones. Trinamic provides some of the smartest stepper motor drivers on the market, and since the German hacker store Watterott released their SilentStepStick breakout boards for the TMC2100 and TMC2130, they are also setting a new standard for DIY 3D printers, mills and pick-and-place robots. I recently acquired a set of both of them for my Prusa i3 3D printer, and the TMC2130 with its SPI configuration interface really caught my attention.

The TMC2130 SilentStepStick should not be confused with the — far more popular — TMC2100 variant. As the name suggests, it comes as a StepStick-compatible breakout board, and just like it’s famous sibling, features a Trinamic IC on the bottom side of the little PCB. Several vias and copper spills conduct heat away from the IC’s center pad, allowing a heatsink on the top side to effectively cool the driver.

The bottom side with the stand-alone mode solder blob jumper next to the IC.

However, unlike the TMC2100, this one won’t let your motors spin right away. You’ve got two options: Hard-wire it in stand-alone mode, which practically turns it into a TMC2100, or hook up to its SPI-interface and dial in if you want your stepper motor shaken or stirred. In fact, plentiful configuration registers make the TMC2130 an extremely hackable chip, so I’m not even thinking about bridging that solder jumper on the SilentStepStick’s bottom side that activates the stand-alone mode.

First Steps

Wiring the TMC2130 to a classic RAMPS 1.4.

As said, before the driver does anything, it wants to be configured, and it’s worth mentioning that all configuration registers are naturally volatile, so if I want to use them in my 3D printer, I need to configure them as part of the printers startup routine.

The RAMPS 1.4 on my 3D printer breaks out the hardware SPI interface of the underlying Arduino through its AUX3 pin header, along with two additional digital pins (D53 and D49), which I used for the cable select signals. After crimping a cable to connect two TMC2130’s to the AUX3 header, I could start digging into the software part.

Watterott provides an example sketch, which writes a basic configuration to the driver’s registers and spins an attached stepper motor. Great stuff, but the datasheet describes 23 configuration registers waiting to be finely tuned, and 8 more to read diagnosis and status data from. So, I wrote a little Arduino library that would make the numerous configuration parameters available in a more practical way. From there, I could just include my library into the Marlin-RC7 3D printer firmware I’m using. Luckily, the current Marlin release candidate already features support for TMC26X drivers, so I could reuse some of its code to put together a Marlin fork that includes 59 of the TMC2130’s parameters in its define-based configuration files. And then, I could take the little buddies out for a spin.

First steps on a RAMPS 1.4 on a somewhat-uino (sorry Massimo). The testing-contraption to the left is a NEMA 17 stepper motor attached to an encoder.

Taking Them For A Spin

With the hardware set up and the software working as supposed, I ran a few sanity tests: toggling parameters on and off and checking how the driver’s behavior changes during printing. Since the TMC2130 let’s you tune almost everything it’s doing, that’s a good first step that helps to eliminate some variables and picking others that are worth a deeper look. Most of the settings can be changed on the fly and mid-print, however, not all parameters can actually be safely changed while the motors are running.

The TMC’s in service. I’m using the SPI-configurable TMC2130’s (silver heatsink) for the X- and Y- axis. The Z-axis and the extruder feature the TMC2100 (black heatsink). All of them are sitting on additional free-runner diode protection shields.
An excerpt of Trinamic’s thorough quick start guide.

To actually tune the drivers for a certain application, Trinamic provides a quick start guide in the datasheet, as well as detailed information on each parameter, and on how they interact. Basically, the first step is adjusting the RMS coil current by using the onboard potentiometer on the SilentStepSticks. Then, we need to chose the analog input pin as a current scaling reference to actually make use of the potentiometer. The mentioned library lets me do this through a simple method:

myStepper.set_I_scale_analog(1); // 0: internal, 1: AIN

The running and holding current are the first real parameter that should be tuned, with the running current typically at the desired maximum current, and the holding current at 70% of this value. The delay between a stillstand and the transition from running current to holding current can be adjusted between 0 and 4 seconds, and for now, I set it to 4 seconds, practically disabling the current reduction while the 3D printer is running. The three values share one write-only register, so the corresponding method call looks like this:

myStepper.set_IHOLD_IRUN(22,31,5); // [0-31],[0-31],[0-5]

and sets the running current to 100% (≙ 31), the holding current to about 70% of this value (≙ 22), and the delay between the two to 4 seconds (≙ 5).

I want torque, so I can leave stealthChop disabled. The datasheet suggests some starting values for configuring the chopper’s off time and the comparator’s blank time settings, but since it’s a key tradeoff between switching noise and torque, it makes sense to iterate through other values as well. The library methods for the two values look like this:

myStepper.set_tbl(1); // [0-3]
myStepper.set_toff(8); // [0-15]

And finally, I need to pick a microstepping resolution and choose if I want to make use of the 256 microstep interpolation feature, covered later in this article:

myStepper.set_mres(32); // {1,2,4,8,16,32,64,128,256}
myStepper.set_intpol(1); // 0: off, 1: interpolate

I have yet to walk through the entire tuning procedure, which includes monitoring the coil current on the scope and eliminating distortions in the zero crossing, but I’m getting a clue of the driver’s potential.

Juice

It’s maximum continuous RMS current of about 1.2 A per coil (at least in the QFN package on the SilentStepSticks) lets it look like a low-current driver, inferior to the common A4988 and DRV8825. In practice, it outperforms both of them by making intelligent use of a 2.5 A peak current margin. This gives it more than enough torque for 3D printing. I wouldn’t recommend pushing them over 0.9 A RMS though since the IC will momentarily pull more current if it needs more. For SilentStepStick users, that’s a Vref of 0.88 V. Through the SPI-interface, you can choose how much current you want to send through the motor coils when it’s spinning, and when it’s idling. You can choose after how many seconds it will start to decrease the current to a lower holding current when the motor is in standstill, and then to an even lower idling current. And, of course, you can also set it to squeeze out the maximum juice for everything.

Shifting The Gears

Where it starts getting interesting are settings like the high-velocity mode. Above a configurable velocity threshold, the driver offers you to automatically switch the chopper to a faster decay time to squeeze out some extra speed. You can also literally shift the gears by letting the driver internally switch from microstepping to full-step mode once it’s up to speed.

Microstepping

Choosing a finer microstepping resolution smoothens the stepper’s movement, reduces vibrations and sometimes even increases the positioning accuracy. However, it also multiplies the load on the microcontroller, which has to churn out 16, 32 or 256 times more step pulses per second. The TMC2130 lets you pick an input resolution between 1 and 256 microsteps per full-step, and then gives you the option of interpolating the output resolution to 256 microsteps. This allows for smooth operation even on increasingly retro 8-bit AVR motion controllers, which cannot deliver high step frequencies. Also, by configuring the TMC2130’s interface to double-edge step pulses, you can at least double the step frequency at almost no cost. Given that the modern IC still features the classic step/direction interface and even an enable pin, those few additional features actually make it a sweet drop-in upgrade for less-recent CNC and 3D printer electronics.

Noise Reduction

The TMC2130’s datasheet promises undistorted output with stealthChop.

Just like the TMC2100, the TMC2130 features two efficient and silent drive modes: spreadCycle, and stealthChop. The former delivers high torque at relatively low noise emissions, the latter one is almost inaudible but delivers a dramatically reduced torque. The flexible IC also allows you to tweak the chopper yourself to find the right balance between torque, noise, and efficiency for your application. One of the more noteworthy options in this regard is the possibility of randomizing the chopper’s off time. Since most of the audible noise is released due to dubstep the chopper busily switching the stepper motor’s coils, this option spreads the noise over a wider frequency range to subjectively silence the stepper motor.

Stall Detection

The TMC2130 notices when the motor is stalled and losing steps by measuring the motor’s back EMF. Along the way, it counts missed steps, allowing the controller to compensate for otherwise irreversible step-loss. It’s also a great way to react to obstacles rather than running into them full-force and, of course, the feature can be used as an axis endstop. Trinamic calls this feature StallGuard, and just like anything else in this motor driver, it’s highly configurable.

Direct Mode

Instead of letting the motor driver handle everything for you, you can also choose the direct mode. This mode practically turns the driver into a two-channel, bipolar constant-current source with SPI interface. You can still use it as a motor driver, but the possibilities reach far beyond that. It’s worth mentioning that the datasheet might be a bit confusing here, and the corresponding XDIRECT register actually accepts two signed 9 bit integers (not 8 bit) for each coil and operates as expected within a numeric range of, naturally, ± 254 (not ± 255) to vary the current between ± Imax/RMS..

The Takeaway

About half a year after the release of Watterott’s breakout board, the potential of smarter stepper motor drivers piqued the curiosity of the 3D printing community, but not much has happened in terms of implementation. Admittedly, it takes some effort to get them running. If you’re still busy dialing in the temperature on your 3D printer, you surely don’t want to add a few dozen new variables, but if you’re keen on getting the best out of it, the TMC2130 has a lot to offer: low-noise printing, high-speed printing, print interrupt on failure and recovery from lost steps. Because the driver IC is so hackable, it’s clearly intended to be tuned in to accommodate specific applications. Throwing it on a general purpose test bench probably won’t yield meaningful, general purpose results.

I hope you enjoyed taking a look at a smarter-than-usual stepper motor driver, as one of the new frontiers of DIY 3D printing, and as an interesting component with many other applications. If you’re thinking about experimenting with this IC or breakout board in your 3D printer, feel free to try my Marlin fork to get started. If you’re building something entirely different, the underlying Arduino library will help you out. Who else is using this part? I’ll be glad to hear about your ideas, applications, and experiences in the comments!


Filed under: 3d Printer hacks, Hackaday Columns

Fail of the Week: Battery Pack Jack Wired Backwards

Last Saturday I had a team of teenage hackers over to build Arduino line-following robots from a kit. Everything went well with the mechanical assembly and putting all the wires on the correct pins. The first test was to check that the motors were moving in the proper direction. I’d written an Arduino program to test this. The first boy’s robot worked fine except for swapping one set of motor leads. That was anticipated because you cannot be totally sure ahead of time which way the motors are going to run.

The motor’s on the second robot didn’t turn at all. As I checked the wiring I smelled the dreaded hot electronics smell but I didn’t see any smoke. I quickly pulled the battery jack from the Arduino and – WOW! – the wires were hot. That didn’t bode well. I checked and the batteries were in the right way. A comparison with another pack showed the wires going into the pack were positioned properly. I plugged in another pack but the motors still didn’t run.

I got my multimeter, checked the voltage on the jack, and it was -5.97 V from center connector to the barrel. The other pack read 6.2 V. I had a spare board and pack so swapped those and the robot worked fine. Clearly the reverse polarity had zapped the motor control ICs. After that everyone had a good time running the robots on a course I’d laid out and went home pleased with their robots.

After they left I used the ohmmeter to check the battery pack and found the wiring was backwards, as you can see in the feature photo. A close inspection showed the wire with a white line, typically indicating positive, indeed went to the positive battery terminal. I shaved the barrel connector down to the wires and the white line wire was connected to the outside of the barrel. FAIL!

This is a particularly bad fail on the part of the battery pack supplier because how hard is it to mess up two wires? You can’t really fault the robot kit vendor because who would expect a battery pack to be bad? The vendor is sending me a new battery pack and board so I’m satisfied. Why did I have an extra board and pack, actually an entire kit? For this exact reason; something was bound to go wrong. Although what I had imagined was for one of the students to break a mechanical part or change wiring and zap something. Instead, we were faced with a self-destructing kit. Prudence paid off.


Filed under: Arduino Hacks, Fail of the Week, Hackaday Columns

A Slew of Open-Source Synthesizers

Hackaday reader [Jan Ostman] has been making microcontroller-based DIY synthesizers for quite a while now. Recently, he’s opened up the source for a lot of them so that you can play along at home. All of these virtual-analog synths and soundmakers can be realized on an Arduino or AVR ATmega328 if you happen to have one lying around.

Extra parts like a keyboard, some pushbuttons, or some potentiometer knobs to twiddle won’t hurt if you’d like to make something more permanent or more obviously playable, like [Jan] does. On the other hand, if you’d just like to get your feet wet, I’ve tweaked his code to be more immediately plug-and-play. The code is straightforward enough that it’s a good learning platform. So let’s take a quick tour through three drum machines and a string synth, each of which you can build on a breadboard in just a few minutes.

To install on an Arduino UNO, fetch the zip file from this GitHub repository, and move each subfolder to your Arduino sketch directory. You’re ready to play along.

Simple Drum Machines

[Jan] has two sample-playback~based drum machines that he’s published the code for: the dsp-D8 with straight-ahead drum samples and the dsp-L8 loaded with Latin percussion. They’re essentially the same code base, but with different samples, so we’ll treat them together.

Working through [Jan]’s code inspired me to write up a longer article on DDS playback, so if you want to brush up on the fundamentals, you can head over there. The short version is that you can change the pitch of playback of a sample by using a counter that’s much larger than the number of data points you’re going to play.

[Jan]’s drum machines all use the AVR’s hardware pulse-width modulation (PWM) peripherals to play the samples back out. You could use something fancier, but this gets the job done with just an optional resistor and capacitor filter on the output, bringing the total parts count to three: Arduino, 1 KOhm resistor, and a decent-sized (0.1 uF?) capacitor. An interrupt service routine (ISR) periodically loads a new sample value into the PWM register, and the AVR’s peripheral hardware takes care of the rest.

One nice touch is the use of a circular buffer that holds the playback sample values until the ISR is ready for them. In the case of the drum machines, there’s not much math for the CPU to do — it just combines the samples from all of the different simultaneous voices — but in his more complicated modules this buffer allows the CPU to occasionally take more time to calculate a sample value than it would otherwise have between updates. It buys [Jan]’s code some breathing room and still allows it to make the sample-playback schedule without glitching.

[Jan] adds individual pitch control for each sample, which is great for live playing or tweaking, and you can watch him use them in his two videos: one for the dsp-D8 and another for the dsp-L8. Wiring up so many knobs is a breadboard-salad, though, so I’ve gone through the code for you with a fine-toothed chainsaw, and hacked off [Jan]’s button-and-knob interface and replaced it with the Arduino’s built-in serial I/O.

To play my version of [Jan]’s drum machines, each sample is mapped to a key in the home row: “asdfjkl;”. If you’ve got a proper serial terminal program that transmits each keystroke in real-time, you’ll be tapping out rhythms at 9600 baud in no time. Note that the Arduino IDE’s built-in terminal only sends the keystroke after you hit “enter” — this makes playing in tempo very difficult. (I use screen /dev/ttyACM0 9600 or the terminal that’s built-in with Python’s pyserial library myself. What do Windows folks use for a real-time terminal?)

If you haven’t already, download this zip file, move each sub-folder to your Arduino sketch directory, and connect an amplified speaker either directly to your Arduino’s pin 11 and ground, or include an RC filter. It’ll only take a second before you’re playing. When you want the full version with all the knobs, head on over to [Jan]’s site.

O2 Minipops

[Jan]’s O2 Minipops machine mimics an old-school rhythm box: the Korg mini pops 7. Whether this primitive drum machine is horribly cheesy or divinely kitschy is in the ear of the beholder, but it’s a classic that has been used all over. [Jan]’s named his after an epic album Oxygene by Jean-Michel Jarre. You’ll hear them starting around 1:40 into the clip. Jarre famously used to press multiple buttons on the Minipops, making more complex drum patterns by playing more than one at a time.

The nice thing about having your own Minipops in firmware is that you can add the features you want to it. Instead of having to mash down multiple plastic buttons live on stage like poor Mr. Jarre, you can just tweak the firmware to suit. Need longer patterns? You’ve got the RAM. Emphasis? Swing? Tap tempo? It’s all just a matter of a few lines of code.

The sound playback code is just like the simpler drum machines above, so we won’t have to cover that again. The only real addition is the sequencer, but that’s where the real magic lies. After all, what’s a drum machine without some beats? Because there are eight possible drum sounds, each beat is a byte and so four bars of 4/4 time is just sixteen bytes stored in memory. I broke the data out into its own header file O2_data.h, so have a look there for the pre-programmed rhythms, and feel free to modify them to suit your own needs.

In order to make the O2 Minipops immediately playable, I stripped out the potentiometer code again (sorry [Jan]!) and passed off control over the serial port. The “user interface” has five controls. Press j and k to switch between patterns and f and d to speed up or slow down. (They’re under your first two fingers in the home row.) The space bar starts and stops the drum machine.

Try switching between the patterns on the fly with j and k — it’s a surprisingly fun way to create your own, slightly less cheesy, patterns. You need to download this code and give it a try. Trust me.

The Solina

[Jan] has also built up a full-fledged string synthesizer keyboard out of just an Arduino Nano. It’s patterned on the Eminent Solina String Ensemble, and we’ve got to say that it gets the sound spot on.

Solina — the Original

[Jan]’s Solina is a “virtual analog” in the sense that it builds up sawtooth waveforms in the microcontroller’s RAM and then outputs the corresponding voltage through PWM. And that’s a good start for a string synthesizer, because a filtered sawtooth waveform is a good first stab at the sound put out by a violin, for example.

Solina — the clone

The secret to the sound of the string section of an orchestra (and to string synthesizers that mimic it) is that it’s a combination of many different bowed instruments all playing at once. No matter how precise the players, they’re each slightly differently tuned, and none of the strings are resonating exactly in phase. The Solina mimics this by detuning each oscillator, naturally, and by moving them in and out of phase with each other. If you want to dig into the details of how exactly [Jan]’s Solina works, he explains it well in this blog post.

Again, I’ve converted it for direct-serial control, and you can control the envelope, detune, LFO speed, and modulation depth over the serial port. Press the spacebar once to simulate a keypress, and again to let go. Try the Solina with detune and pitch modulation around twenty, and play with the LFO rate and other parameters. That’s a lot of useful noise for just some sawtooth waves.

Keyboards and What’s Next

[Jan]’s builds are much more than what we’re demonstrating here, of course. His blog kicks off (in 2009!) with a project that essentially shoe-horns a PC into a keyboard enclosure, and the Solina and others get their own keys too. We’ve just presented the kernel of any such project — there’s a lot of labor-of-love left in wiring up all of the diodes necessary to do detection on a keyboard matrix, to say nothing of building enclosures, wiring up potentiometers, and making nice-looking front panels. But if you want to start down that path, you’ve at least got a good start.

[Jan]’s current project is the Minimo miniature monophonic synth that takes the Solina a step further and adds a lowpass filter with (digital) resonance to it. The resulting sounds are great, so we’re excited to see where [Jan] takes this one in the future.

Thanks again, [Jan], for opening the code up. And if any of you build something with this, be sure to post in the comments and let us all know. Since I started playing around with these, I’ve got the hankering to modularize the code up a bit and make it into something that’s even easier to adapt and modify. Maybe we’ll have to start up a Hackaday.io project — these little simple synths are just too much fun!


Filed under: Arduino Hacks, Hackaday Columns, musical hacks

Embed with Elliot: Audio Playback with Direct Digital Synthesis

Direct-digital synthesis (DDS) is a sample-playback technique that is useful for adding a little bit of audio to your projects without additional hardware. Want your robot to say ouch when it bumps into a wall? Or to play a flute solo? Of course, you could just buy a cheap WAV playback shield or module and write all of the samples to an SD card. Then you wouldn’t have to know anything about how microcontrollers can produce pitched audio, and could just skip the rest of this column and get on with your life.

~45db signal to noise ratio from an Arduino

But that’s not the way we roll. We’re going to embed the audio data in the code, and play it back with absolutely minimal additional hardware. And we’ll also gain control of the process. If you want to play your samples faster or slower, or add a tremolo effect, you’re going to want to take things into your own hands. We’re going to show you how to take a single sample of data and play it back at any pitch you’d like. DDS, oversimplified, is a way to make these modifications in pitch possible even though you’re using a fixed-frequency clock.

The same techniques used here can turn your microcontroller into a cheap and cheerful function generator that’s good for under a hundred kilohertz using PWM, and much faster with a better analog output. Hackaday’s own [Bil Herd] has a nice video post about the hardware side of digital signal generation that makes a great companion to this one if you’d like to go that route. But we’ll be focusing here on audio, because it’s easier, hands-on, and fun.

We’ll start out with a sample of the audio that you’d like to play back — that is some data that corresponds to the voltage level measured by a microphone or something similar at regular points in time. To play the sample, all we’ll need to do is have the microcontroller output these voltages back at exactly the same speed. Let’s say that your “analog” output is via PWM, but it could easily be any other digital-to-analog converter (DAC) of your choosing. Each sample period, your code looks up a value and writes it out to the DAC. Done!

(In fact, other than reading the data from an SD card’s filesystem, and maybe having some on-board amplification, that’s about all those little WAV-player units are doing.)

Pitch Control

In the simplest example, the sample will play back at exactly the same pitch it was recorded if the sample playback rate equals the input sampling rate. You can make the pitch sound higher by playing back faster, and vice-versa. The obvious way to do this is to change the sample-playback clock. Every period you play back one the next sample, but you change the time between samples to give you the desired pitch. This works great for one sample, and if you have infinitely variable playback rates available.

Woof!

But let’s say that you want to take that sample of your dog barking and play Beethoven’s Fifth with it. You’re going to need multiple voices playing the sample back at different speeds to make the different pitches. Playing multiple pitches in this simplistic way, would require multiple sample-playback clocks.

Here’s where DDS comes in. The idea is that, given a sampled waveform, you can play nearly any frequency from a fixed clock by skipping or repeating points of the sample as necessary. Doing this efficiently, and with minimal added distortion, is the trick to DDS. DDS has its limits, but they’re mostly due to the processor you’re using. You can buy radio-frequency DDS chips these days that output very clean sampled sine waves up to hundreds of megahertz with amazing frequency stability, so you know the method is sound.

Example

Let’s make things concrete with a simplistic example. Say we have a sample of a single cycle of a waveform that’s 256 bytes long, and each 8-bit byte corresponds to a single measured voltage at a point in time. If we play this sample back at ten microseconds per sample we’ll get a pitch of 1 / (10e-06 * 256) = 390.625 Hz, around the “G” in the middle of a piano.

Imagine that our playback clock can’t go any faster, but we’d nonetheless like to play the “A” that’s just a little bit higher in pitch, at 440 Hz. We’d be able to play the “A” if we had only sampled 227 bytes of data in the first place: 1 / (10e-06 * 227) = 440.53, but it’s a little bit late to be thinking of that now. On the other hand, if we just ignored 29 of the samples, we’d be there. The same logic works for playing lower notes, but in reverse. If some samples were played twice, or even more times, you could slow down the repetition rate of the cycle arbitrarily.

In the skipping-samples case, you could just chop off the last 29 samples, but that would pretty seriously distort your waveform. You could imagine spreading the 29 samples throughout the 256 and deleting them that way, and that would work better. DDS takes this one step further by removing different, evenly spaced samples with each cycle through the sampled waveform. And it does it all through some simple math.

The crux is the accumulator. We’ll embed the 256 samples in a larger space — that is we’ll create a new counter with many more steps so that each step in our sample corresponds to many numbers in our larger counter, the accumulator. In my example code below, each of the 256 steps gets 256 counts. So to advance one sample per period, we need to add 256 to the larger counter. To go faster, you add more than 256 each period, and to go slower, add less. That’s all there is to it, except for implementation details.

In the graph here, because I can’t draw 1,024 tick marks, we have 72 steps in the accumulator (the green outer ring) and twelve samples (inner, blue). Each sample corresponds to six steps in the accumulator. We’re advancing the accumulator four steps per period (the red lines) and you can see how the first sample gets played twice, then the next sample played only once, etc. In the end, the sample is played slower than if you took one sample per time period. If you take more than six steps in the increment, some samples will get skipped, and the waveform will play faster.

Implementation and Build

So let’s code this up and flash it into an Arduino for testing. The code is up at GitHub for you to follow along. We’ll go through three demos: a basic implementation that works, a refined version that works a little better, and finally a goofy version that plays back single samples of dogs barking.

Filter “circuit”

In overview, we’ll be producing the analog output waveforms using filtered PWM, and using the hardware-level PWM control in the AVR chip to do it. Briefly, there’s a timer that counts from 0 to 255 repeatedly, and turns on a pin at the start and turns it off at a specified top value along the way. This lets us create a fast PWM signal with minimal CPU overhead, and it uses a timer.

Still some jaggies left. Could use better filter.

We’ll use another timer that fires off periodically and runs some code, called an interrupt service routine (ISR), that loads the current sample into the PWM register. All of our DDS code will live in this ISR, so that’s all we’ll focus on.

If this is your first time working directly with the timer/counters on a microcontroller, you’ll find some configuration code that you don’t really have to worry about. All you need to know is that it sets up two timers: one running as fast as possible and controlling a PWM pin for audio output, and another running so that a particular chunk of code is called consistently, 24,000 times per second in this example.

So without further ado, here’s the ISR:

struct DDS {
    uint16_t increment;
    uint16_t position;
    uint16_t accumulator;
    const int8_t* sample;   /* pointer to beginning of sample in memory */
};
volatile struct DDS voices[NUM_VOICES];

ISR(TIMER1_COMPA_vect) {
    int16_t total = 0;

    for (uint8_t i = 0; i < NUM_VOICES; i++) {
        total += (int8_t) pgm_read_byte_near(voices[i].sample + voices[i].position);

        /* Take an increment step */
        voices[i].accumulator += voices[i].increment;
        voices[i].position += voices[i].accumulator / ACCUMULATOR_STEPS;
        voices[i].accumulator = voices[i].accumulator % ACCUMULATOR_STEPS;
        voices[i].position = voices[i].position % SAMPLE_LENGTH;
    }

    total = total / NUM_VOICES;
    OCR2A = total + 128; // add in offset to make it 0-255 rather than -128 to 127
}

The first thing the code does is to define a (global) variable that will hold the state of each voice for as many voices as we want, defined by NUM_VOICES. Each voice has an increment which determines how many steps to take in the accumulator per sample output. The position keeps track of exactly which of the 256 samples in our waveform data is currently playing, and the accumulator keeps track of the rest. Here, we’re also allowing for each voice to play back a different waveform table from memory, so the code needs to keep track of the address where each sample begins. Changing which sample gets played back is as simple as pointing this variable to a different memory location, as we’ll see later. For concreteness, you can imagine this sample memory to contain the points in a sine wave, but in practice any repetitive waveform will do.

So let’s dive into the ISR, and the meat of the routine. Each update cycle, the sum of the output on the different voices is calculated in total. For each voice, the current sample is read from memory, added to the total and then incremented to the next step. Here we get to see how the accumulator works. The increment variable is added to the accumulator. When the accumulator is larger than the number of steps per sample, the position variable gets moved along. Next, the accumulator is shrunk back down to just the remainder of the un-accounted-for values using the modulo operator, and the sample position is wrapped around if necessary with another modulo.

Division?? Modulo??

If you’ve worked with microcontrollers before, alarm bells may be going off in your head right now. The AVR doesn’t have a built-in division routine, so that could take a lot of CPU power. And the modulo operator is even worse. That is, unless the divisor or modulo are powers of two. In those cases, the division is the same as shifting the binary number to the right by the number of bits in the power of two.

A similar operation makes the modulo tolerable. If, for instance, you want a number to be modulo eight, you can simply drop all of the binary bits that correspond to values eight and higher. So, x % 8 can be implemented as x & 0b00000111 where this logical-ANDing just keeps the least-significant three bits. If you’re not in tune with your inner bit-flipper, this can be viewed as a detail — but just know that division and modulo aren’t necessarily bad news if your compiler knows how to implement them efficiently when you choose powers of two for the divisors.

And that gets us to the end of the routine. The sample values were added together, so now they need dividing by the number of voices and centering around the mid-point to fit inside the 8-bit range that the PWM output register requires. As soon as this value is loaded into memory, the PWM hardware will take care of outputting the right waveform on its next cycle.

Refinements

The ISR above is already fairly streamlined. It’s avoided the use of any if statements that would otherwise slow it down. But it turns out we can do better, and this optimized form is often the way you’ll see DDS presented. Remember, we’re running this ISR (in this example) 24,000 times per second — any speedup inside the ISR makes a big difference in overall CPU usage.

The first thing we’ll do is make sure that we have only 256 samples. That way, we can get rid of the line where we limit the sample index to being within the correct range simply by using an 8-bit variable for the sample value. As long as the number of bits in the sample index matches the length of the sample, it will roll over automatically.

We can use the same logic to merge the sample and accumulator variables above into a single variable. If we have an 8-bit sample and an 8-bit accumulator, we combine them into a 16-bit accumulator where the top eight bits correspond to the sample location.

struct DDS {
    uint16_t increment;
    uint16_t accumulator;
    const int8_t* sample;   /* pointer to beginning of sample in memory */
};
volatile struct DDS voices[NUM_VOICES];

ISR(TIMER1_COMPA_vect) {
    int16_t total = 0;

    for (uint8_t i = 0; i < NUM_VOICES; i++) { total += (int8_t) pgm_read_byte_near(voices[i].sample + (voices[i].accumulator >> 8));
        voices[i].accumulator += voices[i].increment;
    }
    total = total / NUM_VOICES;
    OCR2A = total + 128; // add in offset to make it 0-255 rather than -128 to 127
}

You can see that we’ve dropped the position value from the DDS structure entirely, and that the ISR is significantly streamlined in terms of lines of code. (It actually runs about 10% faster too.) Where previously we played the sample at sample + position, we are now playing the sample at sample + (accumulator >> 8). This means that the effective position value will only advance once every 256 steps of the increment — the high eight bits only change once all of the low 256 steps have been stepped through.

None of this is strange if you think about it in base 10, by the way. You’re used to counting up to 99 before the third digit flips over to 100. Here, we’re just using the most-significant bits to represent the sample step, and the number of least-significant bits determines how many increments we need to make before a step is taken. This method is essentially treating the 16-bit accumulator as a fixed-point 8.8 position value, if that helps clear things up. (If not, I’m definitely going to write something on fixed-point math in the future.) But that’s the gist of it.

This is the most efficient way that I know to implement a DDS routine on a processor with no division, but that’s capable of doing bit-shifts fairly quickly. It’s certainly the classic way. The catch is that both the number of samples has to be a power of two, the number of steps per sample has to be a power of two, and the sum of both of them has to fit inside some standard variable type. In practice, this often means 8-bit samples with 8-bit steps or 16-bit samples with 16-bit steps for most machines. On the other hand, if you only have a 7-bit sample, you can just use nine bits for the increments.

Goofing Around: Barking Dogs

As a final example, I’d like to run through the same thing again but for a simple sample-playback case. In the demos above we played repeating waveforms that continually looped around on themselves. Now, we’d like to play a sample once and quit. Which also brings us to the issue of starting and stopping the playback. Let’s see how that works in this new ISR.

struct Bark {
    uint16_t increment = ACCUMULATOR_STEPS;
    uint16_t position = 0;
    uint16_t accumulator = 0;
};
volatile struct Bark bark[NUM_BARKERS];

const uint16_t bark_max = sizeof(WAV_bark);

ISR(TIMER1_COMPA_vect) {
    int16_t total = 0;

    for (uint8_t i = 0; i < NUM_BARKERS; i++) {
        total += (int8_t)pgm_read_byte_near(WAV_bark + bark[i].position);

        if (bark[i].position < bark_max){    /* playing */
            bark[i].accumulator += bark[i].increment;
            bark[i].position += bark[i].accumulator / ACCUMULATOR_STEPS; 
            bark[i].accumulator = bark[i].accumulator % ACCUMULATOR_STEPS;
        } else {  /*  done playing, reset and wait  */
            bark[i].position = 0;
            bark[i].increment = 0;
        }
    }
    total = total / NUM_BARKERS;
    OCR2A = total + 128; // add in offset to make it 0-255 rather than -128 to 127
}

The code here is broadly similar to the other two. Here, the wavetable of dogs barking just happened to be 3,040 samples long, but since we’re playing the sample once through and not looping around, it doesn’t matter so much. As long as the number of steps per position (ACCUMULATOR_STEPS) is a power of two, the division and modulo will work out fine. (For fun, change ACCUMULATOR_STEPS to 255 from 256 and you’ll see that the whole thing comes crawling to a stop.)

The only difference here is that there’s an if() statement checking whether we’ve finished playing the waveform, and we explicitly set the increment to zero when we’re done playing the sample. The first step in the wavetable is a zero, so not incrementing is the same as being silent. That way, our calling code only needs to set the increment value to something non-zero and the sample will start playing.

If you haven’t already, you should at least load this code up and look through the main body to see how it works in terms of starting and stopping, playing notes in tune, and etcetera. There’s also some thought that went into making the “synthesizer” waveforms in the first examples, and into coding up sampled waveforms for use with simple DDS routines like this. If you’d like to start off with a sample of yourself saying “Hackaday” and running that in your code, you’ll find everything you need in the wave_file_generation folder, written in Python. Hassle me in the comments if you get stuck anywhere.

Conclusion

DDS is a powerful tool. Indeed, it’s more powerful than we’ve even shown here. You can run this exact routine at up to 44 kHz, just like your CD player, but of course at an 8-bit sample depth instead of 16. You’ll have to settle for two or three voices instead of four because that speed is really taxing the poor little AVR inside an Uno. With a faster CPU, you can not only get out CD-quality audio, but you can do some real-time signal processing on it as well.

And don’t even get me started on what chips like the Analog Devices high-speed DDS chips that can be had on eBay for just a few dollars. They’re doing the exact same thing, for a sinewave, at very high speed and frequency accuracy. They’re a far cry from implementing DDS in software on an Arduino to make dogs bark, but the principle is the same.


Filed under: digital audio hacks, Hackaday Columns