今回はマイクロビットでI2C電子ペーパモジュールを使ってみるの続きになります。
WaveShare 1.9インチ 91セグメント I2C電子ペーパモジュール(以後、e-paperと略す)をマイクロビットにつなぎ、マイクロビットに内蔵されている温度センサーから得られた結果をe-paperに出力します。
マイクロビットとe-paperとの接続は上記のURLを参考にします。
先に作成したコードを掲載します。
from microbit import * RST_PIN = pin0 BUSY_PIN = pin1 ADDS_COM = 0x3C #60 ADDS_DATA = 0x3D #61 DSPNUM_WB = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] # black DSPNUM_WW = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] # white numbers = [ [0xbf, 0x1f], # 0 [0x1f, 0x00], # 1 [0xfd, 0x17], # 2 [0xf5, 0x1f], # 3 [0x47, 0x1f], # 4 [0xf7, 0x1d], # 5 [0xff, 0x1d], # 6 [0x21, 0x1f], # 7 [0xff, 0x1f], # 8 [0xf7, 0x1f] # 9 ] radix_point = 0x20 degree_centigrad = 0x05 Fahrenheit_degree = 0x06 BLE = 0x08 POW = 0x10 First_black = 0x1f First_white = 0x00 class EPD: def reset(self): RST_PIN.write_digital(1) sleep(200) RST_PIN.write_digital(0) sleep(20) RST_PIN.write_digital(1) sleep(200) def send_command(self, i): i2c.write(ADDS_COM, bytes([i])) sleep(1) def send_data(self, i): i2c.write(ADDS_DATA, bytes([i])) sleep(1) def ReadBusy(self): while(BUSY_PIN.read_digital() == 0): # 0: idle, 1: busy sleep(1) sleep(10) # DU waveform white extinction diagram + black out diagram # Bureau of brush waveform def lut_DU_WB(self): self.send_command(0x82) self.send_command(0x80) self.send_command(0x00) self.send_command(0xC0) self.send_command(0x80) self.send_command(0x80) self.send_command(0x62) # GC waveform # The brush waveform def lut_GC(self): self.send_command(0x82) self.send_command(0x20) self.send_command(0x00) self.send_command(0xA0) self.send_command(0x80) self.send_command(0x40) self.send_command(0x63) # 5 waveform better ghosting # Boot waveform def lut_5S(self): self.send_command(0x82) self.send_command(0x28) self.send_command(0x20) self.send_command(0xA8) self.send_command(0xA0) self.send_command(0x50) self.send_command(0x65) # temperature measurement # You are advised to periodically measure the temperature and modify the driver parameters # If an external temperature sensor is available, use an external temperature sensor def Temperature(self): # micro:bit function temperature sensor. VAR_Temperature = temperature() if ( VAR_Temperature < 10 ): self.send_command(0x7E) self.send_command(0x81) self.send_command(0xB4) else: self.send_command(0x7b) self.send_command(0x81) self.send_command(0xB4) self.ReadBusy() self.send_command(0xe7) # Set default frame time # Set default frame time if (VAR_Temperature<5): self.send_command(0x31) # 0x31 (49+1)*20ms=1000ms elif (VAR_Temperature<10): self.send_command(0x22) # 0x22 (34+1)*20ms=700ms elif (VAR_Temperature<15): self.send_command(0x18) # 0x18 (24+1)*20ms=500ms elif (VAR_Temperature<20): self.send_command(0x13) # 0x13 (19+1)*20ms=400ms else: self.send_command(0x0e) # 0x0e (14+1)*20ms=300ms # Note that the size and frame rate of V0 need to be set during initialization, # otherwise the local brush will not be displayed def init(self): i2c.init() self.reset() self.send_command(0x2B) # POWER_ON sleep(10) self.send_command(0xA7) # boost self.send_command(0xE0) # TSON sleep(10) self.Temperature() def Write_Screen(self, image): self.send_command(0xAC) # Close the sleep self.send_command(0x2B) # turn on the power self.send_command(0x40) # Write RAM address self.send_command(0xA9) # Turn on the first SRAM self.send_command(0xA8) # Shut down the first SRAM for j in range(0, 15): self.send_data(image[j]) self.send_data(0x00) self.send_command(0xAB) # Turn on the second SRAM self.send_command(0xAA) # Shut down the second SRAM self.send_command(0xAF) # display on self.ReadBusy() # IIC.delay_ms(2000) self.send_command(0xAE) # display off self.send_command(0x28) # HV OFF self.send_command(0xAD) # sleep in def Write_Screen1(self, image): self.send_command(0xAC) # Close the sleep self.send_command(0x2B) # turn on the power self.send_command(0x40) # Write RAM address self.send_command(0xA9) # Turn on the first SRAM self.send_command(0xA8) # Shut down the first SRAM for j in range(0, 15): self.send_data(image[j]) self.send_data(0x03) self.send_command(0xAB) # Turn on the second SRAM self.send_command(0xAA) # Shut down the second SRAM self.send_command(0xAF) # display on self.ReadBusy() # IIC.delay_ms(2000) self.send_command(0xAE) # display off self.send_command(0x28) # HV OFF self.send_command(0xAD) # sleep in def sleep(self): self.send_command(0x28) # POWER_OFF self.ReadBusy() self.send_command(0xAC) # DEEP_SLEEP sleep(2000) RST_PIN.write_digital(0) # Split a two-digit number. def divide_number(i): l = [] tens = "" if i >= 10: tens = str(i)[0] ones = str(i)[1] else: ones = str(i)[0] if len(tens) > 0: l = numbers[int(tens)] else: l = [0x00, 0x00] n = numbers[int(ones)] l.append(n[0]) l.append(n[1]) return l print("epd1in9 Demo") epd = EPD() print("init and Clear") epd.init() epd.lut_5S() epd.Write_Screen(DSPNUM_WW) sleep(500) epd.lut_GC() epd.Write_Screen1(DSPNUM_WB) sleep(500) epd.Write_Screen(DSPNUM_WW) sleep(500) epd.lut_DU_WB() sleep(500) while True: # current temporature tmpList = divide_number(temperature()) epd.Write_Screen([ 0x00, tmpList[0], tmpList[1], tmpList[2], tmpList[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, degree_centigrad, 0x00 ]) sleep(1000*60)
※公式サイトのサンプルコードを参考にして改変しています。
https://github.com/inunosinsi/e-paper_on_microbit/blob/main/current_temporature.py
今回のコードは1分毎に温度を取得し、e-paperに出力します。
温度の出力に関して、
print("epd1in9 Demo") epd = EPD() print("init and Clear") epd.init() epd.lut_5S() epd.Write_Screen(DSPNUM_WW) sleep(500) epd.lut_GC() epd.Write_Screen1(DSPNUM_WB) sleep(500) epd.Write_Screen(DSPNUM_WW) sleep(500) epd.lut_DU_WB() sleep(500)
の箇所の最初の手続きはそのまま残してあります。
while True: # current temporature tmpList = divide_number(temperature()) epd.Write_Screen([ 0x00, tmpList[0], tmpList[1], tmpList[2], tmpList[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, degree_centigrad, 0x00 ]) sleep(1000*60)
が温度の出力の箇所になります。
tmpList = divide_number(temperature())
の箇所でマイクロビットの温度センサーが温度のデータを取得し、e-paperで出力できるように、10の位の数字と1の位の数字を分け、出力用のリストに再生成します。
epd.Write_Screen([ 0x00, tmpList[0], tmpList[1], tmpList[2], tmpList[3], 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, degree_centigrad, 0x00 ])
の箇所のWrite_Screenメソッドがe-paperに値を出力する箇所になりまして、要素数15のリストとして出力内容を渡します。
この要素数15というのは、
※図:1.9inch Segment e-Paper Module Manual - Waveshare Wikiより引用
のように対応していて、例えば、
26の2を出力する場合は、リストの1と2の値に何らかの値を指定します。
数字の出力に関しては、
numbers = [ [0xbf, 0x1f], # 0 [0x1f, 0x00], # 1 [0xfd, 0x17], # 2 [0xf5, 0x1f], # 3 [0x47, 0x1f], # 4 [0xf7, 0x1d], # 5 [0xff, 0x1d], # 6 [0x21, 0x1f], # 7 [0xff, 0x1f], # 8 [0xf7, 0x1f] # 9 ]
の値を使用します。
2という数字を出力する場合は、[0xfd, 0x17]の値の組み合わせを用います。
26℃の℃の箇所(リストの13と14)では、
radix_point = 0x20 degree_centigrad = 0x05 Fahrenheit_degree = 0x06 BLE = 0x08 POW = 0x10 First_black = 0x1f First_white = 0x00
の箇所のパラメータのサンプルから選んで使用します。
ここから今回利用したI2Cというシリアル通信について触れていきます。
今回、マイクロビットとe-paperをジャンパワイヤで繋ぐ時、
e-paper | microbit |
---|---|
VCC | 3.3V |
GND | GND |
SDA | GPIO 20 |
SCL | GPIO 19 |
RST | GPIO 0 |
BUSY | GPIO 1 |
になるように繋ぎました。
SDAはSerial Dataの略で、データ用の信号線になります。
一方、SCLはSerial Clockの略で、クロック用の信号線になります。
※図:1.9inch Segment e-Paper Module Manual - Waveshare Wikiより引用
I2CではSDAでデータを送信する際、SCLがあり自身でクロックを発生させることで、マイクロビットでUARTを使ってみるで見たUARTのようにデータ送信側と受信側のボーレートを合わせるといった手続きが不要になります。
実際に送信されるデータの詳細には触れませんが、データを送信する時、送信の種類にコマンドとデータがあり、
スレーブのアドレス - コマンド - データ - コマンド
のような規則でデータを送信します。
※I2Cデバイスをスレーブとし、I2Cデバイスを操作するコンピュータをマスターと呼びます。
※今回のコードではI2Cデバイスに対して書き込みのみを行いましたが、I2Cには読み込みの方のモジュールもあります。