In my last post I talked a little about the process of picking an ARM microcontroller to start using. After doing some more research, I've decided for now to start using the STM32 line of chips. I don't really know how it stands on the technical merits vs the other similar lines; the thing I'm looking at the most is suitability for hobbyist usage. It looks like Freescale is pursuing the hobbyist market more actively, but from what I can make out it looks like the STM32 line of chips has been around longer, gathered some initial adoption, and now there's enough user-documentation to make it usable. A lot of the documentation is probably applicable to all Cortex-M3/M4's, but it's all written for the STM32's and that's what most people seem to be using. So I feel pretty good about going with the STM32 line for now -- I'll be sure to post once I make something with one.
Within the STM32 line, though, there are still a number of options; I've always been confused too why different chips within the same line are so non-portable with each other. Even within the same sub-line (ex STM32 F3) at the same speed and package, there will be multiple different chips as defined by having different datasheets. I also ran into this with the ATmegas -- even though they're "pin and software compatible", there are still a number of breaking differences between the different chips! I guess I had always hoped that picking a microcontroller within a line would be like selecting a CPU for your computer: you select the performance/price tradeoff you want and just buy it. But with microcontrollers I guess there's a bit more lock-in since you have to recompile things, change programmer settings, etc.
At first I was planning on going with a mid-range line of theirs, the STM32 F3, since that's the cheapest Cortex-M4. Turns out that the different between Cortex-M3's and M4's is pretty small: M4's contain more DSP functionality (multiplication and division operations), and an optional FPU (which is included in all STM32 M4's). It looks like the F3 is targeted at "mixed signal applications", since they have a bunch of ADCs including some high-precision SDADCs. I thought about moving down a line to the F1's, which are cheaper M3's that can have USB support, but in the end I decided to move up a line to their top-end F4's. Even a 168MHz chip only ends up being about $11; a fair bit more than the $3 for an ATmega328P, but once you consider the total cost of a one-off project, I think it'll end up being a pretty small expense.
My first intended use is to build a new JTAG adapter; my current one uses an ATmega328 and is limited to about 20KHz. My development platform project, which I keep on putting off finishing, uses a lot of CPLDs and will soon start using FPGAs as well, so JTAG programming time would be a nice thing to improve. Hopefully I'll have something to post about in a few weeks!
Pretty much all the electronics projects I've done so far have used AVR ATmega chips as the central microcontrollers. I've been meaning for a while to step-up into the world of ARM chips: it looks like you can get chips that are much more capable at just around the same price as an ATmega328P, but you can also get chips that are vastly more capable at slightly higher prices.
The problem I'm running into is that the ARM world is way more fragmented than the 8-bit microcontroller world, since ARM's business model is to license out their IP. So choosing a chip isn't just a question of choosing a processor core and performance tier, but also more-or-less investing in learning a specific company's chips and toolchains.
There are a couple prominent lines out there; in the "AVR replacement" range, it seems like the two ARM processor types to consider are the Cortex-M0+ and the Cortex-M4. The M0+ is, as suggested by the name, the lower end of the two, so I'm mostly restricting myself to looking at M4's. Within that category, there are still a lot:
And maybe more. Looking around at other hobbyist-type projects, the only ones I'm seeing pop up are the STM32 and the Kinetis lines. STM32 probably wins by raw count of number of times I've seen it. Kinetis has the potential advantage that Freescale makes the only hobbyist-available Cortex-A9 chips, ie that have a fast 1GHz+ core like in your phone. I'm not sure if that's enough reason to choose their lower line of offerings, but it at least signals to me that they're more invested in the DIY crowd. I've scanned through the datasheets for both the Kinetis and the STM32 and they both seem pretty reasonable; they both have a similar number of Google search results.
The development boards for these things are surprisingly cheap: $18 and $10 for the Kinetis and STM32, respectively. I bought both of them and I'll try to play around with them; if anyone has an experience with this or an opinion either way, I'd love to hear it!
I had messed up one of my circuit boards, and in the debugging process I wanted to eliminate the external crystal as a problem (since there are so few other components in a bare AVR circuit). I looked at the ATmega328 manual, and found that it features an "Internal 128kHz RC Oscillator", which sounded safe enough. I pulled out my Arduino-based ISP programmer, and set the appropriate fuse to select that clock.
The first thing that I realized after doing this is that 128kHz is 128 times less than 16MHz, so that triple blink that happens when you start up your Arduino, that usually only takes about a second, will take on the order of minutes in this mode. I never had the patience to actually sit and wait this long, but the next option in the Clock Sources list is a "Calibrated Internal RC Oscillator". I had stayed away from this since I didn't want to calibrate it, but it seems like you don't have to calibrate it yourself if you're willing to tolerate a 10% frequency uncertainty.
So the ATmega went back into the programmer, but then I got a message along the lines of "invalid device signature: 0x000000". Uh oh. I knew that this was a possibility: for some reason, the ATmega parts use the programmed clock source when in programming mode, instead of defaulting to an internal source, which means that it's possible to program your ATmega into a mode that it is no longer programmable. I knew of this issue, so made sure to not set it to "external clock" mode, so I was surprised that it was still unprogrammable.
After doing some researching, I learned the problem is there is a maximum programming speed based on the clock speed of the target ATmega, and my Arduino-programmer was exceeding it.
Slowing down the programmer
Ok, time to dive into the ArduinoISP source code. It's using a lot of registers that I'm not familiar with, but one that looks promising is the "SPCR" register in the spi_init() function. The ArduinoISP sketch uses the hardware SPI support, and SPCR is the SPI Control Register. Looking at the docs, the bottom two bits of this register control the SPI clock speed, which seems promising -- but the sketch already has them set to the minimum setting of 1/128 of the cpu clock. I forget the exact minimum ISP clock, but it's smaller than the target's cpu clock, and since the two ATmega's clocks were off by a factor of 128, this wasn't going to work.
One thing I debated doing was to reduce the clock speed of the programmer ATmega. If I had alternate-frequency crystals, it would have been decently easy to replace that, though I'm not sure what other effects that would have on the system (would probably screw up the baud rate calculation for the serial port). But, alas, I didn't, so the option would be to reprogram the programmer to use a different clock source, and I wasn't very confident in my ability to do that.
Instead, I decided to modify the programmer's firmware. As I mentioned, the ArduinoISO sketch uses the hardware SPI, which was already clocked as slow as it can go, so I'd have to come up with an alternative SPI implementation. Normally, the difficulty in this would be maximizing the potential clockspeed, but in this case that's not an issue and bit-banging the protocol seemed pretty easy. It probably should have been, but I messed up some of the bit twiddling and I started to run into how much harder it is to debug firmware than it is to debug software running on your primary computer.
Anyway, I was eventually able to get it to work, though the programming was painfully slow (several minutes). If you have the misfortune of getting stuck with a 128kHz ATmega, you can use my modified ArduinoISP code to rescue it.
I'm late in writing this post since Hackweek was a few weeks ago now, but better late than never I suppose.
As I mentioned in my previous hackweek post my goal was to use my new 3D-printer to build some parts for a simple robot.
Unfortunately, getting the 3d-printer working took four out of the five days of Hackweek, so there wasn't much time to get the robot going. I was able to multi-task somewhat, since calibrating the printer involved many periods of waiting for test prints, so I was able to build a simple robot, though the "3d-printed" aspects were minimal. Getting a basic working is surprisingly simple: get some simple DC motors, and apply a voltage across the terminals and they go! These particular motors are small enough that they can be driven with a single LiPoly battery.
Using alligator clips to connect the battery and the motor is all fun and good, but eventually I wanted to control the motors from my ATmega. I used a single L298N motor driver to drive two H-bridges, one per motor, which was surprisingly straightforward (I just built the "typical application" circuit from the datasheet). For input, I used this joystick with the associated breakout board, and "mounted it" on a small breadboard as a simple control:
I used one of my ATmega328 Arduino-like boards to read the analog readings from the joystick (which is just two potentiometers), and use those readings to implement a differential drive control on for the robot. Here's another pic of the on-robot electronics:
So electronically, this set up is extremely simple, and not very innovative; once I had all the parts, it probably only took a few hours to have the wheels turning. Sidenote: maybe I'll write another post about this, but I'm learning that surprisingly, part-selection is where I spend most of the project's design time, since picking the parts involves knowing how they will all fit together, and verifying whether a part will work usually involves a relatively-complete idea of the design as a whole.
It was definitely educational to get the motors turning, especially as controlled by a joystick, but the hard part of the project for me was building a chassis for all the parts. There very first "chassis" I used consisted of just the three main parts (gearbox, breadboard, arduino) taped together, with no rear castor, so the breadboard was dragging along the floor. I decided I wanted a baseplate to mount the gearbox + castor on, so I came up with this T-shape:
Sorry this is the only picture I have; imagine that it's filled in and about 0.5cm tall.
What are those three squares, you say? Well, my idea was to mount the gearbox using self-tapping screws, screwing them directly into the baseplate. I've been printing most of my parts at low "infill density" -- ie while the part looks solid, the inside is only 20% full, to save on materials and printing time -- thus I was worried about whether there was enough material to actually screw into. Ideally I'd be able to print those three screw-areas at 100% fill density, and while the 3d-printer is certainly capable of doing that, Slic3r, my slicing program (the program that takes 3d models and produces a series of line segments) didn't seem capable of it.
So instead, I decided to try creating these small square holes, and to create square "screw plugs" that would fit into them, with small caps on the bottom so that the base plate could rest on them (sorry for the lack of a picture).
This design worked, though there were enough issues that I'm not tempted to do it again. Assembly became pretty complicated, since there was now an additional piece to hold in place while placing the screw. The plugs added a bunch of play to the base plate, both in the XY plane, but also in the Z axis (I think this could have been avoided by making the plugs shorter than the hole). In the future I think I'm going to try just using untapped holes, and use a nut+washer combination on the other side; I think this will be more reliable and not require separate parts.
The base plate let me attach the gearbox and the castor, and with some tape I was able to have a barely-structural robot. It quickly became clear, though, that I needed something to hold the pcb above the gearbox, since it kept on sliding around and would eventually hit the wheels and the whole contraption would fall apart. Here's the design I came up with; these are the three iterations of it, from earliest on the left to final on the right:
The first design had several issues, the worst of which was that it was the wrong size, and secondly that it required a fair amount of support material. The second iteration was the first that worked, but I realized that I wanted guard rails to hold the breadboard in place, which is the main change between v2 and v3. You can see how it mounted on the baseplate:
It had a fair amount of XY stability, but if I were to go back to it, I'd add a small piece on the bottom that would keep it attached to the baseplate, since right now it comes right off when pulled upwards.
Here's a video of it driving; this is before I created the breadboard holder, and you can tell it lacks structural integrity (though one could say it makes it up in spunk):
Overall, even though the 3d-printing aspect didn't turn out how I wanted, I found the experience of building a robot from scratch to be very rewarding, so stay tuned since there will be more robotics-related projects coming up :)
One issue I've quickly run into is that I want to embark on new projects, but don't want to completely disassemble my existing projects in order to get the parts I need. For some parts of the project, like resistors and wire, it's pretty easy to over-buy those and not need to scavenge old projects for them. For other things like breadboards, it's less easy, but at $5 a breadboard, I don't mind over-buying these as well.
The most expensive common component I have, though, is the Arduino-like microcontroller board that I use as the project base. A real Arduino will run you about $22 on Amazon; there may be cheaper options out there, especially if you're willing to buy older versions, but this is the cheapest retail one I've seen so far (usually they're about $30). These things are highly versatile and I wouldn't mind having a couple extras of them, but they're expensive enough that I'm not quite ok saying that I'm going to buy one per project I'm working on.
One very simple option is to simply disconnect the wires from the Arduino when I want to move it to another project, and reconnect the wires when I want to get a project running again. I actually did this for a while, but this quickly became unmanageable, since I was having to remember exactly where all the different wires go.
Another option I've tried is to use the shield interface as a glorified connector, so that reconnecting the Arduino is just a matter of reattaching the shield:
I'm using the SparkFun ProtoShield PCB ($5) with a set of Arduino stackable headers ($1.50), to give me a "connector" which is easy to snap onto Arduinos. This system has served me fairly well, but at $6.50 a shield, I feel like I don't deserve to be swapping these out all the time.
So going back to my original thought, it'd be nice to be able to leave a microcontroller board connected to each project, but to not have it cost $22. I looked around for some lower-cost Arduino variants, but pretty quickly I decided to build my own instead.
Enter the Myduino
Fortunately, with the popularity of the Arduino, there are many published schematics for Arduino-like microcontroller boards. I've built my existing boards off of The Shrimp schematics, so I used that again as a base for this new board. There are a couple ways I had to modify it, though, for its new purpose: first, I need an interface for connecting from the computer to the board in order to program it. I decided to use the SparkFun "FTDI Connector"; I'm not sure how much of a standard this is, but they have it in their Eagle library and it has exactly the pins I wanted, so I decided to go with it (plus I can buy that cable if I want to).
The second decision is how I want to connect from the board to the rest of the project. I decided to stick with the theme of using female headers, but instead of having four separate headers, I decided to have a single 2-row header, to reduce space.
The last decision is what to call it. I've never felt great at naming things, so I decided to not put too much effort into it and just call it the Myduino :P
Here's the schematic I came up with:
There's not a whole lot going on here that isn't common to all ATmega328-based boards, so I'm hoping I didn't mess it up. One thing I've realized in the course of writing this blog post is that I forgot to bring out GND and VCC to the header on the right, so I'm thinking I'll solder some extra loose wires to some of the exposed pads.
The thing that's probably more interesting is the board layout. As I mentioned, one of the primary drivers for this project is to create a low-cost alternative, so my primary goal for the board design was to reduce the board size, since the board cost is directly proportional to its size. So, the board is quite small (1.7"x1.35" to be exact); you can get a sense of proportions by noticing that that's a 28-DIP ATmega328 in the middle. Here's what I came up with:
Note -- all the grey writing (not the white) is stuff that doesn't appear in the final board construction; I probably should have turned it off entirely. Also, there is a ground plane on the back (blue) side, but I usually turn that off for visualization to keep things cleaner.
This board is quite a bit more aggressive in its design than my first board, in a couple different ways. First of all, I used surface-mount components (only simple two-terminal ones), which I've never used before. Second, I actually put some of those components on the bottom of the board to explore the limits of doing that: I feel like I probably can put whatever components I want on either side, including through-hole ones, but I wanted to start first with just the decoupling capacitors, which are generally held to be easy to put on the bottom.
Third, I reduced the pad sizes on the header on the bottom. The header has a pin spacing of 0.1", and the SparkFun library where I got this from has the pads have a 0.075" diameter, giving a 25-mil spacing between the pads. I very much wanted to route the traces between the pads, but I also want to be using 10-mil traces with 10-mil spacing, which won't fit. I had two options: decreasing to 8-mil traces with 8-mil spacing, or decreasing the size of the pads. Decreasing the trace size probably was the "right" choice, since OSH Park can do 6-mil traces with 6-mil spacing, but I'm feeling confident in my soldering and I wanted to test pad-size limits too.
Fourth, I used a ground plane, since that seems like a good thing to do.
Lastly, I did all the routing on this board by hand. Part of the reason for why is because when I first tried auto-routing it, I used the wrong settings (50-mil grid width) which made the autorouter totally unable to route the board. In retrospect, though, I'm pretty happy that I did the routing manually, even though I re-ran the autorouter with better settings and it was able to do it.
I submitted the order to OSH Park for a total cost of $11.45, and I should be getting it back in a few weeks. There are a couple changes that I'm thinking about making, but I'm trying to hold off until I get the boards back to submit a new rev.
So, did I succeed in making this cheap enough? Here's the bill of materials; except where noted, all prices are from DigiKey and don't include any bulk discounts:
- PCB: $3.82 from OSH Park ($11.45 for three boards)
- ATmega328-PU: $2.88
- 1x 20-pin female header: $1.35
- or 1x 24-pin female header: $1.73
- 1x 6-pin female header: $0.67
- 1x 16MHz crystal: $0.36
- 1x pushbutton [couldn't find this exact one on DigiKey and it's cheaper on sparkfun]: $0.35
- 1x 10uF capacitor: $0.18
- 2x 22pF capacitor: $0.10 each
- 2x 10nF capacitor: $0.10 each
- 1x 100nF capacitor: $0.10
- 2x SMD LEDs: $0.08 each
- 2x 330 ohm resistors: $0.02 each
- 1x 10k ohm resistor: $0.02
Which comes out to $10.33, not including DigiKey shipping (starts around $3). I'm actually pretty surprised by this; I thought it would be cheaper, since the board is so minimal. I guess I didn't expect the headers to be so expensive. I can think of a number of ways to cut costs if I wanted to:
- Use seeedstudio to bring the PCB cost down to $1.52 ($9.90 + $5.30 shipping, for 10 boards), though I haven't received my test boards from them yet.
- Use a cheaper ATmega part, for instance this one looks pin-compatible and is $0.80 cheaper
- Redesign the board to not bring all 20 pins out separately to the header. I rarely use more than 8 of the pins on the Arduino, so one possibility is to have a 10-pin header with two of the ATmega pins connected to each header pin, letting you drive the header from either pin.
- Use male headers instead of female ones. This might actually make a lot of sense for breadboarded projects, since the male header could be inserted directly into the breadboard.
- Buy in bulk; this is particularly true of the $0.10 capacitors, which decrease in cost to $0.024 if you buy at least 10 of them.
Overall, right now I'm not dying to implement any of these (except maybe the buying-in-bulk part), since this is cost competitive with the $6.50 "shield connector" option, and will hopefully be way easier to use. Now I just have to wait for the boards to arrive, and figure out a plan for the meantime since I still have projects I want to do.
Alright, I got my $10 soldering iron today and put together my USB->UART board, and I was finally able to program my Arduino-compatible ATmega328! You can see what I'm messing around with here:
I got all the basic Arduino tutorials running, so I decided to try my hand at something a little tougher: a digital "faradmeter", ie capacitance-measurer. I've never heard of a device like this so I'm not sure what it's called, so I'm just going to go with "faradmeter" to parallel "voltmeter" and "ohmmeter". The usefulness of a device like this is a little debatable since it's only really useful for dedicated capacitors which are already going to be labeled, but let's go with it for now.
In the picture above, you can see the measured electrolytic capacitor on the top right of the breadboard. Here's a very basic schematic of what my board looks like; I've omitted all the wiring that's due to the basic Shrimp schematic, which my board is based off; this is my first computer-made schematic, so don't be too harsh on it :)
The schematic is quite simple, but I'm learning that much of a microcontroller project's complexity is in the circuitry, and not just the code, so I'm trying to get practice at creating these schematics.
The basic idea behind this circuit is I'm measuring the capacitance of the capacitor by testing how quickly it charges. I'm using pin A5 as a sense pin, and using both A3 and A4 as drive pins; using two separate pins lets the microcontroller control the amount of current it drives, theoretically increasing the range of capacitances that it can measure.
The basic procedure is the ATmega first fully discharges the capacitor, then charges it back up to roughly half-full and measures the amount of time that process takes, and from that time calculates the capacitance. It starts by charging just with the 22kohm resistor, and then switches to the 1kohm resistor to speed up the process.
There are a couple ways to calculate the capacitance from the charging time; perhaps the simpler one is to essentially time-integrate the inferred current to get the charge on the capacitor, and use C=Q/V to get the capacitance. I decided to go with a slightly more roundabout method of calculating from an exponential RC circuit model (which is derived from C=Q/V); I didn't try both ways to compare, but in theory the exponential approach should be better able to scale to small capacitances, since it can more-correctly calculate based on "large" (compared to the RC constant) time slices.
I tried the circuit on a bunch of the capacitors I have, and after dealing with a number of issues I think it's finally working. I think the one issue that I ran into most, but might have been misattributing so I'm not sure, is that if you switch a pin from driving a logic 1 to being an input pin, with the purpose of disabling the pin, it will actually activate an 20kohm pullup resistor instead of going truly high-impedence. This might not matter too much for digital circuits, since it won't typically change the logic level, but in this system where I'm driving sub-mA currents, it threw off the results. Speaking of results, I'm not sure how accurate mine are since I have no way to double-check them, but they do align closely with the marked capacitances. The schematic I have above seemed to be able to measure down to about the 10nF range, though I bet if I replaced R1 with a larger resistor + improved the code, I could get it down into the 1nF and possibly even 100pF range.
I started yet-another github repo, and you can see the arduino sketch + eagle files here.
I hooked up my "LCD Button Shield" to my faradmeter to directly see the readings, rather than having to look at the serial console. It was actually surprisingly easy to set up, other than the fact that I had bent one of my ATmega pins when inserting it and didn't realize this until I tried using it. The Arduino IDE comes with a "LiquidCrystal" library that is designed to drive displays like this; writing out "hello world" is just a few lines, and writing out the capacitance was just a matter of duplicating the output to both the serial and the lcd.
Also, according to Wikipedia these devices are just called "capacitance meters".