Tuesday, July 29, 2008

SHARP 2Y3A001 F Arduino filtering

I'm using the Sharp 5 beam sensor in a project of mine and I was having trouble with the measurements varying a lot. Stupid me, after checking it out with my Parallax USB Oscilloscope I realized that the input voltage to the sensor wasn't right, I simply didn't have it plugged in right. That stabilized the output and my mean analog readings were close, but I felt that taking the mean wasn't necessarily the best way to go about it, because if you look at the output of the sensor under an oscilloscope it spikes then oscillates, so if you simply do an average of a lot of readings that initial spike will affect your output. I figured that the best value would come from the mode and not from the mean. A mean of the top two frequencies would also work, but for simplicity, I"m just using one. Here is the code I used on the arduino platform. (Essentially just C)

I took 50 samples, put them in an array, applied an insertion sort, and then searched through the list once finding the highest mode. Then I printed out the average mode and min and max to the screen. I also made use of a printFloat function I found floating on the net. Notice I'm also only reading one out of the 5 beams at the moment, I wanted to get the algorithm to work first before changing, but its just a matter of uncommenting a few lines and making some changes. The output from the sensor is not rock solid when you place it down and aim it at an object.


// printFloat prints out the float 'value' rounded to 'places' places after the decimal point
void printFloat(float value, int places) {
// this is used to cast digits
int digit;
float tens = 0.1;
int tenscount = 0;
int i;
float tempfloat = value;

// make sure we round properly. this could use pow from , but doesn't seem worth the import
// if this rounding step isn't here, the value 54.321 prints as 54.3209

// calculate rounding term d: 0.5/pow(10,places)
float d = 0.5;
if (value < 0)
d *= -1.0;
// divide by ten for each decimal place
for (i = 0; i < places; i++)
d/= 10.0;
// this small addition, combined with truncation will round our values properly
tempfloat += d;

// first get value tens to be the large power of ten less than value
// tenscount isn't necessary but it would be useful if you wanted to know after this how many chars the number will take

if (value < 0)
tempfloat *= -1.0;
while ((tens * 10.0) <= tempfloat) {
tens *= 10.0;
tenscount += 1;
}


// write out the negative if needed
if (value < 0)
Serial.print('-');

if (tenscount == 0)
Serial.print(0, DEC);

for (i=0; i< tenscount; i++) {
digit = (int) (tempfloat/tens);
Serial.print(digit, DEC);
tempfloat = tempfloat - ((float)digit * tens);
tens /= 10.0;
}

// if no places after decimal, stop now and return
if (places <= 0)
return;

// otherwise, write the point and continue on
Serial.print('.');

// now write out each decimal place by shifting digits one by one into the ones place and writing the truncated value
for (i = 0; i < places; i++) {
tempfloat *= 10.0;
digit = (int) tempfloat;
Serial.print(digit,DEC);
// once written, subtract off that digit
tempfloat = tempfloat - (float) digit;
}
}





float rawData = 0;
float distance =0;
float alpha[5] = {7545.2,7522,7860.2,8373.9,8093.6};
float beta[5] = {-1.3297,-1.3272,-1.3341,-1.3445,-1.339};
//will be used in equations for different LEDs example : LED1 = 9009x^-1.3591
int iterations = 50;
byte measurements[50];
int mode, TempModeValue;
byte HighestFrequency, TempFrequency;
int i,j,z;
byte key;

void setup(){
Serial.begin(9600); // set up Serial library at 9600 bps
pinMode(13, OUTPUT);
pinMode(11, OUTPUT);
digitalWrite(18,LOW);
for(i=5;i<=9;i++)
digitalWrite(i,HIGH);



}
void loop(){

//distance = rawData;
//Serial.println((int)rawData);
//delay(500);
//Serial.print("?f");//clear screen
rawData =0;
//for(i=4;i<=8;i++)
i=4;
{

///TIME CRITICAL READINGS
digitalWrite(i,LOW);//10cm sensor is inverted
digitalWrite(9,HIGH);
delay(20);
for(z =0;z {
measurements[z] = analogRead(0);
rawData += measurements[z];
}
digitalWrite(i,HIGH);
digitalWrite(9,LOW);
///TIME CRITICAL READINGS OVER


//sort list
for(j=1;j {
key=measurements[j];
i=j-1;
while(measurements[i]>key && i>=0)
{
measurements[i+1]=measurements[i];
i--;
}
measurements[i+1]=key;
}
//take first value as highest
mode = TempModeValue = measurements[0];
HighestFrequency = TempFrequency = 0;

for(i=1;i {
if (measurements[i] == TempModeValue)
TempFrequency++;//represents highest frequency
else
{
TempModeValue = measurements[i];
TempFrequency = 1;
}

if(TempFrequency > HighestFrequency)
{
mode = TempModeValue;
HighestFrequency = TempFrequency;
}
}




rawData /= iterations;
//distance = 1148*pow(rawData,-1.0

//measurements[i-4]= pow(rawData,-1.3591);
//rawData = alpha[i-4]*pow(rawData,beta[i-4]);
for(z=0;z {
printFloat(rawData,2);
Serial.print(',');
Serial.print(measurements[0],DEC);
Serial.print(',');
Serial.print(measurements[49],DEC);
Serial.println();
}

//printFloat(rawData,6);
if(i<8)
//Serial.print(',');
//measurements[i-4] = rawData;
delay(5);
}
// Serial.println();
delay(250);




/*if(Serial.available() > 0)
{
temp = Serial.read();
if( temp == 'r')
{
//printFloat(distance,2);
for(i=0;i<4;i++)
{
printFloat(measurements[i],6);
Serial.print(',');
}
printFloat(measurements[4],6);//so we don't have an extra comma
Serial.println();
/* }
}*/
}

Monday, July 28, 2008

Saturday, July 26, 2008

Saturday, July 19, 2008

compiling issues

I found a site that illustrates the proper order for directives when using g++ as a compiler. I was having the problem that I could make a program compile using relative pathname in the -I option but not when using an absolute path name.

The following worked with relative pathnames


$(CXX) main.cpp -o test -I./.. -L. -lsmile

But i wanted to use absolute path names and i tried this:


$(CXX) main.cpp -o test -I/home/santiago/thesis/SmileHeaderfiles -L -lsmile

which didn't work.
This did work


g++ -I/home/santiago/thesis/SmileHeaderfiles main.cpp -o test -L. -lsmile

Friday, July 18, 2008

Player/Stage Ubuntu 7.10 update

I got player version 2.1.1 and stage 3.0.0 working, player was not too difficult, I just needed to install libglu1-mesa-dev to get rid of some of the dependency issues I was having.

Stage was more difficult, For some reason the program needed me to manually export
export LD_LIBRARY_PATH=/usr/local/lib
for stage to work.

I was getting this error before for google reference:

stage: error while loading shared libraries: libstage.so.3.0.0: cannot open shared object file: No such file or directory


So I added:
export LD_LIBRARY_PATH=/usr/local/lib
to .bashrc and called it a day.

Wednesday, July 16, 2008

two usb webcams same hub, ubuntu 7.04

Well, I know how I got two cameras working on the same hub in Ubuntu 7.04, but apparently it doesn't work in 7.10. If I can get it working again, I'll provide better instructions. The key step is to download the source code for gspca for linux. Then open up gspca_core.c and search for he section where the author says he doesn't know how to set the bandwidth budget so he allows the maximum. Here is the section:


/**
* Endpoint management we assume one isoc endpoint per device
* that is not true some Zoran 0x0572:0x0001 have two
* assume ep adresse is static know
* FIXME as I don't know how to set the bandwith budget
* we allow the maximum
**/
static struct usb_host_endpoint *
gspca_set_isoc_ep(struct usb_spca50x *spca50x, int nbalt)
{
int i, j;
struct usb_interface *intf;
struct usb_host_endpoint *ep;
struct usb_device *dev = spca50x->dev;
struct usb_host_interface *altsetting = NULL;
int error = 0;
PDEBUG(3, "enter get iso ep ");
intf = usb_ifnum_to_if(dev, spca50x->iface);
/* bandwith budget can be set here */
for (i = 4; i; i--) {//changed nbalt to 4
altsetting = &intf->altsetting[i];
for (j = 0; j < altsetting->desc.bNumEndpoints; ++j) {
ep = &altsetting->endpoint[j];
PDEBUG(3, "test ISO EndPoint %d",ep->desc.bEndpointAddress);
if ((ep->desc.bEndpointAddress ==
(spca50x->epadr | USB_DIR_IN))
&&
((ep->desc.
bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_ISOC)) {
PDEBUG(0, "ISO EndPoint found 0x%02X AlternateSet %d",
ep->desc.bEndpointAddress,i);
if ((error =
usb_set_interface(dev, spca50x->iface,
i)) < 0) {
PDEBUG(0, "Set interface err %d",
error);
return NULL;
}
spca50x->alt = i;
return ep;
}
}
}
PDEBUG(0, "FATAL ISO EndPoint not found ");
return NULL;
}

Well as you can see the outer for loop was i = nbalt. I changed that to 4 since it seemed like a nice number. It was really arbitrary. Then do make and make install, and you should be good, then download some program like spcaview and have at it.

Friday, July 11, 2008

Player/Stage Ubuntu 7.10

After several hours struggling with trying to compile from source and having problems, I got Player/Stage to work. I should have known better, Ubuntu always makes things easy.

To install stage:
$sudo apt-get install stage

To run a demo
$stest /usr/share/stage/worlds/simple.world robot1

And if you want other tests look through /usr/share/stage/worlds for other worlds to try.