023 - ESP32 MicroPython: Binary Clock
Introduction
In this article, I would like to share to you on how to create this simple yet cool project using a single 8×8 dot matrix module to display a binary clock – a clock that is represented using binary numeric system.
Bill Of Materials
- An ESP32 development board (or any other development board with MicroPython firmware).
- An 8×8 Dot Matrix module with SPI interface (if you have I2C interface, you just need to use a different driver library and modify the source code a little bit).
- And some jumper wires.
Hardware Instruction
For the hardware part, it is very easy just follow the circuit diagram below which connects the dot matrix to ESP32 as follows:
- Dot matrix VCC to 3.3V.
- Dot matrix GND pin to ESP32 GND pin.
- Dot matrix DIN pin to ESP32 GPIO 23.
- Dot matrix CLK pin to ESP32 GPIO 19.
- Dot matrix CS pin to ESP32 GPIO 18.
Software Instruction
- Copy the max7219 from Jeff Brown github: https://github.com/jgbrown32/ESP8266_MAX7219 or you may copy it in the SOURCE CODE section below.
- And save it to ESP32 MicroPython device root directory by clicking the File menu and select Save As.
- Select MicroPython device and name it as max7219.py and click OK.
- Copy the example source code below. Please feel free to modify it to your liking.
- Enjoy.
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
Source Code
1. Binary Clock:
1# More details can be found in TechToTinker.blogspot.com
2# George Bantique | tech.to.tinker@gmail.com
3
4from machine import Pin, SPI
5from micropython import const
6import framebuf, utime
7
8_DIGIT_0 = const(0x1)
9
10_DECODE_MODE = const(0x9)
11_NO_DECODE = const(0x0)
12
13_INTENSITY = const(0xa)
14_INTENSITY_MIN = const(0x0)
15
16_SCAN_LIMIT = const(0xb)
17_DISPLAY_ALL_DIGITS = const(0x7)
18
19_SHUTDOWN = const(0xc)
20_SHUTDOWN_MODE = const(0x0)
21_NORMAL_OPERATION = const(0x1)
22
23_DISPLAY_TEST = const(0xf)
24_DISPLAY_TEST_NORMAL_OPERATION = const(0x0)
25
26_MATRIX_SIZE = const(8)
27
28# _SCROLL_SPEED_NORMAL is ms to delay (slow) scrolling text.
29_SCROLL_SPEED_NORMAL = 100
30
31class Max7219(framebuf.FrameBuffer):
32 """
33 Driver for MAX7219 8x8 LED matrices
34 https://github.com/vrialland/micropython-max7219
35 Example for ESP8266 with 2x4 matrices (one on top, one on bottom),
36 so we have a 32x16 display area:
37 >>> from machine import Pin, SPI
38 >>> from max7219 import Max7219
39 >>> spi = SPI(1, baudrate=10000000)
40 >>> screen = Max7219(32, 16, spi, Pin(15))
41 >>> screen.rect(0, 0, 32, 16, 1) # Draws a frame
42 >>> screen.text('Hi!', 4, 4, 1)
43 >>> screen.show()
44 On some matrices, the display is inverted (rotated 180°), in this case
45 you can use `rotate_180=True` in the class constructor.
46 """
47
48 def __init__(self, width, height, spi, cs, rotate_180=False):
49 # Pins setup
50 self.spi = spi
51 self.cs = cs
52 self.cs.init(Pin.OUT, True)
53
54 # Dimensions
55 self.width = width
56 self.height = height
57 # Guess matrices disposition
58 self.cols = width // _MATRIX_SIZE
59 self.rows = height // _MATRIX_SIZE
60 self.nb_matrices = self.cols * self.rows
61 self.rotate_180 = rotate_180
62 # 1 bit per pixel (on / off) -> 8 bytes per matrix
63 self.buffer = bytearray(width * height // 8)
64 format = framebuf.MONO_HLSB if not self.rotate_180 else framebuf.MONO_HMSB
65 super().__init__(self.buffer, width, height, format)
66
67 # Init display
68 self.init_display()
69
70 def _write_command(self, command, data):
71 """Write command on SPI"""
72 cmd = bytearray([command, data])
73 self.cs(0)
74 for matrix in range(self.nb_matrices):
75 self.spi.write(cmd)
76 self.cs(1)
77
78 def init_display(self):
79 """Init hardware"""
80 for command, data in (
81 (_SHUTDOWN, _SHUTDOWN_MODE), # Prevent flash during init
82 (_DECODE_MODE, _NO_DECODE),
83 (_DISPLAY_TEST, _DISPLAY_TEST_NORMAL_OPERATION),
84 (_INTENSITY, _INTENSITY_MIN),
85 (_SCAN_LIMIT, _DISPLAY_ALL_DIGITS),
86 (_SHUTDOWN, _NORMAL_OPERATION), # Let's go
87 ):
88 self._write_command(command, data)
89
90 self.fill(0)
91 self.show()
92
93 def brightness(self, value):
94 # Set display brightness (0 to 15)
95 if not 0 <= value < 16:
96 raise ValueError('Brightness must be between 0 and 15')
97 self._write_command(_INTENSITY, value)
98
99 def marquee(self, message):
100 start = 33
101 extent = 0 - (len(message) * 8) - 32
102 for i in range(start, extent, -1):
103 self.fill(0)
104 self.text(message, i, 0, 1)
105 self.show()
106 utime.sleep_ms(_SCROLL_SPEED_NORMAL)
107
108 def show(self):
109 """Update display"""
110 # Write line per line on the matrices
111 for line in range(8):
112 self.cs(0)
113
114 for matrix in range(self.nb_matrices):
115 # Guess where the matrix is placed
116 row, col = divmod(matrix, self.cols)
117 # Compute where the data starts
118 if not self.rotate_180:
119 offset = row * 8 * self.cols
120 index = col + line * self.cols + offset
121 else:
122 offset = 8 * self.cols - row * (8 - line) * self.cols
123 index = (7 - line) * self.cols + col - offset
124
125 self.spi.write(bytearray([_DIGIT_0 + line, self.buffer[index]]))
126
127 self.cs(1)
2. max7219.py driver library:
1# Jeff Brown max7219 driver library
2from machine import Pin, SPI
3from micropython import const
4import framebuf, utime
5
6_DIGIT_0 = const(0x1)
7
8_DECODE_MODE = const(0x9)
9_NO_DECODE = const(0x0)
10
11_INTENSITY = const(0xa)
12_INTENSITY_MIN = const(0x0)
13
14_SCAN_LIMIT = const(0xb)
15_DISPLAY_ALL_DIGITS = const(0x7)
16
17_SHUTDOWN = const(0xc)
18_SHUTDOWN_MODE = const(0x0)
19_NORMAL_OPERATION = const(0x1)
20
21_DISPLAY_TEST = const(0xf)
22_DISPLAY_TEST_NORMAL_OPERATION = const(0x0)
23
24_MATRIX_SIZE = const(8)
25
26# _SCROLL_SPEED_NORMAL is ms to delay (slow) scrolling text.
27_SCROLL_SPEED_NORMAL = 100
28
29class Max7219(framebuf.FrameBuffer):
30 """
31 Driver for MAX7219 8x8 LED matrices
32 https://github.com/vrialland/micropython-max7219
33 Example for ESP8266 with 2x4 matrices (one on top, one on bottom),
34 so we have a 32x16 display area:
35 >>> from machine import Pin, SPI
36 >>> from max7219 import Max7219
37 >>> spi = SPI(1, baudrate=10000000)
38 >>> screen = Max7219(32, 16, spi, Pin(15))
39 >>> screen.rect(0, 0, 32, 16, 1) # Draws a frame
40 >>> screen.text('Hi!', 4, 4, 1)
41 >>> screen.show()
42 On some matrices, the display is inverted (rotated 180°), in this case
43 you can use `rotate_180=True` in the class constructor.
44 """
45
46 def __init__(self, width, height, spi, cs, rotate_180=False):
47 # Pins setup
48 self.spi = spi
49 self.cs = cs
50 self.cs.init(Pin.OUT, True)
51
52 # Dimensions
53 self.width = width
54 self.height = height
55 # Guess matrices disposition
56 self.cols = width // _MATRIX_SIZE
57 self.rows = height // _MATRIX_SIZE
58 self.nb_matrices = self.cols * self.rows
59 self.rotate_180 = rotate_180
60 # 1 bit per pixel (on / off) -> 8 bytes per matrix
61 self.buffer = bytearray(width * height // 8)
62 format = framebuf.MONO_HLSB if not self.rotate_180 else framebuf.MONO_HMSB
63 super().__init__(self.buffer, width, height, format)
64
65 # Init display
66 self.init_display()
67
68 def _write_command(self, command, data):
69 """Write command on SPI"""
70 cmd = bytearray([command, data])
71 self.cs(0)
72 for matrix in range(self.nb_matrices):
73 self.spi.write(cmd)
74 self.cs(1)
75
76 def init_display(self):
77 """Init hardware"""
78 for command, data in (
79 (_SHUTDOWN, _SHUTDOWN_MODE), # Prevent flash during init
80 (_DECODE_MODE, _NO_DECODE),
81 (_DISPLAY_TEST, _DISPLAY_TEST_NORMAL_OPERATION),
82 (_INTENSITY, _INTENSITY_MIN),
83 (_SCAN_LIMIT, _DISPLAY_ALL_DIGITS),
84 (_SHUTDOWN, _NORMAL_OPERATION), # Let's go
85 ):
86 self._write_command(command, data)
87
88 self.fill(0)
89 self.show()
90
91 def brightness(self, value):
92 # Set display brightness (0 to 15)
93 if not 0 <= value < 16:
94 raise ValueError('Brightness must be between 0 and 15')
95 self._write_command(_INTENSITY, value)
96
97 def marquee(self, message):
98 start = 33
99 extent = 0 - (len(message) * 8) - 32
100 for i in range(start, extent, -1):
101 self.fill(0)
102 self.text(message, i, 0, 1)
103 self.show()
104 utime.sleep_ms(_SCROLL_SPEED_NORMAL)
105
106 def show(self):
107 """Update display"""
108 # Write line per line on the matrices
109 for line in range(8):
110 self.cs(0)
111
112 for matrix in range(self.nb_matrices):
113 # Guess where the matrix is placed
114 row, col = divmod(matrix, self.cols)
115 # Compute where the data starts
116 if not self.rotate_180:
117 offset = row * 8 * self.cols
118 index = col + line * self.cols + offset
119 else:
120 offset = 8 * self.cols - row * (8 - line) * self.cols
121 index = (7 - line) * self.cols + col - offset
122
123 self.spi.write(bytearray([_DIGIT_0 + line, self.buffer[index]]))
124
125 self.cs(1)
References And Credits
- Jeff Brown max7219 library: https://github.com/jgbrown32/ESP8266_MAX7219
Posts in this series
- 026 - ESP32 MicroPython: MFRC522 RFID Module
- 025 - ESP32 MicroPython: ESP32 Bluetooth Low Energy
- 024 - ESP32 MicroPython: How to Use SD Card in MicroPython
- 022 - ESP32 MicroPython: MQTT Part 2: Subscribe
- 021 - ESP32 MicroPython: MQTT Part 1: Publish
- 020 - ESP32 MicroPython: RESTful APIs | Demo READ and WRITE
- 019 - ESP32 MicroPython: OpenWeather | RESTful APIs
- 018 - ESP32 MicroPython: Thingspeak | RESTful APIs
- 017 - ESP32 MicroPython: DHT Values Auto Updates using AJAX
- 016 - ESP32 MicroPython: Web Server | ESP32 Access Point
- 015 - ESP32 MicroPython: Web Server | ESP32 Station Mode in MicroPython
- 014 - ESP32 MicroPython: SIM800L GSM Module in MicroPython
- 013 - ESP32 MicroPython: UART Serial in MicroPython
- 012 - ESP32 MicroPython: HC-SR04 Ultrasonic Sensor in MicroPython
- 011 - ESP32 MicroPython: DHT11, DHT22 in MicroPython
- 010 - ESP32 MicroPython: 0.96 OLED in MicroPython
- 009 - ESP32 MicroPython: Non-blocking Delays and Multithreading | Multitasking
- 008 - ESP32 MicroPython: Hardware Timer Interrupts
- 007 - ESP32 MicroPython: How to make some sound with MicroPython
- 006 - ESP32 MicroPython: How to control servo motor with MicroPython
- 005 - ESP32 MicroPython: Pulse Width Modulation
- 004 - ESP32 MicroPython: External Interrupts
- 003 - ESP32 MicroPython: General Purpose Input Output | GPIO Pins
- 001 - ESP32 MicroPython: What is MicroPython
- 000 - ESP32 MicroPython: How to Get Started with MicroPython
No comments yet!