014 - MicroPython TechNotes: 8x8 Dot Matrix Display (I2C)
Introduction
In this article, we will learn on how to use the 8×8 Dot Matrix display with an I2C communication interface using the MicroPython language.
Bill Of Materials
- ESP32 development board.
- Gorillacell ESP32 shield.
- 4-pin female-female dupont jumper wires.
- 8×8 Dot Matrix display (I2C)
Pinout
- GND – for the ground pin.
- VCC – for the supply voltage.
- SDA – for the I2C serial data pin.
- SCL – for the I2C serial clock pin.
Hardware Instruction
- Attach the ESP32 dev board on top of the ESP32 shield and make sure that both USB port are on the same side.
- Attach the dupont wire on the 8×8 Dot Matrix display by following the color coding which is black for the GND, red for the VCC, yellow for the SDA, and white for the SCL pin.
- Attach the other side of the dupont to the ESP32 shield by matching the colors of the wires to the colors of the pin headers that is black to black, red to red, and yellow and the following colors to yellow pin headers.
- Power the ESP32 shield by attaching an external power supply with a USB type-C connector and make sure that the power switch is slide to the ON state.
- Connect the ESP32 to the computer through a micro USB cable. Our demo circuit should now be ready.
Software Instruction
- Go to the source of the driver library from the Github of Tony Smith: https://github.com/smittytone/HT16K33-Python or you may copy it provided below on the SOURCE CODE section of this blog post.
- Save one by one the ht16k33.py and the ht16k33Matrix.py to the MicroPython device root directory.
By clicking the File menu and select Save As. - Select MicroPython device and name it as ht16k33.py and ht16k33Matrix accordingly.
- Enjoy playing with the examples and try to modify it to enhance the learning.
Video Demonstration
Call To Action
For any concern, write your message in the comment section.
You might also like to support my journey on Youtube by Subscribing. Click this to Subscribe to TechToTinker.
Thank you and have a good days ahead.
See you,
– George Bantique | tech.to.tinker@gmail.com
Source Code
1. Example # 1, exploring the basics:
1# More details can be found in TechToTinker.blogspot.com
2# George Bantique | tech.to.tinker@gmail.com
3
4from machine import I2C, Pin, RTC
5from ht16k33matrix import HT16K33Matrix
6from time import sleep
7
8i2c = I2C(scl=Pin(22), sda=Pin(21))
9display = HT16K33Matrix(i2c)
10display.set_brightness(10)
11display.set_angle(270) # properly set the orientation of the display
12
13# # The following lines of code should be tested using the REPL:
14# # 1. To display a text:
15# display.set_character(ord('A'), True).draw()
16#
17# # 2. To display all characters:
18# for char in range(32, 128, 1):
19# display.clear().draw()
20# display.set_character(char, True).draw()
21# sleep(0.5)
22#
23# # 3. To display a scrolling text:
24# display.clear().draw()
25# text = " abcdefghijklmnopqrstuvwxyz 0123456789!$%&*() x00x01 "
26# display.scroll_text(text)
27#
28# # 4. Draw a custom icon on the LED
29# icon = b"x3Cx42xA9x85x85xA9x42x3C"
30# display.set_icon(icon).draw()
31# # Rotate the icon
32# display.set_angle(0).draw()
33#
34# # 5. Clear the LED
35# display.clear().draw()
36#
37# # 6. Record two custom icons using 'define_character()'
38# icon = b"x0Ex18xBEx6Dx3Dx3C"
39# display.define_character(icon, 0)
40# icon = b"x3Cx3Dx6DxBEx18x0E"
41# display.define_character(icon, 1)
42# # Show the previously stored custom icon then Blink the LED
43# display.set_character(0, True).draw()
44# display.set_blink_rate(1)
45#
46# # 7. Inverse the pixel
47# display.set_inverse().draw()
48# # Inverse the pixels (to revert)
49# display.set_inverse().draw()
50#
51# # 8. Clear and stop blinking
52# display.clear().draw()
53# display.set_blink_rate(0)
54#
55# # 9. Plot an X
56# for i in range(4):
57# display.plot(i, i).plot(7 - i, i).plot(i, 7 - i).plot(7 - i, 7 - i)
58# display.draw()
59# time.sleep(PAUSE)
60# assert (display.is_set(0, 0) is True) and (display.is_set(0, 1) is False)
61# display.clear().draw()
62#
63# # 10. Show an animation
64# while True:
65# x = 7
66# y = 0;
67# dx = 0
68# dy = 1;
69# mx = 6
70# my = 7;
71# nx = 0
72# ny = 0;
73#
74# for i in range(0,64):
75# display.plot(x, y).draw();
76#
77# if dx == 1 and x == mx:
78# dy = 1;
79# dx = 0;
80# mx -= 1;
81# elif dx == -1 and x == nx:
82# nx += 1;
83# dy = -1;
84# dx = 0;
85# elif dy == 1 and y == my:
86# dy = 0;
87# dx = -1;
88# my -= 1;
89# elif dy == -1 and y == ny:
90# dx = 1;
91# dy = 0;
92# ny += 1;
93#
94# x += dx;
95# y += dy
96#
97# sleep(0.01)
98#
99# x = 4
100# y = 3
101# dx = -1
102# dy = 0
103# mx = 5
104# my = 4
105# nx = 3
106# ny = 2
107#
108# for i in range(0, 64):
109# display.plot(x, y, 0).draw()
110#
111# if dx == 1 and x == mx:
112# dy = -1;
113# dx = 0;
114# mx += 1;
115# elif dx == -1 and x == nx:
116# nx -= 1;
117# dy = 1;
118# dx = 0;
119# elif dy == 1 and y == my:
120# dy = 0;
121# dx = 1;
122# my += 1;
123# elif dy == -1 and y == ny:
124# dx = -1;
125# dy = 0;
126# ny -= 1;
127#
128# x += dx;
129# y += dy
130#
131# sleep(0.01)
2. Example # 2, binary clock example:
1# More details can be found in TechToTinker.blogspot.com
2# George Bantique | tech.to.tinker@gmail.com
3
4from machine import I2C, Pin, RTC
5from ht16k33matrix import HT16K33Matrix
6from time import sleep
7
8i2c = I2C(scl=Pin(22), sda=Pin(21))
9display = HT16K33Matrix(i2c)
10display.set_brightness(10)
11display.set_angle(90) # properly set the orientation of the display
12display.clear().draw()
13
14rtc = RTC()
15rtc.datetime((2021, 2, 24, 3, 20, 25, 0, 0))
16# rtc.datetime((YYYY, MM, DD, WD, HH, MM, SS, MS))
17# WD 1 = Monday
18# WD 7 = Sunday
19
20def display_binary(decimal, column):
21 # converts decimal number into 8-bit binary
22 binary_str = '{0:8b}'.format(decimal)
23 #print(binary_str)
24 for row in range(0, 8):
25 if binary_str[row] == '1':
26 display.plot(column, row, 1)
27 else:
28 display.plot(column, row, 0)
29
30while True:
31 t = rtc.datetime()
32 #display_binary(decimal value, dot matrix column)
33 display_binary(t[0] % 100, 7) # year
34 display_binary(t[1], 6) # month
35 display_binary(t[2], 5) # day
36 display_binary(t[4], 3) # hour
37 display_binary(t[5], 2) # minutes
38 display_binary(t[6], 1) # seconds
39 display_binary(t[7] // 10000, 0) # subseconds
40 display.draw() # update the dot matrix display
41 sleep(0.0001) # 100ms wait
3. ht16k33.py base driver library:
1# MIT License
2#
3# Copyright (c) 2020 Tony Smith (@smittytone)
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
22class HT16K33:
23 """
24 A simple, generic driver for the I2C-connected Holtek HT16K33 controller chip.
25 This release supports MicroPython and CircuitPython
26 Version: 3.0.2
27 Bus: I2C
28 Author: Tony Smith (@smittytone)
29 License: MIT
30 Copyright: 2020
31 """
32
33 # *********** CONSTANTS **********
34
35 HT16K33_GENERIC_DISPLAY_ON = 0x81
36 HT16K33_GENERIC_DISPLAY_OFF = 0x80
37 HT16K33_GENERIC_SYSTEM_ON = 0x21
38 HT16K33_GENERIC_SYSTEM_OFF = 0x20
39 HT16K33_GENERIC_DISPLAY_ADDRESS = 0x00
40 HT16K33_GENERIC_CMD_BRIGHTNESS = 0xE0
41 HT16K33_GENERIC_CMD_BLINK = 0x81
42
43 # *********** PRIVATE PROPERTIES **********
44
45 i2c = None
46 address = 0
47 brightness = 15
48 flash_rate = 0
49
50 # *********** CONSTRUCTOR **********
51
52 def __init__(self, i2c, i2c_address):
53 assert 0x00 <= i2c_address < 0x80, "ERROR - Invalid I2C address in HT16K33()"
54 self.i2c = i2c
55 self.address = i2c_address
56 self.power_on()
57
58 # *********** PUBLIC METHODS **********
59
60 def set_blink_rate(self, rate=0):
61 """
62 Set the display's flash rate.
63 Only four values (in Hz) are permitted: 0, 2, 1, and 0,5.
64 Args:
65 rate (int): The chosen flash rate. Default: 0Hz (no flash).
66 """
67 assert rate in (0, 0.5, 1, 2), "ERROR - Invalid blink rate set in set_blink_rate()"
68 self.blink_rate = rate & 0x03
69 self._write_cmd(self.HT16K33_GENERIC_CMD_BLINK | rate << 1)
70
71 def set_brightness(self, brightness=15):
72 """
73 Set the display's brightness (ie. duty cycle).
74 Brightness values range from 0 (dim, but not off) to 15 (max. brightness).
75 Args:
76 brightness (int): The chosen flash rate. Default: 15 (100%).
77 """
78 if brightness < 0 or brightness > 15: brightness = 15
79 self.brightness = brightness
80 self._write_cmd(self.HT16K33_GENERIC_CMD_BRIGHTNESS | brightness)
81
82 def draw(self):
83 """
84 Writes the current display buffer to the display itself.
85 Call this method after updating the buffer to update
86 the LED itself.
87 """
88 self._render()
89
90 def update(self):
91 """
92 Alternative for draw() for backwards compatibility
93 """
94 self._render()
95
96 def clear(self):
97 """
98 Clear the buffer.
99 Returns:
100 The instance (self)
101 """
102 for i in range(0, len(self.buffer)): self.buffer[i] = 0x00
103 return self
104
105 def power_on(self):
106 """
107 Power on the controller and display.
108 """
109 self._write_cmd(self.HT16K33_GENERIC_SYSTEM_ON)
110 self._write_cmd(self.HT16K33_GENERIC_DISPLAY_ON)
111
112 def power_off(self):
113 """
114 Power on the controller and display.
115 """
116 self._write_cmd(self.HT16K33_GENERIC_DISPLAY_OFF)
117 self._write_cmd(self.HT16K33_GENERIC_SYSTEM_OFF)
118
119 # ********** PRIVATE METHODS **********
120
121 def _render(self):
122 """
123 Write the display buffer out to I2C
124 """
125 buffer = bytearray(len(self.buffer) + 1)
126 buffer[1:] = self.buffer
127 buffer[0] = 0x00
128 self.i2c.writeto(self.address, bytes(buffer))
129
130 def _write_cmd(self, byte):
131 """
132 Writes a single command to the HT16K33. A private method.
133 """
134 self.i2c.writeto(self.address, bytes([byte]))
4. ht16k33Matrix.py driver library class for the Dot Matrix Display:
1# MIT License
2#
3# Copyright (c) 2020 Tony Smith (@smittytone)
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in all
13# copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21# SOFTWARE.
22from ht16k33 import HT16K33
23
24class HT16K33Matrix(HT16K33):
25 """
26 Micro/Circuit Python class for the Adafruit 8x8 monochrome LED matrix
27 backpack.
28 Version: 3.0.2
29 Bus: I2C
30 Author: Tony Smith (@smittytone)
31 License: MIT
32 Copyright: 2020
33 """
34
35 # *********** CONSTANTS **********
36
37 CHARSET = [
38 b"x00x00", # space - Ascii 32
39 b"xfa", # !
40 b"xc0x00xc0", # "
41 b"x24x7ex24x7ex24", # #
42 b"x24xd4x56x48", # $
43 b"xc6xc8x10x26xc6", # %
44 b"x6cx92x6ax04x0a", # &
45 b"xc0", # '
46 b"x7cx82", # (
47 b"x82x7c", # )
48 b"x10x7cx38x7cx10", # *
49 b"x10x10x7cx10x10", # +
50 b"x06x07", # ,
51 b"x10x10x10x10", # -
52 b"x06x06", # .
53 b"x04x08x10x20x40", # /
54 b"x7cx8ax92xa2x7c", # 0 - Ascii 48
55 b"x42xfex02", # 1
56 b"x46x8ax92x92x62", # 2
57 b"x44x92x92x92x6c", # 3
58 b"x18x28x48xfex08", # 4
59 b"xf4x92x92x92x8c", # 5
60 b"x3cx52x92x92x8c", # 6
61 b"x80x8ex90xa0xc0", # 7
62 b"x6cx92x92x92x6c", # 8
63 b"x60x92x92x94x78", # 9
64 b"x36x36", # : - Ascii 58
65 b"x36x37", #
66 b"x10x28x44x82", # <
67 b"x24x24x24x24x24", # =
68 b"x82x44x28x10", # >
69 b"x60x80x9ax90x60", # ?
70 b"x7cx82xbaxaax78", # @
71 b"x7ex90x90x90x7e", # A - Ascii 65
72 b"xfex92x92x92x6c", # B
73 b"x7cx82x82x82x44", # C
74 b"xfex82x82x82x7c", # D
75 b"xfex92x92x92x82", # E
76 b"xfex90x90x90x80", # F
77 b"x7cx82x92x92x5c", # G
78 b"xfex10x10x10xfe", # H
79 b"x82xfex82", # I
80 b"x0cx02x02x02xfc", # J
81 b"xfex10x28x44x82", # K
82 b"xfex02x02x02", # L
83 b"xfex40x20x40xfe", # M
84 b"xfex40x20x10xfe", # N
85 b"x7cx82x82x82x7c", # O
86 b"xfex90x90x90x60", # P
87 b"x7cx82x92x8cx7a", # Q
88 b"xfex90x90x98x66", # R
89 b"x64x92x92x92x4c", # S
90 b"x80x80xfex80x80", # T
91 b"xfcx02x02x02xfc", # U
92 b"xf8x04x02x04xf8", # V
93 b"xfcx02x3cx02xfc", # W
94 b"xc6x28x10x28xc6", # X
95 b"xe0x10x0ex10xe0", # Y
96 b"x86x8ax92xa2xc2", # Z - Ascii 90
97 b"xfex82x82", # [
98 b"x40x20x10x08x04", #
99 b"x82x82xfe", # ]
100 b"x20x40x80x40x20", # ^
101 b"x02x02x02x02x02", # _
102 b"xc0xe0", # '
103 b"x04x2ax2ax1e", # a - Ascii 97
104 b"xfex22x22x1c", # b
105 b"x1cx22x22x22", # c
106 b"x1cx22x22xfc", # d
107 b"x1cx2ax2ax10", # e
108 b"x10x7ex90x80", # f
109 b"x18x25x25x3e", # g
110 b"xfex20x20x1e", # h
111 b"xbcx02", # i
112 b"x02x01x21xbe", # j
113 b"xfex08x14x22", # k
114 b"xfcx02", # l
115 b"x3ex20x18x20x1e", # m
116 b"x3ex20x20 x1e", # n
117 b"x1cx22x22x1c", # o
118 b"x3fx22x22x1c", # p
119 b"x1cx22x22x3f", # q
120 b"x22x1ex20x10", # r
121 b"x12x2ax2ax04", # s
122 b"x20x7cx22x04", # t
123 b"x3cx02x02x3e", # u
124 b"x38x04x02x04x38", # v
125 b"x3cx06x0cx06x3c", # w
126 b"x22x14x08x14x22", # x
127 b"x39x05x06x3c", # y
128 b"x26x2ax2ax32", # z - Ascii 122
129 b"x10x7cx82x82", #
130 b"xee", # |
131 b"x82x82x7cx10", #
132 b"x40x80x40x80", # ~
133 b"x60x90x90x60" # Degrees sign - Ascii 127
134 ]
135
136 # ********** PRIVATE PROPERTIES **********
137
138 width = 8
139 height = 8
140 def_chars = None
141 rotation_angle = 0
142 is_rotated = False
143 is_inverse = False
144
145 # *********** CONSTRUCTOR **********
146
147 def __init__(self, i2c, i2c_address=0x70):
148 self.buffer = bytearray(self.width)
149 self.def_chars = []
150 for i in range(32): self.def_chars.append(b"x00")
151 super(HT16K33Matrix, self).__init__(i2c, i2c_address)
152
153 # *********** PUBLIC METHODS **********
154
155 def set_angle(self, angle=0):
156 """
157 Set the matrix orientation.
158 Args:
159 angle (integer) Display auto-rotation angle, 0 to -360 degrees. Default: 0
160 Returns:
161 The instance (self)
162 """
163 # Bring the supplied angle to with 0-360 degrees
164 if angle > 360:
165 while angle > 360:
166 angle -= 360
167
168 if angle < 0:
169 while angle < 360:
170 angle += 360
171
172 # Convert angle to internal value:
173 # 0 = none, 1 = 90 clockwise, 2 = 180, 3 = 90 anti-clockwise
174 if angle > 3:
175 if angle < 45 or angle > 360: angle = 0
176 if angle >= 45 and angle < 135: angle = 1
177 if angle >= 135 and angle < 225: angle = 2
178 if angle >= 225: angle = 3
179
180 self.rotation_angle = angle
181 self.is_rotated = True if self.rotation_angle != 0 else False
182 return self
183
184 def set_inverse(self):
185 """
186 Inverts the ink colour of the display.
187 Returns:
188 The instance (self)
189 """
190 self.is_inverse = not self.is_inverse
191 for i in range(self.width):
192 self.buffer[i] = (~ self.buffer[i]) & 0xFF
193 return self
194
195 def set_icon(self, glyph, centre=False):
196 """
197 Displays a custom character on the matrix.
198 Args:
199 glyph (array) 1-8 8-bit values defining a pixel image. The data is passed as columns
200 0 through 7, left to right. Bit 0 is at the bottom, bit 7 at the top
201 centre (bool) Whether the icon should be displayed centred on the screen. Default: False
202 Returns:
203 The instance (self)
204 """
205 length = len(glyph)
206 assert 0 < length <= self.width, "ERROR - Invalid glyph set in set_icon()"
207 for i in range(length):
208 a = i
209 if centre: a = i + ((8 - length) >> 1)
210 self.buffer[a] = glyph[i] if self.is_inverse is False else ((~ glyph[i]) & 0xFF)
211 return self
212
213 def set_character(self, ascii_value=32, centre=False):
214 """
215 Display a single character specified by its Ascii value on the matrix.
216 Args:
217 ascii_value (integer) Character Ascii code. Default: 32 (space)
218 centre (bool) Whether the icon should be displayed centred on the screen. Default: False
219 Returns:
220 The instance (self)
221 """
222 assert 0 <= ascii_value < 128, "ERROR - Invalid ascii code set in set_character()"
223 glyph = None
224 if ascii_value < 32:
225 # A user-definable character has been chosen
226 glyph = self.def_chars[ascii_value]
227 else:
228 # A standard character has been chosen
229 ascii_value -= 32
230 if ascii_value < 0 or ascii_value >= len(self.CHARSET): ascii_value = 0
231 glyph = self.CHARSET[ascii_value]
232 return self.set_icon(glyph, centre)
233
234 def scroll_text(self, the_line, speed=0.1):
235 """
236 Scroll the specified line of text leftwards across the display.
237 Args:
238 the_line (string) The string to display
239 speed (float) The delay between frames
240 Returns:
241 The instance (self)
242 """
243 import time
244
245 assert len(the_line) > 0, "ERROR - Invalid string set in scroll_text()"
246
247 # Calculate the source buffer size
248 length = 0
249 for i in range(0, len(the_line)):
250 asc_val = ord(the_line[i])
251 if asc_val < 32:
252 glyph = self.def_chars[asc_val]
253 else:
254 glyph = self.CHARSET[asc_val - 32]
255 length += len(glyph)
256 if asc_val > 32: length += 1
257 src_buffer = bytearray(length)
258
259 # Draw the string to the source buffer
260 row = 0
261 for i in range(0, len(the_line)):
262 asc_val = ord(the_line[i])
263 if asc_val < 32:
264 glyph = self.def_chars[asc_val]
265 else:
266 glyph = self.CHARSET[asc_val - 32]
267 for j in range(0, len(glyph)):
268 src_buffer[row] = glyph[j] if self.is_inverse is False else ((~ glyph[j]) & 0xFF)
269 row += 1
270 if asc_val > 32: row += 1
271 assert row == length, "ERROR - Mismatched lengths in scroll_text()"
272
273 # Finally, animate the line
274 cursor = 0
275 while True:
276 a = cursor
277 for i in range(0, self.width):
278 self.buffer[i] = src_buffer[a];
279 a += 1
280 self.draw()
281 cursor += 1
282 if cursor > length - self.width: break
283 time.sleep(speed)
284
285 def define_character(self, glyph, char_code=0):
286 """
287 Set a user-definable character for later use.
288 Args:
289 glyph (bytearray) 1-8 8-bit values defining a pixel image. The data is passed as columns,
290 with bit 0 at the bottom and bit 7 at the top
291 char_code (integer) Character's ID Ascii code 0-31. Default: 0
292 Returns:
293 The instance (self)
294 """
295 assert 0 < len(glyph) <= self.width, "ERROR - Invalid glyph set in define_character()"
296 assert 0 <= char_code < 32, "ERROR - Invalid character code set in define_character()"
297 self.def_chars[char_code] = glyph
298 return self
299
300 def plot(self, x, y, ink=1, xor=False):
301 """
302 Plot a point on the matrix. (0,0) is bottom left as viewed.
303 Args:
304 x (integer) X co-ordinate (0 - 7) left to right
305 y (integer) Y co-ordinate (0 - 7) bottom to top
306 ink (integer) Pixel color: 1 = 'white', 0 = black. NOTE inverse video mode reverses this. Default: 1
307 xor (bool) Whether an underlying pixel already of color ink should be inverted. Default: False
308 Returns:
309 The instance (self)
310 """
311 # Check argument range and value
312 assert (0 <= x < self.width) and (0 <= y < self.height), "ERROR - Invalid coordinate set in plot()"
313 if ink not in (0, 1): ink = 1
314 if ink == 1:
315 if self.is_set(x ,y) and xor:
316 self.buffer[x] ^= (1 << y)
317 else:
318 if self.buffer[x] & (1 << y) == 0: self.buffer[x] |= (1 << y)
319 else:
320 if not self.is_set(x ,y) and xor:
321 self.buffer[x] ^= (1 << y)
322 else:
323 if self.buffer[x] & (1 << y) != 0: self.buffer[x] &= ~(1 << y)
324 return self
325
326 def is_set(self, x, y):
327 """
328 Indicate whether a pixel is set.
329 Args:
330 x (int) X co-ordinate left to right
331 y (int) Y co-ordinate bottom to top
332 Returns:
333 Whether the pixel is set (True) or not (False)
334 """
335 assert (0 <= x < self.width) and (0 <= y < self.height), "ERROR - Invalid coordinate set in is_set()"
336 bit = (self.buffer[x] >> y) & 1
337 return True if bit > 0 else False
338
339 def draw(self):
340 """
341 Takes the contents of _buffer and writes it to the LED matrix.
342 NOTE Overrides the parent method.
343 """
344 if self.is_rotated:
345 new_buffer = self._rotate_matrix(self.buffer, self.rotation_angle)
346 else:
347 new_buffer = bytearray(len(self.buffer))
348 for i in range(8): new_buffer[i] = self.buffer[i]
349 draw_buffer = bytearray(17)
350 for i in range(len(new_buffer)):
351 draw_buffer[i * 2 + 1] = (new_buffer[i] >> 1) | ((new_buffer[i] << 7) & 0xFF)
352 self.i2c.writeto(self.address, bytes(draw_buffer))
353
354 # ********** PRIVATE METHODS **********
355
356 def _rotate_matrix(self, input_matrix, angle=0):
357 """
358 Rotate an 8-integer matrix through the specified angle in 90-degree increments:
359 0 = none, 1 = 90 clockwise, 2 = 180, 3 = 90 anti-clockwise
360 """
361 assert angle in (0, 1, 2, 3), "ERROR - Invalid angle in _rotate_matrix()"
362 if angle is 0: return input_matrix
363
364 a = 0
365 line_value = 0
366 output_matrix = bytearray(self.width)
367
368 # NOTE It's quicker to have three case-specific
369 # code blocks than a single, generic block
370 for y in range(self.height):
371 line_value = input_matrix[y]
372 for x in range(7, -1, -1):
373 a = line_value & (1 << x)
374 if a is not 0:
375 if angle is 1:
376 output_matrix[7 - x] = output_matrix[7 - x] + (1 << y)
377 elif angle is 2:
378 output_matrix[7 - y] += (1 << (7 - x))
379 else:
380 output_matrix[x] = output_matrix[x] + (1 << (7 - y))
381 return output_matrix
382
383 def _fill(value=0xFF):
384 """
385 Fill the buffer, column by column with the specified byte value
386 """
387 value &= 0xFF
388 for i in range(self.width): self.buffer[i] = value
References And Credits
-
Tony Smith: https://github.com/smittytone/HT16K33-Python
-
Gorillacell: gorillacell.kr
Posts in this series
- 049 - MicroPython TechNotes: MP3 Player
- 048 - MicroPython TechNotes: Analog Touch Sensor
- 047 - MicroPython TechNotes: E108 GPS
- 046 - MicroPython TechNotes: RF433 Transceivers
- 045 - MicroPython TechNotes: Infrared Transmitter
- 044 - MicroPython TechNotes: Infrared Receiver
- 043 - MicroPython TechNotes: ESP12E WiFi | External WiFi module
- 042 - MicroPython TechNotes: JDY-32 | Bluetooth Low Energy BLE
- 041 - MicroPython TechNotes: Bluetooth HC-06
- 040 - MicroPython TechNotes: Relay
- 039 - MicroPython TechNotes: Electromagnet
- 038 - MicroPython TechNotes: Buzzer
- 037 - MicroPython TechNotes: Servo Motor
- 036 - MicroPython TechNotes: Stepper Motor
- 035 - MicroPython TechNotes: Dual Motor Driver
- 034 - MicroPython TechNotes: DC Motors | Gear Motor and Fan Motor
- 033 - MicroPython TechNotes: TCS34725 RGB Color Sensor
- 032 - MicroPython TechNotes: BMP280 Sensor
- 031 - MicroPython TechNotes: TOF Distance Sensor
- 030 - MicroPython TechNotes: DS3231 RTC
- 029 - MicroPython TechNotes: HC-SR04 Ultrasonic Sensor
- 028 - MicroPython TechNotes: DHT11 Temperature and Humidity Sensor
- 027 - MicroPython TechNotes: Rotary Encoder
- 026 - MicroPython TechNotes: Light Dependent Resistor (LDR)
- 025 - MicroPython TechNotes: Joystick
- 024 - MicroPython TechNotes: Slider Switch
- 023 - MicroPython TechNotes: Continuous Rotation Potentiometer
- 022 - MicroPython TechNotes: Potentiometer | Reading an Analog Input
- 021 - MicroPython TechNotes: Color Touch Sensor
- 020 - MicroPython TechNotes: Touch Sensor
- 019 - MicroPython TechNotes: Switch Module
- 018 - MicroPython TechNotes: Button | Reading an Input
- 017 - MicroPython TechNotes: LASER Module
- 016 - MicroPython TechNotes: RGB LED Matrix
- 015 - MicroPython TechNotes: Neopixel 16
- 013 - MicroPython TechNotes: 8x16 Dot Matrix Display (SPI)
- 012 - MicroPython TechNotes: 8x8 Dot Matrix Display (SPI)
- 011 - MicroPython TechNotes: 1.3 OLED Display
- 010 - MicroPython TechNotes: 0.96 OLED Display
- 009 - MicroPython TechNotes: 7 Segment Display
- 008 - MicroPython TechNotes: 16x2 LCD
- 007 - MicroPython TechNotes: RGB LED
- 006 - MicroPython TechNotes: Traffic Light LED Module
- 005 - MicroPython TechNotes: Gorilla Cell LED | MicroPython Hello World
- 004 - MicroPython TechNotes: Gorilla Cell I/O Devices
- 003 - MicroPython TechNotes: Gorillacell ESP32 Shield
- 002 - MicroPython TechNotes: Introduction for Gorillacell ESP32 Dev Kit
- 001 - MicroPython TechNotes: Get Started with MicroPython
- 000 - MicroPython TechNotes: Unboxing Gorillacell ESP32 Development Kit
No comments yet!