Pages: [1]   Go Down
Author Topic: Creating an optical encoder with an ir sensor  (Read 1598 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am trying to create an optical encoder with an ir sensor. to do this i am using the Sharp IR sensor that will reflect off of a white board that has black segments painted onto it. The sensor is to take the time at the beginning of each black segment and calculate the time it took to go between each of those black segments. I have put together a code that seems to me would work but obviously is not and i cant figure out what is wrong. If anybody has any ideas please let me know. Attached is a diagram of the setup to visualize what i mean. The sensor will be connected to an analog pin and that is why the pinmode has been commented out because someone told me i need to initialize the pin but since it is analog and pinmode is a digital function i dont believe i need it.

The issue that i am having is that the serial monitor continuously prints values when it is in a white segment and none when it is in a black segment. also it prints both positive and negative values and there should be no reason to be printing a negative value.



Code:
//User Changeable Variables
int desiredRevs = 3;
int WheelResolution = 3;

//DO NOT CHANGE ANYTHING BEYOND THIS POINT
int SensorPin = A0;
int time1 = 0;
int time2 = 0;
int time3 = 0;
int Flag0 = 0;
int Flag1 = 0;
int Flag2 = 0;
int Flag3 = 0;
int desiredPulses = WheelResolution * desiredRevs;
int val = 0;
int couple = 0; //1 = beginning of first black, 2 = beginning of white
int status1 = 0;
int deltaT = 0;
int pulses = 0;



void setup()
{
  //pinMode(SensorPin, INPUT);
  Serial.begin(9600);

}

void loop()
{
  if (pulses <= desiredPulses)
  {
    val = analogRead(SensorPin);
    if (val >= 50)
    {
      Flag1 = 1;
      status1 = 1;//black
    }
    else
    {
      Flag1 = 0;
      status1 = 0;//white
    }
    if ( Flag1 == 1 && couple == 0 && status1 ==1)
    {
      couple  = 1;
      time1 = micros() ;
      Serial.print(time1);
    }
    else if ( Flag1 == 0 && couple == 1 && status1 == 0)
    {
      couple = 2;
      time2 = micros();
      Serial.print(time2);

    }
    else if ( Flag1 == 1 && couple == 2 && status1 == 1)
    {
      time3 = micros();
      Serial.print(time3);
      //deltaT = time3 - time1;
      Serial.println(deltaT);
      couple = 1;
      time1 = time3;
      
    }
    
  }
  else
  Serial.println("Done");
  
}


* Sensor setup.png (18.36 KB, 819x460 - viewed 66 times.)
« Last Edit: January 20, 2013, 01:44:19 am by JustinTsuyuki » Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 619
Posts: 33961
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Flag1 and status1 always get set to the same thing, why have them both?

You should be looking to time between the rising edge and falling edge of the sensor. You can do this with a pulse in function, or failing that do it properly by noting the millis time on each transition and subtracting the two.
I can't follow what your code is trying to do but it looks way overly complex.
Logged

Offline Offline
Faraday Member
**
Karma: 62
Posts: 3007
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't like you having   if () {} else if () {} else if () { }   

what if none of those apply ?    If you are having trouble figuring out what your system is doing,  add another "else"
at the end,  and print a message,  so you know which scenarios are not being dealt with.

I'm not clear on why you have three notable outcomes there.    You have something happen when you
go from white to black,    and from black to white .   What is the third one for ?    Can you be sure
your device only rotates in one direction ?

Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sorry i failed to comment this code. First off the sensor is going to be attached to a stationary bike that has a solid wheel so i can not use separate transmitter and receiver, that is why i have chosen the ir sensor i have. But what is going in is that the program will continually read values from the ir sensor, depending on what value is read > or < than 50, it "knows" what color segment it is in. I need the time it takes for the sensor to hit the beginning of one black segement to the beginning of another, not just from black to white and white to black, thus the reason for the second elseif{} condition.

So as the sensor reads values it determines whether it is in black or white and depending on which it determines it is in, it sets Flag1, couple, and status1 to the appropriate values. the reason there is status and flag is just an extra condition, there is no difference. So for the first time that it hits a black space the program will set Flag1 = 1 and status1 = 1 and couple is already 0. the program continues to run and in notices that the next if{} statement is true so it takes time1 and sets couple = 1. now as it continues reading values in the black segment nothing will happen because it meets none of the if{} or elseif{} statements since flag will equal 1, status1 =1, but couple = 1 and not 0. michinyon was wondering about not meeting any of these conditions and i thought if none of the conditions were met it would just begin the sequence again and go through reading values and trying to meet conditions until it did.

the next time it would meet a condition is when it hits the beginning of the "first" white segment where it will set Flag1 = 0, status1 = 0 and since couple is now 1 and not 0 it meets the first elseif{} condition. here it takes time2, for no apparent reason but to take a time. but than it sets couple = 2. again it should not do anything else while reading values in the white segement because flag1 = 0, status1 = 0 and couple now equals 2. so it should just keep reading values til it hits the next black segement.

once it hits the next black space it recognizes that flag1 = 1, status1 = 1, and couple is now 2. Thus it takes time3 and calculates the time it took to get from time1 to time3 (deltaT = time3 - time1). because time3 is a larger number than time1 it should never print a negative number which is one issue i am having. Anyways, it continues the program and sets couple back to one and sets time1 equal to time3. this is so that it restarts the program immediately and doesn't happen to skip this black segment and restart the readings until the "third" black segment.

i hope that clears some stuff up, let me know if there is something else you might be confused on.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 619
Posts: 33961
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

You are making it way too complicated. You need to detect edges, that means when the detector was showing one colour that is diffrent from the last time you measured it. So compair the current reading with the lasts one. At the end of the loop store the current reading in the lasts reading variable. That is all you need to do.
Logged

0
Offline Offline
Shannon Member
****
Karma: 206
Posts: 12062
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You also cannot get away with just a single threshold - there will be noise in the signal
so you must add some hysteresis to the edge detecting.  Perhaps have two thresholds of
40 and 60.
Logged

[ I won't respond to messages, use the forum please ]

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hi everyone, so i hadn't really touched this project for a while cause i was getting nowhere with it but i looked back at it and started to feel i was getting somewhere. I simplified the code quite a bit and everything work perfectly when i have the slight delay at the end, but when i get rid of the delay the program goes crazy and continuously reads different values from the sensor even though the sensor and wheel are completely still and there should be no change in values read. I'm just wondering why i might need this delay for the program to work properly. The code is below.

Code:
//Justin Tsuyuki
//Optical Endocer Code II

//User Changeable Variables
int desiredRevs = 10;
int WheelResolution = 10;

//DO NOT CHANGE ANYTHING BEYOND THIS POINT
int SensorPin = A0;
unsigned long time1 = 0;
unsigned long time2 = 0;
unsigned long time3 = 0;
int Flag = 0;
int desiredPulses = (WheelResolution * desiredRevs)/2;
unsigned long val = 0;
int couple = 0; //1 = beginning of first black, 2 = beginning of white
int status1 = 0;
unsigned long deltaT = 0;
int pulses = 0;



void setup()
{
  pinMode(SensorPin, INPUT);
  Serial.begin(9600);

}

void loop()
{
  while (pulses <= desiredPulses)
  {
    val = analogRead(SensorPin);
    //Serial.println(val);
    //pulses = pulses + 1;
    if (val <= 200)
    {
      Flag = 1;
      if (Flag == 1 && couple == 0)
      {
        couple = 1;
        time1 = micros();
        //Serial.println("Black");
        //Serial.println("time1");
        //Serial.println(time1);
      }
      else if (Flag ==1 && couple == 2)
      {
        time3 = micros();
        deltaT = time3 - time1;
        couple = 1;
        time1 = time3;
        pulses = pulses + 1;
        //Serial.println("Black");
        //Serial.println(pulses);
        Serial.println(deltaT);
        Serial.println(pulses);
      }
    }
    else
    {
      Flag = 0;
      if (Flag == 0 && couple == 1)
      {
        couple = 2;
        //Serial.println("White");
       
      }
    }
    delay(10);
  }
}

A bit about the setup is that there are 15 pulses on the wheel and a max angular velocity on the magnitude of 100 rad/s. With these numbers i calculated that i 1 pulse will take about 4 milliseconds to pass the sensor. now with this i would need to be able to read about 250 pulses per second. Looking into arduino's site, they say that the analog function can read around 2500 pulses/second. Therefore i'm not sure if i'm just totally off on my calculations or if i am misunderstanding the abilities of the analog function.

Any insight to what might help this work better would be greatly appreciated.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 619
Posts: 33961
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Still too complex. For example:-
Code:
Flag = 1;
      if (Flag == 1 && couple == 0)
      {
Think about it, is there any possibility that the variable Flag can possibly be anything other than 1 seeing as in the instruction before you have set it to be 1?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So what is happening is that the cyclist is going to start pedaling and when he gets to top speed they will release the pedals. When that happens the readings will begin. The purpose for clarifying flag 1 or flag 0 and proceeding from there is because i want to begin reading on a white section (<200) not a black section (>200). So i first have it read whether its black or white and proceed from there. Therefore if it begins in white it will proceed accordingly with the code but if it starts on black then flag will turn to 0 and nothing will happen til it reads white. So i have that first if statement to make sure it is in white, then the if/then statements inside that is meant to determine if it is the first white section in the sequence or any subsequent white readings. the outer else statement is to clarify that the sensor is reading a black section and whether or not it is beginning the code in a black section or if the black section is part of the sequence. So i believe i need the

Code:
Flag = 1;
      if (Flag == 1 && couple == 0)

to make sure i am starting off in a white section.
Logged

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 619
Posts: 33961
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So i believe i need the .....
No. It matters not what encloses it you set Flag to 1 and then test to see if it is one. This is always going to be the case full stop.
Logged

Pages: [1]   Go Up
Jump to: