だいたい300円ぐらいのものです。MAX7219 というLEDドライバを使っていて、SPI で表示を変えられます。(正確には 7219 は SPI 対応とは書いてないのですが、CS の扱いが違うだけ? なのか、ほぼSPIと同じインターフェイスです。よくわかりません)
SPI を使ったことがなかったので一応自分で書いてみました。BCD のデコーダが入っており、数字ぐらいの表示なら自分でLEDとのマッピングを持つ必要はありません。
モードがいくつかあって
- 全桁自分で制御 (7セグメント+ドットに対応するビットを自分で入れる)
- 最下位桁だけBCDで残りは自分で制御
- 上位4桁は自分で制御して、下位4桁はBCD
- 全桁BCD
と選べます。7セグでアルファベット表示したい、みたいな場合は全桁自分でやる必要があります (マッピングすなわちフォント情報を持つ)
コード
書いたコードでは、全桁BCDでやるようにしてみました。マッピング持つのが面倒なのと、実質自分が使おうと思う用途だと数字以外表示しなそうだな、という気がしています (7セグでアルファベット表示させるのは視認性が悪いので好きじゃない)
SPI 通信はビット数のキリがいいのでハードウェアを使ってやっています。MAX7219 は 10MHz の SPI らしいのでそのようにしてみました。チップセレクトだけコンストラクタに渡すようにしています。
#include <Arduino.h>
#include <SPI.h>
#include <string.h>
class MAX7219 {
uint8_t CS;
public:
enum class ADDRESS : uint8_t {
NOOP = 0b0000,
DIGIT0 = 1,
DIGIT1 = 2,
DIGIT2 = 3,
DIGIT3 = 4,
DIGIT4 = 5,
DIGIT5 = 6,
DIGIT6 = 7,
DIGIT7 = 8,
DECODE_MODE = 0b1001,
INTENSITY = 0b1010,
SCAN_LIMIT = 0b1011,
SHUTDOWN = 0b1100,
DISPLAY_TEST = 0b1111,
};
enum class SHUTDOWN_MODE : uint8_t {
SHUTDOWN = 0b0,
NORMAL = 0b1,
};
enum class DECODE_MODE : uint8_t {
NO_DECODE_FOR_DIGITS_7_0 = 0b00000000,
CODE_B_DECODE_FOR_DIGIT_0_NO_DECODE_FOR_DIGITS_7_1 = 0b00000001,
CODE_B_DECODE_FOR_DIGIT_3_0_NO_DECODE_FOR_DIGITS_7_4 = 0b00001111,
CODE_B_DECODE_FOR_DIGIT_7_0 = 0b11111111,
};
MAX7219(uint8_t _cs) :
CS(_cs)
{
pinMode(CS, OUTPUT);
}
void write(ADDRESS address, uint8_t data) {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite(CS, LOW);
SPI.transfer(static_cast<uint8_t>(address));
SPI.transfer(data);
digitalWrite(CS, HIGH);
SPI.endTransaction();
}
void begin() {
SPI.begin();
setDecodeMode(DECODE_MODE::CODE_B_DECODE_FOR_DIGIT_7_0);
setScanLimit(7);
setShutdown(false);
setIntensity(8);
for (int i = 0; i < 8; i++) {
write(static_cast<ADDRESS>(i + 1), 1);
}
}
void setDecodeMode(DECODE_MODE mode) {
write(ADDRESS::DECODE_MODE, static_cast<uint8_t>(mode));
}
void setScanLimit(uint8_t limit) {
write(ADDRESS::SCAN_LIMIT, limit);
}
void setIntensity(uint8_t intensity) {
write(ADDRESS::INTENSITY, intensity);
}
void setShutdown(bool shutdown) {
write(ADDRESS::SHUTDOWN, static_cast<uint8_t>(shutdown ? SHUTDOWN_MODE::SHUTDOWN : SHUTDOWN_MODE::NORMAL));
}
void print(const char* buf) {
size_t len = strlen(buf);
uint8_t digit = 0, dp = 0;
for (size_t i = 0; i < len && digit < 8; i++) {
const char c = buf[len - i - 1];
if (c == '.') {
dp = 1<<7;
continue;
}
uint8_t b;
if (c == '-') {
b = 0b1010;
} else
if (c == ' ') {
b = 0b1111;
} else
if ('0' <= c && c <= '9') {
b = static_cast<uint8_t>(c - '0');
} else {
continue;
}
write(static_cast<ADDRESS>(digit + 1), b | dp);
dp = 0;
digit++;
}
for (; digit < 8; digit++) {
write(static_cast<ADDRESS>(digit + 1), 0b1111);
}
}
};
MAX7219 leds(10);
void setup() {
leds.begin();
leds.print("-1234.567");
delay(3000);
}
void loop() {
leds.print(String((float)micros() / 1000).c_str());
delay(29);
}