31 December 2008

Fixing device signature = 0x000000

Summary:

Use AVRDUDE with "-B 8" to write the arduino bootloader of your choice. Then use arduino to do it again.

Details:

Last post was about discovering that I couldn't write a bootloader to a bunch of atmega 644's from the arduino ide. Ditto using avrdude. Indeed, trying to do anything using avrdude resulted in the message:

avrdude: Device signature = 0x000000
avrdude: Expected signature for ATMEGA644 is 1E 96 09
Double check chip, or use -F to override this check.

Turns out that AVR ships many chips with a slow clock speed. So avrdude has to be told to chill out a bit ;->Which can be done by using "-B DELAY" to slow avrdude's clock speed. One of my chips respond with DELAY set to 4. Another 6. Others may require even larger settings. We'll see.

Burning a bootloader using avrdude with "-B 6" seems to change the clock speed on the chip, so that "-B DELAY" is no longer needed, so that bootloaders can now be written from the arduino IDE. But the bootloader loaded using avrdude doesn't seem to interact with the arduino IDE correctly. So, go to the arduino IDE, and burn the bootloader again.

Now all should be well, and you should be able to download sketches to the chip over the serial line.

Clearly, what's happened is downloading using avrdude set the chips clock bits, but did not use the right flags to download the bootloader correctly. With the clock running quickly enough, the arduino IDE uses the correct avrdude options to download the bootloader. I could figure out the right flags and do it in one shot. And probably will. But for now, this is good enough to make my chips useful.

Not dead, just mostly dead

So, to work on my breadboard Sanguino, I needed some Atmega644P's. They were on back order everywhere, and the Sanguino zip files seemed to suggest that it also worked with Atmega644's. Something like $7+ quantity 1, $5 quantity 25. So I got 25 from mouser.

After building the breadboard I needed to download the bootloader. Connected my AvrISPmkII. And ... first chip wouldn't take it - got some weird error from avrdude (more later). Second chip worked like a charm. Ditto third. I figured I'd fried the first chip. Later, I tried to burn the bootloader on the remaining chips. All got the same error:


sudo avrdude -p m644 -c avrisp2 -P usb

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x000000
avrdude: Expected signature for ATMEGA644 is 1E 96 09
Double check chip, or use -F to override this check.

avrdude done. Thank you.


Now, no way did I fry all them chips. Nor could they all be bad, maybe it was a glitch on the bread board? But that didn't make sense, what about them two good 644's that were working just fine ... So I ignored it for the time being.

So, I finished my PCB design, sent it in to golden phoenix PCB - yet another suggestion from Zack (thanks Zack!) - and got it back a week later. Arrived on my doorstep a matter of hours after I left to visit my family for a week. Argh! So I got back late Sunday, and built the first board Monday figuring that no way could the first board I ever designed work, that $120 was surely down the tubes, but that I'd debug it and the second set of PCBS would work fantastic. WRONG. First board worked right first time out.

So I decided to burn the bootloader on the rest of my chips. Again, no go, device signature was 000000. On the 23 remaining chips. Every single one dead.

Hmm, but that doesn't make sense. While a bread board might be electrically wonky, I was now pretty sure my PCB was pretty solid. And I couldn't believe I got 23 dead chips from Mouser. So something weird is afoot.

I poke around on google. Pretty much nothing. Except a hint. Some AT Tinys come from the factory with a slow clock setting, and require some other programmer to set a jumper to slow down the download clock.

Maybe my chips weren't quite dead. Maybe they were just mostly dead.

Now the AvrMkIspII has no such jumper. And avrdude didn't seem to have any such thing. Till I read the help again:


-B bitclock Specify JTAG/STK500v2 bit clock period (us).
...
-i delay ISP Clock Delay [in microseconds]



Well that looked promising. Didn't know which to try first, so -B it was. BING! It worked. Now on one chip I needed to slow it down to 4us. The next 6us. And once the 644 bootloader is downloaded, it seems to adjust the clock speed, so there's no need for that nonsense any further.

I'm pretty sure the rest of my chips are fine. Just need to play around with the clock speed for each one.

So, while my chips sure seemed dead, as Miracle Max said, mostly dead is not all dead.

12 December 2008

Bread board Sanguino notes

Summary

Okay, so you want a Sanguino but you don't want Zach's Sanguino. It's too expensive ;-> Or too red ;-> Or you just have to have it NOW. And you just used up the last of your solder so a strip board is out. What are you to do ... bread board Sanguino.

Of course, nothing in life is free. While the bread board Sanguino is easy and quick, it also is very limited. You'll need a +5V regulated power source. You can either put one together yourself or use something like the Solarbotics bread board power supply. And there's not much space left for other components. And it takes up a bit of space. And ... if all that is okay it's a pretty easy way to quickly get a Sanguino.

Oh, and by the way, I lied. You'll need to do a bit of soldering if you are going to download the Sanguino bootloader or use the USB serial cable ...

Thanks

Thanks to the Arduino creators. And the entire Arduino community. I knew nothing about micro-controllers before I got my first Arduino. Now I know just enough to be dangerous. Actually, a whole lot more than just enough ... And thanks to Zack. One of my projects was bumping against the 16K limit. Sanguino to the rescue. Plus he's been quite helpful as I've been designing a bit beefier board derived from Sanguino.

Parts

Breadboard
Atmega644p
16MHz crystal
momentary switch
4 x .1uF capacitor
2 x 22pF capacitor
10K resistor
3 x 6 pin male header
1 3 pin by 2 row male header
6 wire ribbon cable, about 4-6 inches
3/32 heat shrink tubing, about 4-6 inches
22g wire
Wire cutter and stripper

644p pin configuration

I'll list the 644p pins that are important to the bread board sanguino. See the [[http://www.atmel.com/dyn/Products/Product_card.asp?part_id=3896 summary data sheet]] for more info. Pins 1-20 are on the left side of the chip, pin one at top, pin 20 at bottom. Pins 21 to 40 are on the right side of the chip. Pin 21 on the bottom, pin 40 at top.

6 - MOSI. Side A, row
7 - MISO. Side A, row 16.
8 - SCK. Side A, row 17.
9 - Reset. Side A, row 18.
10 - VCC. Side A, row 19
11 - GND. Side A, row 20
12 - XTAL1. Side A, row 21
13 - XTAL2. Side A, row 22
14 - RXD (read from serial port). Side A, row 23
15 - TXD (transmit to serial port). Side A, row 24
30 - AVCC. Side B, row 20
31 - GND. Side B, row 19
32 - AREF. Side B, row 18

Build it

The bread board Sanguino was derived from the Sanguino schematics. I kept all the critical stuff and tossed the rest.

What is critical: The stuff in the parts list above. Need the crystal to give the Sanguino a clock signal. The 22pf caps are required for the crystal. Three of the .1 uF caps are needed to decouple VCC and GND, AVCC and AGND, and AREF and AGND. The fourth .1 uF cap is used for the reset on download feature. 10K resistor is the reset pin pull-up resistor. A pull-up resistor keeps a pin "pulled" high until a switch connects it to ground, which in this case causes the 644 to reset. Two of the 6 pin male headers are used to make a connector for the FTDI USB to serial cable. The third 6 pin header and the 3 pin by 2 row header are used to make a conversion cable from the AVRMK-ISP2 or USBTiny to the bread board. Ribbon cable is used to make the connecting cables. Heat shrink is used for the connecting cables, making sure that the soldered pins don't short. And lastly, the 22g wire is used to make connections.

**Components **

Put the bread board down vertically. Row 1 at top, blue rail left, red rail right.

Place the 644p into the bread board. Pin 1 into bread board hole 10D.

Place the momenteary switch's pins into bread board rows 1 and 3.

Place the crystal into side A, rows 30 and 32, column B.

Place a .1 uF cap into row 9, one pin in side A, the other in side B. This is the reset on RTS cap. We'll be "building" a serial port on side B, pins 4-9.

Place a .1 uF cap into side B, rows 18 and 19, column H. Decouple AREF from AGND.

Place a .1 uF cap into side B, rows 19 and 20, column I Decouple AVCC from AGND. Yep, row 19, pin 2 from right has 2 cap leads in it. It's a tight fit but can be done.

Place a .1 uF cap into side A, rows 19 and 20, column C. Decouple VCC from GND.

Place 10K resistor into side A, VCC rail, to Side A, hole 18A. This is the pull up resistor for RESET. Strictly speaking it isn't necessary. The 644p has an internal pull up resistor. But it's a little tiny one that is easily defeated. Better to put a bigger one off chip.

Place a 22pf capacitor from Side A, GND rail, to Side A, hole 30A.

Place a 22pf capacitor from Side A, GND rail, to Side A, row 32A.

** Wires

Side A, VCC rail to hole 1a. Used as part of circuit bridging VCC from left rail to right.

Side B, hole 1J to side B VCC rail. Also part of bridge from VCC left to right.

Side A, hole 3B to hole 9B. This will carry RESET from the RESET cap to the momentary switch.

Side B, hole 4J to GND. Carry GND to serial port.

Side B, hole 6J to VCC. Carry VCC to serial port.

Side A, 7A to 23A, and 7E to Side B, 7G. Bring Rx to serial port.

Side A. 8A to 24A, and 8E to SideB, 8G. Bring Tx to serial port.

Side A, 9C to 18C. Bring RESET from chip to reset cap.

Side B, 18J to VCC on right. AREF.

Side B, 19J to GND on right. AGND.

Side B, 20J to VCC on right. AVCC.

Side A, 21C to 31C. XTAL from chip to crystal. Note that the picture is deceiving. It looks like the pin goes to 30C. It doesn't. The wire is bent a bit and goes to 31C. Ditto 21C, it really goes there.

Side A, 22C to 32C. XTAL from chip to crystal.

HUZZAH!!!! That's it, you've got a bread board Sanguino. And no way to talk to it ... Next up, yackety yack.

Yikes, back to the blog

Can't believe it. Ya stop blogging for a couple days and pretty soon it's nine months.

Been doing a bunch of stuff with Arduino's and robotics. Just haven't blogged about 'em. Let's see if I carry through.

I really like Arduino and it's clones/variants. Many interesting ideas, with each having a cool idea. But none having all the stuff I want together in one board. And, recently I've become particularly interested in Sanguino, a big brother to Arduino, using the Atmega644p. So, it seemed like the natural thing to do is build my own board.

First thing to do was bread board the guts to make sure I understood things even minimally. Next post will be working notes which I hope to turn into a web page. I've already taken half of them and posted them at http://sanguino.cc/BreadBoardSanguino. I'm going to put the here too, finish them, and then post them back there again.

I'm now wrapping up the board design. I'll post an article about that too, both here and at Sanguino. Gotta say that Zach has been a big help!

Then I'll post my notes from constructing a TCP/IP traffic light and how I connected it to reflect the status of my companies continuous build system.

02 April 2008

avr vtable madness

Pretty obvious I haven't done much lately. What I did I haven't written anything about. So here goes. I'm skipping the boring stuff. Hokay, all of this is boring to everyone but me ...

After figuring out how to make the 3301 work, I added it to the bot: rewired the imu yrot pin from the arduino to the 3301, connected the 3301 to the arduino, and hacked the bejeezus out the code for the imu.

Downloaded the program, fired it up, and ... I got a couple of lines of output from setup(), then a couple of lines from loop(), and then nothing. Radio silence ...

Took some digging, but eventually figured out that somehow I'd blown the atmega168's 1K of RAM. It had been running just fine, didn't add much, and I ripped a lot out, but still boom in a big way.

Well by this point the code was hash, so I cleaned it all up. Wrote some code abstacting A2d's and the arduino's vs the 3301 and used it in the imu code. Real pretty. But still boom.

Decided to REALLY stripped things, and printed the address of a few variables. Seemed like plenty o' space.

Put most everything back, and ran nm. AHA! avr-gcc puts the vtables in RAM! A consequence of the split I/D space. Was eating up about 500 bytes. Well, I like my polymorphism, but not at the cost of crashing. Removed everything that doesn't absolutely, positively, need to be virtual, and I seem to have lot's of space again. Though I do need to restore a bit of code still ...

So tonight I plan to do a bit more space tuning, and see how much more I can hack out.

23 February 2008

Bits!!!

Found the bits ...

So last night I connected a pot to V+ as a way of experimenting with different voltages and seeing what I values are read. Figured I'd notice something ... And I did. I got screwey values, but they tended to be bimodal. I put the pot in the middle and it reads some 2091 value. And then some -14295's. And then back to 2091. And back to -14295's. So I drop to 0V, or as near as the pot can get to it. And get -8197 and 8188. With +5V: just -12301.

Two high bits are random!

And that makes total sense when thinking about what the MCP3301 datasheet said. For the first two clocks the data out is held at high impedance. Which means random data is read. Next is a 0 bit followed by the value, sign bit first.

Change my code to check the sign bit and set the high three bits appropriately. Now everything is cool. Pot all the way left is -4. Middle is 1904. All the way right is 4083.

So that's 12 bits. As I'm getting a -4 that means I should be able to go down to near -4095 for the other bit. Probably just need to adjust Vref.

10 February 2008

More bits!!!

So, it seems like the 'bots problem balancing has a few possible factors ...

Height: First problem might be the 'bots height. Finally broke down and did a goog search to see how others do this. Most are short stumpy things. Perhaps my robots height is making things harder. I can move the components to a shorter chunk of wood pretty easily, but first want to try other things.

Weight: Large chunk of wood means lot's of inertia and momentum. Perhaps that is keeping the bot from moving things early enough, and keeping them moving when motors reverse direction. Again, want to try other things before going small. I think that a swarm of tall bots is much cooler than a swarm of pygmies.

Speed: Even with the RM2's the motors only go about 120 RPM. Seems like a lot do 200-400 RPM. I've got faster motors, but will need to rebuild a lot of stuff to use them. So let's try something else first.

Tuning: The PID loop is tuned poorly at best. I'm still struggling to get it set up right.

More bits: And lastly, seems like the resolution of the IDG300 might be a problem ... IDG300 will do 300 degrees per second. When we start falling, we get maybe a few degrees per second. Rate is reported at .002v/degree/second. Atmega has a 10 bit A2D with a reference voltage of 5 volts. Or .005 volts per unit. So, falling 3 degrees per second shows up as a one unit change in A2D value. 5 degrees per second shows up as 2 units. At best I'm getting 4-6 units of change ...

That's a good hypothesis ... but there is a contrary data point. Botka. A balancing bot using the IDG300. Perhaps it's PID loop is tuned better. Or maybe it's something else. Or maybe it's that it's shorter. Or it's body or motors. Or ... But no matter, there's no way to know. There's not enough details about how Botka works, so I gotta go on my own ...

I figure the next thing to try is a higher resolution A2D. Have discovered the MCP3301, a 13bit A2D. With it I get at least 8 times the resolution. As it also has full differential inputs and a reference voltage. I should be able to set the high and low voltage to .1v above 0 degree per second and .1V below 0 degree per second. That will let me measure up to 50 degrees per second either way with 13 bits precision. 100 degrees/8000 units means lots 'o resolution!!!!!

Off to wire it up

...

And ... Gak, breadboarded the thing up for just basic testing. Vref at +5, V- at 0. Tried V+ at both 0 and +5. Wildly weird values for both. Every step is a pain in the ... Ummm, make that every step is a chance to learn more.

Done for tonight. Try again later tomorrow or the next day ...

07 January 2008

No time for 'bots

And then my life got crazy with work and kids and ...

Not a lot of coding for a long time.

06 January 2008

Almost balancing!

Bot nearly balancing! Changed code to use floats rather than ints/longs or fixed points implemented on ints/longs. Tweaked target angle and KP value. Console controller can now set target angle and PID control values. Skew motor power as motors are not equal speed/power.

Problem: Target angle slightly off. Tends to drive forward/backward at fixed angle.

Solution 1: add component that sets target angle based on desired vs actual motor speed. Probably a PID controller to set target angle of current PID controller.

Solution 2: add component that sets target angle based on maintaining fixed location. Probably a PID controller to set target angle of current PID controller.

Problem: Only works when tethered and drawing power from USB. Behaves totally nuts when using onboard 9V battery. No idea why yet, need to debug.

05 January 2008

Not enough resolution with integers

Finished code to use Kalman filter. Bot working a lot better than before. Not balancing, but no where near as ill behaved.

Problem: As Self balancing needs moderate power when small angular changes occur I need to have large PID control loop K values. Which means VERY granular changes in speed. For example with Kp=100, we go from speed 0 to speed 100 to speed 200.

Need to either use fixed point or floating point. Some of my old code uses a form of fixed point arithmetic. For example by using milli-gravities and milli-volts rather than gravities and volts. Would be great to use floating point, but I've no idea of the performance issues. In fact, I have no idea of the performance characteristics of the Atmega186 at all.

Solution: I just wrote the sketch Benchmarks/IntLongFloatMult to find out the speed of multiplying int/long/floats. Results: 4M int mults/sec. 2M long mults/sec. 2M float mults/sec.

Floating point is plenty fast. Not much sense in using fixed point. Will rewrite PID, Kalman, and other libraries to use floating point. Much of af the Kalman code already uses floating point so that should be easy ...

03 January 2008

Kalman Kompleted

Finish kalman filter. Now need to use it.

01 January 2008

Kalman Kode

Integrating gyro and accelerometer data requires a Kalman filter.

First draft based upon the Autopilot project. See:

with some modifications adapted from:

YABB 0.1

First bot should be a "quick and dirty" balancer that tries to either maintain the same position, or tries to maintain zero velocity, whichever is easier.

Body built from cardboard. Solarbotics GM9 motors and L298D motor controller. Standard 9.6V toy RC type battery for juice. Arduino controller. Wrote code to read the H48C. Wrote code for very simple PID controller based on a single prior value. Reused code to drive the motors using 3 wires per motor: enable, forward, reverse.

Motors are typically controlled by 3 wires: right high, left high, and enable. Enable makes the motor responsive to the right high and left high control wires. If enable is low, nothing happens no matter what the right and left control wires say. Right high directs power from the h-bridges high side on the right to the low side on the left. Left high directs power from the left high side to the right low side. If right is high and left is low, the motor spins in one direction. Visa versa and the motor spins in the other. If both are the same the two sides of the motor are connected to each other, and the motor brakes. That is, turning the motor generates an electric current that resists the turning. The resistance acts as a brake and regeneratively recharges the battery. Speed is controlled by PWM'ing the enable line. That is, turning it on and off rapidly. Longer the enable line is turned on relative to the time it's turned off, the faster it goes.

Bought a Parallax H48C 3 axis accelerometer from Hobby Engineering. At the same time purchased a Parallax HM55B compass module.

Problem: Debug output is scrambled. A lot of electrical noise from the motors. Trashes the serial connection between the bot and computer. I now suspect that electrical noise from the motors destroyed a bluetooth module I tried on a previous bot.

Purchased some opto isolators from Jameco. Also some OR gates so I can move from 3 wires per motor to two wires per motor: forward, reverse. Need a second battery for logic, just using a 9volt. Now I get clear debug output. While I was at it I also added "or" gates so that I could control the motors with two wires each: E = R or L. Only isue was that I now have to PWM both R and L rather than just E.

That fixed the noise issue, but later on I found out there are other was to do this that might have worked just as well. Primary being a .1uF capacitor across the motor leads. And a better power supply circuit. I may try those later.

Problem: Doesn't balance. Tends to over shoot. Tried tuning PID kp, ki, and kd parameters to no effect.

Perhaps the bot body is too short, making it very hard to drive the motors under the bot. As a friend said, it's easier to balance a pool cue on your hand than a pencil. Rebuild bot using 1/4" x 3" x 3' piece of birch, with the weight at the top. Batteries, breadboard, motor controller.

Problem: Still doesn't balance. In fact, no apparent change.

Perhaps motors aren't powerful enough. Replace GM9 motor with RM2 motor so that speed and torque aren't a problem. 3 times the torque and twice the speed. And a huge current draw at stall ... L298 tends to overheat. And have killed a few RM2's by stalling. At some point I need to put in a resettable fuse so I stop killing these things.

Problem: Still doesn't balance. In fact, no apparent change.

Careful observation shows that H48C readings do not reflect actual tilt when bot is falling. DUH! while falling there is no substantial change in acceleration. Only when I catch the bot do the X and Z readings change a bunch! Accelerometers alone are too slow. Gyros are supposed to be fast and are "supposed" to be used to balance bots. So, I purchased an IDG300 3 axis accelerometer and 2 axis gyro from SparkFun. I also wonder if it could be done with IR sensors. So I bought some of those from hobby engineering. Haven't done much with them yet, but I will. The IDG300 is $110 a pop. The IR sensors, $21 for a pair. The difference will be important if I have a dozen + bots flocking around.

And that catches us up to Jan 1 ...

YABB

Okay, what do you do after you've got a bot to roll around avoiding obstacles. Build a better bot to avoid obstacles. Build the smallest bot you can. The strongest. One that can go up a steep ramp. Yawn ...

What I needed is a project with legs. Something that is challenging and cool and will take a while to get "done". But that has lots of intermediate steps each of which is possible by a guy with limited time on his hands.

So ... YABB, Yet Another Balancing Bot. Long term goal: create a flock of balancing bots that are aware of each other and people and "flock" using Boyd's algorithm. Massive coolness to stand back and watch a flock of self balancing bots make their way toward some destination. Or no destination at all ...

Or, for people to become part of the flock, so that the people move, the flock moves with them.

Rough roadmap:
- Build a single bot that can stand without falling in roughly the same place.
- Extend so the bot can move without falling.
- Add an arm so the bot can get itself up from the reclining position it takes while not moving.
- Convert arm into a "lance". Extend bot so it can raise and lower the lance maintaining balance.
- Add a second bot with a lance.
- Add recognition so bots no where each other are.
- JOUST!
- Ditch lance but retain ability to stand.
- Add multi object tracking so bots know where each other are. Not sure if bots should keep track of where all flock mates are, or just a subset that are "in sight".
- Add Boyd's algorithm so bots flock.

I figure it'll take a couple years to do this. [22 Feb: It's so far taken a couple months and I still don't have a balancing bot!]

We have ignition ...

So I've been messing around with robotics for about a year now, and decided to move my log to a blog. Never logged about the early stuff, nothing to be missed ;->, but I'm filing the entries before 22 Feb, 2008 after the fact. I'm not making anything up from memory, just moving my old log entries into this Blog. Everything after 22 Feb is filed as I try stuff.