Arduino Modulino Light

Ambient light, RGB color and infrared sensor. Measures brightness in lux and red, green, blue and infrared light.

Tested on a real boardHigh confidence

From $8.00

Say it to PAL

“Tell me which color I am holding up to it.”

The code PAL writes

export const params = {
  threshold: { type: 'number', min: 3, max: 20, step: 1, default: 8, label: 'Colour change needed (points)' },
  dropRatio: { type: 'number', min: 0.1, max: 0.6, step: 0.05, default: 0.3, label: 'Brightness drop that means an object is held up' },
  calibrate: { type: 'toggle', default: false, label: 'Calibrate with white paper' },
};
// Colour recognition: shares of r+g+b, an automatic baseline learned while nothing is close, an object detected by a
// sharp drop in the total, and an optional white-paper reference that replaces the automatic baseline.
export default async function (p: Palpable) {
  const LEARN = 2 / (15 + 1); // ~30 s of readings at one every 2 s
  let r = 0, g = 0, b = 0;
  let base: { r: number; g: number; b: number } | null = null; // automatic baseline (shares)
  let baseTotal = 0; // learned room total r+g+b
  let paper: { r: number; g: number; b: number } | null = null; // white-paper reference, replaces base when set
  let calibrating = false;
  let paperSum = { r: 0, g: 0, b: 0 }, paperN = 0;
  let last = '';

  const say = (msg: string) => { if (msg !== last) { last = msg; p.log(msg); } };

  const onReading = () => {
    const total = r + g + b;
    if (total <= 0) return;
    const s = { r: (100 * r) / total, g: (100 * g) / total, b: (100 * b) / total };
    if (calibrating) { paperSum = { r: paperSum.r + s.r, g: paperSum.g + s.g, b: paperSum.b + s.b }; paperN += 1; return; }
    if (!base) { base = s; baseTotal = total; return; }
    const presented = total < p.config.dropRatio * baseTotal;
    if (!presented) {
      // Nothing close: keep learning the room. The baseline is frozen while an object is presented.
      base = { r: base.r + LEARN * (s.r - base.r), g: base.g + LEARN * (s.g - base.g), b: base.b + LEARN * (s.b - base.b) };
      baseTotal += LEARN * (total - baseTotal);
      say('nothing');
      return;
    }
    const ref = paper ?? base;
    const rise = { red: s.r - ref.r, green: s.g - ref.g, blue: s.b - ref.b };
    let colour = 'nothing';
    let best = p.config.threshold;
    for (const [name, d] of Object.entries(rise)) if (d >= best) { best = d; colour = name; }
    say(colour + ' (red ' + rise.red.toFixed(0) + ', green ' + rise.green.toFixed(0) + ', blue ' + rise.blue.toFixed(0) + ' points)');
  };

  let calibrateWas = !!p.config.calibrate;
  p.onConfigChange(async (cfg) => {
    const on = !!cfg.calibrate;
    if (on && !calibrateWas && !calibrating) {
      p.notify('Hold white paper over the light sensor. Calibrating 3… 2… 1…');
      for (const n of [3, 2, 1]) { p.log('Calibrating ' + n + '…'); await p.sleep(1000); }
      paperSum = { r: 0, g: 0, b: 0 }; paperN = 0; calibrating = true;
      await p.sleep(4000); // two readings at one every 2 s
      calibrating = false;
      if (paperN > 0) {
        paper = { r: paperSum.r / paperN, g: paperSum.g / paperN, b: paperSum.b / paperN };
        p.notify('Calibrated — you can put the paper down.');
      } else {
        p.notify('No readings arrived while calibrating — try again.');
      }
    }
    calibrateWas = on;
  });

  p.onSensorChange('modulino-light', 'red', (v) => { r = v; });
  p.onSensorChange('modulino-light', 'green', (v) => { g = v; });
  p.onSensorChange('modulino-light', 'blue', (v) => { b = v; onReading(); });
  await p.waitUntilStopped();
}

“Turn the lights on when it gets dark.”

The code PAL writes

p.onSensorChange('modulino-light', 'light', (lux) => {
  if (lux < 50) p.write('modulino-latch-relay', 'set', { state: 1 });
  else p.write('modulino-latch-relay', 'set', { state: 0 });
});
await p.waitUntilStopped();

When to pick it

Light sensor with RGB colour and infrared channels — choose over VEML7700 (simpler lux-only) when you need colour or IR detection.

About it

The Arduino Modulino Light combines ambient light sensing with RGB color and infrared detection. It measures illuminance from 0 to 120,000 lux and provides red, green, blue and infrared channel data, making it ideal for adaptive lighting systems, color matching, and brightness monitoring.

Facts

Tested

Tested on a real boardHigh confidence

We connected it to a Raspberry Pi, read it over its real connection, checked that it gives accurate readings through Palpable, and signed it off.

I2C address

0x53

The Arduino Modulino Light answers at I2C address 0x53. The address is fixed.

Current

5 mA

The catalog lists a typical draw of 5 mA for the Modulino Light, copied from the maker’s description and not measured by Palpable.

Board size

41 × 25.36 mm

The Modulino Light board measures 41 × 25.36 mm and stands 4.58 mm tall with its parts. It has 4 mounting holes. These dimensions are from the datasheet.

Chip

LTR-381RGB-01

Its sensor is the Lite-On LTR-381RGB-01.

LTR-381RGB-01 datasheet

Free to reuse

Every fact here is open data under CC BY 4.0. Copy it into your own docs or code, and credit Palpable. Download it

This record was last changed on October 17, 2026.

See every part

Tested on a real boardHigh confidenceit knows when it has been picked upAccelerometer + Gyroscopefrom $8.00Tested on a real boardHigh confidenceit feels the weather turning before you doEnvironment Sensorfrom $10.40Tested on a real boardHigh confidenceit knows the room is no longer emptyPresence Sensor (PIR)from $17.30