-
Notifications
You must be signed in to change notification settings - Fork 0
Light
- Introduction
- Reading brightness
- Asking questions instead
- If your readings run backwards
- Wiring and the pin
- Why there is no facade
LightSensor is the photoresistor (LDR) -- how bright is the room. Unlike the other senses it has no facade: the module name already says plainly what it is, so there is nothing a friendlier word would add.
uint8_t brightness = LightSensor::brightnessPercent(); // 0 dark .. 100 bright
if (LightSensor::isDarkerThanPercent(20)) Gestures::play(Gesture::Sleeping);Nothing needs enabling. The photoresistor is a plain analog pin, safe to read before the hardware is wired.
void loop() {
Serial.println(LightSensor::brightnessPercent());
delay(200);
}The scale is 0 for pitch dark and 100 for bright light, matching the official Otto_photoresistorTest example. A lit indoor room typically reads somewhere in the middle; covering the LDR with your hand should drop it sharply and immediately.
The absolute number is not portable between robots. It depends on the LDR, the fixed resistor beside it, and the light in your room -- so treat it as a value to compare against itself, not a physical unit.
if (LightSensor::isDarkerThanPercent(20)) Gestures::play(Gesture::Sleeping);
if (LightSensor::isBrighterThanPercent(80)) Mouth::show(Icon::Surprised);Both comparisons are strict -- darker than, brighter than, never equal to.
Find your two thresholds the same way as every other sensor, in the Serial Console:
> light
64 %
> watch light
Then cover the sensor, shine a phone torch at it, and note the range you actually get. Leave a wide gap between the dark and bright thresholds so a passing shadow does not flip the behaviour back and forth.
Note A behaviour driven directly by a single threshold will chatter when the light sits right on it. Give it hysteresis -- switch to "dark" below 20 % but back to "light" only above 35 % -- or act on a change that has held for several readings.
brightnessPercent() inverts the raw ADC value, because in the standard divider wiring an LDR reads lower as light increases. That matches the official example and the Otto kits.
If yours reports 100 % in the dark, your divider is wired the other way round: the LDR and the fixed resistor have swapped places. Either swap them back -- the tidier fix -- or invert the value in your sketch:
uint8_t brightness = 100 - LightSensor::brightnessPercent();raw() gives you the uninverted ADC reading if you would rather work from it directly:
int raw = LightSensor::raw(); // 0..1023, direction depends on your wiringThe default pin is A7:
OttoConfig cfg;
cfg.lightSensor.pin = A7; // the default
OttoFlow::start(cfg);The official single-sensor examples use A0, so change it if you followed one of those:
cfg.lightSensor.pin = A0;A0 is also the default touch sensor pin. Two sensors cannot share one pin, so if you fit both, one of them has to move. Keeping the photoresistor on A7 is the easier choice, because A6 and A7 are analog-input only on the Nano and the touch sensor -- which needs digitalRead() -- cannot live there.
Every other sensor gets an expressive name on top of its module: Ears over SoundSensor, Balance over Mpu6050. The photoresistor does not, and that is deliberate -- see the naming rules. "LightSensor" is already the name a newcomer would guess, and inventing a body part for it (Skin? Sight?) would make the API harder to use, not easier.
If your sketch reads better with one, a facade is three lines -- see Extending OttoFlow.
See also Sensors for the other senses.
OttoFlow is licensed under GPL-3.0 and wraps OttoDIYLib. Buy the kits at ottodiy.com.
Prologue
Getting Started
The Basics
Digging Deeper
- Bench Testing
- Serial Console
- Calibration
- Bluetooth and the Otto App
- Modules
- The Driver
- Extending OttoFlow
Reference