OCFreaks!

Interfacing LDR with LPC1768

In this tutorial we will see Interfacing of LDR with ARM Cortex-M3 LPC1768 microcontroller. Light Dependent Resistor is the full form of LDR and they are basically used to detect the intensity of light. They are also known as photoresistors or photoconductive cells. The resistance of an LDR is inversely proportional to the intensity of light directly falling on it. Hence under dark conditions the resistance typically rises to around 500KΩ to 5MΩ. Under ambient light the resistance is generally around 2KΩ to 10KΩ. Under very bright light its resistance goes down to around few ohms – in 2 to 20 Ohms range.

For the examples covered in this tutorial, we will use the inbuilt 12bit-ADC module of LPC1768/LPC1769 microcontroller to interface LDR. You can check my LPC1768 ADC Programming Tutorial for reference. Since we cannot directly connect an LDR to the ADC’s input, we need to convert the resistance into an equivalent voltage. By adding another fixed resistor in series we can form a voltage divider network and can connect the common of the resister and LDR to ADC’s input pin. Lets use LDR as R1 and the fixed resistor as R2. The voltage Vout at the common terminal is given as:

Now, to implement this we need a suitable value for R2. The value of R2 in voltage-divider is primarily determined by:

Most of the time using 3.3KΩ or 4.7KΩ or 10KΩ resistor as R2 will do the job. But, always check the manufacturer’s datasheet for max operating current. In case you don’t have access to datasheet, then generally a couple of few milliamps must be safe to operate. For the ones which I have used (which have come in ~5mm package), generally 1mA to 5mA have not been an issue. Some LDR’s also allow 50mA to 75mA+ max current. In my case a resistor of 4.7KΩ just works fine and gives a good full scale range. Given LPC176x uses 3.3V as Vcc, a resistor of 4.7KΩ will limit current to 0.7mA max through LDR under very bright conditions.

Example 1 – Reading the voltage divider output:

In this example we will read the voltage divider output, which changes as the intensity of light changes. The ADC will convert the input voltage to a proportional value between 0 and 4095. We can directly use this value(ADC conversion Result) to detect the intensity of light. A value near 0 means Dark condition and a value near 4096 means very bright light is present. With this example you can see the output values change as you change the intensity of light. Working with this example you can then select a suitable cut-off value or a cut-off range to trigger a function. In this example I have retargeted printf() to redirect its output over UART. The schematic is as shown below:

Source code:


/*(C) Umang Gajera- www.ocfreaks.com
LPC1768/LPC1769 LDR Interfacing Example 1 Source Code for KEIL ARM.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
Also see: https://www.ocfreaks.com/lpc1768-adc-programming-tutorial/
License: GPL.*/

#include <lpc17xx.h>
#include <stdio.h> //For retargeted 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) - not used in this example.

int main(void)
{
	//SystemInit(); //Gets called by Startup code, sets CCLK=100Mhz, PCLK=25Mhz
	initUART0(); //Initialize UART0 for retargeted printf() 
	initTimer0(); //For delayMS()

	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 LDR Interfacing - Example 1.\n");
	
	while(1)
	{
		LPC_ADC->ADCR |= START_CNV; //Start new Conversion (Software controlled)

		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);
		
		delayMS(500); //Slowing down Updates to 2 Updates per second
	}
	
	//return 0; //This won't execute
}
KEIL ARM uV5/uV4 Project for example given above on GitHub @ LDR Interfacing with LPC1768 Example 1 [Successfully tested on Keil uV5.23], Download Project Zip. You can find the HEX file inside objects folder.

Example 2 – Turn on LED when its dark:

In this interfacing example we will turn-on an LED when we detect low light or dark conditions. Instead of an LED you can also connect a Relay which can then switch on a Bulb or something like heater during night in cold regions. Make sure you keep the LDR away from the LED or Bulb since we are only interested in detecting sunlight and not artificial light in this case. Schematic for this example is given as follows:

Source code:


/*(C) Umang Gajera- www.ocfreaks.com
LPC1768/LPC1769 LDR Interfacing Example 2 Source Code for KEIL ARM.
More Embedded tutorials @ www.ocfreaks.com/cat/embedded/
Also see: https://www.ocfreaks.com/lpc1768-adc-programming-tutorial/
License: GPL.*/

#include <lpc176x.h>
#include "ocf_lpc176x_lib.h"

#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) - not used in this example.

#define LDR_CUT_OFF 750 //Define your cut-off value here

int main(void)
{
	//SystemInit(); //Gets called by Startup code, sets CCLK=100Mhz, PCLK=25Mhz
	initTimer0(); //For delayMS()

	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;
	LPC_GPIO0->FIODIR |= (1<<0); //Set P0.0 as output
	LPC_GPIO0->FIOCLR |= (1<<0); //LED initially OFF
	
	int result = 0;
	
	while(1)
	{
		LPC_ADC->ADCR |= START_CNV; //Start new Conversion (Software controlled)

		while((LPC_ADC->ADDR0 & ADC_DONE) == 0);
		
		result = (LPC_ADC->ADDR0>>4) & 0xFFF; //12 bit Mask to extract result
		
		if(result < LDR_CUT_OFF)
		{
			LPC_GPIO0->FIOSET |= (1<<0); //drive P0.0 HIGH - LED ON
		}
		else
		{
			LPC_GPIO0->FIOCLR |= (1<<0); //drive P0.0 LOW - LED OFF
		}
		
		delayMS(50); //wait some time since LDRs don't react immediately.
	}
	//return 0; //This won't execute normally
}
KEIL ARM uV5/uV4 Project for example given above on GitHub @ LDR Interfacing with LPC1768 Example 2 [Successfully tested on Keil uV5.23], Download Project Zip. You can find the HEX file inside objects folder.

Exit mobile version