前回アップしたソースではGC9A01に表示させるフォントが気に入らなかった。
さらにbitmapの表示がどのようにしたらよいものかわからなかったので新たに探してみた。
https://github.com/russhughes/gc9a01_mpy
結果上記のサイトに行きつき、jpgファイル、.pyファイルへ変換してのbitmapファイルの表示方法が分かった。
とりあえず動作はする。実際に車載したときにどうなるか。
from machine import Pin,SPI,I2C,PWM
import gc9a01 # 内包されているfirmwareを使うこと。
import onewire, ds18x20
import time,utime,math
from ds1307 import DS1307 #libフォルダ
from fonts import chango_16 as fontA
from fonts import chango_32 as fontB
import hondaWing #bitmapのpythonスクリプト
def main():
#iniファイルの保存
def SaveIniFile(filename, dictionary):
with open(filename, "w") as f:
for key in dictionary:
f.write("{},{}\n".format(key, dictionary[key]))
#iniファイルの読み取り
def LoadIniFile(filename):
dictionary = {}
with open(filename, "r") as f:
for s in f:
lst = s.strip().split(",")
dictionary[lst[0]] = lst[1]
return dictionary
#使い方
#data = {}
#data["Name"] = "Hippy"
#data["Year"] = "2021"
#SaveIniFile("/MyData.ini", data)
#data = LoadIniFile("/MyData.ini")
#print(data)
#arduinoのMAP関数
def convert(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
#円を書いて塗りつぶす
def circle(x,y,r,c):
tft.hline(x-r,y,r*2,c)
for i in range(1,r):
a = int(math.sqrt(r*r-i*i))#平方根だって
tft.hline(x-a,y+i,a*2,c)
tft.hline(x-a,y-i,a*2,c)
#円を書く
def ring(x,y,r,c):
tft.pixel(x-r,y,c)
tft.pixel(x+r,y,c)
tft.pixel(x,y-r,c)
tft.pixel(x,y+r,c)
#lcd.display()
#utime.sleep(0.1)
for i in range(1,r):
a = int(math.sqrt(r*r-i*i)) # Pythagoras
tft.pixel(x-a,y-i,c)
tft.pixel(x+a,y-i,c)
tft.pixel(x-a,y+i,c)
tft.pixel(x+a,y+i,c)
tft.pixel(x-i,y-a,c)
tft.pixel(x+i,y-a,c)
tft.pixel(x-i,y+a,c)
tft.pixel(x+i,y+a,c)
data = LoadIniFile("ini.ini")
dspMode=data["dspMode"]
face=("FaceA.jpg","FaceD.jpg")
modePin=21 #時刻合わせモードに移行スイッチ
upPin=20 #日付・時計あわせのアップスイッチ
cds = machine.ADC(0) #明るさセンサー GP26がADC0
# 16bitの数値一単位での電圧値を設定します
unit = 0.00005035477
kurai = 20000 #暗いとき
akarui = 65535 #明るいとき
dspMode = 0 #0:アナログ 1:デジタル
mode = 0 #0:通常 1:時計合わせ
sec = 0 #時計合わせの時のセクション 0:Year 1:month 2 day 3 hour 4 minute
uYear = 0 #時計あわせようの値
uMonth = 0
uDate = 0
uHour = 0
uMinute = 0
epSec = 0
swMode = machine.Pin(modePin,machine.Pin.IN,machine.Pin.PULL_DOWN) #スイッチの定義
swUp = machine.Pin(upPin,machine.Pin.IN,machine.Pin.PULL_DOWN) #スイッチの定義
pushStart =0 #押し始めた時間
flgPush = False #押しているか
pushInt = 0 #押されていた時間
DSPIN = 19 #温度計のPin。onewire
dsCnt = 0 #温度計の数
ds_pin = machine.Pin(DSPIN)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin)) #温度計を定義
pw33 = machine.Pin(18,machine.Pin.OUT) #RTCの3.3Vを得るため
pw33.value(1)
tokei=True #RTCが取得できたかフラグ
try: #RTCから現在時刻の取得
i2c_rtc = I2C(0,scl = Pin(17),sda = Pin(16),freq = 100000) #RTCの定義
result = I2C.scan(i2c_rtc)
rtc = DS1307(i2c_rtc)
(year,month,date,day,hour,minute,second,p1)=rtc.datetime()
#RTCから取得した時間を元に 2021/1/1 00:00:00(RP2040のリセット時間)との差分を作成
epSec = utime.mktime((year,month,date,hour,minute,second,0,0)) #1970/1/1 00:00:00からの経過秒
epSec = epSec-1609459200
if year==2000:#RTCからの初取得は2000年となるのでその場合に 2023/2/2 12:00:00にRTCを設定
year = 2023
month = 2
date = 2
day = 4
hour = 12
minute = 0
second = 0
now = (year,month,date,day,hour,minute,second,0)
rtc.datetime(now)
except:
print("not Tokei") #RTCから取得できなかったら tokei非表示
tokei=False
o_ds = bytearray(b'(\x07\x83t/!\x01(') #温度計の個体を特定 外気温
w_ds = bytearray(b'(?\x9b8/!\x01\xd4') # 水温
try:
roms = ds_sensor.scan() #センサーを取得
dsCnt=len(roms) #センサー数を得る
for rom in roms:
print('Found DS devices: ', rom)
except:
dsCnt = 0
#液晶ディスプレイの定義
spi = SPI(1, baudrate=60000000, sck=Pin(10), mosi=Pin(11))
tft = gc9a01.GC9A01(#バックライトはPWMで調整するので指定しない。
spi,
240,
240,
reset=Pin(12, Pin.OUT),
cs=Pin(9, Pin.OUT),
dc=Pin(8, Pin.OUT),
rotation=0)
#バックライトはPWMで調整
pwm = PWM(Pin(25))
pwm.freq(1000)
pwm.duty_u16(akarui)
tft.init()
tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
oldx =120
oldy = 120
while True:
for i in range(100): #バックライトの明るさ調整
# ADCの値を読み込みます(16bitの生の数値)
voltRaw = cds.read_u16()
#print("voltRaw:" + str(voltRaw))
volt = voltRaw * unit
#print( "volt:" + "{:.3f}".format(volt))
if volt > 2:
pwm.duty_u16(kurai)
else:
pwm.duty_u16(akarui)
#モードスイッチが押されているか?
if swMode.value() == 1:
if flgPush : #長押中
pushInt = utime.time()-pushStart
else:
flgPush = True #長押し計測スタート
pushStart = utime.time()
pushInt = 0
else:
if flgPush :# すでに押されていて離した
flgPush=False
pushInt=utime.time()-pushStart #押していた時間を取得
if pushInt > 2: #長押しされた
#print("long")
if mode ==0: #時計合わせモードに移行
tft.fill(gc9a01.WHITE)
(uYear,uMonth,uDate,day,uHour,uMinute,second,p1)=rtc.datetime() #
mode=1
sec=0
else: #時計合わせモードで長押し
if sec == 4:#分まで設定してたら時計合わせ終了
now = (uYear,uMonth,uDate,0,uHour,uMinute,0,0)
rtc.datetime(now)
sec=0
mode=0
tft.fill(gc9a01.WHITE)
tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
oldx=120
oldy=120
else:#次のセクションへ移行
sec=sec+1
else:
print("short") #短押しは表示モード切り替え
#調整用UPボタンの処理
if swUp.value() == 1:
#print("up")
if tokei : #時計表示ができる。
if mode == 1: #時刻調整モード
utime.sleep_ms(200)
if sec ==0:
uYear=uYear+1
if uYear>2100:
uYear=2023
elif sec ==1:
uMonth=uMonth+1
if uMonth>12:
uMonth=1
elif sec ==2:
uDate=uDate+1
if uDate>31:
uDate=1
elif sec ==3:
uHour=uHour+1
if uHour>23:
uHour=0
elif sec ==4:
uMinute=uMinute+1
if uMinute>59:
uMinute=0
else :
#時刻設定モードじゃ無い場合は表示モード切り替え
if dspMode==0:
dspMode=1
tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
data["dspMode"] = dspMode
SaveIniFile("/ini.ini", data)
else:
dspMode=0
data["dspMode"] = dspMode
SaveIniFile("/ini.ini", data)
tft.jpg(face[dspMode], 0, 0, gc9a01.SLOW)
oldx=120
oldy=120
#print(str(uYear)+"/"+str(uMonth)+"/"+str(uDate) + " " + str(uHour)+":"+str(uMinute)+":00")
if mode ==0: #通常表示
#温度の取得
oTemp = 999.99
wTemp = 999.99
oReadErr=""
wReadErr=""
if dsCnt > 0 :#温度計の数が0以上だったら
flgSuc=True
try:
ds_sensor.convert_temp()
utime.sleep_ms(750)
except:
flgSuc=False
if flgSuc:
for rom in roms:
if rom == o_ds :
buf = oTemp
try:
oTemp = ds_sensor.read_temp(rom)
oReadErr="O"
except:
oReadErr="X"
oTemp=buf
else :
buf = wTemp
try:
wTemp = ds_sensor.read_temp(rom)
wReadErr="O"
except:
wReadErr="X"
wTemp=buf
if dspMode==0:
wwTemp = 20 #最小温度
if wTemp <=120 or wTemp > 20: #読み取れている?
wwTemp = wTemp
kakudo = convert(wwTemp,20,120,40,320) #角度を取得
rad = 3.14*kakudo/180 #ラジアン値に変換
r=90 #針の長さ
x = int(r*(math.cos(rad))) + 120 #座標を求める
y = int(r*(math.sin(rad))) + 120
c=gc9a01.BLACK
if wTemp >80:
c=gc9a01.RED
elif wTemp<40:
c=gc9a01.BLUE
tft.write(fontA, "w={:.1f} ".format(wTemp),150,105,c,gc9a01.WHITE)
tft.write(fontA, "o={:.1f} ".format(oTemp),155,120,gc9a01.BLACK,gc9a01.WHITE)
if (x != oldx) or (y !=oldy) :
tft.line(122, 120 ,oldx ,oldy, gc9a01.WHITE)
tft.line(121, 121 ,oldx ,oldy, gc9a01.WHITE)
tft.line(120, 120, oldx, oldy, gc9a01.WHITE)
tft.line(120, 119 ,oldx ,oldy, gc9a01.WHITE)
tft.line(120, 121, oldx, oldy, gc9a01.WHITE)
tft.line(119, 119 ,oldx ,oldy, gc9a01.WHITE)
tft.line(119, 120 ,oldx ,oldy, gc9a01.WHITE)
tft.line(118, 120 ,oldx ,oldy, gc9a01.WHITE)
tft.line(120, 118 ,oldx ,oldy, gc9a01.WHITE)
tft.write(fontA, "20",175, 162,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, "40",94, 190,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, "60",40, 148,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, "80",40, 77,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, "100",94, 31,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, "120",175, 61,gc9a01.BLACK,gc9a01.WHITE)
tft.bitmap(hondaWing,120-int(hondaWing.WIDTH/2),50)
tft.line(122, 120 ,x ,y, gc9a01.RED)
tft.line(121, 121 ,x ,y, gc9a01.RED)
tft.line(120, 120, x, y, gc9a01.RED)
tft.line(120, 119 ,x ,y, gc9a01.RED)
tft.line(120, 121, x, y, gc9a01.RED)
tft.line(119, 119 ,x ,y, gc9a01.RED)
tft.line(119, 120 ,x ,y, gc9a01.RED)
tft.line(118, 120 ,x ,y, gc9a01.RED)
tft.line(120, 118 ,x ,y, gc9a01.RED)
oldx = x
oldy = y
circle(120,120,10,gc9a01.BLACK)
else :
# 温度の表示 右寄せ
tft.write(fontA, "WaterTemp",40,68,gc9a01.BLACK,gc9a01.WHITE)
w = tft.write_len(fontB," {:.2f}".format(wTemp))
tft.write(fontB, " {:.2f}".format(wTemp),210-w,86,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA,wReadErr,40,90,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, "OutTemp",40,128,gc9a01.BLACK,gc9a01.WHITE)
w = tft.write_len(fontB," {:.2f}".format(oTemp))
tft.write(fontB, " {:.2f}".format(oTemp),210-w,146,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA,oReadErr,40,150,gc9a01.BLACK,gc9a01.WHITE)
if tokei :
it = utime.mktime(utime.localtime()) #ローカルでは 2021/1/1 00:00:00として起動した1970/1/1 00:00:00からの経過秒
it = it+epSec #RTC差分の値とあわせて
time = utime.localtime(it) #本当の現在時刻を生成
year=time[0]
month=time[1]
date=time[2]
hour=time[3]
minute=time[4]
second=time[5]
if dspMode==1:
dateStr = "{0:04d}/ {1:02d}/ {2:02d} ".format(year,month,date)
tft.write(fontA, dateStr,56, 195,gc9a01.BLACK,gc9a01.WHITE)
tft.write(fontA, " ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
timeStr = "{0:02d}:{1:02d}:{2:02d} ".format(hour,minute,second)
tft.write(fontA, timeStr,80, 213,gc9a01.BLACK,gc9a01.WHITE)
else: #時計合わせ
dateStr = "{0:04d}/ {1:02d}/ {2:02d} ".format(uYear,uMonth,uDate)
tft.write(fontA, dateStr,60, 195,gc9a01.BLACK,gc9a01.WHITE)
timeStr = "{0:02d}:{1:02d}:00 ".format(uHour,uMinute)
tft.write(fontA, timeStr,82, 213,gc9a01.BLACK,gc9a01.WHITE)
if sec ==0:
tft.write(fontA,"year ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
elif sec ==1:
tft.write(fontA,"month ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
elif sec ==2:
tft.write(fontA,"date ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
elif sec ==3:
tft.write(fontA,"hour ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
elif sec ==4:
tft.write(fontA,"minute ",85, 178,gc9a01.BLACK,gc9a01.WHITE)
utime.sleep_ms(10)
main()