In this tutorial we will discuss how to interface an IR(Infra-Red) photo-diode with ARM Cortex-M3 LPC1768 microcontroller. Its also applicable to LPC1769 and other devices of same family. A photodiode is a diode which additionally converts light i.e. incident photons into electrical current. An IR photodiode is a photodiode which is sensitive to IR light. These photodiodes are easily identifiable since they are black. An IR diode pair i.e. an IR Photodiode along with an IR LED can be used to sense obstacle or as proximity sensor. It is also used in line-follower and similar robots.
Working principle
An IR LED is used as a source of Infra-Red light (i.e. a Transmitter). A revered-biased IR photodiode (Sensor, i.e. a Receiver) is used to detect any IR light reflected from objects in front of the pair. When reflected IR light falls on the IR photodiode it generates a small amount of current corresponding to amount of incident light and in this way it acts as an IR sensor. We can then convert this current into voltage to interface with a micrcontroller using ADC. The analog output can also be converted into 1-bit digital output using a comparator. Commonly available IR modules include a comparator(Op-AMP) or a schmitt-trigger and provide 1-bit digital output (HIGH/LOW) to indicate whether an obstacle is present or not. This makes it easy to interface IR diode pair without using ADC.
IR Photodiode/LED pair (Rx/Tx) and Modules:
Converting Photo Diode current to Voltage
The IR photodiode(IR Sensor) current can be converted into proportional voltage by using a Load Resistance RL. The reverse bias photodiode current (IPD) flowing through the Load Resistance creates a voltage drop which we can measure. Note that the photodiode is reverse biased and a bias voltage is given. This configuration is also known as photoconductive mode. The configuration where bias voltage is absent is called Photovoltaic mode.
We can also use an Op-AMP/Comparator to convert analog signal into digital signal using a potentiometer to set a threshold voltage which defines the sensing distance. In the diagram given below, the voltage drop is given non-inverting pin of LM393 Comparator as Vin. The middle leg of a 10K potentiometer is connected to inverting pin of LM393 Comparator as Vref which sets the thresholds. Depending on Vin and Vref, the comparator output is either HIGH i.e. Logic 1 or LOW i.e. Logic 0. The condition when the output is either 1 or 0 is given in the diagram. For the circuit given below a logic HIGH means an obstacle is detected and a logic LOW means no obstacle is detected. Instead of LM393 you can use any general purpose Op-AMP like LM358/LM324 as a comparator.
Similar kind of circuit is present on IR modules used for proximity sensing, obstacle detection, etc. The potentiometer on these modules is used to set the sensing range/distance. Some IR modules used for line-following robots incorporate a schmitt trigger i.e IC 7414 to convert output to digital(HIGH/LOW). The hysteresis curve of schmitt trigger defines a fixed sensing range/distance in these modules.
IR Interfacing Examples with LPC1768
Interfacing IR photodiode using LPC176x ADC
In this example we will convert the reverse bias current of IR photodiode into proportional voltage using a 10K resistor in presence of 3.3V(Vcc) biasing voltage. We will use the inbuilt 12-bit ADC of LPC1768 to convert the voltage into digital readings. You can check my ADC Tutorial for more. We can set a threshold for the digital values to define sensing range. The ADC readings are inversely proportional to the proximity of an object in front. The code is very similar to LPC176x LDR Interfacing tutorial. The example project linked below also contains retargeted printf() for KEIL which redirects its output to UART0.
Schematic:
Example 1 Source Code:
/*(C) Umang Gajera - www.ocfreaks.com
LPC1768/LPC1769 IR Sensor Interfacing Example 1 Source Code for KEIL ARM.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
Also refer: https://www.ocfreaks.com/lpc1768-adc-programming-tutorial/
License : GPL.*/
#include <lpc17xx.h>
#include <stdio.h> //for printf() - https://www.ocfreaks.com/retarget-redirect-printf-scanf-uart-keil/
#include "ocf_lpc176x_lib.h" //contains initUART0(), initTimer0() & putc() to retarget printf()
#define ADC_CLK_EN (1<<12)
#define SEL_AD0_0 (1<<0) //Select Channel AD0.0
#define CLKDIV 1 //ADC clock-divider (ADC_CLOCK=PCLK/CLKDIV+1) = 12.5Mhz @ 25Mhz PCLK
#define PWRUP (1<<21) //setting it to 0 will power it down
#define START_CNV (1<<24) //001 for starting the conversion immediately
#define ADC_DONE (1U<<31) //define it as unsigned value or compiler will throw #61-D warning
#define ADCR_SETUP_SCM ((CLKDIV<<8) | PWRUP)
#define VREF 3.3 //Reference Voltage at VREFP pin, given VREFN = 0V(GND)
int main(void)
{
//SystemInit(); //Gets called by Startup code, sets CCLK=100Mhz, PCLK=25Mhz
initUART0(); //Initialize UART0 for uart_printf() - defined in ocf_lpc176x_lib.c
initTimer0(); //For delayMS() - defined in ocf_lpc176x_lib.c
LPC_SC->PCONP |= ADC_CLK_EN;
LPC_PINCON->PINSEL1 |= (1<<14); //select AD0.0 for P0.23
LPC_ADC->ADCR = ADCR_SETUP_SCM | SEL_AD0_0;
int result = 0;
printf("OCFreaks.com LPC176x IR Sensor Interfacing Tutorial - Example 1.\n");
while(1)
{
LPC_ADC->ADCR |= START_CNV; //Start new Conversion
while((LPC_ADC->ADDR0 & ADC_DONE) == 0); //Wait untill conversion is finished
result = (LPC_ADC->ADDR0>>4) & 0xFFF; //12 bit Mask to extract result
printf("AD0.0 = %d\n" , result); //Display raw result
delayMS(500); //Slowing down Updates to 2 Updates per second
}
//return 0; //This won't execute
}
Download Project:
Interfacing IR Proximity-Sensor/Obstacle-avoidance Module with LPC1768 using GPIO
In this example will interface the IR module using Pin P0.2. Check the output logic of your IR module and edit the code accordingly. For commonly available IR Proximity Sensor modules, a LOW output means an Obstacle is detected else output is HIGH. For line-follower IR modules based on Schimtt-trigger, a HIGH output means an Obstacle is detected else output is LOW.
Schematic:
Example 2 Source Code:
/*(C) Umang Gajera - www.ocfreaks.com
LPC176x IR Proximity/Obstacle-avoidance Sensor Interfacing Example 2 Source Code for KEIL ARM.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
Also refer: https://www.ocfreaks.com/lpc1768-adc-programming-tutorial/
License : GPL.*/
#include <lpc17xx.h>
#include <stdio.h> //for printf() - https://www.ocfreaks.com/retarget-redirect-printf-scanf-uart-keil/
#include "ocf_lpc176x_lib.h" //contains initUART0(), initTimer0() & putc() to retarget printf()
#define PIN0_1 (1<<1)
int main(void)
{
//SystemInit(); //Gets called by Startup code, sets CCLK=100Mhz, PCLK=25Mhz
initUART0(); //Initialize UART0 for uart_printf() - defined in ocf_lpc176x_lib.c
initTimer0(); //For delayMS() - defined in ocf_lpc176x_lib.c
printf("OCFreaks.com LPC176x ADC Tutorial Example 1.\nSoftware Controlled ADC Mode on AD0.0 Channel.\n");
while(1)
{
//Check the O/P Logic of your IR module. Mine gives LOW when obstacle is detected else HIGH.
if((LPC_GPIO0->FIOPIN & PIN0_1) == 0 )
{
printf("Obstacle Detected!\n");
}
else
{
printf("No Obstacle ahead.\n");
}
delayMS(500); //Slowing down Updates to 2 Updates per second
}
//return 0; //This won't execute
}
Download Project: