diff --git a/LICENSE.txt b/LICENSE.txt index f1f7203..4eeb409 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2016 Mike Causer +Copyright (c) 2016-2023 Mike Causer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index b976cca..fc9268f 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,32 @@ A MicroPython library for quad 7-segment LED display modules using the TM1637 LED driver. -For example, the [Grove - 4 Digit Display module](http://wiki.seeed.cc/Grove-4-Digit_Display/) - ![demo](docs/demo.jpg) -## Examples +### Installation -Copy the file to your device, using ampy, webrepl or compiling and deploying. eg. +Using mip via mpremote: +```bash +$ mpremote mip install github:mcauser/micropython-tm1637 ``` -$ ampy put tm1637.py + +Using mip directly on a WiFi capable board: + +```python +>>> import mip +>>> mip.install("github:mcauser/micropython-tm1637") ``` +Manual installation: + +Copy `tm1637.py` to the root directory of your device. + +## Examples + **Basic usage** -``` +```python import tm1637 from machine import Pin tm = tm1637.TM1637(clk=Pin(5), dio=Pin(4)) @@ -115,84 +126,91 @@ blank | 0b00000000 | 0x00 | 0 # Methods Get or set brightness. -``` +```python brightness(val=None) ``` Write one or more segments at a given offset. -``` +```python write(segments, pos=0) ``` Convert a single hex digit (0x00-0x0f) to a segment. -``` +```python encode_digit(digit) ``` Convert a string to a list of segments. -``` +```python encode_string(string) ``` Convert a single character to a segment. -``` +```python encode_char(char) ``` Display a number in hexadecimal format 0000 through FFFF. -``` +```python hex(val) ``` Display a number -999 through 9999, right aligned. -``` +```python number(num) ``` Display 2 independent numbers on either side of the (optional) colon, with leading zeros. -``` +```python numbers(num1, num2, colon=True) ``` Display a temperature -9 through 99 followed by degrees C. -``` +```python temperature(num) ``` Show a string on the display. Shorthand for write(encode_string()). Limited to first 4 characters. -``` +```python show(string, colon=False) ``` Display a string on the display, scrolling from the right to left, speed adjustable. String starts off-screen and scrolls until off-screen at 4 FPS by default. -``` +```python scroll(string, delay=250) ``` -## Parts +## Modules + +* [Grove 4 Digit Display](https://www.seeedstudio.com/Grove-4-Digit-Display.html) +* [RobotDyn 4-digit LED Display Tube](https://www.aliexpress.com/item/32795908218.html) +* [RobotDyn 6-digit LED Display Tube](https://www.aliexpress.com/item/32800127265.html) +* [Generic TM1637 LED Display Module](https://www.aliexpress.com/item/32657932650.html) -* [WeMos D1 Mini](https://www.aliexpress.com/store/product/D1-mini-Mini-NodeMcu-4M-bytes-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266/1331105_32529101036.html) $4.00 USD -* [Grove 4 Digit Display](https://www.seeedstudio.com/grove-4digital-display-p-1198.html) $5.90 USD -* [Grove Male Jumper Cable](https://www.seeedstudio.com/Grove-4-pin-Male-Jumper-to-Grove-4-pin-Conversion-Cable-%285-PCs-per-Pack%29-p-1565.html) $2.90 USD +For example, the [Grove - 4 Digit Display module](http://wiki.seeed.cc/Grove-4-Digit_Display/) ## Connections -WeMos D1 Mini | 4 Digit Display -------------- | --------------- -D1 (GPIO5) | CLK -D2 (GPIO4) | DIO -3V3 (or 5V) | VCC -G | GND +`CLK` and `DIO` are bit-banged. You can use any GPIO. + +4 Digit Display | TinyPICO | Pi Pico | WeMos D1 Mini +--------------- | ---------| ------- | ------------- +CLK | IO18 | IO27 | D1 (GPIO5) +DIO | IO23 | IO26 | D2 (GPIO4) +VCC | 3V3 | 3V3 | 3V3/5V +GND | GND | GND | G ## Links -* [WeMos D1 Mini](https://wiki.wemos.cc/products:d1:d1_mini) * [micropython.org](http://micropython.org) * [TM1637 datasheet](http://www.titanmec.com/index.php/en/project/download/id/302.html) * [Titan Micro TM1637 product page](http://www.titanmec.com/index.php/en/project/view/id/302.html) * [Nokia 5110 version](https://github.com/mcauser/MicroPython-ESP8266-Nokia-5110-Quad-7-segment) * [BBC micro:bit version](https://github.com/mcauser/microbit-tm1637) -* [Adafruit Ampy](https://learn.adafruit.com/micropython-basics-load-files-and-run-code/install-ampy) + +## License + +Licensed under the [MIT License](http://opensource.org/licenses/MIT). diff --git a/docs/demo.jpg b/docs/demo.jpg index 9537a4b..fefaa17 100644 Binary files a/docs/demo.jpg and b/docs/demo.jpg differ diff --git a/examples/robotdyn-4-digit-decimal/test.py b/examples/robotdyn-4-digit-decimal/test.py new file mode 100644 index 0000000..feb9ffa --- /dev/null +++ b/examples/robotdyn-4-digit-decimal/test.py @@ -0,0 +1,35 @@ +# WeMos D1 Mini -- RobotDyn 4-digit LED Display Tube +# D4 (GPIO2) ----- CLK +# D3 (GPIO0) ----- DIO +# 3V3 ------------ VCC +# G -------------- GND + +# https://www.aliexpress.com/store/product/4-Digit-LED-0-36-Display-Tube-decimal-7-segments-RED-TM1637-disp-size-30x14mm/1950989_32795908218.html + +# this module has a 4-digit 7-segment display with decimal points + +# the TM1637 driver supports 6 digits (called grids in the datasheet) +# on this display, digits left to right are controlled by grid1, grid2, grid3, grid4 +# grid5 and grid6 are not connected + +import tm1637 +from machine import Pin +tm = tm1637.TM1637(clk=Pin(2), dio=Pin(0)) + +# dim +tm.brightness(0) + +# 1234 +tm.write([0x06, 0x5B, 0x4F, 0x66]) + +# 1.234 +tm.write([0x06 | 128, 0x5B, 0x4F, 0x66]) + +# 12.34 +tm.write([0x06, 0x5B | 128, 0x4F, 0x66]) + +# 1.2.3.4. +tm.write([0x06 | 128, 0x5B | 128, 0x4F | 128, 0x66 | 128]) + +# help +tm.show('help') diff --git a/examples/robotdyn-6-digit-decimal/test.py b/examples/robotdyn-6-digit-decimal/test.py new file mode 100644 index 0000000..c841108 --- /dev/null +++ b/examples/robotdyn-6-digit-decimal/test.py @@ -0,0 +1,62 @@ +# WeMos D1 Mini -- RobotDyn 6-digit LED Display Tube +# D4 (GPIO2) ----- CLK +# D3 (GPIO0) ----- DIO +# 3V3 ------------ VCC +# G -------------- GND + +# https://www.aliexpress.com/store/product/6-Digit-LED-0-36-Display-Tube-decimal-7-segments-GREEN-TM1637-disp-size-46x14mm/1950989_32800127265.html + +# this module has two 3-digit 7-segment displays with decimal points +# they are both wired backwards! + +# the TM1637 driver supports 6 digits (called grids in the datasheet) +# on a 4 digit display, digits left to right are typically controlled by grid1, grid2, grid3, grid4 +# on this 6 digit display, digits left to right are grid3, grid2, grid1, grid6, grid5, grid4 +# this means the write function needs to shiffle the order to match + +import tm1637 +from machine import Pin +tm = tm1637.TM1637(clk=Pin(2), dio=Pin(0)) + +# dim +tm.brightness(0) + +# expected: 012345 +# actual: 210543 +tm.write([0x3F,0x06,0x5B,0x4F,0x66,0x6D]) + +# data = 012345 +data = [0x3F,0x06,0x5B,0x4F,0x66,0x6D] +# expected: 012345 +# actual: 012345 +tm.write([data[2], data[1], data[0], data[5], data[4], data[3]]) + +# expected: abcdef +# actual: cbafed +tm.show('abcdef') + +# swap segments 0,2 and segments 3,5 +def swap(segs): + length = len(segs) + if length == 4 or length == 5: + segs.extend(bytearray([0] * (6 - length))) + segs[0], segs[2] = segs[2], segs[0] + if length >= 4: + segs[3], segs[5] = segs[5], segs[3] + return segs + +# data = 012345 +data = [0x3F,0x06,0x5B,0x4F,0x66,0x6D] +# expected: 012345 +# actual: 012345 +tm.write(swap(data)) + +# data = notbad +data = [84, 63, 120, 124, 119, 94] +# expected: notbad +# actual: notbad +tm.write(swap(data)) + +# expected: abcdef +# actual: abcdef +tm.write(swap(tm.encode_string('abcdef'))) diff --git a/examples/seeed-studio-grove-4-digit-display/test.py b/examples/seeed-studio-grove-4-digit-display/test.py new file mode 100644 index 0000000..477e12a --- /dev/null +++ b/examples/seeed-studio-grove-4-digit-display/test.py @@ -0,0 +1,26 @@ +# WeMos D1 Mini -- Seeed Studio Grove 4 Digit Display +# D4 (GPIO2) ----- CLK +# D3 (GPIO0) ----- DIO +# 3V3 ------------ VCC +# G -------------- GND + +# https://www.seeedstudio.com/Grove-4-Digit-Display-p-1198.html +# http://wiki.seeed.cc/Grove-4-Digit_Display/ + +# this module has a 4-digit 7-segment display with two dots between the 2nd and 3rd segments, referred to as the colon + +import tm1637 +from machine import Pin +tm = tm1637.TM1637(clk=Pin(2), dio=Pin(0)) + +# dim +tm.brightness(0) + +# 1234 +tm.write([0x06, 0x5B, 0x4F, 0x66]) + +# 12:34 +tm.write([0x06, 0x5B | 128, 0x4F, 0x66]) + +# cool +tm.show('cool') diff --git a/package.json b/package.json new file mode 100644 index 0000000..1c991b6 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "urls": [ + ["tm1637.py", "github:mcauser/micropython-tm1637/tm1637.py"] + ], + "version": "1.3.0" +} diff --git a/tm1637.py b/tm1637.py index 785e661..0f601f3 100644 --- a/tm1637.py +++ b/tm1637.py @@ -1,4 +1,30 @@ -# MicroPython TM1637 quad 7-segment LED display driver +""" +MicroPython TM1637 quad 7-segment LED display driver +https://github.com/mcauser/micropython-tm1637 + +MIT License +Copyright (c) 2016-2023 Mike Causer + +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. +""" + +__version__ = '1.3.0' from micropython import const from machine import Pin @@ -9,6 +35,7 @@ TM1637_CMD3 = const(128) # 0x80 display control command TM1637_DSP_ON = const(8) # 0x08 display on TM1637_DELAY = const(10) # 10us delay between clk/dio pulses +TM1637_MSB = const(128) # msb is the decimal point or the colon depending on your display # 0-9, a-z, blank, dash, star _SEGMENTS = bytearray(b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F\x77\x7C\x39\x5E\x79\x71\x3D\x76\x06\x1E\x76\x38\x55\x54\x3F\x73\x67\x50\x6D\x78\x3E\x1C\x2A\x76\x6E\x5B\x00\x40\x63') @@ -84,10 +111,10 @@ def brightness(self, val=None): self._write_dsp_ctrl() def write(self, segments, pos=0): - """Display up to 4 segments moving right from a given position. + """Display up to 6 segments moving right from a given position. The MSB in the 2nd segment controls the colon between the 2nd and 3rd segments.""" - if not 0 <= pos <= 3: + if not 0 <= pos <= 5: raise ValueError("Position out of range") self._write_data_cmd() self._start() @@ -103,8 +130,8 @@ def encode_digit(self, digit): return _SEGMENTS[digit & 0x0f] def encode_string(self, string): - """Convert an up to 4 character length string containing 0-9, a-f, - space, dash to an array of segments, matching the length of the + """Convert an up to 4 character length string containing 0-9, a-z, + space, dash, star to an array of segments, matching the length of the source string.""" segments = bytearray(len(string)) for i in range(len(string)): @@ -112,7 +139,7 @@ def encode_string(self, string): return segments def encode_char(self, char): - """Convert a character 0-9, a-z, space or dash to a segment.""" + """Convert a character 0-9, a-z, space, dash or star to a segment.""" o = ord(char) if o == 32: return _SEGMENTS[36] # space @@ -173,3 +200,27 @@ def scroll(self, string, delay=250): for i in range(len(segments) + 5): self.write(data[0+i:4+i]) sleep_ms(delay) + + +class TM1637Decimal(TM1637): + """Library for quad 7-segment LED modules based on the TM1637 LED driver. + + This class is meant to be used with decimal display modules (modules + that have a decimal point after each 7-segment LED). + """ + + def encode_string(self, string): + """Convert a string to LED segments. + + Convert an up to 4 character length string containing 0-9, a-z, + space, dash, star and '.' to an array of segments, matching the length of + the source string.""" + segments = bytearray(len(string.replace('.',''))) + j = 0 + for i in range(len(string)): + if string[i] == '.' and j > 0: + segments[j-1] |= TM1637_MSB + continue + segments[j] = self.encode_char(string[i]) + j += 1 + return segments