pinewell's farmer blog 農業と電子工作、ソフトウェア、バイク、車

2023年2月16日

RasberryPi Picoでの水温計作成 その5

Filed under: その他 — pinewell @ 11:24 PM

前回アップしたソースでは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()

コメントはまだありません »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress