Colour sensors#
The board doesn’t just hand you raw red, green, and blue numbers and leave you to work out what they mean. You teach it the colours you care about, and then ask it a direct question: am I looking at colour 1?
Teaching a colour#
Hold the target in front of the sensor and call teachColor:
exp.teachColor(0, 1); // sensor port 0, this is now "colour 1"
That takes a moment, and it saves to the board’s flash automatically. You do not need to call saveConfigToFlash() afterwards — the teach helpers do it for you.
Each port remembers up to 7 colours, numbered 1 to 7.
exp.teachColor(0, 1); // hold red → colour 1
exp.teachColor(0, 2); // hold blue → colour 2
exp.teachColor(0, 3); // hold yellow → colour 3
Because it is stored in flash, teaching survives power cycles and applies in every OpMode. Teach at the start of the day, use all day.
When teaching refuses#
teachColor() throws rather than storing a colour it doesn’t believe in — if the target is too dark, if the sensor is saturated, or if there is no sensor on that port.
This is on purpose. A badly taught colour is worse than no colour at all: it either never fires or always fires, and both look like a code bug rather than a calibration problem. Better to find out while you’re standing at the robot holding the target.
If it throws, the usual fixes are more light, less light, or holding the target closer.
Reading colours#
int which = exp.getColorClass(0); // 0 = no match, 1-7 = which colour
boolean isRed = exp.seesColor(0, 1); // just asking about colour 1
seesColor() is usually the one you want — it reads as the question you are actually asking:
if (exp.seesColor(0, 1)) {
telemetry.addLine("over red");
}
Teaching from the gamepad#
Rather than hard-coding a teach call, let a driver do it at the field with a button:
if (gamepad1.a && !prevA) {
try {
exp.teachColor(0, 1);
status = "learned colour 1";
} catch (BBRDigitalExpander.BBRException e) {
status = "teach failed: " + e.getMessage();
}
}
prevA = gamepad1.a;
Catching the exception and showing it in telemetry turns a failed teach into something the driver can immediately react to, instead of a stack trace.
The !prevA matters as much as the try. teachColor() writes to flash, and the board takes at most one save per second — so a held button, teaching on every loop, would stall your OpMode to a crawl. Edge detection makes one press mean one teach. See Set up once.
BBRTeachColorExample and BBRThreeColorExample both do this properly.
Letting the board watch for you#
Once a colour is taught, the board can drive a digital output whenever it sees it — with no I2C traffic and no code in your loop at all:
exp.triggerOnColor(0, 0, 1); // output 0 high while port 0 sees colour 1
This also saves automatically. Your match code then reads a stock DigitalChannel. See Digital outputs and triggers.
Raw values#
If you need the underlying numbers — for tuning, or for a classifier of your own — they are in the telemetry block:
BBRDigitalExpander.TelemetryBlock t = exp.readTelemetry();
int[] rgbip = t.rawColor[0]; // r, g, b, ir, proximity
int confidence = t.classConfidence[0]; // 0-255
Classification uses normalized chromaticity rather than raw brightness, which is why a taught colour keeps working as the lighting changes between your workshop and the competition venue.