前回はラズパイPicoのPIO(プログラマブルIO)ステートマシンを使って単体の74HC595を制御しました。今回は2個同時制御、直列接続と並列接続を1回で済ませようとしてツボにハマりました。2個目が動かないデス。なんで?並列接続にて問題追及、動作OKとなりました。ソフトバグの裏に半田付け不良が隠れていた。何ってこったい!
(ラズパイPico関係 総目次はこちら)
半田付けは苦手という意識があるので、表面実装部品を扱うときは注意していたつもりだったのです。しかし、このところ特段の失敗もなかったので、つい見逃してしまいました。DIPの74HC595が入手できなかったので、SOP16品を購入、秋月電子通商の以下のDIP化基板に半田付けしています。
SSOP20ピン(0.65mm)・SOP20ピン(1.27mm)DIP変換基板
ちょうどピタリのSOP16用基板が見当たらなかったので、SOP20用を端の4端子をNCで使っています。表は0.65mmピッチ、裏は1.27mmピッチで2系統対応の優れものです。1.27mmピッチ、余裕っしょ、と慢心したのが失敗の元。
2個並列接続の回路図
今回は、並列接続しか行わなかったです。その回路図は以下に。
回路図的には簡単ですが、前回に比べるとブレッドボード上の物理配線が密になってきたので、クリア信号はインアクティブ、アウトプットイネーブルは常時イネーブルとキメウチにしてしまいました。2個の74HC595それぞれにデータ線を割り当てていますが。クロックは共有です。
2並列化に伴うソフトウエアの変更
さて、2個ならべるだけの並列接続など前回延長で簡単だろ、と思ったですが、結構修正箇所がありました。PIOアセンブラのファイル内の要修正箇所は以下の通り。
-
- シリアルデータの出力を1ビットでなく2ビット単位とした
- シリアルデータの出力ピンを2端子で初期化(これに関わる箇所が3件)
最初、動かん、動かんと悩んだのは、後者の初期化3か所中、1か所の修正もれのため。
; PIO595 ; 74HC595 output test ; opin SI_A(18), SI_B(17) ; spin SCK(19), RCK(20) .program pio595 .side_set 2 .wrap_target pull block side 0 set x, 7 side 0 loop: ; out pins, 1 side 0 out pins, 2 side 0 nop side 0x1 nop side 0 jmp x-- loop side 0 nop side 0x2 nop side 0 .wrap % c-sdk { #include "hardware/gpio.h" static inline void pio595_program_init(PIO pio, uint sm, uint offset, uint opin, uint spin) { pio_sm_config c = pio595_program_get_default_config(offset); // sm_config_set_out_pins(&c, opin, 1); sm_config_set_out_pins(&c, opin, 2); // PAR sm_config_set_out_shift(&c, true, false, 0); // shift_right, no-autopull sm_config_set_sideset_pins(&c, spin); pio_gpio_init(pio, opin); pio_gpio_init(pio, opin+1); // PAR pio_gpio_init(pio, spin); pio_gpio_init(pio, spin+1); // pio_sm_set_consecutive_pindirs(pio, sm, opin, 1, true); pio_sm_set_consecutive_pindirs(pio, sm, opin, 2, true); // PAR pio_sm_set_consecutive_pindirs(pio, sm, spin, 2, true); sm_config_set_clkdiv(&c, 128); pio_sm_init(pio, sm, offset, &c); pio_sm_set_enabled(pio, sm, true); } static inline void pio595_program_stop(PIO pio, uint sm) { pio_sm_set_enabled(pio, sm, false); } %}
C言語ソースの方は、クリア制御、出力制御関係をバッサリ切ってしまったので、短くなりました。出力が2ピンとなるので出力ピンの開始番号の変更は必要。またテストパターンは、74HC595の2個分なので16ビット幅となりました。
#include <stdio.h> #include "pico/stdlib.h" #include "hardware/gpio.h" #include "hardware/pio.h" #include "pio595.pio.h" // 74HC595 PINS #define SI (18) #define SIB (17) #define SCK (19) #define RCK (20) #define G_ (21) #define SCLR_ (22) int main() { uint16_t dat = 0x0001; stdio_init_all(); puts("DUAL 74HC595 PIO state machine."); PIO pio = pio0; uint sm = pio_claim_unused_sm(pio, true); pio_sm_restart(pio, sm); uint offset = pio_add_program(pio, &pio595_program); pio595_program_init(pio, sm, offset, SIB, SCK); outputEnable595(); while (1) { pio_sm_put(pio, sm, dat); if (dat == 0x8000) { dat = 0x0001; } else { dat <<= 1; } //dat = (dat < 255)? ++dat : 0; sleep_us(100); } pio595_program_stop(pio, sm); puts("End of Execution.\r\n"); return 0; }
動かない?信号の確認
ビルドし、ラズパイPicoに書き込んで動作を見たところ、新たに追加した方の74HC595から出力が出ていませんでした。まずはシリアルクロックとデータ線を観察。ダメな方のデータ線にデータが載ってませんでした。発見したのは先に述べたとおりのPIOアセンブラの設定ミスです。それを修正し、両方でシリアルクロックとデータ線を確認しました。こんな感じ。OKです。
しかし、74HC595からのデータが出ませぬ。ようやくハードを疑います。
導通不良発見
ということで、ええい、ままよ、とブレッドボード上の2個の74HC595のポジションを交換してみました(勿論、電源切ってから。)交換したら、今まで出ていなかった側に出力が出て、出ていた側が出なくなりました(まあ、出力レベルをよく観察すれば交換などという暴挙にでなくても分かった筈ですが。)
ダメなDIP化基板をテスタで当たってみると、シリアルクロックの端子の導通不良みたいです。ルーペで見る分にはちゃんと接続しているように見えたのだけれど不良。半田ごてでチョチョイとな。導通しました。ちゃんとチェックしておけよ、自分。
動作確認
導通不良が無くなれば、動作はOKでした。こんな感じ。
目でみると、綺麗に並んでいるように見えますが、上記のテストプログラムのパターンを見れば、DIO8->DIO0->DIO9-> という形で交互に1が入っていったパターンであります。予定どおりか。