Friday, January 30, 2009

Wind-Up Robots

I love these wind-up robots of mine! Now all I need is the B9 from 'Lost in Space', R2D2, and C3-PO!

Wednesday, January 28, 2009

MEMS 2-Axis Accelerometer

I picked up a Memsic 2-axis accelerometer from the sensor drawer at radio shack. I've never used an accelerometer before and this one uses MEMS technology. I hooked it up to my BS2-IC via breadboard and uploaded a maze game.

My next goal is to write C code for it using the AVR libraries and integrate it with my robot. I am thinking it will help with pathfinding as well as being able to tell when my robot is stuck on a chair leg or something.

Monday, January 26, 2009

Wednesday, January 21, 2009

Free upgrade to my electronics tools

I recently received a postcard in the mail from the HR department where I work. They often send out mailings that go straight in the trash, but the thing that caught my eye on this one was an offer for a $100 gift certificate. As I read more, I found out all I had to do was complete a simple health related survey and I would receive a $100 gift certificate to any place on a list of about 350 retailers.

At first, I was going to go with target because they have a good selection of things I could use. Second, I almost went with Hammacher Schlemmer because they have neat stuff. Then I thought about it more before I chose, and i decided that the best thing would be to go with because they have a wide variety of items to chose from.

A couple of days later I received an e-mail containing my Gift Card Code for I quickly entered in this code into my account, and I had $100 in my balance!!! I held on to it for a few days while decided what I wanted, and at the same time added some things to my wish list. In the end, I ended up paying ~$40 because I went a little over, and there is multiple shipping costs from different vendors. Here is what I got for approximately $40USD:

Weller WES51

Weller ETH 1/32" Screwdriver Tip for SMD soldering
(ETA Shown)

1LB Kester 44 0.31" 60/40 Solder

Weller SM1 Solder Dispenser

Pretty good deal if you ask me!!

Monday, January 12, 2009

Battery Monitor - Voltage Divider Circuit

There are many IC's out there that can do what is called "gas gauging" to monitor how much battery is left in your robot, just like in mobile phones.

Since I am somewhat new to electronics, I wanted to learn how to implement a battery monitor sensor by using what is called a voltage divider circuit.

Just like LEDs use a series resistor to ensure they receive no more than 20mA of current, with 5vdc this usually turns out to be a 330ohm resistor.

If you wanted to power this same LED, but all you had was say a 9volt or 12volt power source, then you would have to use a second resistor on the ground side of the LED, which would give you a lower voltage AND lower current.

This voltage divider circuit has many more uses besides just LEDs, it can also be used to create a reference voltage or logical voltage level.

For example, I have a 6vdc NiMH battery, but when fully charged it reads 7.08vdc on the multimeter. For my sensor, I want to say that 5vdc is fully charged. I will do some math to calculate what resistors I need to get a 5vdc Vout. Or in my case, I dread math so I will use a Java applet I found:

The applet will help me get a close approximation to start with. I enter in 7v for Vs, and I find I can get 5.00vdc on the voltmeter with R1 = 20k, and R2 = 50k
Voltage Divider Applet

The only snag apparent right now is that with common 5% resistors, there are only a limited selection to chose from. Unfortunately, there is no such thing as a 5% 20k and 50k resistor.

There is another snag too that i'll tell you about now, is that this circuit is assuming there is nothing connected to Vout, meaning no load. It is basically just a series resistance. The way to deal with that is if you know the current that will be on the load, you can use another series resistor on your 5v. The other way, which is what I will use, is you can add a capacitor between ground, and the voltage you want to stabalize. In my case a 10uF 16V cap is perfect.

According to Ohm's Law, the ratio of voltage across our two resistors will be equal to the ratio of the resistance values themselves. In my case, I want to drop from 7.08 to 5, thats a drop of 2.08. Therefore my ratio is 2.08:5, or more simply 0.416:1. Unfortunately, this ratio will not work using common 5% resistors. I will round down and say my batteries max charge is 7vdc, which is fine as they will lower in voltage as they get older anyway. So lets say 2:5, or 0.4:1 (or for the purpose of the calculator below, 1:0.4)

In this next calculator, the table shows the significant digits (1st digit, and 2nd digit) of standard 5% resistor values. When you type in a ratio, it calculates the corresponding significant digits (1st digit, and 2nd digit) that would be required to complete that ratio.

Resistor Ratio Calculator

Go ahead and type in '0.4' in the desired ratio box.

All you need to do is pick out ratios of valid significant digits (meaning no decimal point, and a number you already see listed on the table, in my case the first 4 in 10:4 is not an existing resistor value).

The table shows that you can use resistance values with the first two digits of (this does not talk about the multiplier) 30:12, or 75:30 to obtain the ratio of 1:0.4.

If instead of doing 2/5 to get 0.4, you had done 5/2, you would have gotten 2.5. If you had specified 1:2.5 (the inverse of 1:0.4), you would have gotten the ratios of 12:30, and 30:75. Which is the same ratios that fit the standard resistor values.

We the voltage out that we want (5vdc) by using any resistors of the ratios that we discovered. We could use (12ohm & 30ohm), (120ohm & 300ohm), (1.2kohm & 3kohm), (12kohm & 30kohm), (120kohm & 300kohm), all the way up to (120Mohm & 300Mohm). The same goes with the 30:75 ratio.

You can check it out by entering some of these values into a calculator:

The sensor:

The way we make this into a sensor, is wire up some sort of battery tap on the MCU board, and the place the 10uF cap across your positive and negative voltages. Place your two resistors in series on each end of the cap. From the two resistor wires that are connected, place a wire coming off of there and crimp it with a molex connector

From there you can plug that into a male header coming off of a pin on your microprocessor. The pin should be one that is using your mcu's 8-bit ADC. This way theoretically, a full battery would return 255, and a drained battery would be closer to zero (although your robot may start malfunction a lot earlier). You have to test to see the lowest voltages your robot can operate at. From there you can either flash some sort of LED, or have it enter into an algorithm that searches out for a charger beacon, or tape on the ground leading to the charger.

From all of that your robot will know when its low and power, and will be able to implement a self-charging routine.

Homemade Benchtop Power Supply

For all my robotics and electronics prototyping needs!!

For Christmas, my step-mother received a new laptop, that being said there is always old junk that needs to go.

(I always can think of way to put old desktops and laptops to work.)

Anyway, I snatched up the power supply out of the old desktop and followed this tutorial:


Now easy access to these regulated voltages:
24v (+12, -12), 17v (+5, -12), 15.3v (+3.3, -12), 12v (+12, 0), 10v (+5, -5), 8.3v (+3.3v, -5), 7v (+12, -5), 5v (+5, 0), 3.3v (+3.3, 0), -5v (-5, 0), -12v (-12, 0)

When I have time I am going to go in and modify it a bit. I am going to add the switch to the front panel, as the one on the back panel is hard to reach. I am also going to add a 3mm LED holder, because when the LED contact touches the chassis it grounds, and does not light.

Adding a Parallax Ping to an AVR using C

Parallax Ping Sensor Image


I chose to go with the Parallax Ping Ultrasonic Sensor for this upgrade to my robot. Though only tested on an ATmega8, 168, and 128 this should port over to any AVR 8-bit RISC microcontroller. The reason I chose this sensor is because it is readily available at some local electronics locations instead of having to order online. Most notably, this sensor can be picked up at your local Radio Shack in the Sensor drawer. The datasheet can be found on the Parallax website here (.pdf), please download yourself a copy. You also need to make sure that you have Procyon AVRlib installed.


The section were most interested in on the datasheet is the 'Communication Protocol' section on page 2.

Here we see that the trigger pulse requires the pin to go high (+5vdc) for a minimum of 2 microseconds, but typically 5 microseconds. If you look at the image above the table you see that it starts low (0vdc), goes high for 5us, and then goes low again. To do this we have to set the pin to be an output, and then we send our trigger pulse. Next, we toggle the pin to be an input and then we listen. We are listening for the Ping Sensor to send the pin a pulse which brings the pin high (+5vdc). While we are listening we have to go into a loop, where the only exit condition is if the pin goes high. Once we receive the signal we are waiting for, we immediatly exit the loop, start the timer, and enter another loop waiting for the singal to end when the pin goes low (0vdc). The last part is to get that timer data into a variable and then do the math to calculate the distance of the object. The minimum and maximum distance the Ping Sensor can read is 3cm to 300cm. The distance is only necesarry if we want to output it to UART in human readable format. Otherwise we can just take the value returned from the timer and use that in the main code to make decisions with.

You will need to create some sort of connector cable to interface with your MCU

You will also have to create some sort of mount. Your mount will differ depending on if you want to mount it directly to the chassis or to a servo. For now this tutorial only covers mounting it to the chassis and using it as a touchless bumper.


Timer -

We are going to use a basic timer in order to record the time that the Ping sensor brings the pin high. Which in turn we can use to calculate the distance away and object is. You need to include the timer header file depending on which mcu you're using.

#include "timer.h"
#include "timerx8.h"

We also need to add this simple function:

//**************RESET TIMER**************
void reset_timer_0(void) {
//restart timer count
TCNT0=0x00;//clear timer
//clear timer0's overflow counter.

We also need some sort of function for going backward:

void robot_go_back(void)

In the Initialize area of your code add this line:

timerInit(); // initialize the timer system

Registers -

Image of an ATmega8/ATmega168 with ports:

Port registers allow for lower-level and faster manipulation of the i/o pins on the microcontroller. The ATmega8 and ATmega168 have three ports: B, C, and D.

Each port is controlled by three registers, which are also used in the macros.
The DDR register, determines whether the pin is an INPUT or OUTPUT.
The PORT register controls whether the pin is HIGH or LOW.
The PIN register reads the state of INPUT pins set to input with the macros.

DDR and PORT registers are both read and write accessible.
PIN registers correspond to the state of inputs and may only have read access.

The registers are specified with the name of the register and the port (ex. PORTx) x being the port.

DDRD – The Port D Data Direction Register
PORTD – The Port D Data Register
PIND – The Port D Input Pins Register - read only

DDRB - The Port B Data Direction Register
PORTB – The Port B Data Register
PINB – The Port B Input Pins Register - read only

DDRC – The Port C Data Direction Register
PORTC – The Port C Data Register
PINC – The Port C Input Pins Register

Macros -

There is a header file called sfr_defs.h which is included in io.h. SFR stands for special functions register and the file contains a few useful macros which we can use:

#define bit_is_clear (sfr, bit) (!(_SFR_BYTE(sfr) & _BV(bit)))

Test whether bit bit in IO register sfr is clear. This will return non-zero if the bit is clear, and a 0 if the bit is set.

#define bit_is_set (sfr, bit) (_SFR_BYTE(sfr) & _BV(bit))
Test whether bit bit in IO register sfr is set. This will return a 0 if the bit is clear, and non-zero if the bit is set.

#define loop_until_bit_is_clear (sfr, bit) do { } while (bit_is_set(sfr, bit))
Wait until bit bit in IO register sfr is clear.

#define loop_until_bit_is_set(sfr, bit) do { } while (bit_is_clear(sfr, bit))
Wait until bit bit in IO register sfr is set.

These macros associate simple commands with complicated bitwise operators. You can see examples of these macros in action in the code below.

#define PORT_ON( port_letter, number )            port_letter |= (1<<number)
#define PORT_OFF( port_letter, number ) port_letter &= ~(1<<number)
#define PORT_ALL_ON( port_letter, number ) port_letter |= (number)
#define PORT_ALL_OFF( port_letter, number ) port_letter &= ~(number)
#define FLIP_PORT( port_letter, number ) port_letter ^= (1<<number)
#define PORT_IS_ON( port_letter, number ) ( port_letter & (1<<number) )
#define PORT_IS_OFF( port_letter, number ) !( port_letter & (1<<number)

#define PINGPIN    2          // assign a pin to the Ping Sensor
#define DDR DDRC
#define PORT PORTC
#define PIN PINC


void ping(void) {
    PORT_ON(DDR, PINGPIN);   // Switch PingPin to OUPUT
// ------Trigger Pulse--------------
PORT_OFF(PORT, PINGPIN); // Bring PingPin low before starting trigger pulse
delay_us(2); // Wait for 2 microseconds
PORT_ON(PORT, PINGPIN); // Bring PingPin High for 5us according to spec sheet.
delay_us(5); // Wait for 5 microseconds
PORT_OFF(PORT, PINGPIN);; // Bring PingPin Low and standby
//--------End Trigger Pulse---------------------
loop_until_bit_is_set(PIN, PINGPIN); // Loop until the the PingPin goes high (macro found in sfr_def.h)
//clears timer, reset overflow counter
reset_timer_0(); //reset timer 0
loop_until_bit_is_clear(PIN, PINGPIN); // Loop until the the PingPin goes low (macro found in sfr_def.h)
//read timer0's overflow counter
//255 is count before overflow, dependent on clock
int elapsed_time=timer0GetOverflowCount()*255+TCNT0;
PingVal = elapsed_time * 2.068965517;t
} // end ping function

In your Main:

// All the values are based on running at 8MHz. You can see in the comments, I multiplied the original 1MHz values by 8.
while(1) {
//Object Avoider
if (PingVal > 8) {
// object detected
if (sharp_IR_reading > scan_thresh) {
//240 far right, 400 center, 448 far left
//object on left
if(scan_angle > 380)
while (sharp_IR_reading > scan_thresh) {
} // end while
//object on right
else if(scan_angle < 360) // 41 * 8
while (sharp_IR_reading > scan_thresh) {
} // end while
} // end if
// object not detected
} // end if
else {
while (PingVal < 16) {
} // end while
for (int i = 0; i > 5; i++)
} // end else
delay_cycles(3200);//a small delay to prevent crazy oscillations >; 400 * 8
} // end while loop

Saturday, January 3, 2009

Atmel AVR High Voltage Fuse Reset

(Lesson Learned: Divots should face each other)


1 - Breadboard
1 - Set of breadboard jumper wires
2 - ATmegas (one good one, and the one you're locked out of)
2 - Regulated power sources, 12vdc and 5vdc
1 - LED
1 - 2N3903 or 2N3904 transistor (available at Radio Shack)
1 - Tactile/Momentary Button (Omron B3F-1000 is a popular one, can be stuck into a breadboard)
20 - 1K Ohm Resistors, 1/4 watt is fine.

This tutorial is based off of the work of Jeff Keyzer at his website:

I have attached a hex file containing the code to 'fix' a locked ATmega8, If you want to use his code, you have to have the Arduino IDE installed and you have to compile it with that. Once you have the .hex file, you can upload it to your mcu via AVR Studio if you like.

Make sure before you compile it, that you change the high and low fuse values based on the ones listed on the AVR Fuse Calculator website:

The schematics he provides are bit tricky without an actual Arduino if you are just using an ATmega on a breadboard.

You can use an Arduino pin map to help:

Otherwise I am providing the basic pin connections below (refer to the schematic for hooking up the transistor, led, and button):

Note: The form here is the pin number followed by the pin name.

Connections w/1k ohm resistor in series:

Good Atmega -> Bad Atmega

2PD0 -> 14PB0

3PD1 -> 15PB1

4PD2 -> 16PB2

5PD3 -> 17PB3

6PD4 -> 18PB4

11PD5 -> 19PB5

12PD6 -> 23PC0

13PD7 -> 24PC1

15PB1 -> 6PD4

16PB2 -> 5PD3

17PB3 -> 4PD2

18PB4 -> 3PD1

19PB5 -> 11PD5

23PC0 -> LED, Button

25PC2 -> 25PC2

26PC3 -> 9PB6

27PC4 -> 12PD6

28PC5 -> 13PD7


Other connections (no resistor):

Good Atmega -> Bad Atmega

14PB0 -> 22AGND, 21AREF, 7VCC

24PC1 -> button

Just remember it will be easier to work with if you place the two ATmegas on the breadboard with the divots facing each other. I learned this from experience ;)

Once you get it all hooked up, here is how it goes:

  • Apply the voltages.
  • Wait for the red LED to turn on (if it isn’t already)
  • Push the 'Go' tactile button
  • As soon as the LED turns back on, the AVR is unlocked!

Any questions, feel free to contact me.