Hyodot が 2026年08月29日10時45分59秒 に編集
コメント無し
本文の変更
# 作品の紹介 - この作品は、8桁の7セグメントLEDモジュールを使って「Hello World」と英文字を表示します。 - 8桁の7セグメントLEDモジュールは、DFROBOTの「3-Wire LED Module 8 Digital」、品番は「DFR0090」です。スイッチサイエンスなどから入手できます。 - 使用言語は、MicroPythonです。マイコンは、Raspberry Pi Pico2です。他のPicoでも使えます。 - 「Lチカの次に何をしよう?」という方にピッタリです。 # 作品紹介動画 [作品紹介動画](https://www.youtube.com/watch?v=sN6VUnjW-xM) # DFR0090について - DFR0090(3-Wire LED Module 8 Digital)は、マイコンから見るとSPI接続のモジュールです。ただし、マイコン側のMISOに相当する端子はないので、3-Wireと表記しているのかも知れません。 - 8桁の7セグメントLEDであり、上位桁からデータ入力し、表示しながら下位桁に右シフトします。 - 「日」字型の7つのセグメントと「.」ドットを加え、8bitに対応したデータをSPI通信で送信します。 - すべてのセグメントを点灯するときは、8ビットのすべてを「0」にします。 - すべてのセグメントを消灯するときは、8ビットのすべてを「1」にします。 - ダイナミック表示ではないので、表示したいデータ1回送るだけで表示し続けます。 # DFR0090利用のコツ - DFR0090を使用するうえで、少し戸惑ったのは、LowTrue(bit=0)で点灯することと、上位桁(左端)からデータ入力し下位桁(右端)に右シフトすることです。 - すべてのセグメントを消灯するときは、8ビットのすべてを「1」にする必要がありますが、MicroPythonの癖なのか、74HC595の癖なのか、SPIで最上位ビット(dot表示に対応)を「1」にすると2桁にわたって表示され、うまく表示できません。 - 解決策として、Pico側のSPI-MOSI端子とDFR0090のDATA端子間にハードウェアのインバータ(74HC04)を入れました。(CKLとCEにもインバータを2回=バッファとして=利用していますが、インバータが余ったから入れただけです) - この作品では、dot表示はできません。 # 主要部品 |デバイス名|用途|接続方法| |:-------------------------|:--------------|:-------------|:----------------| |Raspberry Pi Pico2 | マイコン | DFR0090とSPI接続| |DFR0090 | LED Module 8 Digital | Pico2とSPI接続| |74HC04 | MOSI信号反転用 | Pico2 と DFR0090間| |三端子レギュレータ | Pico2電流負担軽減 | USB5V⇒3.3V| ## 入手先など(ご参考) Raspberry Pi Pico 2 https://www.switch-science.com/products/9809 DFROBOT-DFR0090 3-Wire LED Module 8 Digital (Arduino Compatible) https://www.switch-science.com/products/4187 6回路インバーター TC74HC04AP https://akizukidenshi.com/catalog/g/g114058/ 低損失三端子レギュレーター 3.3V1A BA033CC0T https://akizukidenshi.com/catalog/g/g113675/ # 配線接続図  一言でいうと、PicoのSPI-MOSI信号からDFR0090のDATA信号間に、インバータを入れるだけです。 - SPI信号接続部分の拡大図  - ブレッドボードの配線の画像  - ブレッドボードの配線の拡大画像  - DFR0090 Input側コネクタ の信号  # プログラムの紹介 ## プログラム ### spi74hc595cp.py ```MicroPython:spi74hc595cp.py ######################################################################################### # spi74hc595cp.py # 2026/08/24 programed by Hyodo # # DFROBOT-DFR0090 74HC595使用のSPI接続 7セグメントLED_ x 8 Digits # # DFROBOT-DFR0090 利用上の留意事項 # ● 8桁のLEDは、各桁に74HC595を使用。データは上位桁から入り下位桁に右シフトされる。 # データが下位桁から入り上位桁に左シフトされるのであれば、「Hello World」の順に送ればよいが、 # データが上位桁から入り下位桁に右シフトされる場合は「dlroW olleH」の順に送る必要がある。 # このプログラムでは、関数 ledspi_str(): と ledspi_str_rvs(): 内で対応した。 # ● DFROBOT-DFR0090 へのデータは Low(bit=0)で点灯するので、0b00000000 で全セグメントとドットが点灯し、 # 0b11111111 で全セグメントとドットが消灯するのだが、MicroPythonでは、0b11111111 をうまく送出できない。 # 送信方法を工夫すれば可能になるかもしれないが、面倒なのでハードウェアでインバータを入れることにし、 # プログラム内のセグメントデータは high(bit=1)で点灯、「0」で消灯する構造にした。 # 上記2点は、どちらも逆の設定のほうが、デバイスとしては使いやすい。私が設計するならそのようにします。 # # Pico2 SPI mosi端子と DFROBOT-DFR0090 SPI-DATA 間にインバータを入れてデータを反転させました。 # 74HC04(Inverter) # Pico 2 gpioNo PinNo PinNo PinNo DFR0090 # SPI mosi Pin(19) [25] -----13 |> 12------ SPI-DATA # # ######################################################################################### # from machine import SPI, Pin from utime import sleep # μtimeからsleepを組み込む # SPI Setting cs7 = Pin(17, Pin.OUT) spi = SPI(0, baudrate=5_000_000, polarity=1, phase=1, sck=Pin(18), mosi=Pin(19), miso=Pin(16)) # DFROBOT-DFR0090 は、出力デバイスで入力はないため、miso=Pin(16) には未接続です。 # 7segment LED size of digits DFROBOT-DFR0090は8桁です。 _DIGITS_SIZE = 8 # Segment Map ・・・ 日の字型の7セグメントLEDの位置関係は次のとおりです。 # # ---a--- # | | # f b # | | # ---g--- # | | # e c # | | # ---d--- . (dot) # # Segment Data bit=1 LED On ・・・ ビットデータを「1」にセットしたセグメントが点灯します。 # どのように設定するかは自由ですが、最上位の「.」(dot)を「1」にすると、文字データではなくなるためか # Micropython側でうまく送れなません。送信方法(データ構造)を工夫すれば可能になるかも。 # # Dec .gfedcba id Hex n32 = 0b00000000 # 00 : 0x20 : Null n33 = 0b00101010 # 01 : 0x21 : ! n34 = 0b00100010 # 02 : 0x22 : " n35 = 0b01001001 # 03 : 0x23 : # n36 = 0b01101100 # 04 : 0x24 : $ n37 = 0b00100100 # 05 : 0x25 : % n38 = 0b01011010 # 06 : 0x26 : & n39 = 0b00000010 # 07 : 0x27 : ' n40 = 0b00111001 # 08 : 0x28 : ( n41 = 0b00001111 # 09 : 0x29 : ) n42 = 0b01110000 # 10 : 0x2a : * n43 = 0b01000110 # 11 : 0x2b : + n44 = 0b00010000 # 12 : 0x2c : , n45 = 0b01000000 # 13 : 0x2d : - n46 = 0b00001000 # 14 : 0x2e : . n47 = 0b01010010 # 15 : 0x2f : / n48 = 0b00111111 # 16 : 0x30 : 0 n49 = 0b00000110 # 17 : 0x31 : 1 n50 = 0b01011011 # 18 : 0x32 : 2 n51 = 0b01001111 # 19 : 0x33 : 3 n52 = 0b01100110 # 20 : 0x34 : 4 n53 = 0b01101101 # 21 : 0x35 : 5 n54 = 0b01111101 # 22 : 0x36 : 6 n55 = 0b00100111 # 23 : 0x37 : 7 n56 = 0b01111111 # 24 : 0x38 : 8 n57 = 0b01101111 # 25 : 0x39 : 9 n58 = 0b01000001 # 26 : 0x3a : : n59 = 0b01000101 # 27 : 0x3b : ; n60 = 0b01011000 # 28 : 0x3c : < n61 = 0b01001000 # 29 : 0x3d : = n62 = 0b01001100 # 30 : 0x3e : > n63 = 0b00101011 # 31 : 0x3f : ? n64 = 0b01011111 # 32 : 0x40 : @ n65 = 0b01110111 # 33 : 0x41 : A n66 = 0b01111100 # 34 : 0x42 : b n67 = 0b01011000 # 35 : 0x43 : c n68 = 0b01011110 # 36 : 0x44 : d n69 = 0b01111001 # 37 : 0x45 : E n70 = 0b01110001 # 38 : 0x46 : F n71 = 0b00111101 # 39 : 0x47 : G n72 = 0b01110110 # 40 : 0x48 : H n73 = 0b00011001 # 41 : 0x49 : i n74 = 0b00001101 # 42 : 0x4a : J n75 = 0b01111010 # 43 : 0x4b : K n76 = 0b00111000 # 44 : 0x4c : L n77 = 0b01010101 # 45 : 0x4d : m n78 = 0b01010100 # 46 : 0x4e : n n79 = 0b01011100 # 47 : 0x4f : o n80 = 0b01110011 # 48 : 0x50 : P n81 = 0b01100111 # 49 : 0x51 : q n82 = 0b01010000 # 50 : 0x52 : r n83 = 0b00101101 # 51 : 0x53 : S n84 = 0b00110001 # 52 : 0x54 : T n85 = 0b00111110 # 53 : 0x55 : U n86 = 0b01111110 # 54 : 0x56 : V n87 = 0b00011101 # 55 : 0x57 : w n88 = 0b01101010 # 56 : 0x58 : X n89 = 0b01101110 # 57 : 0x59 : Y n90 = 0b00011011 # 58 : 0x5a : Z n91 = 0b00100001 # 59 : 0x5b : [ n92 = 0b01100100 # 60 : 0x5c : \ n93 = 0b00001100 # 61 : 0x5d : ] n94 = 0b00100011 # 62 : 0x5e : ^ n95 = 0b00001000 # 63 : 0x5f : _ : . # Ascii Code 順とかで特定の範囲のデータ(数字、英文字、記号など)を送信するために用意しました。 # 上記の一覧で id値を指定して利用するように考えています。 buff = [n32, n33, n34, n35, n36, n37, n38, n39, n40, n41, n42, n43, n44, n45, n46, n47, n48, n49, n50, n51, n52, n53, n54, n55, n56, n57, n58, n59, n60, n61, n62, n63, n64, n65, n66, n67, n68, n69, n70, n71, n72, n73, n74, n75, n76, n77, n78, n79, n80, n81, n82, n83, n84, n85, n86, n87, n88, n89, n90, n91, n92, n93, n94, n95] ######################################################################################### # ここからは、関数の登録です。 # Clear LED # t を指定することで、消去直後の待ち時間を指定できます。指定しなければ 0 sec def ledspi_clear(t=0): print('Clear LED') for i in range(_DIGITS_SIZE): cs7.value(0) spi.write(chr(n32)) cs7.value(1) sleep(t) # Display str 関数 # 上位桁(左端)から表示しながら下位桁(右端)に右シフトする。 # DFROBOT-DFR0090 で s='12345678' を '12345678' と表示する関数 # データの並びを逆順序にする操作を入れています。 # t を指定することで、シフトの時間間隔を指定できます。指定しなければ 0 sec def ledspi_str(s, t=0): print('LED Display str', s) # 文字列 s をリスト lm に変換 lm = [] for i in range(len(s)):lm.append(s[i]) # リストの並びを逆順序にする # この操作は、DFROBOT-DFR0090 上位桁から表示して下位桁に右シフトする構造のために必要 lm.reverse() for i in range(len(lm)): cs7.value(0) j = int(ord(lm[i]) - 32) spi.write(chr(buff[j])) cs7.value(1) sleep(t) # Display str reverse 関数 # 下位桁(右端)から表示しながら上位桁左端)に左シフトする。 # DFROBOT-DFR0090 で s='12345678' を '12345678' と表示する関数 # データの並びを逆順序にする操作を入れています。 # t を指定することで、シフトの時間間隔を指定できます。指定しなければ 0 sec def ledspi_str_rvs(s, t=0): print('LED Display str reverse', s) # 文字列 s の先頭に、表示モジュールの桁数分のスペースを追加する stx = '' for i in range(_DIGITS_SIZE):stx += ' ' s = stx + s print(s) for i in range(len(s) - _DIGITS_SIZE +1): # 先頭から _DIGITS_SIZE ずつ取り出して逆順序に並び替える val_s = s[i:i+_DIGITS_SIZE] # 文字列 val_s をリスト lm に変換 lm = [] for j in range(len(val_s)):lm.append(val_s[j]) # リストの並びを逆順序にする # この操作は、DFROBOT-DFR0090 上位桁から表示して下位桁に右シフトする構造のために必要 lm.reverse() # リスト lm を表示する for k in range(len(lm)): cs7.value(0) n = int(ord(lm[k]) - 32) # 文字コードを id に変換するための-32 spi.write(chr(buff[n])) cs7.value(1) sleep(t) print() # Display buff m to n # 登録した記号などを、テーブルの指定された範囲で表示する。 # DFROBOT-DFR0090 対応して、下位桁(右端)から表示しながら上位桁左端)に左シフトするため、 # データの並びを逆順序にする操作を入れています。 # t を指定することで、シフトの時間間隔を指定できます。指定しなければ 0.5 sec def ledspi_m2n(m, n, t=0.5): print(f'LED Display buff {m} to {n}') # 文字列 lst の先頭に、表示モジュールの桁数分の Null(無表示データ)を用意する lst = [] for i in range(_DIGITS_SIZE):lst.append(chr(buff[0])) # 文字列 に、指定された範囲の表示データを追加する for i in range(m, n):lst.append(chr(buff[i])) # 文字列 lst の末尾に、表示モジュールの桁数分の Null(無表示データ)を用意する for i in range(_DIGITS_SIZE):lst.append(chr(buff[0])) print(lst) for i in range(len(lst) - _DIGITS_SIZE +1): # 文字列 s の先頭から _DIGITS_SIZE ずつ取り出して逆順序に並び替える val_lst = lst[i:i+_DIGITS_SIZE] # 文字列 val_s をリスト lm に変換 lm = [] for j in range(len(val_lst)):lm.append(val_lst[j]) # リストの並びを逆順序にする # この操作は、DFROBOT-DFR0090 上位桁から表示して下位桁に右シフトする構造のために必要 lm.reverse() # リスト lm を表示する for k in range(len(lm)): cs7.value(0) spi.write(lm[k]) cs7.value(1) sleep(t) print() ''' # Display buff m to n ご参考 # DFROBOT-DFR0090 ではなく、下位桁から表示しながら上位桁に左シフトするモジュールの場合 # 下位桁から表示しながら上位桁に左シフトする。プログラムはシンプルで済む。 def ledspi_m2n(m, n, t=0.5): print(f'LED Display buff {m} to {n}') for i in range(m, n): cs7.value(0) spi.write(chr(buff[i])) cs7.value(1) sleep(t) print() ''' ######################################################################################### # ここからがメインプログラムになります。 # Micropython Main Program # Clear LED ledspi_clear() # LED Test data='12345678' 上位桁から右シフトで表示する。シフト間隔は 0.5秒 val_str = str.upper('12345678') print('ledspi_str(val_str)', val_str) ledspi_str(val_str, 0.5) sleep(1) # Clear LED ledspi_clear() # LED Test data='12345678' 下位桁から左シフトで表示する。シフト間隔は 0.5秒 val_str = str.upper('12345678') print('ledspi_str_rvs(val_str)', val_str) ledspi_str_rvs(val_str, 0.5) sleep(1) # Clear LED ledspi_clear() # Display Hello World to Left val_str = str.upper('Hello World ') ledspi_str_rvs(val_str, 0.5) sleep(1) # Clear LED ledspi_clear() # Numerical val_str = str.upper('Numeric ') ledspi_str(val_str) sleep(2) ledspi_m2n(16, 26) # Clear LED ledspi_clear(1) # Alphabet val_str = str.upper('Alphabet') ledspi_str(val_str) sleep(2) ledspi_m2n(33, 59) # Clear LED ledspi_clear(1) # Symbol-1 val_str = str.upper('Symbol-1') ledspi_str(val_str) sleep(2) ledspi_m2n(0, 16, 1) # Clear LED ledspi_clear(1) # Symbol-2 val_str = str.upper('Symbol-2') ledspi_str(val_str) sleep(2) ledspi_m2n(26, 33, 1) # Clear LED ledspi_clear(1) # Symbol-3 val_str = str.upper('Symbol-3') ledspi_str(val_str) sleep(2) ledspi_m2n(59, 64, 1) # Clear LED ledspi_clear(1) for k in range(3): # Hello val_str = str.upper('Hello ') ledspi_str(val_str, 0) sleep(1) # World val_str = str.upper('World ') ledspi_str(val_str, 0) sleep(1) # Clear LED ledspi_clear(1) # Bye Bye val_str = str.upper('Bye Bye - - - End !') ledspi_str_rvs(val_str, 0.5) # プログラム終了 ``` ## プログラムの説明 ### 7セグメントLEDのセグメントとデータの関係 MicroPythonで7セグメントLEDのセグメントのデータは、次のように構成します。 何も表示しない(a~g、および、dotのセグメントを点灯しない)場合と、dotを除くセグメントを点灯して「8」を表示する場合を示します。  |10進数相当| .gfedcba | id | Hex | 表示内容 | |:-----------|:--------------|:------|:------|:-----------| | n32 | 0b00000000 | 00 | 0x20 | 何も表示しない | | n56 | 0b01111111 | 24 | 0x38 | 「8」を表示する | ### 関数の説明 4つの関数を用意しました。 #### ledspi_clear(t=0) 関数 - この関数は、8桁すべての7セグメントLEDを消灯します。 n32 は n32 = 0b00000000 であり、全セグメント点灯しないデータです。 #### ledspi_str(s, t=0) 関数 - この関数は、上位桁(左端)から表示しながら下位桁(右端)に右シフトします。 - 文字列 s を引数として渡します。 #### ledspi_str_rvs(s, t=0) 関数
- この関数は、下位桁(右端)から表示しながら上位桁左端)に左シフトします。
- この関数は、下位桁(右端)から表示しながら上位桁(左端)に左シフトします。
- 文字列 s を引数として渡します。 # もう少し楽しむには - プログラムでは、英文字を7セグメントLEDで表示するbitの組み合わせを、私の感覚で作りました。bitの組み合わせは、プログラムで設定できます。オレはこうしたい、わたしならこうする、というものがあると思います。キャラクターの表示もできます。 - 私ができなかった dot「.」表示をしてみてください。 - あぁ、動いた、終わり。ではなく、自分なりの表示を作り楽しむことで、プログラムスキルがアップします。是非、挑戦してください。
**最後までご覧いただきありがとうございます。何かの参考になれば幸いです。**
**最後までご覧いただきありがとうございます。何かのご参考になれば幸いです。**