7
7
from machine import Pin , SPI , I2C , freq
8
8
from utime import ticks_ms , ticks_diff
9
9
import uasyncio as asyncio
10
- import micropython
10
+ from micropython import const , mem_info
11
11
import gc
12
12
13
- from aswitch import Switch , Delay_ms
13
+ from primitives .switch import Switch
14
+ from primitives .delay_ms import Delay_ms
14
15
from ssd1351_16bit import SSD1351 as SSD # STM Asm version
15
16
from writer import CWriter
16
17
import courier17 as font # Main text
20
21
from interpolate_a import Interpolator # STM assembler version
21
22
22
23
freq (216_000_000 ) # In old version improved update rate 750ms -> 488ms
23
- loop = asyncio .get_event_loop ()
24
24
25
25
eliza = lambda * _ : None
26
26
27
+ # Possible modes. Note there is no point in having a _HOLD mode as the text
28
+ # fields are not updated so it would never show.
29
+ _NORM = const (0 )
30
+ _AUTO = const (1 )
31
+ _HOG = const (2 )
32
+
27
33
class Cam :
28
34
29
35
def __init__ (self , txt_rf_ms , verbose ):
36
+ self .txt_rf_ms = txt_rf_ms
30
37
self .verbose = verbose
31
38
self .tmax = 30 # Initial temperature range
32
39
self .tmin = 15
33
- self .auto_range = False
40
+ self .mode = _NORM
34
41
# Enable initial update
35
42
self .rf_disp = True
36
43
self .rf_txt = True
@@ -40,13 +47,13 @@ def __init__(self, txt_rf_ms, verbose):
40
47
41
48
# Instantiate switches
42
49
self .timer = Delay_ms (duration = 2000 ) # Long press delay
43
- # Release arg rarg is for future use. Enables calling switch to be identified.
50
+ # Release arg rarg enables calling switch to be identified.
44
51
for item in (('X4' , self .chmax , 5 , self .ar , 0 ), ('Y1' , self .chmax , - 5 , self .ar , 1 ),
45
52
('X5' , self .chmin , 5 , eliza , 2 ), ('X6' , self .chmin , - 5 , eliza , 3 )):
46
- sw , func , arg , rfunc , rarg = item
53
+ sw , func , arg , long_func , rarg = item
47
54
cs = Switch (Pin (sw , Pin .IN , Pin .PULL_UP ))
48
55
cs .close_func (self .press , (func , arg ))
49
- cs .open_func (self .release , (rfunc , rarg ))
56
+ cs .open_func (self .release , (long_func , rarg ))
50
57
51
58
# Instantiate display
52
59
pdc = Pin ('X1' , Pin .OUT_PP , value = 0 )
@@ -60,20 +67,20 @@ def __init__(self, txt_rf_ms, verbose):
60
67
ssd .fill (0 )
61
68
ssd .show ()
62
69
70
+ self .avg = 0.0
63
71
# Instantiate PIR temperature sensor
64
72
i2c = I2C (2 )
65
73
pir = AMG88XX (i2c )
66
74
pir .ma_mode (True ) # Moving average mode
67
75
68
76
# Run the camera
69
- loop .create_task (self .run (pir , ssd ))
70
- loop .create_task (self .refresh_txt (txt_rf_ms ))
77
+ asyncio .create_task (self .run (pir , ssd ))
71
78
72
79
# A switch was pressed. Change temperature range.
73
80
def press (self , func , arg ):
74
81
self .timer .trigger ()
75
- if self .auto_range : # Short press clears auto range
76
- self .auto_range = False # Leave range unchanged
82
+ self .mode = _NORM
83
+ if self .mode == _AUTO : # Short press clears auto range, leaves range unchanged
77
84
self .rf_disp = True
78
85
self .rf_txt = True
79
86
else :
@@ -92,13 +99,18 @@ def chmin(self, val):
92
99
93
100
def release (self , func , arg ):
94
101
if self .timer .running (): # Brief press: re-enable display
95
- self .rf_disp = True
96
102
self .rf_txt = True # Show changed range
103
+ self .rf_disp = True
97
104
else :
98
- func (arg )
99
-
100
- def ar (self , _ ):
101
- self .auto_range = True
105
+ func (arg ) # eliza will leave it with rf_disp False
106
+
107
+ def ar (self , sw ): # Long press callback, top switch
108
+ if sw : # Animal detection mode
109
+ self .mode = _HOG
110
+ self .tmin = self .avg
111
+ self .tmax = self .avg + 5
112
+ else : # Auto range
113
+ self .mode = _AUTO
102
114
self .rf_disp = True
103
115
self .rf_txt = True # Show changed range
104
116
@@ -112,9 +124,9 @@ def draw_scale(self, ssd):
112
124
val -= dt
113
125
114
126
# Refreshing text is slow so do it periodically to maximise mean image framerate
115
- async def refresh_txt (self , tim ):
127
+ async def refresh_txt (self ):
116
128
while True :
117
- await asyncio .sleep_ms (tim )
129
+ await asyncio .sleep_ms (self . txt_rf_ms )
118
130
self .rf_txt = True
119
131
120
132
# Run the camera
@@ -151,15 +163,16 @@ async def run(self, pir, ssd):
151
163
sum_t += val
152
164
ssd .rect (col * 2 , row * 2 , 2 , 2 , ssd .rgb (* self .mapper (val )))
153
165
await asyncio .sleep (0 )
154
- if self .auto_range :
166
+ self .avg = round (sum_t / 1024 )
167
+ if self .mode == _AUTO :
155
168
self .tmin = round (min_t )
156
169
self .tmax = round (max_t )
157
170
if self .rf_disp :
158
171
if self .rf_txt :
159
172
wri_l .set_textpos (ssd , 66 , 0 )
160
173
wri_l .printstring ('Max:{:+4d}C\n ' .format (int (max_t )))
161
174
wri_l .printstring ('Min:{:+4d}C\n ' .format (int (min_t )))
162
- wri_l .printstring ('Avg:{:+4d}C' .format (round ( sum_t / 1024 ) ))
175
+ wri_l .printstring ('Avg:{:+4d}C' .format (self . avg ))
163
176
wri_s .set_textpos (ssd , 128 - arial10 .height (), 64 )
164
177
wri_s .setcolor (yellow , black )
165
178
wri_s .printstring ('Chip:{:5.1f}C' .format (pir .temperature ()))
@@ -168,19 +181,24 @@ async def run(self, pir, ssd):
168
181
wri_s .printstring ('{:4d}C ' .format (self .tmax ))
169
182
wri_s .set_textpos (ssd , 28 , 95 )
170
183
wri_s .setcolor (green , black )
171
- wri_s .printstring ('AR:{:s}' .format ('on ' if self .auto_range else 'off' ))
184
+ if self .mode == _HOG :
185
+ wri_s .printstring ('Hog ' )
186
+ elif self .mode == _NORM :
187
+ wri_s .printstring ('Norm ' )
188
+ else :
189
+ wri_s .printstring ('Auto ' )
172
190
wri_s .set_textpos (ssd , 64 - arial10 .height (), 90 )
173
191
wri_s .setcolor (blue , black )
174
192
wri_s .printstring ('{:4d}C ' .format (self .tmin ))
175
193
self .rf_txt = False
176
194
ssd .show ()
177
195
self .verbose and print (ticks_diff (ticks_ms (), t ))
178
196
gc .collect ()
179
- # self.verbose and micropython. mem_info()
197
+ # self.verbose and mem_info()
180
198
181
199
# stack: 1276 out of 15360
182
200
# GC: total: 196672, used: 52128, free: 144544
183
201
# No. of 1-blocks: 365, 2-blocks: 106, max blk sz: 1024, max free sz: 2545
184
202
185
203
cam = Cam (2000 , False ) # Refresh text every 2000ms. Verbose?
186
- loop . run_forever ( )
204
+ asyncio . run ( cam . refresh_txt () )
0 commit comments