The task is very simple. I have a solar tracker. I have a microcontroller that knows what direction the tracker should be pointing. I have a cordless drill that I've taken apart to do the actual work. So why is it taking me WEEKS AND WEEKS to get this working? I can't even turn the drill on yet, at least not without threat of releasing the magic smoke.
It should be extremely simple. Here is how a drill works.
OK, so it should be easy to just replace the human-operated switch with a microcontroller-operated one.
The microcontroller replaces the human and relay replaces the switch. It's a high-amp relay because on the very first magic smoke release test I found that the drill draws 20 amps (or more!). It's also a 15V battery, so I managed to remember the resistance of the motor as being .7 ohms which makes the V=IR math work out.
However, when I almost melted my entire apparatus on the second test I realized that the motor is only about .1 ohms. How on earth can I be feeding 15V to .1 ohms and only drawing 20 amps? Including a current-limiting resistor doesn't improve things much, since it just wastes a bunch of power getting really, really hot. After a little thought, I decided to actually look at the drill switch. I can't get it open, but I was able to confirm this much:
I don't know how, but that magic box is somehow limiting the current. One thing I can see in there is a transistor, which could definitely do the job....except it would have to be awfully high power to handle 20 amps. Or maybe it isn't? Maybe the 20 was transient and it normally feeds more like 2-3 amps? No idea. Which leads me to think maybe I need to give up and do something like this:
Which is stupid. If I knew how it worked, I could probably hook the microcontroller directly to the magic box and forego all my rubegoldbergian relay stuff (which should be a post on it's own...). It's also annoying that I know this can't be an unsolved problem. But I must not be thinking of the right keywords to find the solution.
I cracked 50 lb of weight loss today. I'm still on track (±ε) to reach my original goal by Christmas. It also happens to be, as of yesterday, 10 lbs in 100 days, or almost exactly 350 calories/day.
Pursuant to that, I have made a breakthrough in food reduction technology. One of my favorite meals is...undocumented on this site?! WHAT. Anyway, it involves guacamole. The problem I've had is that I need to make enough to use up an entire avocado, which now that my metamabolism needs fewer calories is a little too much. Avocado turns brown if you look at it funny, so I can't put the excess in the fridge. I also can't throw it away because of the starving children in Africa. However, it turns out to freeze just fine. So now I can make M/Nths of a recipe which not only vastly reduces the hit points but also means I only use M avocados every N days.
I'm trying to embed a microcontroller into a project that I'll describe more later. All I know is Arduino, so I'm going with that. (I guess I could just use the Atmega chip or however that works, but baby steps, people.) The basic Arduino is a little unwieldy for this, but last night I finished soldering and testing the Really Bare Bones Board. And besides being much smaller and breadboard-compatible, it's also much cheaper because it pushes some of the cost of the unit into a one-time-purchase cable.
Number One Son, age 9, is trollering me. He just found out about HTML and has made a couple of pages. (With random size changes and font colors, naturally.) He keeps calling the .html file a "program".
I've never been completely happy with my temperature logger. It's a bit fragile in the sense that if anything at all goes wrong, and there's no way to tell that at the time, I lose the entire run. I lost a run Memorial Day weekend.
Instead of storing the measurements on the Arduino, I'd like to instantly beam them onto my computer far inside the safety of the house. That way I can track things realtime as well as be assured that I have them. Coincidentally, for my birthday, I got both another Arduino1 and Making Things Talk.
The book describes a great number of schemes to make microcontrollers talk to each other and to computers. You can use wireless networking, bluetooth, XBee, etc (I have only the vaguest notion what some of these are). Naturally the easiest protocols require the most expensive hardware. I only need one way, slow communication, so I got a simple RF module.
Claim:
It works just like a serial port! Just connect the transmitter to the TX pin and the receiver to the RX pin! It Just Works(tm)!
Reality:
No.
Perhaps my unit was faulty. I found many tutorials and guides across the internets and while results varies, I can't ever really say it worked. I did see data appear for a short time, but mainly what I saw was noise. Or nothing at all, which is even less explicable.
Last night I had a brainwave. Or brainstorm. Something happened to my brain and it resulted in an idea. Why not use a wireless laptop as the go between? The kids have these OLPC dealies. The laptop has a USB port and does WiFi. I have a WiFi router (specifically purchased, used, to work with these laptops). About 30 minutes and 10 lines of Python later, I was reading values from /dev/ttyUSB0 and sending them out over a socket to my desktop to another 15 minutes and 20 lines of Python.
The guts of the entire scheme are already there. But with so much success so fast, I'd like to add features. For instance, instant graphing of values on both ends. A protocol so that the laptop knows if there's been an error and can tell me, out in the field. When I have more than one sensor, I'll need a way to indicate which sensor had what value. It'll be like a complete Science Sensing Station!
1If you are at all interested in robots, sensors, controlling stuff with computers, electronics or just plain messing around, I highly recommend the Arduino. That SparkFun item is all you need, assuming you have a USB port (and possibly a cable). Well....you may also need some external electronics, depending on what you want to do. LEDs, resistors, motors, etc.
A lot of things, many of them new to me, went into this project. We have "regular" programming, "device" programming, a communication protocol, stepper motor control, motor mounting, power supply design and the mathematics of drawing an optimal line on a pixelated display. Some comments on each.
Mounting
I originally thought this was going to be the hardest part. "The rest is just sitting at my computer desk and either typing or handling tiny pieces of electronics" was my opinion. In fact, I just cut a couple spacers and then improvised mounting plates from....I don't know what that stuff is. It's like countertop covering. In any case, this part took maybe 45 minutes. It helps that one vital component of the mount is masking tape.
Connecting the steppers to the knobs went through some iterations. The motors had gears on the ends, but of course the EAS isn't geared. I tried various ways of coupling one to the other, but wasn't satisfied. (This turned out to be a power supply problem, which I talk about below, but I didn't know that at the time.) In the end I managed to remove the gears--they are just press fit, so you can knock them off with a nailset and a hammer. The shafts of both motors and the EAS were almost all the same size, which in turn was just a tiny bit bigger than the internal diameter of some plastic tubing. I just cut a short length as a sleeve and voila.
Stepper Motor Control
Physical Computing was invaluable. In fact, reading about how to control a stepper was what gave me the original idea of controlling an EAS1. (The guts of that section are online.) I originally tried to do the entire thing with totally generic components, i.e. plain transistors, but I soon gave that up. I unbent enough to use 2 dual H-bridges. Still generic, but you can't get them at Radio Shack (but what CAN you get at Radio Shack?). This compacts the wiring and anyway the motors need more current than a regular transistor can switch.
If this were a real product, I would definitely build/buy a stepper control board. Finer control isn't an issue, but sweet mother of crap this thing is loud. I think a board can ramp the amperage up and down to give a smoother movement that won't shake the house down.
"Device" Programming
The Arduino libraries include an object-oriented Stepper control library, but it wasn't really suited to what I was doing. The most basic fact it cared about was the RPM. The most basic fact I cared about was how many steps to take. So I wrote my own SingleStepper library. That makes me sound alphanerdy, but seriously, it was just a matter of copying and tweaking the existing library.
Another reason for writing my own was that the Stepper lib left the current on even when the motor wasn't turning. That's great if you need the torque to stay on, but non-great if you have a limited budget of amperage. So my library also turns the power on only long enough to move the motor, then turns it back off.
Communication Protocol
The stock Arduino serial comm library only supports reading a byte at a time. WTF ARDUINO ? Naturally I need to send coordinates larger than 255. The solution is conceptually not too difficult: Send a two-byte int a byte at a time and reassemble on the other end. This actually took a couple days to implement, though, because Python (on the other end of the wire) isn't geared towards working with binary data and then there's the question of negative numbers, twos complement, endianness, etc.
Also, in the case where a lot of coordinates are being generated very quickly, the internal buffer can overflow and the EAS goes haywire. So each coordinate has to be ACKed by the controller before the next is sent.
Line Drawing
Here's another place where I didn't go 100% from my own bootstraps. I actually did start deriving this myself, but soon realized that there were going to be special cases and stuff and I wasn't interested in debugging those. Instead, I just adapted a classic algorithm. I didn't use any of the optimizations on that page, since they are more for a digital display than position control. I did make one optimization of my own, though, which was to not move each motor a single step at a time if I could take 5 steps with one and then 1 with the other.
Theoretically, one could turn both motors on at the same time but at different rates to draw diagonal lines. But even if I had the electric power to do that it's just too hard to attempt.
"Regular" Programming
This is so dead simple that it's really not that interesting, but just for completeness: Generate a series of coordinates (either by hand typing in your own or using some equation) and send them out the serial port.
Actually, I should explain that a bit. I chose to implement this as a display-like device. You give it a coordinate pair X,Y and it moves there. The Arduino handles everything after being handed the values. So for instance the sine wave is being calculated as a series of points in Python on my computer and then sent over to the microcontroller for plotting.
Power Supply
Of these all, the one that I figured out last was the power. The EAS isn't really made with computer control in mind. The controls are surprisingly sticky. At first I thought the coupling between motor and EAS was slipping, but I eventually eliminated that. The power supply I bought is rated up to 1.5A, but only puts out 5V, so the motors only drew about 700mA. Turns out that wasn't quite enough to consistently turn the knobs. By bypassing the power supply, I was able to feed 1A directly to each motor (one at a time) and that was enough.
It may still be a little short, though, because I still get the occasional glitch. But I don't have a wall wart that puts out more than an amp at more than 8V.
Cost
The steppers I got out of a broken inkjet printer. (I really lucked out on that, I later realized. Two other inkjets I disassembled had steppers but they were tiny.) I already had the mounting stuff and the Arduino, as well as wires, resistors, etc. I had to buy the H-bridges, the power supply, a heatsink and some power resistors. That probably adds up to $20 or $25. But I can and will reuse it all, especially the power supply, which was the most expensive single purchase.
Oh yeah, and I had to buy an EAS. But one of my design goals (as well as an instruction from my seven year old) was to not alter it beyond being used by humans afterwards. So I consider that a capital investment as well.
1Gave me the idea, but I wasn't actually spurred to do anything until I saw the EAS clock. The auto-erase functionality of the clock would be really nice to have, but I'd like to point out that the ability to draw curves is even nicer.
Per request, here's a closeup of a diagonal line. You can't see the "pixels".
That said, you actually can see the "pixels" in some curves. I think that's because of the (mathemetical) stepping involved in going from floating math to integer.
A few weeks ago I was really proud of myself for figuring out how to make a binary clock with multiplexed outputs to save pins. Now I learn about charlieplexing and I'm agog. Simply agog.
One project I've been kind of wanting to make is an LED cube. To illustrate just how awesome charlieplexing is, look at how many output pins you'd need to drive an LED cube of a given size compared to the simple multiplexing I "invented".
Edge Length
# LEDs
Req. Multiplexed Outputs
Req. Charlieplexed Outputs
3
27
12
6
4
64
20
9
5
125
30
12
6
216
42
16
So on the Arduino, where I think I have 12 ports to work with, I could either do a 3x3x3 cube the old and busted way or do a 5x5x5 cube the new hotness way. (Or maybe I have 18-19 ports, in which case it's still 3x3x3 the old way but now 6x6x6 the new way.) But how can you possibly control that many LEDs with so few ports? Read the instructable!
Or read this simplified summary: Basically, you set things up so that every port can be either positive or negative. Then attach your LEDs so that every possible combination of ports lights one up. (Remember that LEDs are one-way valves, so port A being positive with B negative can light one LED while reversing polarity can light another one. Just remember not to cross the streams.) "Every possible combination" of N ports is N *(N - 1), so with, say, 9 ports you can control 9 * 8 = 72 LEDs.
5x5x5 isn't enough to be a 3D display, though. But a larger cube could be decomposed into smaller cubes each controlled by a separate microcontroller. 10x10x10 is probably large enough to show some cool animation, although coordinating 8 microcontrollers might be a pain. Not to mention wiring up 1000 LEDs.
I've seen these binary clocks around the office. They are fairly cool, but they fail to please in one important way: Each decimal digit is represented separately. 14 seconds is represented as a binary 1 and a binary 4, rather than a binary 14. Granted, reading 6 bits depicting 0-59 seconds is a little harder than the 4 bits required for 0-9. But is ease of use really the primary concern of a binary clock?
MISSION: Build this clock the right way. Namely, 6 bits for the seconds, 6 bits for the minutes and 5 bits for the hour (or maybe 4 bits for the hour with 1 bit for AM/PM). (Another idea would be a straight-up 17 bits for the 86400 seconds in a day, but seriously.)
Now then. I know there are clock chips out there. And it is probably possible to do this using hardware only, say with a 555. But I'm a dumb programmer, so everything looks like a Turing-complete problem to me. Plus I already have an Arduino. So that's the medium of choice. Using an Arduino, some LEDs and resistors and pure force of will, I'm going to make this work.
But there's a problem already. My design calls for 17 LEDs. The Arduino only has 14 output ports1, 2 of which I can't use because they are special. The solution to this problem is multiplexing. The basic idea is that you use X/Y coordinates to address each LED, Battleship-style. So for MxN LEDs, you only need M+N ports.
Let's say I want to light up the LED labeled 0,0. I need to apply positive voltage to A (the left column) and negative to 1 (the bottom row). B and C should be low while 1 and 2 should be high to "push the wrong way" against the remaining diodes.
But now there's another problem. Let's say I want to light up both 0,0 and 2,2. I apply positive to A and C and negative to 1 and 3...and I get all four corners lit up. Long story short, it is also necessary to employ a spot of subterfuge. If I want 0,0 and 2,2 lit up, I have to do them one at a time, but switch back and forth so fast nobody's the wiser.
And finally, there's the little matter of the clock function itself. There isn't an API call for that exactly, but the underlying chip supports interrupts. I basically just copyandpasted the timer code from elsewhere and then added a long comment explaining it to myself, probably incorrectly.
Grainy video (the ticking is an amazingly coincidental loud clock in the same room):
Somewhat less grainy still shot:
The code:
#include <avr/interrupt.h>
#include <avr/io.h>
#define NUMPOS 6
#define NUMNEG 3
int pos[NUMPOS] = {9,8,7,6,5,4};
int neg[NUMNEG] = {12,11,10};
int i = 0;
int j = 0;
int k = 0;
int lastpos = 0;
int lastneg = 0;
int isr_counter = 0;
int oldsecond = 0;
volatile int second = 0;
int seconds = 0;
int minutes = 31;
int hours = 13;
/*
Here's how I think this works. The Atmega168 clock runs at 16MHz.
The "prescaler" divides that down. In this case, it clicks at 2MHz.
Each time it clicks, it increments at 8 bit register by 1. The register
overflows after 256 clicks. That overflow is the interrupt we receive.
2000000 clicks/second divided by 256 clicks/overflow = 7812.5 overflows/second.
So if I could count 7812.5 overflows, I know a second has elapsed. I can't
find .5 of an overflow, so I should really use the /4 prescaler. But
a) that uses more power and b) I can't figure out what bits to set to do that.
*/
ISR(TIMER2_OVF_vect) {
isr_counter++;
if (isr_counter > 7811) {
second++;
isr_counter = 0;
}
};
void SetupTimer2(){
//Timer2 Settings: Timer Prescaler /8, mode 0
//Timer clock = 16MHz/8 = 2Mhz or 0.5us
//The /8 prescale gives us a good range to work with
//so we just hard code this for now.
TCCR2A = 0;
TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20;
//Timer2 Overflow Interrupt Enable
TIMSK2 = 1<<TOIE2;
//load the timer
TCNT2=0;
}
void setup() {
for(i = 0; i<NUMPOS; i++) {
pinMode(pos[i], OUTPUT);
}
for(i = 0; i<NUMNEG; i++) {
pinMode(neg[i], OUTPUT);
}
for(i = 0; i<NUMPOS; i++) {
digitalWrite(pos[i],LOW);
}
for(i = 0; i<NUMNEG; i++) {
digitalWrite(neg[i],HIGH);
}
Serial.begin(9600);
SetupTimer2();
}
void showXY(int col, int row) {
digitalWrite(pos[lastpos],LOW);
digitalWrite(neg[lastneg],HIGH);
digitalWrite(pos[row],HIGH);
digitalWrite(neg[col],LOW);
lastpos = row;
lastneg = col;
}
void loop() {
// time changed, so readjust all the details
if (oldsecond != second) {
if (second > 59) {
second = 0;
minutes++;
if (minutes > 59) {
minutes = 0;
hours++;
if (hours > 23) {
hours = 0;
}
}
}
seconds = second;
oldsecond = second;
}
// seconds is column 2 and has 6 bits
k = 2;
for(j=0; j<6; j++) {
if (seconds >> j & 1) {
showXY(k,j);
}
}
// minutes is column 1 and has 6 bits
k = 1;
for(j=0; j<6; j++) {
if (minutes >> j & 1) {
showXY(k,j);
}
}
// hours is column 0 and has 5 bits
k = 0;
for(j=0; j<5; j++) {
if (hours >> j & 1) {
showXY(k,j);
}
}
}
1Possibly not true. I found one post that said the 6 analog in ports could be used as digital out. But even if multiplexing isn't strictly necessary for this project, it would be for a larger one.
For some reason this "ambient orb" Arduino project blew me away. The basic setup is very easy: red, green and blue LEDs mixed in different amounts. (Putting them inside a diffusing cover helps the mixing.) There are only two catches:
LEDs aren't dimmable the way incandescents are, so how do you control mix?
Finding LEDs of all three colors in the same output is nearly impossible.
The solution to the first catch is Pulse Width Modulation. Basically, you send tiny bursts of current so it flickers on and off faster than you can see it. The more time it spends on (the "duty cycle") the brighter it seems. Doing this from the Arduino is simply a matter of adjusting a number to say what you want the duty cycle to be in the range 0-255.
For the second catch, I pored over catalogs and websites trying to find matching LEDs. I did find them more than once, but it was always coming out too expensive. I mean, I was blown away by the idea, but not to the tune of $10! (Maybe I should have called this blog "The Cheap Bastard".)
I actually do already have all three colors, but the single blue LED I have is a trillion times brighter than any of the others. Really, it's blinding. I could have just bought a new blue to match the low-level reds and greens I have, but what power are they? Is there any way to figure that out, maybe from power consumption?
Finally I realized I could just use a bunch of reds and greens and also cut the blue's power in half (i.e. never get the PWM duty cycle above 50%) and it comes out all right. Mostly. The blue is still too powerful and swamps the blue-green transition.
Why is the green almost invisible in the video? Is the CCD in the camera less sensitive to green? Is the green really a lot less powerful and my eyes just adjust to it?
Some pics of the final state:
You might notice an extra button. I decided to write to EEPROM rather than an array after all. The reason was an unreliable power situation. A 9V battery lasts for a few hours and I didn't want to lose hours of data at the last second. So we have a switch for power on/off, a button for "send data" and a button for "start collecting data". The last one is I can control when the EEPROM starts getting overwritten the next time I turn it on.
That relatively minor change forced a paradigm shift in what processing was done where. Originally, I was just reading the voltage ratio from the pin and sending it to the PC that did the work to convert to degrees. The pin reports a value in 10 bits (i.e. 0-1023) but the EEPROM stores only bytes (i.e. 0-255). I could have renormalized to the smaller range, but only at the loss of a lot of precision. Instead, I now calculate the temp right on the Arduino. Surprisingly (to me, anyway), you can use the regular math library functions like log(). So then I end up with a temperature that practically speaking won't get above 255 or below 0, and even if it did I could add or subtract a constant to recenter it to my working range.
I will describe what temperature I was logging in another post, but for now here's the pretty graph.
OK, so I had the temperature (sorry if this reads like a novel--I'm writing this one after the fact), but I already had that with a kitchen thermometer. The whole point of this is data collection. From the docs and examples, I think most people are using the Arduino attached to a computer, which makes logging a simple matter of reading the serial port and writing to the hard drive. But the temperatures I'm going to be logging will be located far away from a USB port.
My initial plan was to write the values to the "EEPROM" (no, me neither), but:
It only supports 512 bytes. At one sample every two minutes, that's only 4 hours.
It only supports a limited number of writes. Large, but limited.
I don't really need the ability to save the values through a power cycle.
Instead I went with an array in RAM. I just have to be sure to get the data before I turn it off or the battery runs out.
And how do I get the data off? I have a button that tells the thing to dump the data to the serial port. This is really a simple feature, but I learned a lot while doing it. That's because, even as an electronics n00b, my analog electronics sk1llz leave my digital ones in the dust.
Here's the schematic for a digital switch. Notice that it doesn't really work like an analog switch. That's because you aren't sending electricity around a digital circuit like with a simple flashlight, you are sending voltage around the circuit. Or so this one experience indicated to me. D2 is the digital port. When S is open, as shown, D2 is HIGH (i.e. 5V) with respect to ground. If I close S, current flows (which is why R exists--to limit the current, which means R should be as high as feasibly possible, at least so I infer), but more to the point D2 and ground are electrically connected, meaning it is now LOW (0V).
Question: I think I could have had D2 at LOW by default and switched to HIGH. Would that save power? Ideally, a voltage doesn't have a current, but I don't know how the voltage comparison happens internally.
Anyway, this circuit and the previous one can be put in parallel. The thermistor one reads temps until the buffer array is full and the switch one waits for someone to press it and when someone does, it spews data.
All that remained was to make it small and robust enough to survive an afternoon outside, with light breezes, sunshine, etc. So I soldered the components onto a board (seriosly, this project is like 1/4 of all the soldering I've ever done--I'm a total, total N))B) and slapped it into a tupperware container.
There have been many times when I've wanted to log temperatures. No useful reasons, I just like collecting data. The problem is that temperature logging devices are like $50 and up and of course they only do that one thing. After the orgy of temperature data collection is done, it just sits on the shelf.
But I'd been hearing about this Arduino dealie, which is an open-source microcontroller that only costs about $35. I figured that I could put a thermistor on there and make my own logger, which would not only be cheaper but I'd also have a versatile device for other projects. I've never used a microcontroller before, plus electronics above the level of a flashlight circuit confuses me, so it's been an adventure. Fortunately the Arduino is supereasy.
For that matter, the electronics of this were prettyeasy. The hardest part was doing the math to convert a thermistor reading into a temperature one. I harvested a thermistor from a broken (except for the thermistor) electronic thermometer. (It was easy to identify, since it was sticking way up away from the rest of the circuit board and and had "therm" written next to it.)
A thermistor varies its resistance based on temperature. That means that if you apply a voltage, you'll get a varying amount of current out. But the Arduino input port measures voltage level, which means you need to turn a varying resistance into a varying voltage instead. That's easy with a voltage divider.
"Th" is the thermistor, and A1 is the steak sauce Arduino analog input port. The total voltage drop across both resistors is a constant 5V, but how much drops across each resistor depends on the ratio of their values. So when the thermistor changes, the voltage at A1 also changes.
Now you just need a way to convert a voltage reading to a temperature reading. I assumed it would be a linear relationship, but it isn't, it's exponential. When you buy a thermistor, apparently they give you two numbers. A baseline resistance (at 25°C,) and a number B. Apparently you are supposed to know this equation:
RT = RTzeB(1/T - 1/Tz)
Oh sure, THAT equation! RT is the resistance of the thermistor, which you can figure out based on the read voltage and known values of the circuit. RTz is the resistance at 25°C (or whatever baseline), which is Tz. T is the temperature you want and B is the magic number.
I didn't get my thermistor from any fancy-shmancy store so I didn't have the magic number. Instead, I used the thermistor to measure hot and cold water (calibrated by a kitchen thermometer). Plugging in those readings I was able to solve for B. Just using math got me within 2 or 3 degrees (over the range 0-100°C--I haven't tested outside that range). Then a little empirical fudging got me right on the money.