Skip to content

Commit f802582

Browse files
committed
feat(wsen-pads): Climate Station example with OLED Display.
1 parent bf8a482 commit f802582

2 files changed

Lines changed: 302 additions & 0 deletions

File tree

lib/hts221/examples/env_station.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
from machine import I2C, SPI, Pin
2+
from time import sleep_ms
3+
import ssd1327
4+
from hts221 import HTS221
5+
6+
# === Ecran ===
7+
spi = SPI(1)
8+
dc = Pin("DATA_COMMAND_DISPLAY")
9+
res = Pin("RST_DISPLAY")
10+
cs = Pin("CS_DISPLAY")
11+
display = ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs)
12+
13+
# === Capteur ===
14+
i2c = I2C(1)
15+
sensor = HTS221(i2c)
16+
17+
# === Calibration ===
18+
print("Calibration en cours...")
19+
temps = []
20+
hums = []
21+
for _ in range(10):
22+
temps.append(sensor.temperature())
23+
hums.append(sensor.humidity())
24+
sleep_ms(200)
25+
26+
OFFSET_TEMP = 20.0 - (sum(temps) / len(temps))
27+
OFFSET_HUM = 50.0 - (sum(hums) / len(hums))
28+
print(f"Offset T: {OFFSET_TEMP:.2f} Offset H: {OFFSET_HUM:.2f}")
29+
print("Calibration OK")
30+
31+
# === Dessin ===
32+
# Zone safe pour ecran rond : carré 90x90 centré => x:[19,109] y:[19,109]
33+
SAFE_X = 19
34+
SAFE_Y = 19
35+
SAFE_W = 90
36+
SAFE_H = 90
37+
38+
def draw_hline(x, y, w, color=255):
39+
for i in range(w):
40+
display.pixel(x + i, y, color)
41+
42+
def draw_vline(x, y, h, color=255):
43+
for i in range(h):
44+
display.pixel(x, y + i, color)
45+
46+
def draw_rect(x, y, w, h, color=255):
47+
draw_hline(x, y, w, color)
48+
draw_hline(x, y + h - 1, w, color)
49+
draw_vline(x, y, h, color)
50+
draw_vline(x + w - 1, y, h, color)
51+
52+
def draw_fill_rect(x, y, w, h, color=255):
53+
for i in range(h):
54+
draw_hline(x, y + i, w, color)
55+
56+
def draw_circle(cx, cy, r, color=255):
57+
x = r
58+
y = 0
59+
err = 0
60+
while x >= y:
61+
display.pixel(cx + x, cy + y, color)
62+
display.pixel(cx + y, cy + x, color)
63+
display.pixel(cx - y, cy + x, color)
64+
display.pixel(cx - x, cy + y, color)
65+
display.pixel(cx - x, cy - y, color)
66+
display.pixel(cx - y, cy - x, color)
67+
display.pixel(cx + y, cy - x, color)
68+
display.pixel(cx + x, cy - y, color)
69+
y += 1
70+
err += 1 + 2 * y
71+
if 2 * (err - x) + 1 > 0:
72+
x -= 1
73+
err += 1 - 2 * x
74+
75+
def draw_bar_h(x, y, w, h, value, min_val, max_val, color=200):
76+
draw_rect(x, y, w, h, 80)
77+
ratio = (value - min_val) / (max_val - min_val)
78+
ratio = max(0.0, min(1.0, ratio))
79+
filled = int((w - 2) * ratio)
80+
if filled > 0:
81+
draw_fill_rect(x + 1, y + 1, filled, h - 2, color)
82+
83+
def comfort_label(temp, hum):
84+
if 18 <= temp <= 26 and 40 <= hum <= 60:
85+
return "OK", 255
86+
elif temp > 30 or hum > 75:
87+
return "CHAUD", 180
88+
elif temp < 15 or hum < 25:
89+
return "FROID", 150
90+
else:
91+
return "BIEN", 200
92+
93+
def draw_screen(temp, hum):
94+
display.fill(0)
95+
96+
# Bordure circulaire decorative
97+
draw_circle(64, 64, 62, 60)
98+
draw_circle(64, 64, 60, 40)
99+
100+
# === TITRE ===
101+
display.text("ENV STATION", 19, 22, 200)
102+
draw_hline(19, 31, 90, 80)
103+
104+
# === TEMPERATURE ===
105+
display.text("TEMP", 19, 37, 120)
106+
temp_str = f"{temp:.1f}C"
107+
display.text(temp_str, 19, 47, 255)
108+
109+
# Barre temperature (0-50C)
110+
draw_bar_h(19, 57, 90, 7, temp, 0, 50, 220)
111+
112+
# === SEPARATEUR ===
113+
draw_hline(19, 67, 90, 70)
114+
115+
# === HUMIDITE ===
116+
display.text("HUM", 19, 72, 120)
117+
hum_str = f"{hum:.1f}%"
118+
display.text(hum_str, 19, 82, 255)
119+
120+
# Barre humidite (0-100%)
121+
draw_bar_h(19, 92, 90, 7, hum, 0, 100, 200)
122+
123+
# === CONFORT ===
124+
label, c_color = comfort_label(temp, hum)
125+
draw_hline(19, 102, 90, 70)
126+
cx = 64 - len(label) * 4
127+
display.text(label, cx, 106, c_color)
128+
129+
display.show()
130+
131+
# === Boucle principale ===
132+
print("Station environnementale demarree")
133+
while True:
134+
try:
135+
temp = sensor.temperature() + OFFSET_TEMP
136+
hum = sensor.humidity() + OFFSET_HUM
137+
hum = max(0.0, min(100.0, hum))
138+
print(f"T:{temp:.2f}C H:{hum:.2f}%")
139+
draw_screen(temp, hum)
140+
except Exception as e:
141+
print("Erreur:", e)
142+
display.fill(0)
143+
display.text("ERREUR", 35, 55, 255)
144+
display.text(str(e)[:16], 0, 70, 150)
145+
display.show()
146+
sleep_ms(1000)
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
from machine import I2C, SPI, Pin
2+
from time import sleep_ms
3+
import ssd1327
4+
from wsen_pads import WSEN_PADS
5+
from hts221 import HTS221
6+
7+
# === Ecran ===
8+
spi = SPI(1)
9+
dc = Pin("DATA_COMMAND_DISPLAY")
10+
res = Pin("RST_DISPLAY")
11+
cs = Pin("CS_DISPLAY")
12+
display = ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs)
13+
14+
# === Capteurs ===
15+
i2c = I2C(1)
16+
pads = WSEN_PADS(i2c) # pression + temperature
17+
hts = HTS221(i2c) # humidite
18+
19+
# === Calibration ===
20+
print("Calibration en cours...")
21+
temps = []
22+
hums = []
23+
press = []
24+
for _ in range(10):
25+
temps.append(pads.temperature())
26+
hums.append(hts.humidity())
27+
press.append(pads.pressure_hpa())
28+
sleep_ms(200)
29+
30+
OFFSET_TEMP = 20.0 - (sum(temps) / len(temps))
31+
OFFSET_HUM = 50.0 - (sum(hums) / len(hums))
32+
OFFSET_PRES = 1013.0 - (sum(press) / len(press))
33+
print(f"Offset T:{OFFSET_TEMP:.2f} H:{OFFSET_HUM:.2f} P:{OFFSET_PRES:.2f}")
34+
print("Calibration OK")
35+
36+
# === Dessin ===
37+
def draw_hline(x, y, w, color=255):
38+
for i in range(w):
39+
display.pixel(x + i, y, color)
40+
41+
def draw_vline(x, y, h, color=255):
42+
for i in range(h):
43+
display.pixel(x, y + i, color)
44+
45+
def draw_rect(x, y, w, h, color=255):
46+
draw_hline(x, y, w, color)
47+
draw_hline(x, y + h - 1, w, color)
48+
draw_vline(x, y, h, color)
49+
draw_vline(x + w - 1, y, h, color)
50+
51+
def draw_fill_rect(x, y, w, h, color=255):
52+
for i in range(h):
53+
draw_hline(x, y + i, w, color)
54+
55+
def draw_circle(cx, cy, r, color=255):
56+
x = r
57+
y = 0
58+
err = 0
59+
while x >= y:
60+
display.pixel(cx + x, cy + y, color)
61+
display.pixel(cx + y, cy + x, color)
62+
display.pixel(cx - y, cy + x, color)
63+
display.pixel(cx - x, cy + y, color)
64+
display.pixel(cx - x, cy - y, color)
65+
display.pixel(cx - y, cy - x, color)
66+
display.pixel(cx + y, cy - x, color)
67+
display.pixel(cx + x, cy - y, color)
68+
y += 1
69+
err += 1 + 2 * y
70+
if 2 * (err - x) + 1 > 0:
71+
x -= 1
72+
err += 1 - 2 * x
73+
74+
def draw_bar_h(x, y, w, h, value, min_val, max_val, color=200):
75+
draw_rect(x, y, w, h, 80)
76+
ratio = (value - min_val) / (max_val - min_val)
77+
ratio = max(0.0, min(1.0, ratio))
78+
filled = int((w - 2) * ratio)
79+
if filled > 0:
80+
draw_fill_rect(x + 1, y + 1, filled, h - 2, color)
81+
82+
def comfort_label(temp, hum, pres):
83+
if 18 <= temp <= 26 and 40 <= hum <= 60 and 1000 <= pres <= 1025:
84+
return "IDEAL", 255
85+
elif temp > 30 or hum > 75:
86+
return "CHAUD", 180
87+
elif temp < 15 or hum < 25:
88+
return "FROID", 150
89+
elif pres < 1000:
90+
return "BASSE P", 150
91+
elif pres > 1025:
92+
return "HAUTE P", 200
93+
else:
94+
return "CORRECT", 200
95+
96+
def draw_screen(temp, hum, pres):
97+
display.fill(0)
98+
99+
# Bordure circulaire decorative
100+
draw_circle(64, 64, 62, 60)
101+
draw_circle(64, 64, 60, 40)
102+
103+
# === TITRE ===
104+
display.text("CLIMAT", 35, 20, 255)
105+
draw_hline(19, 29, 90, 100)
106+
107+
# === TEMPERATURE ===
108+
display.text("T", 19, 35, 120)
109+
temp_str = f"{temp:.1f}C"
110+
display.text(temp_str, 29, 35, 255)
111+
draw_bar_h(19, 44, 90, 5, temp, 0, 50, 220)
112+
113+
# === HUMIDITE ===
114+
display.text("H", 19, 52, 120)
115+
hum_str = f"{hum:.1f}%"
116+
display.text(hum_str, 29, 52, 255)
117+
draw_bar_h(19, 61, 90, 5, hum, 0, 100, 180)
118+
119+
# === PRESSION ===
120+
display.text("P", 19, 69, 120)
121+
pres_str = f"{pres:.0f}hPa"
122+
display.text(pres_str, 29, 69, 255)
123+
draw_bar_h(19, 78, 90, 5, pres, 950, 1050, 160)
124+
125+
# === SEPARATEUR ===
126+
draw_hline(19, 86, 90, 70)
127+
128+
# === CONFORT ===
129+
label, c_color = comfort_label(temp, hum, pres)
130+
cx = 64 - len(label) * 4
131+
display.text(label, cx, 92, c_color)
132+
133+
# === CAPTEURS ===
134+
draw_hline(19, 102, 90, 50)
135+
display.text("PADS+HTS221", 22, 106, 60)
136+
137+
display.show()
138+
139+
# === Boucle principale ===
140+
print("Station climatique demarree")
141+
while True:
142+
try:
143+
temp = pads.temperature() + OFFSET_TEMP
144+
hum = hts.humidity() + OFFSET_HUM
145+
pres = pads.pressure_hpa()+ OFFSET_PRES
146+
hum = max(0.0, min(100.0, hum))
147+
print(f"T:{temp:.2f}C H:{hum:.2f}% P:{pres:.1f}hPa")
148+
draw_screen(temp, hum, pres)
149+
except Exception as e:
150+
print("Erreur:", e)
151+
display.fill(0)
152+
display.text("ERREUR", 35, 55, 255)
153+
display.text(str(e)[:16], 0, 70, 150)
154+
display.show()
155+
sleep_ms(1000)
156+

0 commit comments

Comments
 (0)