【ラズパイ】OLEDで情報ステーションを作成!グラフも表示

2024/07/19

OLED ラズパイ

  • B!
サムネ
サムネ

今回はOLEDディスプレイを2つ使って様々な情報を表示するディスプレイを作ります。

使用したOLEDは裏面の抵抗の位置を変えることで異なるI2Cアドレスに変更することができるため、デュアル画面で多くの情報が表示できるようになっています。

oled.py
from busio import I2C
from adafruit_ssd1306 import SSD1306_I2C
import board
import time
from PIL import Image, ImageDraw, ImageFont
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
import datetime
import shutil
import dht11
import RPi.GPIO as GPIO
import os
import csv

GPIO.setmode(GPIO.BCM)
instance = dht11.DHT11(pin=14)

i2c = I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)#addr=0x48
cahnnel0 = AnalogIn(ads, ADS.P0)

display_1 = SSD1306_I2C(128, 64, I2C(board.SCL, board.SDA), addr=0x3c)#addr=0x3c
display_2 = SSD1306_I2C(128, 64, I2C(board.SCL, board.SDA), addr=0x3d)#addr=0x3d

#初期化
display_1.fill(0)
display_2.fill(0)
display_1.show()
display_2.show()

image_1 = Image.new("1", (display_1.width, display_1.height))
draw_1 = ImageDraw.Draw(image_1)

image_2 = Image.new("1", (display_2.width, display_2.height))
draw_2 = ImageDraw.Draw(image_2)

font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 17)
s_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 12)
ms_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 10)
m_font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 8)

x = 0
temp_list = []
humi_list = []
print('[Program Activation]')

try:
    while True:
        #記録ファイル(データを記録する場合のみ)
        dt_csv = datetime.date.today() #日付取得
        path = '/home/pi/Desktop/mnt/data/' + str(dt_csv) + '.csv'
        
        #今日のファイルがあるか
        is_file = os.path.isfile(path)
        if is_file:
            pass
        else:
            #無い場合は作成する
            with open(path, 'w') as f:
                fieldnames  = ['DateTime', 'Temperature', 'Humidity', 'Cds', 'Moist', 'Moist_label', 'Watering']
                writer = csv.DictWriter(f, fieldnames=fieldnames )
                writer.writeheader()
                print('created', str(dt_csv) + '.csv') 
        
        #明るさを取得(cds)
        cds_v = 0
        c_label = 'Display ON'
        #暗い時はディスプレイをOFFにする
        if (cahnnel0.voltage) > 2.9:
            cds_v = 1
            c_label = 'Display OFF'
        
        #CPU温度取得
        with open('/sys/class/thermal/thermal_zone0/temp') as t:
            temp = round(int(t.read()) / 1000, 1)

        #日付を取得
        dt = datetime.datetime.now().strftime('%H:%M')
        dt_data = datetime.datetime.now().replace(microsecond=0)
        #DHT11から温湿度データを取得する
        while True:
            temphumi = instance.read()
            if temphumi.is_valid():               
                t = temphumi.temperature
                h = temphumi.humidity
                break
        #Cdsデータ
        c0_vol = str(round(cahnnel0.voltage, 3))
        
        #共有ストレージの容量を取得
        result = shutil.disk_usage('/home/pi/Desktop/mnt/')
        total = str(round((result.total / 1024**4), 2)) + 'T'
        used = str(round((result.used / 1024**3), 2)) + 'G'
        free = str(round((result.free / 1024**4), 2)) + 'T'
        
        #Display_1(cds, 温度, 湿度)
        draw_1.rectangle((0,0,display_1.width,display_1.height), outline=0, fill=0)
        draw_1.text((3, 42), 'Cds[v]', font=ms_font, fill=1)
        draw_1.text((46, 42), 'TEMP', font=ms_font, fill=1)
        draw_1.text((87, 42), 'HUMI', font=ms_font, fill=1)
        draw_1.text((3, 52), c0_vol, font=ms_font, fill=1)
        draw_1.text((46, 52), str(t) + 'C', font=ms_font, fill=1)
        draw_1.text((87, 52), str(h) + '%', font=ms_font, fill=1)
        draw_1.text((2, 0), str(40), font=m_font, fill=1)
        draw_1.text((7, 30), str(0), font=m_font, fill=1)
        draw_1.text((116, 0), str(1), font=m_font, fill=1)
        draw_1.text((116, 30), str(0), font=m_font, fill=1)
        draw_1.text((6, 15), 'T', font=m_font, fill=1)
        draw_1.text((117, 15), 'H', font=m_font, fill=1)

        #Display_2(更新時間, CPU温度, ストレージ状態)
        draw_2.rectangle((0,0,display_1.width,display_1.height), outline=0, fill=0)
        draw_2.text((0, 0), '[upd]' + str(dt), font=s_font, fill=1)
        draw_2.text((85, 0), '[CPU]', font=s_font, fill=1)
        draw_2.text((84, 18), str(temp) + 'C', font=s_font, fill=1)
        draw_2.text((0, 18), '[DISK]', font=s_font, fill=1)
        draw_2.text((3, 36), 'TOTAL', font=s_font, fill=1)
        draw_2.text((46, 36), 'USED', font=s_font, fill=1)
        draw_2.text((87, 36), 'FREE', font=s_font, fill=1)
        draw_2.text((3, 48), total, font=s_font, fill=1)
        draw_2.text((46, 48), used, font=s_font, fill=1)
        draw_2.text((87, 48), free, font=s_font, fill=1)

        #書き込み
        display_1.image(image_1)
        display_2.image(image_2)

        #グラフの線
        display_1.line(14,0,14,40,1)
        display_1.line(114,0,114,40,1)
        display_1.line(0,40,128,40,1)
        
        #データセット
        T = int(t)
        H = int(h)
        temp_list.append(T)
        humi_list.append(H)
        x = len(temp_list)
        
        #リストの中身が100個になったら古い値を消す
        if x == 100:
            temp_list.pop(0)
            humi_list.pop(0)
        
        #温度グラフ表示(実線)
        x = 0
        for i in temp_list:
            x += 1
            display_1.circle(14+x,40-i,1,1)
        
        #湿度グラフ表示(点線)
        p = 1
        x = 0
        for i in humi_list:
            x += 1
            
            #交互に処理することで点線にする
            if p == 1:
                display_1.circle(14+x,int(40-(40*(i/100))),1,1)
                p = 0
            else:
                display_1.circle(14+x,int(40-(40*(i/100))),0,0)
                p = 1

        print(str(T)+'C',str(H)+'%', c0_vol, c_label)
        
        #ディスプレイに表示
        if cds_v == 0:
            display_1.show()
            display_2.show()
        else:
            display_1.fill(0)
            display_2.fill(0)
            display_1.show()
            display_2.show()
        
        #####その他のデータを追加する場合#####
        moist = 'NULL'
        moist_label = 'NULL'
        watering = 'NULL'
        data = [[dt_data, t, h, c0_vol, moist, moist_label, watering]]
        
        with open(path, 'a') as f:
            writer = csv.writer(f)
            writer.writerows(data)
        
        latest = '/home/pi/Desktop/mnt/latestdata/latest.csv'
        with open(latest, 'w', newline='') as f:
            fieldnames  = ['DateTime', 'Temperature', 'Humidity', 'Cds', 'Moist', 'Moist_label', 'Watering']
            writer = csv.DictWriter(f, fieldnames=fieldnames )
            writer.writeheader()
            writer = csv.writer(f)
            writer.writerows(data)
        ######################################
        
        time.sleep(60)

except KeyboardInterrupt:
    draw_1.rectangle((0,0,display_1.width,display_1.height), outline=0, fill=0)
    draw_2.rectangle((0,0,display_1.width,display_1.height), outline=0, fill=0)
    display_1.image(image_1)
    display_2.image(image_2)
    display_1.show()
    display_2.show()
    GPIO.cleanup()
    print('Cleanup')

Writer

アイコン
Python×Raspi IoTシステム・Bot・ラズパイの記録
  • プログラミング
  • IoT
  • Python
\FOLLOW ME/ 𝕏

Ranking

Community

Search