🌟 NoraGatewayのOLED180度ローテート 🎉
2025年5月30日
2026年6月5日
概要
NoraGateway で動作する OLED ディスプレイの表示を 180 度回転し、上下反転させる手順書です。
前提条件
- 作業ディレクトリ:
/usr/ofp(OLED 関連ファイルが置かれている場所) - Status-dsp.py(スクリプト本体)
- バックアップ用の余裕(万が一に備えて元ファイルは必ずコピーしてください)
手順
⚠️ 作業前に必ず元のファイルをバックアップしてください。
1. /usr/ofp/Status-dsp.py をバックアップする。
sudo cp /usr/ofp/Status-dsp.py /usr/ofp/Status-dsp.py.bak
2. エディタで Status-dsp.py を開く。
sudo nano /usr/ofp/Status-dsp.py
3. スクリプト内で oled.image(image) と書かれている行を探す(表示処理のキモとなる箇所)。
4. oled.image(image) の直前に以下の 1 行を追加する。
image = image.rotate(180)
📝 この操作をスクリプト内の以下すべての表示箇所に対して繰り返してください。
- 起動メッセージ
- コールサイン&IP 表示
- ネットワークエラー
- シャットダウン/リスタート
- 通常ステータス表示
- アイドル履歴
- 画面クリア
5. ファイルを保存して(「Ctrl + X」→「Y」→「Enter」)、動作確認する。
python /usr/ofp/Status-dsp.py
✅ OLED の表示が 180 度回転(上下反転)していれば成功です。
トラブルシューティング
- Pillow が未インストール:
ModuleNotFoundError: No module named 'PIL'が出た場合は以下を実行する。
pip install Pillow - 表示ずれやサイズの問題:180 度回転後に座標が合わない場合は、
oled.offset(x, y)などで微調整してください。
Status-dsp.py 全文
以下は修正済みの Status-dsp.py 全文です(参考用)。
# OLED display Program for HotSpot nora V2.3 by JR1OFP
import sys
sys.path.append("/home/pi/env/lib/python3.9/site-packages/")
import board
import digitalio
from PIL import Image, ImageDraw, ImageFont
import adafruit_ssd1306
from time import sleep
import socket
import os
# Check OLED.txt file and remove file
if os.path.isfile('./OLED.txt'):
os.remove('./OLED.txt')
# SSD1306 settings
DEVICE_ADR = 0x3C
DISP_WIDTH = 128
DISP_HEIGHT = 64
# Reset pin setup
RESET_PIN = digitalio.DigitalInOut(board.D4)
# Initialize I2C and OLED
i2c = board.I2C()
oled = adafruit_ssd1306.SSD1306_I2C(DISP_WIDTH, DISP_HEIGHT, i2c, addr=DEVICE_ADR, reset=RESET_PIN)
# Clear display
oled.fill(0)
oled.show()
# Create initial blank image
image = Image.new("1", (oled.width, oled.height))
draw = ImageDraw.Draw(image)
# Rotate for upside down
image = image.rotate(180)
oled.image(image)
oled.show()
# Load fonts
font1 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 13)
font2 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 14)
font3 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 17)
font4 = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", 18)
# Show startup message
draw.text((0, 0), "HotSpot nora", font=font2, fill=255)
draw.text((0, 25), "Connecting...", font=font2, fill=255)
draw.text((0, 48), "XRF Reflector club", font=font2, fill=255)
image = image.rotate(180)
oled.image(image)
oled.show()
sleep(10)
# Create OLED.txt to indicate display used
with open('./OLED.txt', 'w'):
pass
# Initialize history buffers
callsignbk = [' '] * 13
timebk = [str(i) for i in range(1,14)]
txrxbk = [' '] * 13
lastcallsign = '---'
txrxdata1 = ' '
callsign1 = ' '
bkcnt = 0
lastbkcnt = 11
bkn = 0
nosigcnt = 0
linkto = '---'
timesig = '---'
# Remove old status file if exists
if os.path.isfile('./NoraGateway.status'):
os.remove('./NoraGateway.status')
# Get IP address
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
IP = s.getsockname()[0]
break
except:
sleep(3)
# Read callsign from version.txt
with open('/boot/version.txt', 'r') as vf:
data = vf.readline()
callsign0 = data[5:13]
# Show initial HotSpot info
image = Image.new("1", (oled.width, oled.height))
draw = ImageDraw.Draw(image)
draw.text((0, 0), "HotSpot :", font=font2, fill=255)
draw.text((15,20), callsign0, font=font3, fill=255)
draw.text((0,46), "IP:", font=font1, fill=255)
draw.text((18,46), IP, font=font1, fill=255)
image = image.rotate(180)
oled.image(image)
oled.show()
sleep(10)
# Main loop
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
IP = s.getsockname()[0]
NWstatus = "ok"
except:
image = Image.new("1", (oled.width, oled.height))
draw = ImageDraw.Draw(image)
draw.text((0,0), "Network error", font=font3, fill=255)
draw.text((0,36), "Connecting...", font=font2, fill=255)
image = image.rotate(180)
oled.image(image)
oled.show()
NWstatus = "error"
nosigcnt = 60
bkn = 12
if NWstatus == "error":
if os.path.isfile('./NoraGateway.status'):
os.remove('./NoraGateway.status')
sleep(3)
continue
# Network OK
if os.path.isfile('./NoraGateway.status'):
# Parse status file
with open('./NoraGateway.status','r') as sf:
lines = sf.readlines()
# ...(省略: Status ファイル解析ロジック)
# 音声コマンド検出・表示・システム制御
#
continue
# ...(以降、履歴表示やアイドル時の処理)
