Code Snippet for QTR-1RC

Hi -

Is there a snippet of code available that shows how the QTR-1RC is operated at its basic level to complete just the steps listed in the description of its operation, i.e.

The typical sequence for reading a sensor is:

Set the I/O line to an output and drive it high
Allow at least 10 us for the 10 nF capacitor to charge
Make the I/O line an input (high impedance)
Measure the time for the capacitor to discharge by waiting for the I/O line to go low

I know that this can be done using the calls from the library. But I want to see how what the basic coding looks like. Primarily how it is implemented using the timer functions…

Thanks

Dan

Hello.

I assume that, given the forum you are posting in, you asking how to do this with the micocontroller on the 3pi? It sounds like your basic question boils down to: “how do you time something with a hardware timer (not the Pololu AVR library functions) on an ATmega328p?” Is that correct?

If so, you can look through the source code of the library to see what we do with the timers, and another great resource is the ATmega328 datasheet, which describes how the hardware timers work and explains all the timer registers. I can potentially provide you with a very simple example or I can walk you through any confusing parts of the library source code or the datasheet. Please note, however, that the timers on the 3pi are all used for multiple things, such as generating the system timer, the PWM for the motors, playing notes on the buzzer, etc. As such, the library takes care to use them in a way that will generally get the most out of them without creating conflicts. If you change the timer registers outside the framework of the library, you will likely break any library functions that rely on that timer.

- Ben

Hi Ben -

I tried something like this but I keep getting an elapsed time reading of close to 6 no matter where the sensor is directed. Seems that something like this “should” work. I thought that the something like the pulseIn function would be ideal if you could specify the time to start instead of depending on a state change.

I will look through the other materials that you suggested - but if you have a comment on this attempt I would be interested.

Dan

 */
Code to read 3Pi IR sensor 
*/

#include <OrangutanLCD.h>
#include <OrangutanPushbuttons.h>

OrangutanLCD lcd;
OrangutanPushbuttons buttons;

const int buttonA = 9;
const int buttonB = 12;
const int buttonC = 13;
const int sensor0 = 14;
const int sensor1 = 15;
const int sensor2 = 16;
const int sensor3 = 17;
const int sensor4 = 18;

unsigned long startTime;
unsigned long elapsedTime;

unsigned char button;   // Define a button variable
  
void setup(){

  delay(250);
  lcd.clear();
  lcd.print("Read");
  lcd.gotoXY(0,1);
  lcd.print("Sensors!");
  button =buttons.waitForPress(ANY_BUTTON);
  
}


void loop()
{ 
  
//************* Read One Sensor and Display Value on LCD ****************** 
  
// Charge capacitor for 20 usec

  pinMode(sensor2, OUTPUT);
  digitalWrite(sensor2, HIGH);
  delayMicroseconds(20);
  digitalWrite(sensor2, LOW);

// Change pin to input and time how long it takes to go LOW

  pinMode(sensor2,INPUT);
  startTime = micros();
  while(digitalRead(sensor2) == HIGH)
  {       
  }
  elapsedTime = micros() - startTime;
  lcd.clear();
  lcd.print("sensor 0");
  lcd.gotoXY(0,1);
  lcd.print(elapsedTime);
  button =buttons.waitForPress(ANY_BUTTON);
}
  

As soon as you call digitalWrite(sensor2, LOW) you are basically starting to discharge the capacitor. You should make the sensor pin an input first:

pinMode(sensor2, OUTPUT);
digitalWrite(sensor2, HIGH);
delayMicroseconds(20);
pinMode(sensor2,INPUT);
digitalWrite(sensor2, LOW);  // disable internal pull-up on sensor2 pin

Does that make a difference in how your program behaves? Also, is there a reason why you don’t want to use our QTR libraries for this?

- Ben

Hi Ben -

That worked! The time to go low is approximately 100 usec when the sensor is placed on over a white sheet of paper and between 700-800 usec when over a piece of black tape.

I agree that using the library is an easier option. I just wanted to be able to show in a simple code how the sensor actually operated. I am considering using the 3Pi in a introduction to robots class that I may be developing.

All the best,

Dan

code is attached…


//    Sample Code  to operate IR Sensor

#include <OrangutanLCD.h>
#include <OrangutanPushbuttons.h>

OrangutanLCD lcd;
OrangutanPushbuttons buttons;

const int buttonA = 9;
const int buttonB = 12;
const int buttonC = 13;

//Define pins for the five 3Pi IR sensors
const int sensor0 = 14;
const int sensor1 = 15;
const int sensor2 = 16;
const int sensor3 = 17;
const int sensor4 = 18;

unsigned long startTime;
unsigned long elapsedTime;

unsigned char button;   // Define a button variable
  
void setup(){

  delay(250);
  lcd.clear();
  lcd.print("Read");
  lcd.gotoXY(0,1);
  lcd.print("Sensors!");
  button =buttons.waitForPress(ANY_BUTTON);
  
}


void loop()
{ 
  
//************* Read One Sensor and Display Value on LCD 

  pinMode(sensor2, OUTPUT);       // Set sensor pin to output
  digitalWrite(sensor2, HIGH);
  delayMicroseconds(50);          // Charge capacitor for 50 usec
  pinMode(sensor2,INPUT);         
  digitalWrite(sensor2, LOW);     
  startTime = micros();
  while(digitalRead(sensor2) == HIGH)
  {       
  }
  elapsedTime = micros() - startTime;
  lcd.clear();
  lcd.print("sensor 2");
  lcd.gotoXY(0,1);
  lcd.print(elapsedTime);
  button =buttons.waitForPress(ANY_BUTTON);
}
  

@navillus55,

You can change this part

  startTime = micros();
  while(digitalRead(sensor2) == HIGH)
  {       
  }
  elapsedTime = micros() - startTime;

You can use

elapsedTime = pulseIn(sensor2, HIGH);

[]'s
Ewerton