generated from jtobinart/Temp
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcydr.py
452 lines (397 loc) · 18.4 KB
/
cydr.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
# CYDc Library
# Tags: Micropython Cheap Yellow Device DIYmall ESP32-2432S028R
# Last Updated: June 14, 2024
# Author(s): James Tobin
# License: MIT
# https://github.com/jtobinart/MicroPython_CYD_ESP32-2432S028R
######################################################
# MIT License
######################################################
'''
Copyright (c) 2023 James Tobin
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
'''
######################################################
# Library Information
######################################################
'''
cydr.py:
v1.3
- Simple WIFI functions added. Users may connect to an existing WIFI netowrk while creating a instance of the CYD
class by assigning values to wifi_ssid and wifi_password (replace None with your WIFI login information:
cyd = CYD(rgb_pmw=False, speaker_gain=512, display_width=240, display_height=320, wifi_ssid = None, wifi_password = None)
or users can connect to a network by calling the cyd.wifi_connect("ssid", "password") after CYD instance has been created.
- Users can also create an Access Point (AP) for other devices to connect to by using cyd.wifi_create_ap("ssid").
- Users can now specify the dimensions of their display while creating an instance of the CYD class by assigning new values
to display_width and display_height.
v1.2
SD card initialization and mounting have been streamed lined and users no longer need to declare that they want to
use the SD card when creating an instance of the CYD class.
v1.1
Double Tap detection implemented. XPT2046 touch switched from SPI to SoftSPI.
v1.0
This is a higher-level library to control DIYmall's ESP32-2432S028R, also known as the Cheap Yellow Display (CYD).
TO DO:
- Implement continuous touch
- Implement DAC pin 26 for the speaker instead of using PWM
- SD card creates a critical error when using keyboard interrupt
- Implement easy Bluetooth functions
'''
######################################################
# Pin Reference
######################################################
"""
Pins
0 Digital Boot Button
1 Digital Connector P1 - TX
2 Digital Display - TFT_RS / TFT_DC
3 Digital Connector P1 - RX
4 Digital RGB LED - Red
5 Digital SD Card - SS [VSPI]
6 Digital Unpopulated Pad U4: pin 6 - SCK / CLK
7 Digital Unpopulated Pad U4: pin 2 - SDO / SD0
8 Digital Unpopulated Pad U4: pin 5 - SDI / SD1
9 Digital Unpopulated Pad U4: pin 7 - SHD / SD2
10 Digital Unpopulated Pad U4: pin 3 - SWP / SD3
11 Digital Unpopulated Pad U4: pin 1 - SCS / CMD
12 Digital Display - TFT_SDO / TFT_MISO [HSPI]
13 Digital Display - TFT_SDI / TFT_MOSI [HSPI]
14 Digital Display - TFT_SCK [HSPI]
15 Digital Display - TFT_CS [HSPI]
16 Digital RGB LED - Green
17 Digital RGB LED - Blue
18 Digital SD Card - SCK [VSPI]
19 Digital SD Card - MISO [VSPI]
21 Digital Display & Connector P3 - TFT_BL (BackLight) / I2C SDA
22 Digital Connector P3 & CN1 - I2C SCL
23 Digital SD Card - MOSI [VSPI]
25 Digital Touch XPT2046 - CLK [Software SPI]
26 Analog Speaker - !!!Speaker ONLY! Connected to Amp!!!
27 Digital Connector CN1 - Can be used as a capacitive touch sensor pin.
32 Digital Touch XPT2046 - MOSI [Software SPI]
33 Digital Touch XPT2046 - CS [Software SPI]
34 Analog LDR Light Sensor - !!!Input ONLY!!!
35 Digital P3 Connector - !!!Input ONLY w/ NO pull-ups!!!
36 Digital Touch XPT2046 - IRQ !!!Input ONLY!!!
39 Digital Touch XPT2046 - MISO !!!Input ONLY!!! [Software SPI]
"""
######################################################
# Import
######################################################
from ili9341 import Display, color565
from xpt2046 import Touch
from machine import Pin, SPI, ADC, PWM, SDCard, SoftSPI
import network
import os
import time
class CYD(object):
######################################################
# Color Variables
######################################################
BLACK = color565( 0, 0, 0)
RED = color565(255, 0, 0)
GREEN = color565( 0, 255, 0)
CYAN = color565( 0, 255, 255)
BLUE = color565( 0, 0, 255)
PURPLE = color565(255, 0, 255)
WHITE = color565(255, 255, 255)
######################################################
# Function List
######################################################
'''
cyd = CYD(rgb_pmw=False, speaker_gain=512, display_width=240, display_height=320, wifi_ssid = None, wifi_password = None) # Initialize CYD class
cyd.display.ili9341_function_name() # Use to access ili9341 functions.
cyd._touch_handler(x, y) # Called when a touch occurs. (INTERNAL USE ONLY)
cyd.touches() # GETS the last touch coordinates.
cyd.double_tap(x, y, error_margin = 5) # Check for double taps.
cyd.rgb(color) # SETS rgb LED color.
cyd._remap(value, in_min, in_max, out_min, out_max) # Converts a value form one scale to another. (INTERNAL USE ONLY)
cyd.light() # GETS the current light sensor value.
cyd.button_boot() # GETS the current boot button value.
cyd.backlight(value) # SETS backlight brightness.
cyd.play_tone(freq, duration, gain=0) # Plays a tone for a given duration.
cyd.mount_sd() # Mounts SD card
cyd.unmount_sd() # Unmounts SD card.
cyd.wifi_connect(ssid, password) # Connects to a WLAN network.
cyd.wifi_isconnected() # Checks to see that the wifi connection is connected.
cyd.wifi_ip() # Get the CYD's IPv4 address on your WLAN.
cyd.wifi_create_ap(_ssid) # Creates an Access Point (AP) WLAN network.
cyd.shutdown() # Safely shutdown CYD device.
'''
def __init__(self, rgb_pmw=False, speaker_gain=512, display_width=240, display_height=320, wifi_ssid = None, wifi_password = None):
'''
Initialize CDYc
Args:
rgb_pmw (Default = False): Sets RGB LED to static mode. (on/off), if false
Sets RGB LED to dynamic mode. (16.5+ million color combination), if true
Warning: RGB LED never completely turns off in dynamic mode.
speaker_gain (Default = 512): Sets speaker's volume. The full gain range is 0 - 1023.
display_width (Default = 240): Reset if needed.
display_height (Default = 320): Reset if needed.
'''
# Display
hspi = SPI(1, baudrate=40000000, sck=Pin(14), mosi=Pin(13))
self.display = Display(hspi, dc=Pin(2), cs=Pin(15), rst=Pin(0), width=display_width, height=display_height)
self._x = 0
self._y = 0
# Backlight
self.tft_bl = Pin(21, Pin.OUT)
self.tft_bl.value(1) #Turn on backlight
# Touch
self.last_tap = (-1,-1)
sspi = SoftSPI(baudrate=500000, sck=Pin(25), mosi=Pin(32), miso=Pin(39))
self._touch = Touch(sspi, cs=Pin(33), int_pin=Pin(36), int_handler=self._touch_handler)
# Boot Button
self._button_boot = Pin(0, Pin.IN)
# LDR: Light Sensor (Measures Darkness)
self._ldr = ADC(34)
# RGB LED
self._rgb_pmw = rgb_pmw
if self._rgb_pmw == False:
self.RGBr = Pin(4, Pin.OUT, value=1) # Red
self.RGBg = Pin(16, Pin.OUT, value=1) # Green
self.RGBb = Pin(17, Pin.OUT, value=1) # Blue
else:
self.RGBr = PWM(Pin(4), freq=200, duty=1023) # Red
self.RGBg = PWM(Pin(16), freq=200, duty=1023) # Green
self.RGBb = PWM(Pin(17), freq=200, duty=1023) # Blue
print("RGB PMW Ready")
# Speaker
self._speaker_pin = Pin(26, Pin.OUT)
self.speaker_gain = int(min(max(speaker_gain, 0),1023)) # Min 0, Max 1023
self.speaker_pwm = PWM(self._speaker_pin, freq=440, duty=0)
# SD Card
# The user needs to run mount_sd() to access SD card.
self._sd_ready = False
self._sd_mounted = False
# WIFI
if wifi_ssid is not None:
print("Connecting to wifi...")
self.wifi_connect(wifi_ssid, wifi_password) # connect to WLAN Network
print("CYD ready...")
######################################################
# Touchscreen Press Event
######################################################
def _touch_handler(self, x, y):
'''
Interrupt Handler
This function is called each time the screen is touched.
'''
# X needs to be flipped
x = (self.display.width - 1) - x
self._x = x
self._y = y
#print("Touch:", x, y)
def touches(self):
'''
Returns last stored touch data.
Return:
x: x coordinate of finger 1
y: y coordinate of finger 1
'''
x = self._x
y = self._y
self._x = 0
self._y = 0
return x, y
def double_tap(self, x, y, error_margin = 10):
'''
Returns whether or not a double tap was detected.
Return:
True: Double-tap detected.
False: Single tap detected.
'''
# Double tap to exit
if self.last_tap[0] - error_margin <= x and self.last_tap[0] + error_margin >= x:
if self.last_tap[1] - error_margin <= y and self.last_tap[1] + error_margin >= y:
self.last_tap = (-1,-1)
return True
self.last_tap = (x,y)
return False
######################################################
# RGB LED
######################################################
def rgb(self, color):
'''
Set RGB LED color.
Args:
color: Array containing three int values (r,g,b).
if rgb_pmw == False, then static mode is activated.
r (0 or 1): Red brightness.
g (0 or 1): Green brightness.
b (0 or 1): Blue brightness.
if rgb_pmw == True, then dynamic mode is activated.
r (0-255): Red brightness.
g (0-255): Green brightness.
b (0-255): Blue brightness.
'''
r, g, b = color
if self._rgb_pmw == False:
self.RGBr.value(1 if min(max(r, 0),1) == 0 else 0)
self.RGBg.value(1 if min(max(g, 0),1) == 0 else 0)
self.RGBb.value(1 if min(max(b, 0),1) == 0 else 0)
else:
self.RGBr.duty(int(min(max(self._remap(r,0,255,1023,0), 0),1023)))
self.RGBg.duty(int(min(max(self._remap(g,0,255,1023,0), 0),1023)))
self.RGBb.duty(int(min(max(self._remap(b,0,255,1023,0), 0),1023)))
def _remap(self, value, in_min, in_max, out_min, out_max):
'''
Internal function for remapping values from one scale to a second.
'''
in_span = in_max - in_min
out_span = out_max - out_min
scale = out_span / in_span
return out_min + (value - in_min) * scale
######################################################
# Light Sensor
######################################################
def light(self):
'''
Light Sensor (Measures darkness)
Return: a value from 0.0 to 1.0
'''
return self._ldr.read_u16()/65535
######################################################
# Button
######################################################
def button_boot(self):
'''
Gets the Boot button's current state
'''
return self._button_boot.value
######################################################
# Backlight
######################################################
def backlight(self, val):
'''
Sets TFT Backlight Off/On
Arg:
val: 0 or 1 (0 = off/ 1 = on)
'''
self.tft_bl.value(min(max(val, 0),1))
######################################################
# Speaker
######################################################
def play_tone(self, freq, duration, gain=0):
'''
Plays a tone (Optional speaker must be attached!)
Args:
freq: Frequency of the tone.
duration: How long does the tone play for.
gain: volume
'''
self.speaker_pwm.freq(freq)
if gain == 0:
gain = self.speaker_gain
self.speaker_pwm.duty(gain) # Turn on speaker by resetting speaker gain
time.sleep_ms(duration)
self.speaker_pwm.duty(0) # Turn off speaker by resetting gain to zero
######################################################
# SD Card
######################################################
def mount_sd(self):
'''
Mounts SD Card
'''
try:
if self._sd_ready == False:
self.sd = SDCard(slot=2)
self._sd_ready = True
if self._sd_ready == True:
os.mount(self.sd, '/sd') # mount
self._sd_mounted = True
print("SD card mounted. Do not remove!")
except:
print("Failed to mount SD card")
def unmount_sd(self):
'''
Unmounts SD Card
'''
try:
if self._sd_mounted == True:
os.unmount('/sd') # mount
self._sd_mounted = False
print("SD card unmounted. Safe to remove SD card!")
except:
print("Failed to unmount SD card")
######################################################
# Wifi
######################################################
def wifi_connect(self, ssid, password):
'''
Connects to a WLAN network.
The CYD (client) can connect to an existing WLAN network (station).
Args:
ssid: The name of the network you want to connect to.
password: The network password for the ssid you are connecting to.
'''
self.wifi = network.WLAN(network.STA_IF) # Creates a station interface
self.wifi.active(True)
self.wifi.config(reconnects=3) # Sets timeout count
print('connecting to network...')
self.wifi.connect(ssid, password) # Connects to an existing network
while not self.wifi.isconnected():
pass
print('network config:', self.wifi_ip()) # Get the interface's IPv4 addresses
def wifi_isconnected(self):
'''
Checks to see that the wifi connection is connected.
Returns:
True: Device connected to a network.
False: Device not connected to a network.
'''
return self.wifi.isconnected()
def wifi_ip(self):
'''
Get the CYD's IPv4 address on your WLAN.
Returns: The IP address of your device.
'''
ip, _, _, _ = self.wifi.ifconfig()
return ip
def wifi_create_ap(self, _ssid):
'''
Creates an Access Point (AP) WLAN network.
Other devices (clients) can connect to this CYD (station) via wifi.
Args:
_ssid: The name of your new AP. This is the wifi id that client devices are going to connect to.
'''
self.wifi_ap = network.WLAN(network.AP_IF) # Create AP interface
self.wifi_ap.config(ssid=_ssid) # Set the SSID of your AP
self.wifi_ap.config(max_clients=10) # Set how many devices can connect to your AP network
self.wifi_ap.active(True) # Activate the AP interface
print('network config:', self.wifi_ip()) # Get your device's IPv4 address
######################################################
# Shutdown
######################################################
def shutdown(self):
'''
Resets CYD and properly shuts down.
'''
self.display.fill_rectangle(0, 0, self.display.width-1, self.display.height-1, self.BLACK)
self.display.draw_rectangle(2, 2, self.display.width-5, self.display.height-5, self.RED)
self.display.draw_text8x8(self.display.width // 2 - 52, self.display.height // 2 - 4, "Shutting Down", self.WHITE, background=self.BLACK)
time.sleep(2.0)
self.unmount_sd()
self.speaker_pwm.deinit()
if self._rgb_pmw == False:
self.RGBr.value(1)
self.RGBg.value(1)
self.RGBb.value(1)
else:
self.rgb(0,0,0)
self.tft_bl.value(0)
self.display.cleanup()
print("========== Goodbye ==========")