Pololu IR sensors raw vs calibrated readings

Hello,

I bought the Pololu QTRX-HD-05RC 5-channel IR sensor and connected it to an Arduino Mega on pins 26-30.
I'd like to skip the calibration phase and use raw sensor values.

Using the examples based on readLineBlack(sensorValues[i]) which includes calibration, I get very good results between 0 and 1000.
However, using the non-calibrated read(sensorValues[i]), I only get values between about 150 and 650 while this should be between 0 and 2500. The difference while on or off the black line is not enough to base steering decisions on. Same IR sensors, same hardware, same black line on a white surface.
The code is entirely based on the examples from the QTR library (QTRRCExample and QTRRCRawValuesExample) included in v4.0.

What am I missing?

For one, not following the posting directions given in the "How to get the best out of the forum" post.

I'm willing to make a stab at it though: code that expects corrected data won't work properly for uncorrected data.

1 Like

You're absolutely right, my apologies. Here's the code I use. And yes, I'm completely new to this.

  1. with calibration:
#include <QTRSensors.h>
QTRSensors qtr;
const uint8_t SensorCount = 5;
uint16_t sensorValues[SensorCount];

void setup()
{
  Serial.begin(9600);
  qtr.setTypeRC();
  qtr.setSensorPins((const uint8_t[]){26, 27, 28, 29, 30}, SensorCount);
  delay(1000);

  Serial.println((String)"Start calibration");
  for (uint16_t i = 0; i < 400; i++)
  {
    qtr.calibrate();
  }
  Serial.println((String)"Stop calibration");

  // print the calibration minimum values measured when emitters were on
  Serial.begin(9600);
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(qtr.calibrationOn.minimum[i]);
    Serial.print(' ');
  }
  Serial.println();

  // print the calibration maximum values measured when emitters were on
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(qtr.calibrationOn.maximum[i]);
    Serial.print(' ');
  }
  Serial.println();
  delay(1000);
}

void loop()
{
  qtr.readLineBlack(sensorValues);
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(sensorValues[i]);
    Serial.print('\t');
  }
  delay(250);
  Serial.println();
}
  1. without calibration, using raw values:
#include <QTRSensors.h>
QTRSensors qtr;
const uint8_t SensorCount = 5;
uint16_t sensorValues[SensorCount];

void setup()
{
  Serial.begin(9600);
  qtr.setTypeRC();
  qtr.setSensorPins((const uint8_t[]){26, 27, 28, 29, 30}, SensorCount);
  delay(1000);
}

void loop()
{
  qtr.read(sensorValues);
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(sensorValues[i]);
    Serial.print('\t');
  }
  Serial.println();
  delay(250);
}

I think I found the solution in the meantime. What I didn't know is that each IR sensor is not the same, so low and high return values are different for each one. Even when blocking all light I didn't get values over 650 so thought I had a problem in my code. Instead, you need to process each sensor individually to figure out whether it's on a white or black surface. It's the difference between high and low that matters, not the actual value.

If anyone with the same problem stumbles on this post, here's an easy way to solve it (at least that's how I did it). Feel free to comment if there are other, better ways to do this. Thresholds should of course be modified for your specific situation. This code will return --X-- if your sensor array is positioned correctly and something else if it's not.

#include <QTRSensors.h>
QTRSensors qtr;
const uint8_t SensorCount = 5;
uint16_t sensorValues[SensorCount];
int sensorThreshold[5] = {350,200,200,200,350}; 

void setup()
{
  Serial.begin(9600);
  qtr.setTypeRC();
  qtr.setSensorPins((const uint8_t[]){26, 27, 28, 29, 30}, SensorCount);
  delay(1000);
}

void loop()
{
  qtr.read(sensorValues);
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(sensorValues[i]);
    Serial.print('\t');
  }
  Serial.print('\t');

  for (uint8_t i = 0; i < SensorCount; i++)
  {
    if (sensorValues[i] > sensorThreshold[i]) 
    {
      Serial.print("X");  // black surface detected
    }
    else 
    {
      Serial.print("-");  // white surface detected
    }
  }
  Serial.println();
  delay(250);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.