mehre I²C Nachrichten versenden

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
mre
User
Beiträge: 5
Registriert: Mittwoch 30. Januar 2019, 08:17

Hallo zusammen,
ich bin neu hier und möchte mich ganz kurz vorstellen.
Ich heiße Marcel bin 28 Jahre und komme aus der nähe von Darmstadt bei Frankfurt.
Ich programmiere seit ca 1 Jahr gelegentlich in Python, zum einen um meine Neugierde nach neuen Sachen zu stillen, zum anderen weil ich es extrem gut finde, ein Programm zu schreiben das genau so ist wie ich es brauche.

Jetzt zu meinem Anliegen.
(Python Version 3.7, Library: Std Python, SMBus, QtDesigner)

Ich habe eine Fließbank gebaut die ich jetzt als Upgrade mit einer Steuerung ausstatte (bisher wurden Wassersäulen abgelesen) bzw schon ausgestattet habe. Jetzt bin ich daran das passende Programm zu schreiben mit GUI und so weiter.
Gesteuert wird mit einem Raspberry Pi 3. Zur Berechnung werden mit dem I²C Bus über einen ADS1115 ADC 2 Drucksensoren ausgelesen.
Der eine Sensor misst einen Differenzdruck und der andere einen Statischen Druck im inneren der Fließbank.
Das auslesen funktioniert auch schon im Versuch soweit ganz gut.
Jetzt ist es aber so, dass ich die Sensoren einmal für die Berechnung der Durchflussmenge benötige und zum anderen zur Regelung des Prüfdruckes.

Meine Frage ist jetzt, wie kann ich vor dem auslesen des ADC (Analog Digital Converter) feststellen ob gerade auf dem Bus eine Nachricht verschickt wird.
Da die Druckabfrage (Statisch) der Regelung kontinuierlich läuft und die Druckabfrage (Differenz) der Berechnung eben nicht, habe ich die Befürchtung dass ich irgendwann das Szenario habe, dass 2 Nachrichten aus unterschiedlichen Funktionen gleichzeitig verschickt werden.

Gibt es eine Möglichkeit der Bus Statusabfrage oder habt Ihr eine Idee wie ich das "Problem" eventuell lösen könnte.

Oder eventuell ist meine Befürchtung komplett unbegründet, weil eventuell die verwendete SMBus Bibliothek die anstehenden Nachrichten ganz automatisch nacheinander versendet und darauf achtet eben keine 2 Nachrichten zeitgleich zu senden.


Vielen Dank schonmal für Eure Hilfe.

Liebe Grüße
Marcel
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ohne mehr Code zu sehen kann man das nicht genau beurteilen. Wenn du Threads benutzt (was du nicht solltest), DANN kannst du solche Probleme haben. Im Zweifel hast du schon welche, die dir nur noch gar nicht bewusst sind (weil eben solche Kollisionen selten auftreten, aber WENN dann sind sie entweder fatal oder schlimmer noch subtil fehlerhaft).

Rein aus der Perspektive des I2C-Busses und seiner Einbindung in das OS ist es kein Problem, weil dort Anfragen serialisiert werden. Sonst koenntest du nicht mehrere I2C-Geraete haben, die von unabhaengigen Programmen gesteuert werden. Aber innerhalb deines eigenen Programms kann es gut sein, dass du mit Nebenlaeufigkeit etwas verbockst.

Der Weg darum ist die Benutzung des Busses entweder immer synchron zu machen, also einfach aufzurufen aus der GUI. Wenn du aber periodisch/automatisch Dinge machen willst, dann benutzt du dafuer am besten Timer.
mre
User
Beiträge: 5
Registriert: Mittwoch 30. Januar 2019, 08:17

Vielen Dank schonmal für deine schnelle Antwort,

Codebeispiele sind aktuell schwer da er nicht fertig ist und sich noch der Übersichtlichkeit halber in mehreren Scripten verteilt.

Derzeit ist es so dass die Druckregelung in einem separaten Thread läuft (ich weis soll man nicht machen), die Fließbank Steuerung und alles andere läuft aus einem Script der GUI Steuerung heraus.
Ich habe "bis jetzt :-)" diesen Weg gewählt, da ich nicht weis wie ich beides abarbeiten soll ohne das eine Funktion der Druckregelung eine anderen Funktion der Steuerung blockiert, behindert oder ausbremst.

Kann ich das SMBus Modul so verstehen das die zu sendenden Nachrichten in einer Art Schlange anstehen und dann versendet werden wenn Sie an der Reihe sind?

Währe super wenn Du mir kurz erklären würdest wie Du das mit den Timern meinst. Wenn es zur Beschreibung irgendwelche speziellen Ausdrucksweißen gibt schreib Sie einfach hin.
Was ich nicht verstehe werde ich ergoogeln.

Gruß Marcel
__deets__
User
Beiträge: 14528
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Stichwort fuer Qt ist einfach nur QTimer. Damit kannst du periodisch kurz Aufgaben erledigen (wie eben den aktuellen Druck bestimmen), ohne einen Thread zu bemuehen.

Und die Regelung, die ja im Zweifel Zustandsbehaftet ist, machst du auch ueber einen QTimer. Da ist die Herausforderung wie man die so in Einzelschritte zerlegt, dass die per Timer getriggert funktioniert. Denn "while True: if diesunddas: tu_jenes()" geht da halt nicht mehr. Dazu kann man zB einen Zustandsautomaten bemuehen:

Code: Alles auswählen


class Steuerung:
      IDLE, RAMP_UP, RAMP_DOWN = "idle", "ramp_up", "ramp_down"

      def __init__(self):
            self._state = self.IDLE
      
      def timer_callback(self, elapsed_time): # muss regelmaessig aufgerufen werden
             if self._state == self.IDLE:
                  if irgendwas_das_den_zustand_aendert():
                          self._state = self.RAMP_UP
             elif self._state == self.RAMP_UP:
                     ...
Und das SMBModul kannst du genau NICHT so verstehen. Auf KERNEL-Ebene deines OS ist das so. Wenn du in EINEM Programm aus verschiedenen Threads auf das SMBmodul zugreifst, dann kann das krachen. Nicht wegen dem unterliegenden I2C (das ist ja das vom Kernel, und kommt damit klar), sondern weil das Modul selbst nicht dafuer gedacht ist.
mre
User
Beiträge: 5
Registriert: Mittwoch 30. Januar 2019, 08:17

Vielen Dank für Deine Hilfe.
Ich werde mir das mal vornehmen und versuchen einzubinden.

Gruß Marcel
Antworten