目次
はじめに
電子工作の入門用に最適なデバイスを紹介します。
少し高いのですが、使ってみたらものすごく楽でした。初学者の方はここから始めるのが良いと思います。
リンク
これ、何が初心者に優しいの?
Waveshare RP2040-LCD-0.96は、Raspberry Pi Pico互換のRP2040ボードに、0.96インチ 160×80のIPSカラーLCDが最初から実装されています。さらに USB Type-C、リチウム電池端子+充電IC、強化レギュレータ(DC-DC)まで載っていて、単体で小型ガジェットが作りやすい構成です
つまり「Pico本体+液晶+配線+電源」を別々に揃えてハマるポイント(配線ミス/ピン違い/電源周り)を、かなり減らせます。
このデバイスで「できること」を明確に(ハード/機能一覧)
ボードに最初から載っているもの(=追加部品なしでできること)
- 0.96インチ IPSカラーLCD(160×80 / 65K色)**で表示できる
- USB Type-Cで給電&MicroPython書き込み(UF2ドラッグ&ドロップ)
- リチウム電池端子(MX1.25)+充電IC搭載でバッテリー駆動が作りやすい
- 高効率DC-DC(TPS63000)搭載(高負荷でも電源が安定しやすい)
- BOOT / RESETボタンが基板上にある(書き込み・復帰がラク)
LCDを使ってみよう
MicroPythonのファームウェアをインストールしてください。詳細は、過去記事参照ください。
メカエレ Blog | 電子工作とライフ…


Raspberry Pi Pico(Pico W・2W対応)セットアップ|Wi‑Fi接続・LED制御【入門】
Raspberry Pi Pico(Pico W・2W対応)のセットアップ方法から、Wi‑Fi接続・内蔵LEDのMicroPython制御まで、図解付きでわかりやすく徹底解説。
以下をpico_lcd_0inch96.pyとして保存します。
from machine import Pin,SPI,PWM
import framebuf
import time
#color is BGR
RED = 0x00F8
GREEN = 0xE007
BLUE = 0x1F00
WHITE = 0xFFFF
BLACK = 0x0000
class LCD_0inch96(framebuf.FrameBuffer):
def __init__(self):
self.width = 160
self.height = 80
self.cs = Pin(9,Pin.OUT)
self.rst = Pin(12,Pin.OUT)
# self.bl = Pin(13,Pin.OUT)
self.cs(1)
# pwm = PWM(Pin(13))#BL
# pwm.freq(1000)
self.spi = SPI(1)
self.spi = SPI(1,1000_000)
self.spi = SPI(1,10000_000,polarity=0, phase=0,sck=Pin(10),mosi=Pin(11),miso=None)
self.dc = Pin(8,Pin.OUT)
self.dc(1)
self.buffer = bytearray(self.height * self.width * 2)
super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
self.Init()
self.SetWindows(0, 0, self.width-1, self.height-1)
def reset(self):
self.rst(1)
time.sleep(0.2)
self.rst(0)
time.sleep(0.2)
self.rst(1)
time.sleep(0.2)
def write_cmd(self, cmd):
self.dc(0)
self.cs(0)
self.spi.write(bytearray([cmd]))
def write_data(self, buf):
self.dc(1)
self.cs(0)
self.spi.write(bytearray([buf]))
self.cs(1)
def backlight(self,value):#value: min:0 max:1000
pwm = PWM(Pin(13))#BL
pwm.freq(1000)
if value>=1000:
value=1000
data=int (value*65536/1000)
pwm.duty_u16(data)
def Init(self):
self.reset()
self.backlight(10000)
self.write_cmd(0x11)
time.sleep(0.12)
self.write_cmd(0x21)
self.write_cmd(0x21)
self.write_cmd(0xB1)
self.write_data(0x05)
self.write_data(0x3A)
self.write_data(0x3A)
self.write_cmd(0xB2)
self.write_data(0x05)
self.write_data(0x3A)
self.write_data(0x3A)
self.write_cmd(0xB3)
self.write_data(0x05)
self.write_data(0x3A)
self.write_data(0x3A)
self.write_data(0x05)
self.write_data(0x3A)
self.write_data(0x3A)
self.write_cmd(0xB4)
self.write_data(0x03)
self.write_cmd(0xC0)
self.write_data(0x62)
self.write_data(0x02)
self.write_data(0x04)
self.write_cmd(0xC1)
self.write_data(0xC0)
self.write_cmd(0xC2)
self.write_data(0x0D)
self.write_data(0x00)
self.write_cmd(0xC3)
self.write_data(0x8D)
self.write_data(0x6A)
self.write_cmd(0xC4)
self.write_data(0x8D)
self.write_data(0xEE)
self.write_cmd(0xC5)
self.write_data(0x0E)
self.write_cmd(0xE0)
self.write_data(0x10)
self.write_data(0x0E)
self.write_data(0x02)
self.write_data(0x03)
self.write_data(0x0E)
self.write_data(0x07)
self.write_data(0x02)
self.write_data(0x07)
self.write_data(0x0A)
self.write_data(0x12)
self.write_data(0x27)
self.write_data(0x37)
self.write_data(0x00)
self.write_data(0x0D)
self.write_data(0x0E)
self.write_data(0x10)
self.write_cmd(0xE1)
self.write_data(0x10)
self.write_data(0x0E)
self.write_data(0x03)
self.write_data(0x03)
self.write_data(0x0F)
self.write_data(0x06)
self.write_data(0x02)
self.write_data(0x08)
self.write_data(0x0A)
self.write_data(0x13)
self.write_data(0x26)
self.write_data(0x36)
self.write_data(0x00)
self.write_data(0x0D)
self.write_data(0x0E)
self.write_data(0x10)
self.write_cmd(0x3A)
self.write_data(0x05)
self.write_cmd(0x36)
self.write_data(0xA8)
self.write_cmd(0x29)
def SetWindows(self, Xstart, Ystart, Xend, Yend):#example max:0,0,159,79
Xstart=Xstart+1
Xend=Xend+1
Ystart=Ystart+26
Yend=Yend+26
self.write_cmd(0x2A)
self.write_data(0x00)
self.write_data(Xstart)
self.write_data(0x00)
self.write_data(Xend)
self.write_cmd(0x2B)
self.write_data(0x00)
self.write_data(Ystart)
self.write_data(0x00)
self.write_data(Yend)
self.write_cmd(0x2C)
def display(self):
self.SetWindows(0,0,self.width-1,self.height-1)
self.dc(1)
self.cs(0)
self.spi.write(self.buffer)
self.cs(1)
if __name__=='__main__':
lcd = LCD_0inch96()
lcd.fill(BLACK)
lcd.text("Hello pico!",35,15,GREEN)
lcd.text("This is:",50,35,GREEN)
lcd.text("Pico-LCD-0.96",30,55,GREEN)
lcd.display()
lcd.hline(10,10,140,BLUE)
lcd.hline(10,70,140,BLUE)
lcd.vline(10,10,60,BLUE)
lcd.vline(150,10,60,BLUE)
lcd.hline(0,0,160,BLUE)
lcd.hline(0,79,160,BLUE)
lcd.vline(0,0,80,BLUE)
lcd.vline(159,0,80,BLUE)
lcd.display()
time.sleep(3)
#game GUI
###
lcd.fill(WHITE)
i=0
while(i<=80):
lcd.hline(0,i,160,BLACK)
i=i+10
i=0
while(i<=160):
lcd.vline(i,0,80,BLACK)
i=i+10
lcd.display()
###
x=80
y=40
color=RED
colorflag=0
KEY_UP = Pin(2,Pin.IN,Pin.PULL_UP)
KEY_DOWN = Pin(18,Pin.IN,Pin.PULL_UP)
KEY_LEFT= Pin(16,Pin.IN,Pin.PULL_UP)
KEY_RIGHT= Pin(20,Pin.IN,Pin.PULL_UP)
KEY_CTRL=Pin(3,Pin.IN,Pin.PULL_UP)
KEY_A=Pin(15,Pin.IN,Pin.PULL_UP)
KEY_B=Pin(17,Pin.IN,Pin.PULL_UP)
while(1):
key_flag=1
if(key_flag and (KEY_UP.value()==0 or KEY_DOWN.value()==0 \
or KEY_LEFT.value()==0 or KEY_RIGHT.value()==0 \
or KEY_CTRL.value()==0 or KEY_A.value()==0 \
or KEY_B.value()==0 )):
time.sleep(0.05)
key_flag=0
m=x
n=y
###go up
if(KEY_UP.value() == 0):
y=y-10
if(y<0):
y=70
if(KEY_DOWN.value() == 0):
y=y+10
if(y>=80):
y=0
if(KEY_LEFT.value() == 0):
x=x-10
if(x<0):
x=150
if(KEY_RIGHT.value() == 0):
x=x+10
if(x>=160):
x=0
if(KEY_CTRL.value() == 0):
colorflag+=1
if(colorflag==1):
color=RED
elif(colorflag==2):
color=GREEN
elif(colorflag==3):
color=BLUE
colorflag=0
lcd.fill_rect(m,n,10,10,WHITE)
lcd.hline(m,n,10,BLACK)
lcd.hline(m,n+10,10,BLACK)
lcd.vline(m,n,10,BLACK)
lcd.vline(m+10,n,10,BLACK)
lcd.rect(x+1,y+1,9,9,color)
if(KEY_A.value() == 0):
lcd.fill_rect(x+1,y+1,9,9,color)
lcd.fill_rect(m+1,n+1,9,9,color)
if(KEY_B.value() == 0):
lcd.fill(WHITE)
i=0
while(i<=80):
lcd.hline(0,i,160,BLACK)
i=i+10
i=0
while(i<=160):
lcd.vline(i,0,80,BLACK)
i=i+10
lcd.display()
time.sleep(1)内蔵の温度センサーの値を表示してみます。
from machine import ADC
import time
from pico_lcd_0inch96 import LCD_0inch96, BLACK, WHITE, GREEN
# 内部温度センサ(ADC4)
sensor_temp = ADC(4)
conversion_factor = 3.3 / 65535
def read_temp_c():
adc_u16 = sensor_temp.read_u16()
voltage = adc_u16 * conversion_factor
# 近似式
temp_c = 27 - (voltage - 0.706) / 0.001721
return temp_c, adc_u16
lcd = LCD_0inch96()
lcd.backlight(800) # 0..1000で設定
while True:
temp_c, adc_u16 = read_temp_c()
lcd.fill(BLACK)
lcd.text("RP2040-LCD-0.96", 10, 8, WHITE)
lcd.text("CPU Temp:", 10, 30, WHITE)
lcd.text("{:.1f} C".format(temp_c), 10, 48, GREEN)
lcd.text("ADC={}".format(adc_u16), 10, 66, WHITE)
lcd.display()
time.sleep(1)参考情報
バックライト設定
バックライトは明るさと消費電力のトレードオフになります。
このサンプルでは backlight(0..1000) で明るさを指定しています。体感のおすすめは以下のような感じです
- 600〜800:室内で見やすく、電力も抑えめ(まずここ)
- 900〜1000:かなり明るい(屋外寄り/写真撮影向け、電力増)
- 200〜400:暗い部屋向け(眩しさ軽減)
文字を書く
lcd.text(文字, x, y, 色) で書けます。
サイズ指定はできません(標準の framebuf.text() は固定フォント)
- だいたい 1文字 8×8 px の等幅フォントです
- 大きくしたい場合は「大きいフォント描画(ビットマップフォント)」や「自前で拡大描画」が必要になります
色
- 16bitなので理論上 65,536色 あります(厳密にはRGB565の表現範囲)
- よく使う色は定数化しておくのがラクです(あなたのコードにもあります)
その他の機能
framebuf.FrameBuffer を継承しているので、以下がそのまま使えます
lcd.fill(color):画面塗りつぶしlcd.pixel(x, y, color):点lcd.hline(x, y, w, color)/lcd.vline(x, y, h, color):横線/縦線lcd.line(x0, y0, x1, y1, color):直線lcd.rect(x, y, w, h, color):枠線の四角lcd.fill_rect(x, y, w, h, color):塗りつぶし四角lcd.blit(fb, x, y):別のFrameBuffer画像を貼る(アイコン表示など)- 最後に
lcd.display():LCDに転送(これを呼ばないと画面が更新されません)
まとめ
これまでも電子工作を始める際、まずディスプレイで見える化すること!と言ってきましたがこの製品には最初からついています。配線する必要すらありません。これは素晴らしいことだと思いますので、ぜひここから始めてください。
次はこのデバイスを使ってリチウム電池の充電にチャレンジしてみようかと思います。
メカエレ Blog | 電子工作とライフ…


Raspberry Pi PicoでOLEDディスプレイを使う方法|I2C文字表示ガイド
Raspberry Pi Picoを使ってI2C接続のOLED(有機EL)ディスプレイに文字や温度表示を出す方法を、配線図・MicroPythonコード例付きでわかりやすく解説。
リンク
コメント