This display seems to have 32 addressable LEDs controlled by only
7 pins. Judging from this fact, and from the provided pinout table, it
looks like a Charlieplexed matrix.
A typical way to drive this kind of matrix is by looping over the
cathodes. You pull one cathode pin LOW
, and then pull HIGH
all the
anodes of the LEDs you want to shine which are connected to this
particular cathode. Wait a few milliseconds, then move to the next
cathode. It is important that all pins that are not involved in lighting
an LED remain in INPUT
mode.
For example, let's say you want to light all the segments of the first
digit (display an “8”) while keeping everything else off. You first pull
pin 1 LOW
(first cathode) and pull HIGH
pins 2–5 (segments F, G, C
and D). Let that shine for a few milliseconds, then put everything to
high impedance (pins to INPUT
) and move to the next cathode: pin 2
goes LOW
and pin 1 (segment A) goes HIGH
. And so on until you have
done all the cathodes.
For the coding part, I would suggest using a 7×7 matrix of booleans
telling whether a particular segment is meant to be lit. The indices of
the array would be row = cathode number and column = anode number. The
array would have the same structure as the pinout table you posted,
except for the fact that the lines and columns would have indices
ranging 0–6 instead of 1–7. This should make it easy to handle
refreshing the display.
Drawing the digits is a bit trickier than with traditional 7-segment
displays, as for each segment you will have to find its coordinates in
the matrix (cathode number and anode number). For this, I would use a
“mapping matrix” that stores the mapping (digit number, segment number)
→ (cathode number, anode number).
Below is a tentative, and untested, implementation of these strategies.
Note that I did not write a function to output a digit, but that should
be easy to implement on top of the set_segment()
function defined
here. Besides, the question of how to draw a digit once you know how to
control individual segments is the standard 7-segment problem, for which
you should be able to find many tutorials.
Note that this code assumes you drive the display directly, using no
iterface other than current-limiting resistors. This carries the risk of
either overloading the cathode outputs or having the display be too dim,
depending on the current-limiting resistors. You may want to use
transistors for the cathodes, in which case you would have a set of
cathode pins different from the set of anode pins.
// Arduino pins connected to the display.
const uint8_t display_pins[7] = {2, 3, 4, 5, 6, 7, 8};
// Which segments are lit. Each segment is located in this matrix at
// the coordinates [cathode][anode].
bool segment_lit[7][7];
// Coordinates in the matrix above where a segment can be found.
struct SegmentCoordinates {
uint8_t cathode;
uint8_t anode;
};
// segments[digit][segment] gives the coordinates of
// any segment (0 = A) of any digit (0 = 1st digit).
const SegmentCoordinates segments[4][7] = {
// seg: A B C D E F G
{{1, 0}, {2, 0}, {0, 3}, {0, 4}, {3, 0}, {0, 1}, {0, 2}},
{{2, 1}, {3, 1}, {1, 4}, {5, 1}, {4, 1}, {1, 2}, {1, 3}},
{{3, 4}, {4, 2}, {4, 3}, {0, 5}, {2, 5}, {2, 3}, {2, 4}},
{{5, 6}, {6, 5}, {5, 4}, {3, 5}, {5, 3}, {4, 5}, {6, 4}}
};
// Turn a segment OFF (lit = false) or ON (lit = true).
void set_segment(uint8_t digit, uint8_t segment, bool lit) {
SegmentCoordinates coordinates = segments[digit][segment];
segment_lit[coordinates.cathode][coordinates.anode] = lit;
}
void setup(){}
void loop() {
static uint8_t cathode; // currently used cathode
// Set the current cathode to OUTPUT LOW.
digitalWrite(display_pins[cathode], LOW);
pinMode(display_pins[cathode], OUTPUT);
// Set the relevant anodes to OUTPUT HIGH.
for (int anode = 0; anode < 7; anode++) {
if (segment_lit[cathode][anode]) {
digitalWrite(display_pins[anode], HIGH);
pinMode(display_pins[anode], OUTPUT);
}
}
// Let that shine for a while.
delay(10);
// Turn off everything.
for (int pin = 0; pin < 7; pin++) {
pinMode(display_pins[pin], INPUT);
}
// Move to the next cathode.
if (++cathode >= 7) cathode = 0;
}
I used delay()
here for simplicity. In production code you would
handdle the timings with millis()
in a non-blocking fashion, in the
spirit of the “Blink without delay” tutorial.