ラズパイPicoの7セグメントLEDのSPI接続方法を見直しました
私が書いた記事で、以下の記事が比較的読まれているのでなぜだろうと思っていたんですが、ふと思い立って、再度実行してみたら動かないんです。
おかしいなぁと思っていろいろ調べてみたんですが、皆目見当がつきません。
そこでChatGPT先生とやりとりをしていて、SPI通信を行う際は、トランザクションの設定が必要です、と言われました。
???🤔
今までトランザクションの開始と終了なんて考慮していないよ?
でもだまされたと思って試したところ、なんと動きました。
動いたのはよかったのですが、それにしてもなんとも腑に落ちません。Raspberry pi Pico のプラットフォームの仕様が変わったのかもしれない。とさらに調べていたら、earlephilhower版プラットフォームのバージョンアップ履歴 リリース3.6.0において、「SPIトランザクションとSPISlaveが追加されました」という項目があります。つまりこのバージョン以降SPIの記述方法が変わっているんですね。
Arduino IDE 側も同様に変更になっているので、この時 2023年9月にSPIの扱いが大きく変わったということです。
さらにもう少し調べると、
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
の2行も非推奨になって、SPISettings を使え となっています。
ということで、以下にトランザクションを考慮したコードを記します。
マイコンは pico互換の Tiny2040 を利用しています。
また、前回のコードをブラッシュアップして、少々記述方法が変わっています。
まずは配線方法から。
/**
* マイコン:Tiny2040.
* 利用製品:秋月電子通商 AE-7SEG-BOARD-KIT.
* 開発環境:VScode + PlatformIO + earlephilhower版RP2040プラットフォーム.
*
*/
#include <Arduino.h>
#include <SPI.h>
const byte digits[] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01100111, // 9
0b01110111, // A
0b01111100, // b
0b00111001, // C
0b01011110, // d
0b01111001, // E
0b01110001, // F
0b10000000 // dot
};
int waitTime = 300;
byte colorR = 0;
byte colorG = 63;
byte colorB = 127;
// Tiny2040には、SPI1は実在しない
// Tiny2040のSPI0はデフォルトは D0-D3 となっている
//byte pinRX = D0; // 別名:MISO
//byte pinCS = D1; // 別名:SS
//byte pinSCK = D2; // SCK
//byte pinTX = D3; // 別名:MOSI
//今回はSPI0を D4-D7 で使用することとする
//byte pinRX = D4; // 7セグLEDでは使わない
//byte pinCS = D5; // 7セグLEDではCSとして使わない
byte pinLatch = D5; // 汎用ピン(latch)として使用する
byte pinSCK = D6; // SPI0のSCKとして使用
byte pinTX = D7; // SPI0のTXとして使用
byte pinR = D18; // LED RED
byte pinG = D19; // LED GREEN
byte pinB = D20; // LED BLUE
void setup() {
pinMode(pinLatch, OUTPUT);
pinMode(pinSCK, OUTPUT);
pinMode(pinTX, OUTPUT);
pinMode(pinR, OUTPUT);
pinMode(pinG, OUTPUT);
pinMode(pinB, OUTPUT);
// pinLatch はSPI接続ではないので SPIとしては定義しない
SPI.setSCK(pinSCK);
SPI.setTX (pinTX);
SPI.begin ();
}
// SPIの設定 SPICLOCKは1MHzに, MSBFIRDT, SPI_MODE0 はデフォルト値
SPISettings SPIConfig(1000000, MSBFIRST, SPI_MODE0);
void loop() {
for (int forLoop = 0; forLoop < 17; forLoop++) {
SPI.beginTransaction(SPIConfig); // トランザクションを開始し、SPICLOCKを設定
digitalWrite(pinLatch, LOW); // データ送信前にLATCHをLOWにして準備
SPI.transfer(digits[forLoop]); // SPI通信でデータ送信
digitalWrite(pinLatch, HIGH); // データ送信後にLATCHをHIGHにしてデータを確定
SPI.endTransaction(); // トランザクションを終了
// おまけ Tiny2040のLEDの色を変えてみる
analogWrite(pinR, colorR + map(forLoop, 0, 16, 0, 255));
analogWrite(pinG, colorG + map(forLoop, 0, 16, 0, 255));
analogWrite(pinB, colorB + map(forLoop, 0, 16, 0, 255));
delay(waitTime);
}
}
もし前回の記事を読まれて、うまく動かないなとなった方は、今回のコードを試してみてください。
でも、SPI0, SPI1 といったSPI接続そのものについて知りたい方、Tiny2040ではなくラズパイPicoでの記述方法を知りたい方は、前回記事を参照してください。
にしても以前と互換性のない変更は、いろいろと困りますね。。
余談ですが、配線図は Fritzingで作ろうと思ったんですが、秋月7セグLEDキットもTiny2040も部品がないので、自分で作ろうかと作り方を調べたり必要なデータを用意しようとしたんですが、かなり大変なので写真にしちゃいました😆