Skip to content

Commit 83892eb

Browse files
Kaan OzenKaan Ozen
authored andcommitted
feat(apds9960): Add OLED color lamp example.
1 parent 83b7a45 commit 83892eb

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
"""Color lamp example using APDS9960 and SSD1327 OLED.
2+
3+
Detects the color of an object placed near the APDS9960 sensor.
4+
Includes an auto-calibration phase for ambient room light.
5+
Displays the dominant color and raw RGBC values on a round OLED layout.
6+
The background brightness matches the ambient light intensity dynamically.
7+
"""
8+
9+
from time import sleep_ms
10+
11+
import ssd1327
12+
from apds9960 import uAPDS9960 as APDS9960
13+
from machine import I2C, SPI, Pin
14+
15+
# Layout Constants
16+
MIN_CLEAR = 10
17+
TITLE_Y = 24
18+
TITLE_X = 28
19+
COLOR_Y = 40
20+
COLOR_X = 44
21+
GRID_ROW1_Y = 70
22+
GRID_ROW2_Y = 90
23+
GRID_COL1_X = 20
24+
GRID_COL2_X = 72
25+
26+
# Calibration Constants
27+
CALIB_TEXT1_X = 12
28+
CALIB_TEXT1_Y = 54
29+
CALIB_TEXT2_X = 16
30+
CALIB_TEXT2_Y = 74
31+
CALIB_COLOR = 15
32+
CALIB_BASELINE = 50
33+
CALIB_SAMPLES = 30
34+
CALIB_DELAY_MS = 100
35+
CALIB_BUFFER_DIVISOR = 10
36+
37+
# Hardware Initialization
38+
i2c = I2C(1)
39+
apds = APDS9960(i2c)
40+
apds.enable_light_sensor()
41+
spi = SPI(1)
42+
dc = Pin("DATA_COMMAND_DISPLAY")
43+
res = Pin("RST_DISPLAY")
44+
cs = Pin("CS_DISPLAY")
45+
display = ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs)
46+
47+
print("=======================")
48+
print(" Color Lamp ")
49+
print("=======================")
50+
print("Press Ctrl+C to exit.")
51+
52+
try:
53+
# Auto-Calibration Phase
54+
print("Calibrating ambient light... Leave the sensor uncovered.")
55+
display.fill(0)
56+
display.text("Calibrating...", CALIB_TEXT1_X, CALIB_TEXT1_Y, CALIB_COLOR)
57+
display.text("Do not cover", CALIB_TEXT2_X, CALIB_TEXT2_Y, CALIB_COLOR)
58+
display.show()
59+
60+
max_clear_calib = CALIB_BASELINE # Baseline minimum
61+
# Sample light for about 3 seconds
62+
for _ in range(CALIB_SAMPLES):
63+
c = apds.ambient_light()
64+
max_clear_calib = max(max_clear_calib, c)
65+
sleep_ms(CALIB_DELAY_MS)
66+
67+
# Add a small buffer to the max calibration so it doesn't max out too easily
68+
MAX_CLEAR = max_clear_calib + (max_clear_calib // CALIB_BUFFER_DIVISOR)
69+
print("Calibration complete. MAX_CLEAR set to:", MAX_CLEAR)
70+
sleep_ms(500)
71+
72+
# --- Main Loop ---
73+
while True:
74+
# Read RGBC values from the sensor
75+
c = apds.ambient_light()
76+
r = apds.red_light()
77+
g = apds.green_light()
78+
b = apds.blue_light()
79+
80+
# Determine background greyscale intensity (0 to 15)
81+
clamped_c = max(0, min(c, MAX_CLEAR))
82+
bg_color = (clamped_c * 15) // MAX_CLEAR
83+
84+
# Determine text contrast (Dark text on light background, and vice-versa)
85+
text_color = 0 if bg_color > 7 else 15
86+
87+
# Determine dominant color
88+
dominant_name = "DARK"
89+
if c > MIN_CLEAR:
90+
if r > g and r > b:
91+
dominant_name = "RED"
92+
elif g > r and g > b:
93+
dominant_name = "GREEN"
94+
elif b > r and b > g:
95+
dominant_name = "BLUE"
96+
else:
97+
dominant_name = "MIXED"
98+
99+
# Drawing Phase
100+
display.fill(bg_color)
101+
102+
display.text("Dominant:", TITLE_X, TITLE_Y, text_color)
103+
display.text(dominant_name, COLOR_X, COLOR_Y, text_color)
104+
105+
# Draw Raw RGBC values in a 2x2 Grid
106+
display.text("R:{}".format(r), GRID_COL1_X, GRID_ROW1_Y, text_color)
107+
display.text("G:{}".format(g), GRID_COL2_X, GRID_ROW1_Y, text_color)
108+
display.text("B:{}".format(b), GRID_COL1_X, GRID_ROW2_Y, text_color)
109+
display.text("C:{}".format(c), GRID_COL2_X, GRID_ROW2_Y, text_color)
110+
111+
display.show()
112+
sleep_ms(100) # Slower poll rate to avoid screen flickering and make text readable
113+
114+
except KeyboardInterrupt:
115+
print("\nColor lamp stopped.")
116+
finally:
117+
# Clean up and power off display on exit
118+
display.fill(0)
119+
display.show()
120+
sleep_ms(100)
121+
display.power_off()

0 commit comments

Comments
 (0)