LM358 dark switch with an Arduino on an Arduino Uno
An LM358 comparator lights an LED when the LDR goes dark, past a threshold set by a knob, and an Uno reads its answer on pin 2 and both voltages on A0 and A1. The whole build, an Arduino Uno and 6 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Intermediate Runs in your browser. Free, and no account needed.
The parts retail for about $31. On Mokxi they're free.
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// LM358 dark switch: the op-amp decides, the Arduino listens.
//
// 10 k from 5 V and an LDR to GND make a divider: middle -> LM358 1IN+ and A0
// a 10 k pot across 5 V and GND: wiper -> LM358 1IN- and A1
// LM358 1OUT -> pin 2, and through 470 ohm to an LED
//
// Amplifier 1 of the LM358 has no feedback, so it is a comparator: when the
// divider (it rises as the room gets darker) is above the pot's wiper, the
// output goes high and lights the LED; below it, the output drops to ground.
// The Arduino does no comparing at all. It reads the comparator's answer on
// pin 2, and reads both voltages on A0 and A1 so you can see why.
//
// An LM358's output stops 1.5 V under its supply, and the LED's current
// drops a little more inside the chip, so "high" here is 3.15 V rather than
// 5 V. An ATmega328P on 5 V is only sure of a HIGH above 3.0 V, so pin 2 reads
// it, with little to spare: that is why the LED has 470 ohm and not 220,
// which would pull the output down to 2.9 V.
const int COMPARATOR_PIN = 2;
const int SENSOR_PIN = A0;
const int THRESHOLD_PIN = A1;
bool dark = false;
bool first = true;
unsigned long printedAt = 0;
long millivolts(int pin) {
return (long)analogRead(pin) * 5000L / 1023L;
}
void setup() {
Serial.begin(9600);
pinMode(COMPARATOR_PIN, INPUT);
pinMode(LED_BUILTIN, OUTPUT);
Serial.println("LM358 dark switch");
}
void loop() {
bool nowDark = digitalRead(COMPARATOR_PIN) == HIGH;
if (first || nowDark != dark) {
first = false;
dark = nowDark;
digitalWrite(LED_BUILTIN, dark ? HIGH : LOW);
Serial.println(dark ? "dark: comparator HIGH, lamp on" : "light: comparator LOW, lamp off");
}
if (millis() - printedAt >= 1000) {
printedAt = millis();
Serial.print("sensor ");
Serial.print(millivolts(SENSOR_PIN));
Serial.print(" mV, threshold ");
Serial.print(millivolts(THRESHOLD_PIN));
Serial.println(" mV");
}
}
Parts list
8 parts, plus the jumper wires. They retail for about $31; on Mokxi they're free.
- 1 × Arduino Uno R3
- 1 × Half breadboard
- 1 × Light sensor
- 1 × Resistor, 10k Ω
- 1 × Potentiometer
- 1 × LM358 dual op-amp
- 1 × Resistor, 470 Ω
- 1 × LED, red
How it is wired
7 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.
- Arduino Uno R3 pin 2; LM358 dual op-amp pin 1OUT; Resistor, 470 Ω pin 1
- Arduino Uno R3 pin 5V; Resistor, 10k Ω pin 2; Potentiometer pin 1; LM358 dual op-amp pin VCC
- Ground: Arduino Uno R3 pin GND; Light sensor pin 1; Potentiometer pin 3; LM358 dual op-amp pin GND; LM358 dual op-amp pin 2IN+; LED, red pin C
- Arduino Uno R3 pin A0; Light sensor pin 2; Resistor, 10k Ω pin 1; LM358 dual op-amp pin 1IN+
- Arduino Uno R3 pin A1; Potentiometer pin 2; LM358 dual op-amp pin 1IN-
- LM358 dual op-amp pin 2IN-; LM358 dual op-amp pin 2OUT
- Resistor, 470 Ω pin 2; LED, red pin A
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.