Calibration not successful on QTR 8RC

On my robotic vehicle I use two QTR 8RC sensors. I noticed recently that one of the sensors occasionally (let say one reading out of four) misses the black line though it is riding above it. When I tried to calibrate (qtr.calibrate()) this qtr sensor it seems I can’t. No matter what surface is transversed under the sensor during the calibration, the subsequent qtr.calibrationOn.minimum and qtr.calibrationOn.maximum seemingly return the very same values for each of the 8 IR sensors. The average min values for all sensors are around 700 and max values are 2500. So even when a white sheet of paper is put under the qtr 8rc, the same values appear. The same results come out when I put a black sheet of paper under the qtr 8rc sensor. This makes no sense. Why isn’t the new calibration successful? Let me note that the same code worked before just fine.

Hello.

To isolate the problem I recommend simplifying your setup as much as possible. Can you test the sensor array board in question by itself with a minimal system separate from the rest of your setup (i.e. just the sensor array, microcontroller, and power supply)? Please test the RC example programs form our Arduino library for the Pololu QTR Reflectance Sensors with minimal modification and post samples of the Serial Monitor outputs with descriptions of how you were using the sensor.

Also, can you post some pictures of your setup? Close-ups of both sides of the board along with pictures that show all the connections in your minimal test setup would be the most useful.

- Patrick

Hi Patrick,

thank you for your quick response. This morning the said QTR can’t read a simple black line on a white sheet of paper any more. I also started to suspect a HW failure of some kind. It will take some time to dismantle the device from the robot. The device is composed of an Arduino Nano Every mounted next to the QTR sensor array and connected with soldered wires. The central unit is a raspeberry pi which communicates with the Arduino via a USB port. I suspect some issue with the wires or a cold joint.

You are welcome to post the best pictures you can for now and I can let you know if I see any obvious problems. Additionally, if it is hard for you to disconnect the other hardware, it could still be helpful if you test the example programs I suggested from our library without changing any connections and post the Serial Monitor output from the Arduino.

Other than that though, I cannot offer much additional advice.

- Patrick

Hi Patrick,

thank you for the advice. Yesterday I set up the testing environment consisting of the said assembly (nano + qtr) and a rpi. I could upload the Blink sketch to the nano and it worked. When I uploaded my existing sketch it was upoladed successfully but it failed to yield any response neither to the rpi nor to serial monitor. I will try with the sketches from your library as you suggested.

PS
I am still figuring out how to post a picture in my reply.

First I loaded QTRRCExample. It worked. Then I loaded my sketch QTR_desni using 9600 baud rate and it worked, then I increased the baud rate to 250000 and it worked. I have no explanation. I can’t spot an error. It could be that the error is stochastic. I will install the device again into the robotic vehicle where I can do more complex testing. It will take a while though as currently I am also fixing some other issues and the robot is n’t operational right now.

QTR_desni.ino

#include <QTRSensors.h>
#include <EEPROM.h>

QTRSensors qtr;

#define NUM_SENSORS   8     // number of sensors used
#define TIMEOUT       2500  // waits for 2500 microseconds for sensor outputs to go low
#define EMITTER_PIN   10     // emitter is controlled by digital pin 2

//follows commands sent from raspberry pi via serial
//reads black line position, calibrates, reads calibrated values, stores calibrated values, recals calibrated values


//EEPROM Addressing for calibration storage
#define addrCalibratedMinimumOn 0
#define addrCalibratedMaximumOn 32

const uint8_t SensorCount = 8;
uint16_t sensorValues[SensorCount];

String nom = "Arduino";
String msg;
int termination = 0;
int blackline = 0; //0 - no black line, 1 - black line
int16_t line_position;
int16_t previous_border = 0; //stores the old margin value (either 0 or 7000)
bool last_reading = false; //was the last reading correct or not 


void setup() {
  // configure the sensors
  qtr.setTypeRC();
  qtr.setSensorPins((const uint8_t[]){12, 11, 10, 9, 8, 7, 6, 5}, SensorCount); //desni  
  qtr.setEmitterPin(4);
  // configure the communication  
  Serial.begin(250000); 
}

void loop() {
  readSerialPort();
  if (msg == "a") { // returns position
    sendData();
  }else if(msg == "b") { // returns readings of all 8 sensors + position 
    termination=0;
    sendDataa();    
  }else if(msg=="c"){ //cal - calibration
    calibrateQTR();  
  }else if(msg=="d"){ // reads calibrated min and max values
    readQTR();
  }else if(msg=="e"){ // store
    storeQTR();
  }else if(msg=="f"){ // recall
    recallQTR();  
    Serial.println();     
  }else if(msg=="g"){ // recals calibrated data and then returns position based on data compared with the treshold
    recallQTR();
    sendDataT(); 
  }else if(msg=="h"){ // returns position based on data compared with the treshold
    sendDataT();       
  }
  delayMicroseconds(1); // 
}

void readSerialPort() {
  msg = "";
  if (Serial.available()) {
    delayMicroseconds(1);
    while (Serial.available() > 0) {
      msg += (char)Serial.read();
    }
    Serial.flush();
  }
  delayMicroseconds(1);
}

void sendData() {
  //write data 
  line_position = qtr.readLineBlack(sensorValues);
  if ((line_position == 7000) || (line_position == 0)) {
    //test if senzor over black termination (transverse) line
    termination = 0;
    for (uint8_t i = 0; i < SensorCount; i++)
    {
      if (sensorValues[i] > 800) {
        termination += 1;
        } 
     } 
     if (termination >= 5) { //5 sensors over should suffice to report a transverse line
       line_position = 8000;
     }   
  }
  Serial.println(line_position); // comment this line out if you are using raw values
  //Serial.println();
  delayMicroseconds(1);
}

void sendDataT() {//reads position data, compares it to treshold and returns result
  line_position = qtr.readLineBlack(sensorValues);
  if ((line_position > 0) && (line_position < 7000)){  
    blackline = 0;
    for (uint8_t i = 0; i < SensorCount; i++)
    {
      if (sensorValues[i] >= 800) {
        blackline = 1;
        break;
        } 
     } 
     if (blackline == 0) { //one sensor reporting black is enough, none means 0 or 7000
       line_position = previous_border;
       last_reading = false;
     } 
     else {
        last_reading = true;
        if (line_position <= 3500){
          previous_border = 0;
        }
        else {
           previous_border = 7000;
        }
     }
  }   
  else { 
    if (last_reading) {
      previous_border =  line_position; 
    } 
    else {
      line_position = previous_border;//the reading from the last iteration was false, so take the previous border value
    }
  }
  Serial.println(line_position); // comment this line out if you are using raw values
  //Serial.println();
  delayMicroseconds(1);
}

void sendDataa() 
{

  line_position = qtr.readLineBlack(sensorValues);
  
  //test if senzor over black termination (cross) line
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    if (sensorValues[i] > 800) {
      termination += 1;
      } 
   }     
  //print values
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(sensorValues[i]);
    Serial.print("__");
  }
  if (termination == 8) {
    line_position = 8000;
  }
  Serial.print(termination); 
  Serial.print("_:");
  Serial.println(line_position);
  delay(250);
}

void calibrateQTR()
{
  
  delay(500);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // turn on Arduino's LED to indicate we are in calibration mode

  // 2.5 ms RC read timeout (default) * 10 reads per calibrate() call
  // = ~25 ms per calibrate() call.
  // Call calibrate() 400 times to make calibration take about 10 seconds.
  for (uint16_t i = 0; i < 400; i++)
  {
    qtr.calibrate();
  }
  digitalWrite(LED_BUILTIN, LOW); // turn off Arduino's LED to indicate we are through with calibration
  Serial.println();
}

void readQTR() //Reading Calibration Data...
{

  for (uint8_t i = 0; i < SensorCount; i++)
  {
    Serial.print(qtr.calibrationOn.minimum[i]);
    Serial.print('_');
  }
  
  // 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();
}

void storeQTR() //Storing Calibration Data into EEPROM...
{
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    EEPROM.put(addrCalibratedMinimumOn+(i*sizeof(qtr.calibrationOn.minimum[i])), qtr.calibrationOn.minimum[i]);
  }

  for (uint8_t i = 0; i < SensorCount; i++)
  {
    EEPROM.put(addrCalibratedMaximumOn+(i*sizeof(qtr.calibrationOn.maximum[i])), qtr.calibrationOn.maximum[i]);
  }
  
  Serial.println();

}

void recallQTR() //Recalling Calibration Data from EEPROM...
{

  qtr.calibrate(); 
  for (uint8_t i = 0; i < SensorCount; i++)
  {
    EEPROM.get(addrCalibratedMinimumOn+(i*2), qtr.calibrationOn.minimum[i]);
  }

  for (uint8_t i = 0; i < SensorCount; i++)
  {
    EEPROM.get(addrCalibratedMaximumOn+(i*2), qtr.calibrationOn.maximum[i]);
  }  

}

Well I am glad to at least hear that the QTR array is working in the simplified setup with our example programs. Unfortunately thought that means the problem likely has something to do with how your larger system works, and we cannot offer much specific advice for that.

I am not sure how practical it will be with your robot, but in general, the best troubleshooting approach for these types of problems is to start with your simplified setup and add the other parts of your system (including both the hardware and software aspects) onto it one piece at a time, testing in between so that you can try to isolate what particular addition introduces the problem again.

- Patrick

I installed a new sensor (made of a brand new arduino nano every and a Pololu qtr 8rc taken out of packaging from the original order of 3 QTRs). I tested it on my lab desk. Then I connected it with the robot and tested it. It worked. Then I installed it on its position under the robot and it worked, though with some isolated faults (not reading the obvious black line). It worked so just in one session. After that I switched off the robot. When I returned and switched on the robot, this new qtr totally degraded. It doesn’t see the black line any more, because the maxvalues went off. This is now the print out of min and max values: 116_116_116_116_116_116_116_116_65535_65535_65535_65535_65535_65535_65535_65535
I performed again the calibration, but the results are the same:
116_116_116_116_116_116_116_116_65535_65535_65535_65535_65535_65535_65535_65535
I admit I am lost. I would appreciate any clue what to do next.

Unfortunately, I do not have much to offer as far a specific clues or suggestions. I suspect the behavior you are seeing is a result of some quirk of your program and/or microcontroller behavior that the simplified system you tested earlier somehow did not capture.

If you are ever in doubt about the QTR-8RC array itself, you can always double check it by reading the raw sensor readings using the QTRRCRawValuesExample.ino program from our Arduino library with minimal modification.

- Patrick

Thank you Patrick. I understand that in my situation the help that can be provided remotely is limited. I am writing this lines now more for the sake of reference for anyone facing similar problems. Yesterday I started the robot and the qtr repeated this behavior of not letting itself to get calibrated. Then I reloaded my sketch and the sensor started to operate as initially, so it works with some random reading errors. I am more and more convinced, that the cause of trouble could be EMI (electromagnetic interference). The qtr and arduino are placed cca 15 cm from a rather powerful 1kW BLDC motor. This isn’t an ideal solution, but I kind of feel that I have the situation under control now and basically the robot can perform what it was built for - a few demonstrations. Please, consider this thread as closed. If in the course of further testing I will come to some better explanation, I will inform you.

Wow! That is a powerful motor. Your hypothesis that the motor could be generating enough noise to cause this behavior sounds reasonable. Testing your array while the motor is not running and comparing it to when the motor is running could help verify that, though I suppose there could still be some interference from the motor when it is unpowered if it uses permanent magnets.

Anyways, I am glad to hear that you at least have the issue somewhat understood and under control! Thanks for letting us know.

- Patrick