Understanding the Sensor Behind the Thing - LDR Sensor


1. Introduction

The objective of this task was to understand the working of an analog sensor, analyze its datasheet, collect real-time data, and visualize the results. The Light Dependent Resistor (LDR) was chosen as the sensor.

2. Sensor Selection




  • Diameter: 5mm
  • No. of Pins: 2
  • Type: PCB Through Hole
  • Max Operating Temperature: +800°C (Approx.)
  • Dark resistance: 1-20MΩ

3. Working Principle

An LDR changes its resistance based on light intensity using the photoelectric effect. More light → less resistance. Less light → higher resistance.

Input Voltage & Current

Operated at 5V. Current depends on the resistance of the LDR and the value of the series resistor used.

4. Raw Data Using Oscilloscope

Components used:

  • LDR
  • 10kΩ Resistor (Voltage Divider)
  • 5V Power Supply
  • Oscilloscope (MSO/DSO)



Conditions observed:

  • High Light: Low Resistance, High Voltage



  • Medium Light: Moderate Resistance, Intermediate Voltage



  • Low Light: High Resistance, Low Voltage


5. Tinkercad Simulation






Used:

  • 10kΩ Resistor
  • LDR
  • Arduino Uno
  • LCD (LiquidCrystal_I2C)

Code implemented ADC reading, voltage calculation, resistance conversion, lux estimation, current calculation and displayed results on LCD & serial monitor.

Conditions observed:

  • High Light





  • Medium Light





  • Low Light





Code

                    #include 
                    #include 

                    LiquidCrystal_I2C lcd(0x20, 16, 2);  // Update I2C address if needed
                    int LDR_PIN = A0;  // LDR connected to A0
                    const float R_fixed = 10000.0;  // 10kΩ resistor in voltage divider

                    // Adjusted Calibration Constants (Use Best-Fit Values from Python)
                    const float A = 300.0;  // Replace with your calculated A
                    const float B = 1.2;    // Replace with your calculated B

                    // Function to get stable readings
                    int getSmoothReading(int pin, int samples = 10) {
                      long sum = 0;
                      for (int i = 0; i < samples; i++) {
                        sum += analogRead(pin);
                        delay(5);  // Reduce noise
                      }
                      return sum / samples;
                    }

                    void setup() {
                      Serial.begin(9600);
                      lcd.init();
                      lcd.backlight();
                      lcd.setCursor(0, 0);
                      lcd.print("Light Intensity:");
                    }

                    void loop() {
                      int adcValue = getSmoothReading(LDR_PIN);
                      float voltage = (adcValue / 1023.0) * 5.0;  // Convert ADC to voltage

                      // Calculate LDR resistance
                      float R_LDR = R_fixed * (1023.0 / adcValue - 1.0);
                      
                      // Convert resistance to Lux using updated formula
                      float lux = A * pow(R_LDR, -B);

                      // Calculate current (I = V / R_LDR)
                      float current = (R_LDR > 0) ? voltage / R_LDR : 0;  // Avoid division by zero

                      // Display on LCD (Two Lines)
                      lcd.setCursor(0, 1);
                      lcd.print("Lx:");
                      lcd.print(lux, 4);  // Show Lux with 4 decimal places
                      lcd.print(" V:");
                      lcd.print(voltage, 2);

                      delay(1000);
                      lcd.clear();
                      
                      lcd.setCursor(0, 0);
                      lcd.print("R: ");
                      lcd.print(R_LDR, 0);
                      lcd.print("Ω");

                      lcd.setCursor(0, 1);
                      lcd.print("I: ");
                      lcd.print(current * 1000, 2);  // Convert A to mA for better readability
                      lcd.print(" mA");

                      // Print to Serial Monitor
                      Serial.print("ADC: ");
                      Serial.print(adcValue);
                      Serial.print(" | R_LDR: ");
                      Serial.print(R_LDR, 0);
                      Serial.print("Ω | Lux: ");
                      Serial.print(lux, 4);  // Show Lux with 4 decimal places
                      Serial.print(" lx | Voltage: ");
                      Serial.print(voltage, 2);
                      Serial.print(" V | Current: ");
                      Serial.print(current * 1000, 2);
                      Serial.println(" mA");

                      delay(1000);  // Refresh Rate
                    }


                      
                  


6. Real Hardware Implementation


Arduino Integration




Used:

  • 10kΩ Resistor
  • LDR
  • Arduino Uno
  • LCD (LiquidCrystal_I2C)

Conditions observed:

  • High Light









  • Medium Light









  • Low Light









Same code and concept as Tinkercad, implemented using real components. Displayed output both on LCD and Serial Monitor.


Code

                    #include 
                    #include 

                    LiquidCrystal_I2C lcd(0x27, 16, 2);  // Update I2C address if needed
                    int LDR_PIN = A0;  // LDR connected to A0
                    const float R_fixed = 10000.0;  // 10kΩ resistor in voltage divider

                    // Adjusted Calibration Constants (Use Best-Fit Values from Python)
                    const float A = 300.0;  // Replace with your calculated A
                    const float B = 1.2;    // Replace with your calculated B

                    // Function to get stable readings
                    int getSmoothReading(int pin, int samples = 10) {
                      long sum = 0;
                      for (int i = 0; i < samples; i++) {
                        sum += analogRead(pin);
                        delay(5);  // Reduce noise
                      }
                      return sum / samples;
                    }

                    void setup() {
                      Serial.begin(9600);
                      lcd.init();
                      lcd.backlight();
                      lcd.setCursor(0, 0);
                      lcd.print("Light Intensity:");
                    }

                    void loop() {
                      int adcValue = getSmoothReading(LDR_PIN);
                      float voltage = (adcValue / 1023.0) * 5.0;  // Convert ADC to voltage

                      // Calculate LDR resistance
                      float R_LDR = R_fixed * (1023.0 / adcValue - 1.0);
                      
                      // Convert resistance to Lux using updated formula
                      float lux = A * pow(R_LDR, -B);

                      // Calculate current (I = V / R_LDR)
                      float current = (R_LDR > 0) ? voltage / R_LDR : 0;  // Avoid division by zero

                      // Display on LCD (Two Lines)
                      lcd.setCursor(0, 1);
                      lcd.print("Lx:");
                      lcd.print(lux, 4);  // Show Lux with 4 decimal places
                      lcd.print(" V:");
                      lcd.print(voltage, 2);

                      delay(1000);
                      lcd.clear();
                      
                      lcd.setCursor(0, 0);
                      lcd.print("R: ");
                      lcd.print(R_LDR, 0);
                      lcd.print(" Ohms");

                      lcd.setCursor(0, 1);
                      lcd.print("I: ");
                      lcd.print(current * 1000, 2);  // Convert A to mA for better readability
                      lcd.print(" mA");

                      // Print to Serial Monitor
                      Serial.print("ADC: ");
                      Serial.print(adcValue);
                      Serial.print(" | R_LDR: ");
                      Serial.print(R_LDR, 0);
                      Serial.print("Ω | Lux: ");
                      Serial.print(lux, 4);  // Show Lux with 4 decimal places
                      Serial.print(" lx | Voltage: ");
                      Serial.print(voltage, 2);
                      Serial.print(" V | Current: ");
                      Serial.print(current * 1000, 2);
                      Serial.println(" mA");

                      delay(1000);  // Refresh Rate
                    }


                  


ESP32 Integration

Arduino lacks built-in WiFi for cloud logging. Switched to ESP32 WROOM to enable Firebase integration. Faced some limitations with NodeMCU ESP8266 such as ADC resolution and connectivity.



9. ESP32 Code Snippet (Firebase)












Code

                      #include 
                      #include 
                      #include 
                      #include "addons/TokenHelper.h"
                      #include "addons/RTDBHelper.h"

                      #define WIFI_SSID "YourWiFi"
                      #define WIFI_PASSWORD "YourPassword"
                      #define API_KEY "YourFirebaseAPIKey"
                      #define DATABASE_URL "YourDatabaseURL"

                      FirebaseData fbdo;
                      FirebaseAuth auth;
                      FirebaseConfig config;
                      bool signupOK = false;
                      #define LDR_PIN 34
                      #define FIXED_RESISTOR 10000.0
                      const float A = 300.0;
                      const float B = 1.2;
                      unsigned long sendDataPrevMillis = 0;

                      void setup() {
                          Serial.begin(115200);
                          WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
                          while (WiFi.status() != WL_CONNECTED) { delay(300); }
                          config.api_key = API_KEY;
                          config.database_url = DATABASE_URL;
                          Firebase.begin(&config, &auth);
                          Firebase.reconnectWiFi(true);
                      }

                      void loop() {
                          if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 1000)) {
                              sendDataPrevMillis = millis();
                              int adcValue = analogRead(LDR_PIN);
                              float voltage = (adcValue / 4095.0) * 3.3;
                              float R_LDR = (FIXED_RESISTOR * (3.3 / voltage - 1.0));
                              float lux = A * pow(R_LDR, -B);
                              Firebase.RTDB.setFloat(&fbdo, "LDR_Sensor/LUX", lux);
                          }
                      }


                  


10. Conclusion

This project enabled complete understanding of the LDR sensor, from analog behavior to real-time monitoring and cloud data logging using ESP32. It showcases practical implementation of IoT-based sensor systems and calibration techniques.