Skip to content

Commit 82eae4c

Browse files
authored
Added a 14 segment LED example, driven by the HT16K33 (#219)
No fritzing parts available for the device so no diagrams
1 parent aa9a72b commit 82eae4c

File tree

5 files changed

+281
-0
lines changed

5 files changed

+281
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ App|Description
8686
[ssd1306_i2c](i2c/ssd1306_i2c) | Convert and display a bitmap on a 128x32 or 128x64 SSD1306-driven OLED display
8787
[pa1010d_i2c](i2c/pa1010d_i2c) | Read GPS location data, parse and display data via I2C.
8888
[pcf8523_i2c](i2c/pcf8523_i2c) | Read time and date values from a real time clock. Set current time and alarms on it.
89+
[ht16k33_i2c](i2c/ht16k33_i2c) | Drive a 4 digit 14 segment LED with an HT16K33.
8990

9091
### Interpolator
9192

i2c/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ if (NOT PICO_NO_HARDWARE)
1010
add_subdirectory(ssd1306_i2c)
1111
add_subdirectory(pa1010d_i2c)
1212
add_subdirectory(pcf8523_i2c)
13+
add_subdirectory(ht16k33_i2c)
1314
endif ()

i2c/ht16k33_i2c/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_executable(ht16k33_i2c
2+
ht16k33_i2c.c
3+
)
4+
5+
# pull in common dependencies and additional i2c hardware support
6+
target_link_libraries(ht16k33_i2c pico_stdlib hardware_i2c)
7+
8+
# create map/bin/hex file etc.
9+
pico_add_extra_outputs(ht16k33_i2c)
10+
11+
# add url via pico_set_program_url
12+
example_auto_set_url(ht16k33_i2c)

i2c/ht16k33_i2c/README.adoc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
= Attaching a 4 digit 14 segment LED driven by the HT15k33 via I2C
2+
3+
This example code shows how to interface the Raspberry Pi Pico to one HT16K33 driven 4 digit 14 segment LED. The device used for development
4+
uses VCC at 5v, but also allows the I2C voltage to be selected by connecting the vi2c pin to the appropriate voltage, in the Pico case 3v3 as the
5+
GPIO pins are not 5v tolerant.
6+
7+
NOTE: Other manufacturers make very similar devices with very similar names (e.g. Vinka VK16K33)). These may or may not work!
8+
9+
== Wiring information
10+
11+
Wiring up the device requires 5 jumpers, to connect VCC (3.3v), GND, vi2c (3v3), SDA and SCL. The example here uses I2C port 0, which is assigned to GPIO 4 (SDA) and 5 (SCL) in software. Power is supplied from the 3.3V pin.
12+
13+
WARNING: Some displays of this type are 5v with no option to select 3v3 for the I2c. If you wish to use a 5v display you will need to use level shifters on the SDA and SCL lines to convert from the 3.3V used by the RP2040.
14+
15+
Connections on Raspberry Pi Pico board, other boards may vary.
16+
17+
GPIO 4 (pin 6)-> SDA on LED board
18+
GPIO 5 (pin 7)-> SCL on LED board
19+
GND (pin 38) -> GND on LED board
20+
5v (pin 40) -> VCC on LED board
21+
3.3v (pin 36) -> vi2c on LED board
22+
23+
== List of Files
24+
25+
CMakeLists.txt:: CMake file to incorporate the example in to the examples build tree.
26+
ht15k33_i2c.c:: The example code.
27+
28+
== Bill of Materials
29+
30+
.A list of materials required for the example
31+
[[ht15k33_i2c-bom-table]]
32+
[cols=3]
33+
|===
34+
| *Item* | *Quantity* | Details
35+
| Breadboard | 1 | generic part
36+
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
37+
| ht16k33 based LCD panel | 1 | generic part
38+
| M/M Jumper wires | 5 | generic part
39+
|===

i2c/ht16k33_i2c/ht16k33_i2c.c

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/**
2+
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <stdio.h>
8+
#include <string.h>
9+
#include "pico/stdlib.h"
10+
#include "hardware/i2c.h"
11+
#include "pico/binary_info.h"
12+
#include <ctype.h>
13+
14+
/* Example code to drive a 4 digit 14 segment LED backpack using a HT16K33 I2C
15+
driver chip
16+
17+
NOTE: The panel must be capable of being driven at 3.3v NOT 5v. The Pico
18+
GPIO (and therefore I2C) cannot be used at 5v. In development the particular
19+
device used allowed the PCB VCC to be 5v, but you can set the I2C voltage
20+
to 3.3v.
21+
22+
Connections on Raspberry Pi Pico board, other boards may vary.
23+
24+
GPIO 4 (pin 6)-> SDA on LED board
25+
GPIO 5 (pin 7)-> SCL on LED board
26+
GND (pin 38) -> GND on LED board
27+
5v (pin 40) -> VCC on LED board
28+
3.3v (pin 36) -> vi2c on LED board
29+
*/
30+
31+
// How many digits are on our display.
32+
#define NUM_DIGITS 4
33+
34+
// By default these display drivers are on bus address 0x70. Often there are
35+
// solder on options on the PCB of the backpack to set an address between
36+
// 0x70 and 0x77 to allow multiple devices to be used.
37+
const int I2C_addr = 0x70;
38+
39+
40+
// commands
41+
42+
43+
#define HT16K33_SYSTEM_STANDBY 0x20
44+
#define HT16K33_SYSTEM_RUN 0x21
45+
46+
#define HT16K33_SET_ROW_INT 0xA0
47+
48+
#define HT16K33_BRIGHTNESS 0xE0
49+
50+
// Display on/off/blink
51+
#define HT16K33_DISPLAY_SETUP 0x80
52+
// OR/clear these to display setup register
53+
#define HT16K33_DISPLAY_OFF 0x0
54+
#define HT16K33_DISPLAY_ON 0x1
55+
#define HT16K33_BLINK_2HZ 0x2
56+
#define HT16K33_BLINK_1HZ 0x4
57+
#define HT16K33_BLINK_0p5HZ 0x6
58+
59+
// Converts a character to the bit pattern needed to display the right segments.
60+
// These are pretty standard for 14segment LED's
61+
uint16_t char_to_pattern(char ch) {
62+
// Map, "A" to "Z"
63+
int16_t alpha[] = {
64+
0xF7,0x128F,0x39,0x120F,0xF9,0xF1,0xBD,0xF6,0x1209,0x1E,0x2470,0x38,0x536,0x2136,
65+
0x3F,0xF3,0x203F,0x20F3,0x18D,0x1201,0x3E,0xC30,0x2836,0x2D00,0x1500,0xC09
66+
};
67+
68+
// Map, "0" to "9"
69+
int16_t num[] = {
70+
0xC3F,0x406,0xDB,0x8F,0xE6,0xED,0xFD,0x1401,0xFF,0xE7
71+
};
72+
73+
if (isalpha(ch))
74+
return alpha[toupper(ch) - 'A'];
75+
76+
if (isdigit(ch))
77+
return num[ch - '0'];
78+
79+
return 0;
80+
}
81+
82+
/* Quick helper function for single byte transfers */
83+
inline void i2c_write_byte(uint8_t val) {
84+
#ifdef i2c_default
85+
i2c_write_blocking(i2c_default, I2C_addr, &val, 1, false);
86+
#endif
87+
}
88+
89+
90+
void ht16k33_init() {
91+
i2c_write_byte(HT16K33_SYSTEM_RUN);
92+
i2c_write_byte(HT16K33_SET_ROW_INT);
93+
i2c_write_byte(HT16K33_DISPLAY_SETUP | HT16K33_DISPLAY_ON);
94+
}
95+
96+
// Send a specific binary value to the specified digit
97+
inline void ht16k33_display_set(int position, uint16_t bin) {
98+
uint8_t buf[3];
99+
buf[0] = position * 2;
100+
buf[1] = bin & 0xff;
101+
buf[2] = bin >> 8;
102+
i2c_write_blocking(i2c_default, I2C_addr, buf, count_of(buf), false);
103+
}
104+
105+
inline void ht16k33_display_char(int position, char ch) {
106+
ht16k33_display_set(position, char_to_pattern(ch));
107+
}
108+
109+
void ht16k33_display_string(char *str) {
110+
int digit = 0;
111+
while (*str && digit <= NUM_DIGITS) {
112+
ht16k33_display_char(digit++, *str++);
113+
}
114+
}
115+
116+
void ht16k33_scroll_string(char *str, int interval_ms) {
117+
int l = strlen(str);
118+
119+
if (l <= NUM_DIGITS) {
120+
ht16k33_display_string(str);
121+
}
122+
else {
123+
for (int i = 0; i < l - NUM_DIGITS + 1; i++) {
124+
ht16k33_display_string(&str[i]);
125+
sleep_ms(interval_ms);
126+
}
127+
}
128+
}
129+
130+
void ht16k33_set_brightness(int bright) {
131+
i2c_write_byte(HT16K33_BRIGHTNESS | (bright <= 15 ? bright : 15));
132+
}
133+
134+
void ht16k33_set_blink(int blink) {
135+
int s = 0;
136+
switch (blink) {
137+
default: break;
138+
case 1: s = HT16K33_BLINK_2HZ; break;
139+
case 2: s = HT16K33_BLINK_1HZ; break;
140+
case 3: s = HT16K33_BLINK_0p5HZ; break;
141+
}
142+
143+
i2c_write_byte(HT16K33_DISPLAY_SETUP | HT16K33_DISPLAY_ON | s);
144+
}
145+
146+
int main() {
147+
148+
stdio_init_all();
149+
150+
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
151+
#warning i2c/ht16k33_i2c example requires a board with I2C pins
152+
#else
153+
// This example will use I2C0 on the default SDA and SCL pins (4, 5 on a Pico)
154+
i2c_init(i2c_default, 100 * 1000);
155+
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
156+
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
157+
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
158+
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
159+
// Make the I2C pins available to picotool
160+
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
161+
162+
printf("Welcome to HT33k16!\n");
163+
164+
ht16k33_init();
165+
166+
ht16k33_display_set(0, 0);
167+
ht16k33_display_set(1, 0);
168+
ht16k33_display_set(2, 0);
169+
ht16k33_display_set(3, 0);
170+
171+
again:
172+
173+
ht16k33_scroll_string("Welcome to the Raspberry Pi Pico", 150);
174+
175+
// Do a speeding up propeller effort using the inner segments
176+
int bits[] = {0x40, 0x0100, 0x0200, 0x0400, 0x80, 0x2000, 0x1000, 0x0800};
177+
for (int j = 0;j < 10;j++) {
178+
for (int i = 0;i< count_of(bits); i++) {
179+
for (int digit = 0;digit <= NUM_DIGITS; digit++) {
180+
ht16k33_display_set(digit, bits[i]);
181+
}
182+
sleep_ms(155 - j*15);
183+
}
184+
}
185+
186+
char *strs[] = {
187+
"Help", "I am", "in a", "Pico", "and ", "Cant", "get ", "out "
188+
};
189+
190+
for (int i = 0; i < count_of(strs); i++) {
191+
ht16k33_display_string(strs[i]);
192+
sleep_ms(500);
193+
}
194+
195+
sleep_ms(1000);
196+
197+
// Test brightness and blinking
198+
199+
// Set all segments on all digits on
200+
ht16k33_display_set(0, 0xffff);
201+
ht16k33_display_set(1, 0xffff);
202+
ht16k33_display_set(2, 0xffff);
203+
ht16k33_display_set(3, 0xffff);
204+
205+
// Fade up and down
206+
for (int j=0;j<5;j++) {
207+
for (int i = 0; i < 15; i++) {
208+
ht16k33_set_brightness(i);
209+
sleep_ms(30);
210+
}
211+
212+
for (int i = 14; i >=0; i--) {
213+
ht16k33_set_brightness(i);
214+
sleep_ms(30);
215+
}
216+
}
217+
218+
ht16k33_set_brightness(15);
219+
220+
ht16k33_set_blink(1); // 0 for no blink, 1 for 2Hz, 2 for 1Hz, 3 for 0.5Hz
221+
sleep_ms(5000);
222+
ht16k33_set_blink(0);
223+
224+
goto again;
225+
226+
return 0;
227+
#endif
228+
}

0 commit comments

Comments
 (0)