3D Drucker Monitoring - Wägezelle / Längenmessung

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
RSV-Tuono
User
Beiträge: 1
Registriert: Sonntag 16. Januar 2022, 11:30

Hallo zusammen,
bin Anfänger und versuche mir 2Scripte zusammenzubasteln ...

Ich möchte meinen 3D Drucker über meine Haussteuerung überwachen.
Dies geschieht bereits über MQTT und funktioniert ganz gut.
Abgefragt werden Wete wie ENDSTELLUNG und LÄNGENMESSUNG.
Zusätzlich sollen jetzt weitere Sensordaten hinzukommen:
- WÄGEZELLE HX711 für das Filament Gewicht
- TEMPERATURMESSUNG über I2C des Druckerbetts

Für die Wägezelle habe ich folgendes Script zum Testen verwendet:
https://github.com/tatobari/hx711py/blob/master/example.py

Diese funktioniert für sich alleine auch sehr gut und ausreichend genau.

Aktuelles Script LÄNGENMESSUNG und ENDSCHALTER:

Code: Alles auswählen

#!/usr/bin/env python3
import paho.mqtt.client as mqtt
import time
import RPi.GPIO as GPIO
import threading
import sys
from hx711 import HX711

#MQTT
broker= "123.456.78.9"
port="1234"
topic="raspberry"
user="user"
pwd="passwort"

#COUNTER
count=0

#WAAGE
#referenceUnit = -410
#hx = HX711(5, 6)
#hx.set_reference_unit(referenceUnit)

def on_connect(client, userdata, flags, rc):
       # print(f"Connected with code {rc}")
       print("OK")

def set_interval(func, sec):
  def func_wrapper():
    set_interval(func, sec)
    func()
  t = threading.Timer(sec, func_wrapper)
  t.start()
  return t

def zeroI():
  global count, state, val
  state =  GPIO.input(24)

  print (count)

  #print (val)

  print (state)
  count = count

  client.publish("haussteuerung/counter", (count))
  client.publish("haussteuerung/state", (state))
  #client.publish("haussteuerung/value", (val))

set_interval(zeroI, 3.0) #nur zum Test auf 3 sec

client = mqtt.Client("RASPBERRY")
client.username_pw_set(username=user, password=pwd)
client.on_connect = on_connect
client.connect(broker, port, 60)

while True:
  GPIO.setmode(GPIO.BCM)
  GPIO.setup(23, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
  GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)

  GPIO.wait_for_edge(23, GPIO.RISING)
  count = count + 1

  GPIO.cleanup()

client.loop_forever()

Leider bekomme ich das auslesen des Wertes
val = hx.get_weight(5)
nicht so in mein vorhandenes Script integriert,dass es fehlerfrei läuft.

Kann mich bitte jemand bei meinem Problem unterstützen?
Danke im Voraus
imonbln
User
Beiträge: 149
Registriert: Freitag 3. Dezember 2021, 17:07

Dein Code hat sehr viele Probleme, mal sehen, ob ich die alle sortiert bekomme.

1.) bei dem Imports sollte man immer zuerst die Standards Imports aufführen und dann die aus den Pips, die Reihenfolge sollte also ungefähr so sein:

Code: Alles auswählen

import time
import threading
import sys

import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
from hx711 import HX711
2.) man sollte immer Daten von Programmfluss trennen, die Konfiguration des MQTT gehört also nicht direkt in den Sourcecode, sondern besser in ein separates Konfigurationsfile (ich würde JSON oder yaml nehmen, aber es geht auch alles andere)

3.) Globale Variablen sind immer ein Problem! Wie dieser Counter vermeide sie, wenn immer möglich, das schlüssel Wort global ist bei mir auch ein redflag, immer wenn ich es sehe, gehe ich davon aus das etwas mit dem Design nicht stimmt. (Ich würde sagen in 95% der Fälle, trifft die Annahme zu).
4.) eingerückt wird in Python immer mit 4 Spaces (immer!)
5.) hx ist auskommentiert, kann also zurzeit nicht gehen :wink:
6.) die Funktion set_interval, sieht komisch aus sollte das vielleicht ein Decorator werden? Außerdem denke ich, dass hier eine Rekursion ohne Abbruchbedingung erfolgt. Da sie sich innerhalb der func_wrapper selbst ruft, das wird irgendwann zum RecursionError führen.
7.) der Name des Clients sollte Teil der Konfiguration sein.
8.) die Nebenläufigkeit in deinem Programm kann nicht funktionieren! Da der while True loop nie verlassen wird, wird der Eventloop des MQTT client nie gestartet. Hier fehlt also ein weiter threat oder du probierst es mit ayncio.

Aus dem von dir verlinken Beispiel und den Readme von https://github.com/sbtinstruments/asyncio-mqtt zusammen kopiert könnte folgender Code ungefähr das machen, was du willst.

Code: Alles auswählen

#!/usr/bin/env python3
import asyncio
import contextlib
import itertools

import asyncio_mqtt
import RPi.GPIO as GPIO
from hx711 import HX711

async def mqtt_srv()
    ''' 
    asynchrones aufsetzten des MQTT
    '''
    async with contextlib.AsyncExitStack() as stack:
        tasks = set()
        stack.push_async_callback(cancel_tasks, tasks)

        with open('mqttsettings.json') as jin:
            config = json.load(jin)

        client = asyncio_mqtt.Client(config['name'])
        client.username_pw_set(username=config['user'], password=config['password'])
        client.connect(config['broker'], config['port'], 60) 

        await stack.enter_async_context(client)

        task = asyncio.create_task(post_hx71(client))
        tasks.add(task)
        await asyncio.gather(*tasks)


async post_hx71(client):
    ''' 
    Asynchronens abfragen des Sensors und Senden der Werte an über den MQTT broker

    TODO: Cleanup wenn der Threat beendet wird.
    '''

    hx = HX711(5, 6)
    hx.set_reading_format("MSB", "MSB")

    referenceUnit = 1 
    hx.set_reference_unit(referenceUnit)

    hx.reset()
    hx.tare()

    for cnt in itertools.count():
        val = hx.get_weight(5)
        await client.publish('haussteuerung/counter', cnt)
        await client.publish('haussteuerung/value', val)


async def cancel_tasks(tasks):
    for task in tasks:
        if not task.done():
            with contextlib.suppress(asyncio.CancelledError):
                task.cancel()
                await task


async def main():
    reconnect_interval = 3  # [seconds]
    while True:
        try:
            await mqtt_srv()
        except asyncio_mqtt.MqttError as error:
            print(f'Error "{error}". Reconnecting in {reconnect_interval} seconds.')
        finally:
            await asyncio.sleep(reconnect_interval)


if __name__ == "__main__":
    asyncio.run(main())
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@imonbln,

ich glaube da fehlt ein "def" in

async post_hx71(client):

Falls RSV-Tuono die Lösung mit der json-Datei nutzen möchte, muss das json Modul auch noch importiert werden.
Warum hast du die GPIO-Abfrage weggelassen?

Die username_pw_set() Methode gibt es beim asyncio_mqtt.Client() eigentlich nicht, aber
username und password kann man wohl auch bei der Instanziierung des asyncio_mqtt.Client() übergeben.

client.connect() muss "awaited" werden, denke ich.

Und wenn ich das richtig verstehe, wird die connect() Methode auch eigentlich bei der Übergabe an den AsyncExitStack ausgelöst. Kann also passieren , dass die so zweimal aufgerufen wird.
imonbln
User
Beiträge: 149
Registriert: Freitag 3. Dezember 2021, 17:07

@rogerb

Wahrscheinlich hast du b recht, ich habe das nur schnell zusammen kopiert, ich habe den Sensor nicht und das einfach blind mal runtergeschrieben, das bleiben kleine Fehler nicht aus.
Antworten