QTR-8RC without libraries (ChipKit)

Hi everybody,
I’m currently working on a line and wall follower using the micro ChipKit UNO 32, and I recently bought the QTR-8C sensors for the line follower. Everything seemed fine until I discovered that the QTR library doesn’t work with ChipKit (as far as I know).
So I started to work on the code without using the famous library, but it didn’t end in anything good…
What I’ve read in the QTR-8Rx user’s guide (pololu.com/docs/pdf/0J12/QTR-8x.pdf) is that I have to follow these points:

  1. Turn on IR LEDs (optional)
  2. Set the I/O line to an output and drive it high
  3. Allow at least 10 us for the 10 nF capacitor to charge
  4. Make the I/O line an input (high impedance)
  5. Measure the time for the capacitor to discharge by waiting for the I/O line to go low
  6. Turn off IR LEDs (optional)

I think I’ve get it except for the point number 5. How can I measure that time? Does anybody have any example of this sensor without using the libraries? I paste here the code I made, but doesn’t work at all (it gives me the value 1 all the time):

#define sensor1 2

int value1 = 0;

void setup()
{
  Serial.begin(9600);
}
 
void loop()
{
   pinMode(sensor1, OUTPUT);
  digitalWrite(sensor1, HIGH);
 
  delay(1);
  
  pinMode(sensor1, INPUT);

  value1 =digitalRead (sensor1);

  Serial.println(value1);

   delay(3000);
  
}

Hello.

I am a little surprised that our Arduino library doesn’t work on the ChipKit. Here is the part of the library that actually reads the sensors:

#define numSensors  3
#define maxValue  4000

unsigned char pins[] = {2, 3, 7};
unsigned int sensor_values[numSensors];

unsigned char i;

for(i = 0; i < numSensors; i++)
{
	sensor_values[i] = maxValue;
	digitalWrite(pins[i], HIGH);	// make sensor line an output
	pinMode(pins[i], OUTPUT);		// drive sensor line high
}

delayMicroseconds(10);				// charge lines for 10 us
for(i = 0; i < numSensors; i++)
{
	pinMode(pins[i], INPUT);		// make sensor line an input
	digitalWrite(pins[i], LOW);		// important: disable internal pull-up!
}

unsigned long startTime = micros();	
while (micros() - startTime < maxValue)
{
	unsigned int time = micros() - startTime;
	for (i = 0; i < numSensors; i++)
	{
		if (digitalRead(pins[i]) == LOW && time < sensor_values[i])
			sensor_values[i] = time;
	}
}

That part might just work for you if you try it. After you run it, the sensor_values[] array contains the raw readings from the sensors connected to the ChipKit pins specified in the pins[] array.

- Ben

I’ve added everything you wrote on the code from “unsigned char i” until the end to the void loop and added at the end of the code a Serial.println(sensor_values[i]) but everything I get in the serial monitor is a number increasing from 0 to… who knows?
How can I get good reads in the Serial monitor? (I though they should be just 0 or 1, as it’s a digital sensor) What does this part of the code exactly means? (I’m just learning how to program)

unsigned long startTime = micros();   
while (micros() - startTime < maxValue)
{
   unsigned int time = micros() - startTime;
   for (i = 0; i < numSensors; i++)
   {
      if (digitalRead(pins[i]) == LOW && time < sensor_values[i])
         sensor_values[i] = time;

Thank you very much Ben

You should be seeing numbers from 0 to 4000. The QTR-RC sensors have outputs that can be read by digital pins, but they output is an analog reading of the reflectance represented by the duration of the pulse (you get a lot more information than just 0 or 1).

The portion of the code you quoted times how long the output of each sensor stays high. After maxValue microseconds have elapsed, the loop times out.

- Ben

I see what you men but… where do I exactly have to add the print to see the values in the Serial Monitor? I know that question can seem a bit stupid, but I’ve tried to add it at the end of the code but didn’t get to anything, and if I entered the print function inside the last for I obtained 0 or 1 values without any sense (and in some cases values of 4000, but just 0, 1 or 4000, nothing among them).

Thank you

Can you try the following program?

#define numSensors  3
#define maxValue  4000

unsigned char pins[] = {2, 3, 7};
unsigned int sensor_values[numSensors];

void readSensors()
{
   unsigned char i;

   for(i = 0; i < numSensors; i++)
   {
      sensor_values[i] = maxValue;
      digitalWrite(pins[i], HIGH);   // make sensor line an output
      pinMode(pins[i], OUTPUT);      // drive sensor line high
   }

   delayMicroseconds(10);            // charge lines for 10 us
   for(i = 0; i < numSensors; i++)
   {
      pinMode(pins[i], INPUT);      // make sensor line an input
   }

   unsigned long startTime = micros();   
   while (micros() - startTime < maxValue)
   {
      unsigned int time = micros() - startTime;
      for (i = 0; i < numSensors; i++)
      {
         if (digitalRead(pins[i]) == LOW && time < sensor_values[i])
            sensor_values[i] = time;
      }
   }
}

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


void loop()
{
   unsigned char i;

   readSensors();
   for (i = 0; i < numSensors; i++)
   {
      Serial.print(sensor_values[i]);
      Serial.print("  ");
   }

   delay(1000);
   Serial.println();
}

If that doesn’t work the way you expect, can you tell me how you have everything connected and describe your test procedure? A picture of your setup might help.

- Ben

Thank you very much Ben! Now I’ve understood the code, and the way you read the time the capacitor takes to discharge.
The program does work, but the difference in the readings between black and white surfaces are really small. Do you know how this problem could be solved? Thank you for you dedication

P.S My configuration is the one you see in this picture: pololu.com/picture/view/0J621, but without using the 3.3 V nor the LedON outputs.

Well, to start with, some details could help. What readings are you getting? How do you have the sensor mounted and what voltage are you powering it at? What is your black surface and what is your white surface? Can you post a picture of your setup?

- Ben