<body bgcolor=#000033"><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener("load", function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <iframe src="http://www.blogger.com/navbar.g?targetBlogID=4830160160028833890&amp;blogName=DanShope.com&amp;publishMode=PUBLISH_MODE_FTP&amp;navbarType=BLUE&amp;layoutType=CLASSIC&amp;searchRoot=http%3A%2F%2Fblogsearch.google.com%2F&amp;blogLocale=en_US&amp;homepageUrl=http%3A%2F%2Fwww.danshope.com%2Fblog%2F" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" height="30px" width="100%" id="navbar-iframe" allowtransparency="true" title="Blogger Navigation and Search"></iframe> <div></div>

Wednesday, June 24, 2009

Sharp IR Rangefinders and Arduino: Make your Robot Smarter

Adding distance or proximity sensors to your robot is a great way to start exploring your environment intelligently. Rangefinders allow a non-contact method of “seeing” obstacles and can be employed in mapping and maze solving as well.

The Sharp family of infrared (IR) rangefinders is very popular amongst hobby roboticists because they are low-cost and easy to interface with (Voltage, Ground, and Signal). These hook up to a single analog input pin on the Arduino or similar microcontroller systems. There are a few caveats to watch out for though.

If your application is very time sensitive and needs tightly controlled, you’ll want to find out how long polling your sensor(s) takes. The Sharp sensors output an analog value (as a voltage), but microcontrollers only understand digital values (1 or 0), so that analog value has to be converted. Analog to digital conversion is pretty fast, but it can introduce some delays.

The sensors are also very noisy, meaning the analog output signal has a lot of "jitter" -- 20cm does not always equal 280, etc. Your code will have to account for this jitter, so you'll need to collect some real-world values to build your sensor model. This problem is exacerbated by the next issue, but can be overcome with a little bit of thought and time. I don't provide you the solution here because it's really dependent on your application. There is, however, a tool to help you evaluate your sensors (see below).

Moving on, take a look at this graph:

You’ll notice something interesting here – the graph has a weird curve and isn’t linear at all. This becomes tricky when trying to teach the robot to understand distance from the analog output of the sensor.

There are a few ways to get around this. If all you want is a simple threshold say “nothing closer than 20cm” then you can simply run a few tests with an object placed 20cm away from the sensor, and then hardcode that value into your program. Generally it’s a bit more complicated, if you want the program to understand varying distance.

Method 1:
Approach: Find a best-fit curve (generally exponential or polynomial) using a statistics package (Excel, R, Minitab)
Pros: Easy to implement, gets you started fast.
Cons: Requires floating point math, which isn’t natively supported by most microcontrollers. You can still use floating point, but it’s slow and inefficient in most cases.

Method 2:
Approach: Gather some data points and create a look up table of values. Your code will linearly interpolate values between each data point (ie, 5cm=600, 10cm=300, etc).
Pros: Uses integer math which is fast and efficient
Cons: Takes up more memory and doesn’t give exact values

Method 2 is the preferred approach as most embedded system developers take great pains to avoid floating point math. You can have some floating point math on the Arduino and be alright. I have a large (6KB) program right now that has floating point littered all over the place (it’s necessary for this code) and execution time runs just fine.

To help with gathering your data for both method 2 and simple thresholding I wrote a quick little application that interfaces with the Arduino’s serial connection. This app will pull your data in and calculate some basic statistics such as standard deviation, mean average, and range of values. You can store the data for future computation and reference.

Download the IRanalzyer at http://www.danshope.com/calton/ir.html

To use the IRanalyzer you need to send values from the Arduino. Here’s a sample sketch to get you started:


#define SerialSpeed 115200 //typical values are 9600 or 115200
#define SampFrequency 10 //sampling frequency in Hz (cycles per second)
#define AnalogPIN 0 //define your pin here

int mDelay;

void setup()
{
Serial.begin(SerialSpeed);
mDelay = 1000/SampFrequency; //calculate delay for proper sampling rate
}

void loop()
{
delay(mDelay); //delay in milliseconds
Serial.println( analogRead(AnalogPIN) ); //reads the analog port and prints value over serial
}

Labels: , , , , , , , , , , , ,


Thursday, March 12, 2009

Do You Know How to Arduino?

I had a great day prototyping with new Arduino Duemilanove. Other than the frustaingly long name we got along pretty well!

The board came from SparkFun along with a protoboard -- I didn't get the protoshield yet, but it's only another $16 so it might be a future purchase. Also arriving today was the compact accelerometer breakout board from RobotShop. One box came by snail mail, the other by UPS, so it was quite exciting when they arrived literally within minutes of each other.

The Duemilanove is a great board -- solid components, automatic power switching, plenty of IO, and an upgraded ATmega chip. I'm definitely going to like having the extra storage on board for my new project.

I had to do a lot of fiddling to get the accelerometer to work well, but most of this was software tweaking. The actual circuitry took all of fifteen minutes and the arudino sketch was really fast.

#include

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  Serial.print("X");
  Serial.print(analogRead(2));
  Serial.print(",Y");
  Serial.print(analogRead(1));
  Serial.print(",Z");
  Serial.print(analogRead(0));
  Serial.print("|");  
  delay(250); 
}
There's the arduino code to read three analog values from the accelerometer -- I've pushed them into a format that looks like 'X000,Y000,Z000|' for ease of parsing. The code sets up the serial communications at 115200, a common speed for PC work.

If you're hooking your board up to say a BASIC stamp or other board, the speed will typically be 9600baud. This is simple - just change the setup code to say Serial.begin(9600);.

So, back to the filtering issues -- the Arduino board runs at 5V, so it expects an analog pin to input between 0 to 5V. The accelerometer outputs from 0 to 3.3V, so it effectively loses 33% of the full range of the arduino pin.

Arduino outputs a signal (when it reads the pin) between 0 and 1024. For an accelerometer, 0 means full negative acceleration, while 1024 means full positive accleration. What "Full" means varies on your accelerometer sensitivity range. Mine is adjustable from +/-1.5g to +/-6g (g==multiples of gravity, i.e. 9.81m/s^2).

To graph the data I needed to scale my output == instead of 1024 being max, 675 was the new maximum; 0 stayed the same. There was also a dropout issue where the signal would drop to full negative (0V, 0 output) every few seconds. This was determined to be a software issue, so I simply discarded any input that matched this characteristic.

It's pretty trivial in most langauges to set up a serial port monitor -- you can also simply use the serial port monitor right in the Arduino IDE, but you can't do anything except watch the raw data scan by....pretty useless for actual work, but great for debugging.




I consider myself a visual learner, and assuming you're the same -- here's the final accelerometer data. The green is the Z axis, red == X axis, and blue == Y axis. The X and Y axis average to around zero, which is good == the board was level and stationary. The green axis is hovering below the rest...do you know why?

Yep, we still haven't figured out how to turn gravity off. I think that's a good thing! If we're properly calibrated, the Z axis will be registering an average of 1g when standing still.

Well, I'm off to prototype more stuff! Now to try a Sharp IR rangefinder and some more serial data transfer using the digitial pins (0 & 1).

Labels: , , ,


Subscribe to RSS Feed
Subscribe to DanShope.com
Who writes This Stuff?
Daniel Shope is the site owner and moderator of DanShope.com, a portal dedicated to robotics and engineering. Dan is currently a student at Carnegie Mellon University and is pursuing dual degrees in Mechanical and Biomedical engineering.

View Daniel Shope's profile on LinkedIn
Advertisements