Zobrazení údajů na displeji

Odpovědět
LSiler
Příspěvky: 4
Registrován: pát 04. bře 2022 5:31:44

Zobrazení údajů na displeji

Příspěvek od LSiler » pát 04. bře 2022 5:38:50

Zdravím, jsem sice úplný začátečník, ale snažím se. Pořídil jsem si Raspberry pi 4B 2GB, pro sledování letového provozu Flightaware, na RPI jsem nandal Waveshare UPS HAT kvůli výpadkům proudu, kde přes příkaz sudo python3 INA219.py lze sledovat údaje z UPS HAT. A chtěl jsem dostat údaje z UPS HAT na připojený OLED display Adafruit 128x32 px který komunikuje přes I2C piny a vubec se mi to nedaří. Mohl by mi někdo pomoci? Předem děkuji
Uživatelský avatar
PetrSmetana
Příspěvky: 310
Registrován: pon 22. črc 2019 9:06:45
Bydliště: Mnich
Dal poděkování: 28 poděkování
Dostal poděkování: 60 poděkování
Kontaktovat uživatele:

Re: Zobrazení údajů na displeji

Příspěvek od PetrSmetana » úte 08. bře 2022 16:35:31

Podle toho na co jsem koukal ten UPS HAT využívá i piny SDA/SCL (I2C) - pokud tedy využíváš ten pythoní soubor, bylo by fajn odbavovat I2C komunikaci směrem k UPS HAT i I2C displeji přímo v něm - aby se ti dva skritpy nesnažily ovládnout I2C piny zároveň ... máš už nějaký kód k nahlédnutí, kde se snažíš o danou komunikaci?
Modré z nebe na počkání, zázraky do dvou dnů.
LSiler
Příspěvky: 4
Registrován: pát 04. bře 2022 5:31:44

Re: Zobrazení údajů na displeji

Příspěvek od LSiler » stř 09. bře 2022 6:06:54

Ahoj, já jsem těžký případ, jsem úplný začátečník co se týče programování, takže vlastně vůbec netuším jak na to, zkoušel jsem různé návody co jsem našel a vůbec se mi nepodařilo probudit ten displej, myslel jsem, že když by se přidala cesta do toho souboru INA219, který zobrazuje údaje v terminálu, tak by to mohlo zobrazovat údaje i na displeji, ale vůbec nevím jak na to. Byl bych rád za jakoukoliv radu, ale vím, že je to časově náročné. Předem děkuji.
Uživatelský avatar
PetrSmetana
Příspěvky: 310
Registrován: pon 22. črc 2019 9:06:45
Bydliště: Mnich
Dal poděkování: 28 poděkování
Dostal poděkování: 60 poděkování
Kontaktovat uživatele:

Re: Zobrazení údajů na displeji

Příspěvek od PetrSmetana » stř 09. bře 2022 10:51:14

Základ - abys věděl do implementuješ bych doporučil knihu od Martina Malého - online zdarma je zde: https://knihy.nic.cz/files/edice/hradla ... nocipy.pdf ... pokud máš základy elektroniky, tak koukni na I2C sběrnici - ať zhruba tušíš co a kam se snažíš napojit.

V pythonu to bude chtít stáhnout knihovnu pro tvůj displej, kterou nalinkuješ do skriptu který má na starosti UPS HAT. V nějakém vnitřním cyklu, který má na starosti základní běh aplikace bych pak zapisoval potřebné údaje na displej. Případně zkus shodit UPS HAT a nejdřív připojit jen displej a zkusit ho rozhýbat přes nějaký "example skript" ... ten pak můžeš překuchat do toho skriptu pro správu UPS HATU ...
Modré z nebe na počkání, zázraky do dvou dnů.
LSiler
Příspěvky: 4
Registrován: pát 04. bře 2022 5:31:44

Re: Zobrazení údajů na displeji

Příspěvek od LSiler » čtv 17. bře 2022 13:24:09

Takže jsem probudil display přes example skript:

# SPDX-FileCopyrightText: 2017 Tony DiCola for Adafruit Industries
# SPDX-FileCopyrightText: 2017 James DeVito for Adafruit Industries
# SPDX-License-Identifier: MIT

# This example is for use on (Linux) computers that are using CPython with
# Adafruit Blinka to support CircuitPython libraries. CircuitPython does
# not support PIL/pillow (python imaging library)!

import time
import subprocess

from board import SCL, SDA
import busio
from PIL import Image, ImageDraw, ImageFont
import adafruit_ssd1306


# Create the I2C interface.
i2c = busio.I2C(SCL, SDA)

# Create the SSD1306 OLED class.
# The first two parameters are the pixel width and pixel height. Change these
# to the right size for your display!
disp = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c)

# Clear display.
disp.fill(0)
disp.show()

# Create blank image for drawing.
# Make sure to create image with mode '1' for 1-bit color.
width = disp.width
height = disp.height
image = Image.new("1", (width, height))

# Get drawing object to draw on image.
draw = ImageDraw.Draw(image)

# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=0)

# Draw some shapes.
# First define some constants to allow easy resizing of shapes.
padding = -2
top = padding
bottom = height - padding
# Move left to right keeping track of the current x position for drawing shapes.
x = 0


# Load default font.
font = ImageFont.load_default()

# Alternatively load a TTF font. Make sure the .ttf font file is in the
# same directory as the python script!
# Some other nice fonts to try: http://www.dafont.com/bitmap.php
# font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', 9)

while True:

# Draw a black filled box to clear the image.
draw.rectangle((0, 0, width, height), outline=0, fill=0)

# Shell scripts for system monitoring from here:
# https://unix.stackexchange.com/question ... d-cpu-load
cmd = "hostname -I | cut -d' ' -f1"
IP = subprocess.check_output(cmd, shell=True).decode("utf-8")
cmd = 'cut -f 1 -d " " /proc/loadavg'
CPU = subprocess.check_output(cmd, shell=True).decode("utf-8")
cmd = "free -m | awk 'NR==2{printf \"Mem: %s/%s MB %.2f%%\", $3,$2,$3*100/$2 }'"
MemUsage = subprocess.check_output(cmd, shell=True).decode("utf-8")
cmd = 'df -h | awk \'$NF=="/"{printf "Disk: %d/%d GB %s", $3,$2,$5}\''
Disk = subprocess.check_output(cmd, shell=True).decode("utf-8")

# Write four lines of text.

draw.text((x, top + 0), "IP: " + IP, font=font, fill=255)
draw.text((x, top + 8), "CPU load: " + CPU, font=font, fill=255)
draw.text((x, top + 16), MemUsage, font=font, fill=255)
draw.text((x, top + 25), Disk, font=font, fill=255)

# Display image.
disp.image(image)
disp.show()
time.sleep(0.1)


Ale vůbec netuším jak upravit skript INA219, který zobrazuje údaje jen v terminálu:

import smbus
import time

# Config Register (R/W)
_REG_CONFIG = 0x00
# SHUNT VOLTAGE REGISTER (R)
_REG_SHUNTVOLTAGE = 0x01

# BUS VOLTAGE REGISTER (R)
_REG_BUSVOLTAGE = 0x02

# POWER REGISTER (R)
_REG_POWER = 0x03

# CURRENT REGISTER (R)
_REG_CURRENT = 0x04

# CALIBRATION REGISTER (R/W)
_REG_CALIBRATION = 0x05

class BusVoltageRange:
"""Constants for ``bus_voltage_range``"""
RANGE_16V = 0x00 # set bus voltage range to 16V
RANGE_32V = 0x01 # set bus voltage range to 32V (default)

class Gain:
"""Constants for ``gain``"""
DIV_1_40MV = 0x00 # shunt prog. gain set to 1, 40 mV range
DIV_2_80MV = 0x01 # shunt prog. gain set to /2, 80 mV range
DIV_4_160MV = 0x02 # shunt prog. gain set to /4, 160 mV range
DIV_8_320MV = 0x03 # shunt prog. gain set to /8, 320 mV range

class ADCResolution:
"""Constants for ``bus_adc_resolution`` or ``shunt_adc_resolution``"""
ADCRES_9BIT_1S = 0x00 # 9bit, 1 sample, 84us
ADCRES_10BIT_1S = 0x01 # 10bit, 1 sample, 148us
ADCRES_11BIT_1S = 0x02 # 11 bit, 1 sample, 276us
ADCRES_12BIT_1S = 0x03 # 12 bit, 1 sample, 532us
ADCRES_12BIT_2S = 0x09 # 12 bit, 2 samples, 1.06ms
ADCRES_12BIT_4S = 0x0A # 12 bit, 4 samples, 2.13ms
ADCRES_12BIT_8S = 0x0B # 12bit, 8 samples, 4.26ms
ADCRES_12BIT_16S = 0x0C # 12bit, 16 samples, 8.51ms
ADCRES_12BIT_32S = 0x0D # 12bit, 32 samples, 17.02ms
ADCRES_12BIT_64S = 0x0E # 12bit, 64 samples, 34.05ms
ADCRES_12BIT_128S = 0x0F # 12bit, 128 samples, 68.10ms

class Mode:
"""Constants for ``mode``"""
POWERDOW = 0x00 # power down
SVOLT_TRIGGERED = 0x01 # shunt voltage triggered
BVOLT_TRIGGERED = 0x02 # bus voltage triggered
SANDBVOLT_TRIGGERED = 0x03 # shunt and bus voltage triggered
ADCOFF = 0x04 # ADC off
SVOLT_CONTINUOUS = 0x05 # shunt voltage continuous
BVOLT_CONTINUOUS = 0x06 # bus voltage continuous
SANDBVOLT_CONTINUOUS = 0x07 # shunt and bus voltage continuous


class INA219:
def __init__(self, i2c_bus=1, addr=0x40):
self.bus = smbus.SMBus(i2c_bus);
self.addr = addr

# Set chip to known config values to start
self._cal_value = 0
self._current_lsb = 0
self._power_lsb = 0
self.set_calibration_32V_2A()

def read(self,address):
data = self.bus.read_i2c_block_data(self.addr, address, 2)
return ((data[0] * 256 ) + data[1])

def write(self,address,data):
temp = [0,0]
temp[1] = data & 0xFF
temp[0] =(data & 0xFF00) >> 8
self.bus.write_i2c_block_data(self.addr,address,temp)

def set_calibration_32V_2A(self):
"""Configures to INA219 to be able to measure up to 32V and 2A of current. Counter
overflow occurs at 3.2A.
..note :: These calculations assume a 0.1 shunt ohm resistor is present
"""
# By default we use a pretty huge range for the input voltage,
# which probably isn't the most appropriate choice for system
# that don't use a lot of power. But all of the calculations
# are shown below if you want to change the settings. You will
# also need to change any relevant register settings, such as
# setting the VBUS_MAX to 16V instead of 32V, etc.

# VBUS_MAX = 32V (Assumes 32V, can also be set to 16V)
# VSHUNT_MAX = 0.32 (Assumes Gain 8, 320mV, can also be 0.16, 0.08, 0.04)
# RSHUNT = 0.1 (Resistor value in ohms)

# 1. Determine max possible current
# MaxPossible_I = VSHUNT_MAX / RSHUNT
# MaxPossible_I = 3.2A

# 2. Determine max expected current
# MaxExpected_I = 2.0A

# 3. Calculate possible range of LSBs (Min = 15-bit, Max = 12-bit)
# MinimumLSB = MaxExpected_I/32767
# MinimumLSB = 0.000061 (61uA per bit)
# MaximumLSB = MaxExpected_I/4096
# MaximumLSB = 0,000488 (488uA per bit)

# 4. Choose an LSB between the min and max values
# (Preferrably a roundish number close to MinLSB)
# CurrentLSB = 0.0001 (100uA per bit)
self._current_lsb = .1 # Current LSB = 100uA per bit

# 5. Compute the calibration register
# Cal = trunc (0.04096 / (Current_LSB * RSHUNT))
# Cal = 4096 (0x1000)

self._cal_value = 4096

# 6. Calculate the power LSB
# PowerLSB = 20 * CurrentLSB
# PowerLSB = 0.002 (2mW per bit)
self._power_lsb = .002 # Power LSB = 2mW per bit

# 7. Compute the maximum current and shunt voltage values before overflow
#
# Max_Current = Current_LSB * 32767
# Max_Current = 3.2767A before overflow
#
# If Max_Current > Max_Possible_I then
# Max_Current_Before_Overflow = MaxPossible_I
# Else
# Max_Current_Before_Overflow = Max_Current
# End If
#
# Max_ShuntVoltage = Max_Current_Before_Overflow * RSHUNT
# Max_ShuntVoltage = 0.32V
#
# If Max_ShuntVoltage >= VSHUNT_MAX
# Max_ShuntVoltage_Before_Overflow = VSHUNT_MAX
# Else
# Max_ShuntVoltage_Before_Overflow = Max_ShuntVoltage
# End If

# 8. Compute the Maximum Power
# MaximumPower = Max_Current_Before_Overflow * VBUS_MAX
# MaximumPower = 3.2 * 32V
# MaximumPower = 102.4W

# Set Calibration register to 'Cal' calculated above
self.write(_REG_CALIBRATION,self._cal_value)

# Set Config register to take into account the settings above
self.bus_voltage_range = BusVoltageRange.RANGE_32V
self.gain = Gain.DIV_8_320MV
self.bus_adc_resolution = ADCResolution.ADCRES_12BIT_32S
self.shunt_adc_resolution = ADCResolution.ADCRES_12BIT_32S
self.mode = Mode.SANDBVOLT_CONTINUOUS
self.config = self.bus_voltage_range << 13 | \
self.gain << 11 | \
self.bus_adc_resolution << 7 | \
self.shunt_adc_resolution << 3 | \
self.mode
self.write(_REG_CONFIG,self.config)

def getShuntVoltage_mV(self):
self.write(_REG_CALIBRATION,self._cal_value)
value = self.read(_REG_SHUNTVOLTAGE)
if value > 32767:
value -= 65535
return value * 0.01

def getBusVoltage_V(self):
self.write(_REG_CALIBRATION,self._cal_value)
self.read(_REG_BUSVOLTAGE)
return (self.read(_REG_BUSVOLTAGE) >> 3) * 0.004

def getCurrent_mA(self):
value = self.read(_REG_CURRENT)
if value > 32767:
value -= 65535
return value * self._current_lsb

def getPower_W(self):
self.write(_REG_CALIBRATION,self._cal_value)
value = self.read(_REG_POWER)
if value > 32767:
value -= 65535
return value * self._power_lsb

if __name__=='__main__':

# Create an INA219 instance.
ina219 = INA219(addr=0x42)
while True:
bus_voltage = ina219.getBusVoltage_V() # voltage on V- (load side)
shunt_voltage = ina219.getShuntVoltage_mV() / 1000 # voltage between V+ and V- across the shunt
current = ina219.getCurrent_mA() # current in mA
power = ina219.getPower_W() # power in W
p = (bus_voltage - 6)/2.4*100
if(p > 100):p = 100
if(p < 0):p = 0

# INA219 measure bus voltage on the load side. So PSU voltage = bus_voltage + shunt_voltage
#print("PSU Voltage: {:6.3f} V".format(bus_voltage + shunt_voltage))
#print("Shunt Voltage: {:9.6f} V".format(shunt_voltage))
print("Load Voltage: {:6.3f} V".format(bus_voltage))
print("Current: {:9.6f} A".format(current/1000))
print("Power: {:6.3f} W".format(power))
print("Percent: {:3.1f}%".format(p))
print("")

time.sleep(2)

Je to pro mě opravdu španělská vesnice.
LSiler
Příspěvky: 4
Registrován: pát 04. bře 2022 5:31:44

Re: Zobrazení údajů na displeji

Příspěvek od LSiler » čtv 17. bře 2022 13:29:08

A dalsí věc je, když skript spustíš přes terminál a terminál zavřeš, tak display neaktualizuje údaje na displeji, to musí být terminál stále spuštěný, nebo to lze nějak upravit v tom skriptu? Byl bych ti moc zavázán za pomoc s tímto, ale i chápu, že to je moc.
Uživatelský avatar
PetrSmetana
Příspěvky: 310
Registrován: pon 22. črc 2019 9:06:45
Bydliště: Mnich
Dal poděkování: 28 poděkování
Dostal poděkování: 60 poděkování
Kontaktovat uživatele:

Re: Zobrazení údajů na displeji

Příspěvek od PetrSmetana » pon 21. bře 2022 8:58:23

Tak kde začít ... :) Pro běh na pozadí můžeš nainstalovat třeba screen (apt update && apt install screen). Pak spustíš screen a v něm příkaz pro běh skriptu a pak CTRL+A+D ... tím se ze screenu odhlásíš ... screen pak obnovíš přes screen -r

Nicméně tohle by si možná zasloužilo vlastní službu přes systemd ... jednoduchá služba popsána třeba tuto - viewtopic.php?f=37&t=130&p=604#p618 - místo bt.sh by tam byl tvůj skript.

Pokud je displej probuzen, zkus do toho začít tlačit logiku z toho ovladače pro ten UPS HAT.

Funkční část toho zaslaného skriptu začíná za:

while True:

To je hlavní smyčka programu, která se vykonává stále dokola. Chápu, že je pro tebe složité se zorientovat, ale ani já nejsem takový lumen, abych dal na první dobrou dohromady kód k periferiím, které neznám a nemůžu je otestovat. Pokud jsem někdy plaval ve vývoji, používal jsem metodu pokus/omyl a hodně jsem googlil :) Nedělal někdo už nějaké obdobné zapojení, jako chceš ty?
Modré z nebe na počkání, zázraky do dvou dnů.
Odpovědět