ESP32-WROOM-32EでMicroPythonを使い開発(通信編)

〔ESP-WROOM-02〕 〔マイコンのトップに戻る〕
[準備編] [module編] [GPIO編]   [I2S編] [WiFi編] [BLE編1] [BLE編2] [BLE編3] [色々編]


このページでは、ESP32-WROOM-32EのUART/SPI/I2Cを行ってみようと思います。
尚、ESP32-WROOM-32Eの端子配列一覧は前ページのこちらを参照願います。

《UART》

ESP32-WROOM-32Eには、UART0UART1UART2の3個のハードウェアUARTが有ります。
UART0は、GPIO1(TX)/GPIO3(RX)のピンでUSBと繋がっていて"REPL"(デフォルト)で使われます、
UART1は、GPIO9(RX)/GPIO10(TX)のピンですが、SPIフラッシュピンで使用なので使えません。
残りのUART2は利用できます、ピンは、 GPIO16(RX)/GPIO17(TX)です。
UART配線図
接続相手は、FT234XこちらのUSBシリアル変換
モジュールを使ってPCに繋いでみます。

電源はUSB接続で、
回路電源はボード出力3.3Vです。
UART2のGPIO16(RX)/GPIO17(TX)を使います。
FT432Xのピンは左から[5V][GND][TXD][RXD]の
順です。
あ、4番ピンにLED配線するのを忘れています。

@ ESP32-WROOM-32EボードをUSBでPCに繋ぎます。
A "PyCharm"を起動させ、こちらのCを操作する必要が有ります。(起動時最初のみ設定)
B "main.py"を新規登録して下記スクリプトを"main.py"に貼り付けましょう。
  (登録済みなら上書き貼り付けでも行いましょう)
C シリアル(TeraTerm等)端末を起動し、FT432Xの通信のポートで待ちましょう。
D ESP32-WROOM-32Eに書き込みます
  左側プロジェクトウインドウから"main.py"の文字を右クリックをして、[実行(U)'Flash main.py']を
  クリックします。
--------------------------------------------------------------------------------
import time
from machine import UART, Pin

# UART2を初期化(GPIO16=RX GPIO17=TX)
uart2 = UART(2, 9600)
uart2.init(9600, bits=8, parity=None, stop=1)
# ピン4番(GPIO4)をLED出力で割り付ける
led = Pin(4, Pin.OUT)

i = 0
led.on()                       # LED点灯
while True:
    if i > 30 : break          # 30カウントで終了
    uart2.write(str(i)+'\r\n') # UART出力
    i=i+1
    time.sleep_ms(1000)        # 1000msで繰り返す
led.off()                      # LED消灯
--------------------------------------------------------------------------------
動作はLEDが点灯し1秒毎のカウントを行い30カウントしたらLED消灯で終了です。

E シリアル端末に0〜30までの数値が表示されるはずです。

machine.UART
UART0を使いたい場合は、ESP8266の[通信編]を見ましょう。
uart1 = UART(1, baudrate=9600, rx=22, tx=23)
又は
uart2 = UART(2, baudrate=9600, rx=22, tx=23)
とすれば、"GPIOマトリクス機能"で任意のピンにUARTが利用出来る様です。
この機能、内蔵ペリフェラル用の信号は設定によって好きなピンに再割り当てする事が可能な様です。
まぁ、PICのPPS機能みたいなぁ感じいみたいなぁ。
だがぁ、高速信号は、パフォーマンス低下を回避する為にGPI16(RX)/GPIO17(TX)ピンを使いましょう。

ヘルプ(machine.UART)
詳しい説明は、ここ(ESP8266)又は、ここを参照しましょう。

《SPI》

3つのハードウェアSPIが有り高速(通信速度最大80MHz)です、
1(0Ch)つ目は、内蔵のSPIフラッシュと接続されているので使えません。
2(1Ch)つ目のピンは、GPIO12(MISO)/GPIO13(MOSI)/GPIO14(SCK)/GPIO15(SS)ピンです。
3(2Ch)つ目のピンは、GPIO19(MISO)/GPIO23(MOSI)/GPIO18(SCK)GPIO5(SS)ピンです。
(GPIO5/15のSS信号はスレーブ時に利用しますが、ここではスレーブ機能は実験していません)
複数のデバイスが同じバスを共有できます。各デバイスには、通信を行うバス上の特定のデバイスを
選択する為の個別の4番目の信号 SS(Slave Select)が必要です。
SSシグナルの管理はユーザーコードで(machine.Pin クラス経由で)行う必要があります。

SPIの接続相手として”7セグメントLEDシリアルドライバモジュール”を使ってみます。

SPI配線図
電源はUSB接続で、
回路電源はボード出力3.3Vです。
SPIはGPIO14(SCK)/GPIO13(MOSI)/
GPIO12(MISO)と、SS(CS)はLATCH信号として
GPIO4を使っています。
尚、今回はGPIO12(MISO)は使っていません。

@ ESP32-WROOM-32EボードをUSBでPCに繋ぎます。
A "PyCharm"を起動させ、こちらのCを操作する必要が有ります。(起動時最初のみ設定)
B "main.py"を新規登録して下記スクリプトを"main.py"に貼り付けましょう。
  (登録済みなら上書き貼り付けでも行いましょう)
C ESP32-WROOM-32Eに書き込みます
  左側プロジェクトウインドウから"main.py"の文字を右クリックをして、[実行(U)'Flash main.py']を
  クリックします。
--------------------------------------------------------------------------------
import time
from machine import SPI, Pin

# 7セグデータ
data = b'\x3F\x06\x5B\x4F\x66\x6D\x7D\x07\x7F\x6F'
buff = bytearray(1)

# SPIを初期化
spi = SPI(1, baudrate=2000000, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
# ピン4番(GPIO4)をSS(CS:LATCH)出力で割り付ける
ss = Pin(4, Pin.OUT)

x = 0
while True:
    ss.value(0)            # LATCH信号OFF
    buff[0] = data[x]
    x = x + 1
    if x > 9 : x = 0
    spi.write(buff)        # 7セグデータの出力
    ss.value(1)            # LATCH信号ON
    time.sleep_ms(1000)    # 1000msで繰り返す
--------------------------------------------------------------------------------
動作は数字0から9の表示を繰り返すだけです。

machine.SPI
SPI機能も"GPIOマトリクス機能"で任意のピンにSPIが利用出来る様です。
ですがぁ、通信速度が40MHzに制限される様です。

polarity はクロック極性でアイドリング時のクロック状態(HIGHTかLOWか)を示します。
(0=LOWで0V、1=HIGTで5V)
phas はクロック位相でシフトされたデータを読取るタイミング(立上がりエッジか立下がりエッジか)を
示します。(0=SCKの第1エッジ読み取る、1=SCKの第2エッジ読み取るを意味)

ヘルプ(machine.SPI)
詳しい説明は、ここ又は、ここを参照しましょう。


ソフトウェアSPI

ソフトウェアSPIモジュールも実装されています。
from machine import SoftSPI, Pin

spi = SoftSPI(baudrate=2000000, polarity=0, phase=0, sck=Pin(25), mosi=Pin(27), miso=Pin(26))
と上記のコードを書き換え、配線も入れ替えて実験を行った結果動作しました。

ヘルプ(machine.SoftSPI)
詳しい説明は、ここを参照しましょう。

sk7SEG_74HC.py】 *1)

7セグメントLEDに数値を表示させるライブライです。
この7セグモジュールを複数個配線させる場合はこちらを参照しましょう。
↓ファイルはここからダウンロードして下さい。
"sk7SEG_74HC.py"

@ ダウンロードし解凍させ、"sk7SEG_74HC.py"ファイルを"PyCharm"の
  プロジェクトディレクトリ(ここでは"espTest"を作成している)へコピーします。
A ESP32-WROOM-32EボードをUSBでPCに繋ぎます。
B "PyCharm"を起動させ、こちらのCを操作する必要が有ります。(起動時最初のみ設定)
C ESP32-WROOM-32Eに書き込みます
  左側プロジェクトウインドウから"sk7SEG_74HC.py"の文字を右クリックをし、
  [実行(U)'Flash sk7SEG_74HC.py']を選んでクリックします。
D "MicroPython REPL"を動作させましょう。
  メニューバーから[ツール]->[MicroPython]->[MicroPython REPL]を順番にクリックします。

REPL(sk7SEG_74HC.py操作)
7セグモジュールを3個接続した場合の例です。
小数点を指定する場合は、"12.3"や"-1.5"と文字列で指定します。
使い方は"sk7SEG_74HC.py"ファイル内の"demo()"関数を参照しましょう。
尚、"demo()"内のSPI接続はESP8266となっています、他のESP32等は書き換えましょう。

 例えば、この様に配線した場合で、
 [ESP(MOSI)]--[(SDI) LED1 (SDO)]--[(SDI) LED2 (SDO)]--[(SDI) LED3 (SDO)]
 "123"を出力した場合は、[3][2][1]と表示されます。[1][2][3]としたい場合は、
 [(SDO) LED1 (SDI)]--[(SDO) LED2 (SDI)]--[(SDO) LED3 (SDI)]--[ESP(MOSI)]
 と接続します。

《SDカード》

ESP8266の場合は、こちらの様に"sdcard.py"を別途ダウンロードして操作を行っていましたが、
ESP32では"machine.SDCrad"モジュールが有る様なので少し記述をして置きますが、
基本操作は、ESP8266の場合と同じです。尚、"sdcard.py"でも動作します。

クラス SDCard -- SD メモリカード”のドキュメントを参照しましょう。

ドキュメントによるスロット"2"のSPI配線(SPIの2Ch)を行った場合のスクリプトが下記です。
尚、SCL/SDAピンは外部プルアップを行っています。
--------------------------------------------------------------------------------
from machine import SDCard
import uos

# SDカードの初期化とマウントを行う
sd = SDCard(slot=2)
uos.mount(sd, "/sd")

print('SD test')
f = open('/sd/test.txt')
dt = f.readline()
print(dt)
f.close()

uos.umount("/sd")
import gc
gc.collect()
print('Done')
--------------------------------------------------------------------------------
スロット"1"のSD/MMC配線を行った場合のコードが下記です。
尚、D1/D3のピンは外部でプルアップしています。(D0:GPIO2/D2:GPIO12の外部プルアップは注意)
d0 = Pin(2, Pin.PULL_UP)
d2 = Pin(12, Pin.PULL_UP)
sd = SDCard(slot=1, width=4, freq=40000000)
uos.mount(sd, "/sd")
因みに、freq は SD/MMC インタフェースの周波数を Hz で指定します(ESP32 でのみサポート)。
って言う事はぁ、SPI接続時の速度はどうやってぇ設定できるのだろう?

当初、
丸々二日さんざん、ああだ・こうだとSPI配線を変えたり、SD/MMC配線にしたりや
MicroPythonのファームウエアを入れ替えたり、コードを書き換えたりしたけど"OSError: 16"...
でぇ、諦めかけた時、ふとSDカードをSDスロットから抜き差しを行ったら急に動作を始めました。
"OSError: 16"・"OSError: -256"等出る場合は抜き差しを行ってみてみてぇ。

※ ESPでのsdcard操作は、使うSDカードを選んだりや微妙なタイミングがある様でどうも使いずらい
  もう少し成熟して欲しいぞぉ。

《I2C》

2つのハードウェアI2Cが有り、識別子 0 と 1 がついています。
識別子 0のピンは、GPIO18(SCL)/GPIO19(SDA)ピンです。
識別子 1のピンは、GPIO25(SCL)/GPIO26(SDA)ピンです。

I2Cの接続相手として”DAコンバータ MCP4725を利用しD/A変換を行う”を使ってみます。

I2C配線図
電源はUSB接続で、
回路電源はボード出力3.3Vです。
I2CはGPI26(SDA)/GPI55(SCL)を使っています
ピンのプルアップ抵抗はチップ内蔵を使います
I2Cアドレスは"0x60"です。


@ ESP32-WROOM-32EボードをUSBでPCに繋ぎます。
A "PyCharm"を起動させ、こちらのCを操作する必要が有ります。(起動時最初のみ設定)
B "main.py"を新規登録して下記スクリプトを"main.py"に貼り付けましょう。
  (登録済みなら上書き貼り付けでも行いましょう)
C ESP32-WROOM-32Eに書き込みます
  左側プロジェクトウインドウから"main.py"の文字を右クリックをして、[実行(U)'Flash main.py']を
  クリックします。
--------------------------------------------------------------------------------
import time
from machine import I2C, Pin

buff = bytearray(2)

# I2Cを初期化(I2Cのプルアップ抵抗はチップ内蔵を使う)
Pin(26, Pin.OUT, Pin.PULL_UP)
Pin(25, Pin.OUT, Pin.PULL_UP)
i2c = I2C(1, scl=Pin(25), sda=Pin(26), freq=100000)

x = 2000                      # 2000-4095ステップで繰り返します
while True:
    buff[0] = x >> 8          # Fast Mode/Normal Mode/D11-D8
    buff[1] = x & 0xff        # D7-D0(電圧のステップ数12bit)hex
    x = x + 1
    if x >= 4095 : x = 2000
    i2c.writeto(0x60, buff)   # I2Cアドレス0x60のデバイスにデータを送る
    time.sleep_ms(5)          # 5msで繰り返す
--------------------------------------------------------------------------------
動作は約1.6V(2000)-3.3V(4095)の出力を5ms毎に繰り返すだけです。
又、確認用としてLEDを付けときました。

machine.I2C
I2C機能も"GPIOマトリクス機能"で任意のピンにI2Cが利用出来る様です。
ですがぁ、GPIO32-GPIO39ピンは入力専用なので使用できません。

ヘルプ(machine.I2C)
詳しい説明は、ここ又は、ここを参照しましょう。


ソフトウェアI2C

ソフトウェアI2Cモジュールも実装されています。
from machine import SoftI2C, Pin

Pin(13, Pin.OUT, Pin.PULL_UP)
Pin(14, Pin.OUT, Pin.PULL_UP)
i2c = SoftI2C(scl=Pin(14), sda=Pin(13), freq=100000)
と上記のコードを書き換え、配線も入れ替えて実験を行った結果動作しました。

ヘルプ(machine.SoftSPI)
詳しい説明は、ここを参照しましょう。
i2c.scan()の操作




sk7SEG_74HC.pyを追加(*1) 2021/06/16

[GPIO編へ] [ページ上へ] [I2S編へ]


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2021 Shigehiro Kimura All Rights Reserved.