Reading Ambient Light

Hi All,

I’m trying to read the ambient light using a single QTR-1RC Reflectance Sensor. My controller is the Baby Orangutan.

I seem to be able to read the reflected light value easy enough. But when I set QTR_EMITTERS_OFF the behaviour doesn’t change. I’m trying essentially to determine if my robot has crawled under something.

#include <pololu/orangutan.h>
#include <avr/io.h>
#define F_CPU 20000000  // system clock is 20 MHz
#include <util/delay.h>  // uses F_CPU to achieve us and ms delays

// Global Variables
unsigned int reflectSensor[1];
const int NUM_QTR_PINS = 1, QTR_TIMEOUT = 2000, QTR_EMITTER_PIN = 255;
unsigned char QTR_PINS[] = {8};

void reflectors_init()
{	
	// Initialize the QTR (Reflectance Sensors) (from the Pololu library)
	qtr_rc_init(QTR_PINS, NUM_QTR_PINS, QTR_TIMEOUT, QTR_EMITTER_PIN);	
	// Calibrate QTR sensors with emitters turned off for ambient light
   int i;  
   for (i = 0; i < 250; i++)  // make the calibration take about 5 seconds  
   {  
     red_led(1);
     qtr_calibrate(QTR_EMITTERS_OFF);  
     delay(20);  
	 red_led(0);
	 delay(20); 
   }   
}

int main()
{		
	// initialize QTR sensors
	reflectors_init();
	red_led(0);
while(1)
	{
			red_led(0);
			delay_ms(200);
			qtr_read(reflectSensor, QTR_EMITTERS_OFF);
			
						
			if (reflectSensor[0] < 1750) //is under something
			{
				red_led(1);
				delay_ms(200);
			} else {
				red_led(0);
			}
			red_led(0);
            }
}

Any help would be appreciated.

Cheers,
- Will Kruss

Hello.

The QTR-1RC and QTR-1A sensors do not offer independent emitter control; if you look at the board schematic, you can see that the IR LED is connected directly to VIN and will be on whenever the board is powered. Can you explain how you have the sensor mounted and describe your calibration procedure?

- Ben

Hi Ben,

Ahh rats. Okay is there a manner in which I can get an ambient light reading? Or a different sensor I should be looking at?

Basically I just want to be able to detect when my robot drives itself under something. The idea was simply to calibrate on startup to get a reading. Then compare this to any newer readings and if all of a sudden there’s a lot less ambient light assume we are under something.

The sensor is just mounted at the top of the robot (vehicle). I can easily detect if something with reflection (white, green, yellow, red etc.) is within a couple of cm but that’s about it. Can’t distinguish between black and no reflection either so I think I’m way off track with this one :slight_smile:

Cheers,
- Will

The calibration routine requires you to expose the sensor to the maximum and minimum levels of incident IR light you expect it to encounter, and then the read() function scales the output based on that calibration. For your application, this would involve calling the calibration routine while it is being exposed to ambient light and while the ambient light is being blocked. However, I think you can probably do just fine with skipping calibration altogether and looking only at the raw sensor output, which should correspond pretty closely with the actual detected ambient IR.

Please keep in mind that the sensor is sensitive to IR light (peak wavelength of 940 nm), so its output will not always be a reliable measure of the ambient visible light in a room (it really depends on what is producing light). If you will be passing under high obstacles, the reflection from the IR LED will probably not be strong enough to mess with your readings. If you will be passing under low obstacles, such that the surface is within a few centimeters of the sensor, you might want to disable the emitter by cutting the trace that powers the LED or removing the resistor in series with the LED (this is the resistor that does not connect to the OUT pin).

- Ben

Hey Ben,

Sounds excellent. I have a couple of these so will try to cut the trace powering the LED.

Do you know what range to expect from a raw qtr_read when no calibration has been performend?

Thanks Ben,
- Will

It’s just measuring the time it takes for the capacitor to discharge, so the range will be anywhere from a few microseconds to whatever you set as a timeout. The units will be 0.4 us (so a reading of 50 would correspond to 50*0.4 us = 20 us).

- Ben

Hey Ben,

You are a superstar! That worked brilliantly. I can now take a base reading when the robot turns on, and if it moves under something the ambient light reading changes markedly. If the ambient reading only changes a little bit I’ll update my base reading. This will enable me to detect when the robot is under something, so if it gets stuck it can reverse until the ambient light returns, then do a turn to negotiate around the object.

Still not sure how to go about using the accelerometer properly for the purpose of determining whether the robot is moving or has crashed into something. Any suggestions on how to go about that would be appreciated. I’ve determined the accelerometer is working fine however by simply doing this:

start_analog_conversion(6);  // start initial conversion
	
	do {
		delay_ms(10);
	} while (analog_is_converting());
	
	BaseX = analog_conversion_result();
	start_analog_conversion(6);   // start next conversion
	
	while(1)
	{
		if (!analog_is_converting())     // if conversion is done...
		{
			sum += analog_conversion_result();  // get result
			start_analog_conversion(6);   // start next conversion
			if (++samples == 5)           // if 20 samples have been taken...
			{
				avg = sum / 5;             // compute 20-sample average of ADC result
				samples = 0;
				sum = 0;
			}
		}
		
		if (samples == 0)
		{
			if (avg > (BaseX + 2)) {
				red_led(1);                 // red LED on
				delay_ms(250);
				red_led(0);                 // red LED off
				delay_ms(250);
			}
			if (avg < (BaseX - 2)) {
				red_led(1);
				delay_ms(250);
				red_led(0);                 // red LED off
				delay_ms(250);
			}
		}
				
	}

That tells me if the Base value for X has changed by at least 2. The problem with the LED tutorial example I think is that the values I’m getting back are around 80, give or take about 20 if I move the robot around, which isn’t enough on the scale of 0-255 for the LED brightness to really tell if it’s working.

Cheers,
- Will