Frequenzen und Sensoren

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
PhlppSchlz
User
Beiträge: 8
Registriert: Dienstag 25. Februar 2020, 08:47

Da mir vor ein paar Wochen schon einmal hier super geholfen wurde, versuche ich es mal wieder. Mein Programm liest Beschleunigung auf einer Achse eines MPU6050 aus, um Vibrationen zu messen. Ziel sind 1000 Hz, welche das Programm ungefähr schafft. Leider schwankt die Zeit noch. Jetzt hatte ich beat.cronus entdeckt, welches relativ genaue Frequenzen möglich macht. Sind mit dem Sensor und dem Raspberry Pi 4 B überhaupt ungefähre 1200Hz möglich, sodass ich auf 1000 Hz herunterregeln kann?
Nutze ich etwas was zu lange braucht aber mit anderen Verfahren schneller möglich wäre? Bräuchte da glaube ich mal einen Anstoß von erfahrerenen Pythonern :wink:

Code: Alles auswählen

import smbus
import math
import pandas as pd
import os
import datetime
import time
import cronus.beat as beat

power_mgmt_1 = 0x6b
power_mgmt_2 = 0x6c
                 
def read_byte(reg):
    return bus.read_byte_data(address, reg)
                 
def read_word(reg):
    h = bus.read_byte_data(address, reg)
    l = bus.read_byte_data(address, reg+1)
    value = (h << 8) + l
    return value
                 
def read_word_2c(reg):
    val = read_word(reg)
    if (val >= 0x8000):
        return -((65535 - val) + 1)
    else:
        return val
                 
def dist(a,b):
    return math.sqrt((a*a)+(b*b))
         
bus = smbus.SMBus(1) # bus = smbus.SMBus(0) fuer Revision 1
address = 0x68       # via i2cdetect                
                
bus.write_byte_data(address, power_mgmt_1, 0)
                
#beat.set_rate(500) #=500Hz
while True:   #beat.true():                      #Auslesen des Sensors
              p = p + 1
                        
              start = time.time()
                    
              beschleunigung_xout = read_word_2c(0x3b)
              beschleunigung_xout_skaliert = abs(beschleunigung_xout) / 16384.0
                        
              save = open(f'/home/pi/gyropro/Messungen/Daten{e}.csv','a')        #Abspeichern der Daten
              save.write(f'{p},{str(abs(beschleunigung_xout_skaliert))}\n')
              save.close()
                        
              end = time.time()
                        
                        
              print(end - start)
                        
              #beat.sleep()                                       
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

cronus stellt nur sicher, dass du nichts falsch machst was die Berechnung der Wartezeit angeht. Wenn das dann aber nicht reicht, um die Stabilitaet der Messungen zu garantieren, dann ist etwas anderes faul. Und das ist auch nicht weiter verwunderlich: was du da vorhast geht ohne groesseren Aufwand nicht. Du probierst Daten mit stabiler, und relativ hoher Frequenz zu erhalten. Dafuer ist ein normales Betriebssystem nicht ausgelegt. Und dafuer ist auch die Sprache Python nicht ausgelegt.

Es gibt (und die nutze ich auch) die Moeglichkeit, den speziellen PREEMPT_RT-Branch des Kernels zu verwenden. Damit kann man sowohl den Prozess von Python, als auch die beteiligten Kernel-Tasks des I2C-Subsystems so hoch priorisieren, dass sie mit hoher Garantie stabil das Timing erreichen. Das ist der mindeste erste Schritt, den man da tun muss. Der zweite bedeutet ggf. die Abkehr von Python, denn die Sprache ist inhaerent nicht echtzeit-faehig. Das liegt daran, dass sie permanent Speicher anfordert und freigibt, und das kann ein Echtzeit-Prozess sich nicht erlauben. Fuer sowas geeignet sind die Programmiersprachen C, C++ und Rust.

Wenn ich an deiner Stelle waere, dann wuerde ich das Problem *ganz* anders loesen, denn ich vermute mal, dass deine Kenntnisse mit dem was ich da oben beschrieben habe nicht zu knapp ueberfordert sind. Dazu musst du dir einen Microcontroller wie zB den Arduino oder Parallax Propeller (mein Favorit) besorgen. Den so zu programmieren, dass er mit einem hoch stabilen Timing die IMU ausliest ist kein Problem. Der hat ja nix anderes zu tun. Die ermittelten Werte liefert er dann ueber die serielle Schnittstelle ab. Dabei wuerde ich mich auf binaere Werte nur fuer die 3 Achsen Gyro/Acc beschraenken, um so wenig Overhead wie moeglich zu haben. Diese Daten liest du dann in Python ein, und durch die dabei erfolgte Bufferung zwischendurch in der seriellen Schnittstelle entkoppelst du dich von den harten Timing-Constraints. Dazu ist es gegebenenfalls auch noch von Vorteil, eben den Buffer der seriellen Schnittstelle auf Arduino-Seite zu vergroessern: http://folk.uio.no/jeanra/Microelectron ... uffer.html
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Zu deinem Programm: da gibt's auch noch eine Menge zu verbessern, was die Situation ggf. ein bisschen verbessert - aber nicht garantiert!

Man oeffnet und schliesst eine Datei nicht unnuetz die ganze Zeit. Man oeffnet die einmal vorher, und schliesst sie vor beenden des Programms. Dazu zB das with-statement benutzen. Du darfst auch nichts auf der Kommandozeile mit print ausgeben, das kann beliebig lange verzoegern. Besser ist es also, das logging-Modul zu verwenden, und via Kommando-Zeilen-Argumenten das Programm so zu gestalten, dass es die Ausgaben nur explizit auf Anforderung macht, wenn man was debuggen will. Und sonst seine Schnauze haelt.

Und das du das beat gar nicht benutzt weisst du wahrscheinlich selbst.
PhlppSchlz
User
Beiträge: 8
Registriert: Dienstag 25. Februar 2020, 08:47

ok das erschließt schon mal einiges für mich. Dann weiß ich schonmal, dass man früher oder später auf C umsteigen muss. Das Print habe natürlich nur zum testen drin. Wenn ich allerdings mit einem zweiten Programm die Datei hochlade, muss ich die Datei doch geschlossen haben, damit ich immer die aktuellste hochlade, oder liege ich da falsch? Vielen Dank für die ausführliche Antwort, dass hilft mir schonmal gut weiter. Werde mal schauen ob ich da einen Mikrocontroller zum auslesen einbaue.
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du irrst dich. Woher weiß denn “das hochladen”, ob da gerade was offen oder geschlossen ist? Du hast dafür keinerlei Vorkehrungen getroffen, und entsprechend ist das auch nicht garantiert.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1021
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ich sag es ungern, aber mit einem Mikrocontroller wirst du sicherlich einfacher zum Ziel kommen.
Ich würde auch nicht unbedingt die Geschwindigkeit der Welle erfassen, sondern eher einen Vibrationssensor einsetzen und diese z.B. am Motorgehäuse befestigen.
Damit lässt sich dann z.B. vorhersagen wann die Lager getauscht werden müssen. Natürlich muss man vorher auch Referenzmessungen machen (in Ordnung oder kaputt).
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
__deets__
User
Beiträge: 14540
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und eine IMU die Beschleunigungen misst unterscheided sich wie genau von einem Vibrationssensor?
Antworten