Frequenzmessung/Datenlogger

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
Bl3nder
User
Beiträge: 139
Registriert: Freitag 3. Januar 2020, 17:07

Schönen guten Tag,


Ich möchte für die Arbeit mit einem Raspberry Pi 3B+ eine Art Datenlogger bauen.An diesem werden Temperatur ,Feuchtigkeit sowie die Windgeschwindigkeit gemessen.

Per I2C habe Ich Spannungswerte messen können das hat alles problemlos geklappt.(Temperatur und Feuchte werden als Spannungswerte abgegriffen nach einem AD Wandler).

Das Ausgangssignal der Windgeschwindigkeitssensors ist eine Frequenz hier gibt es zwei Methoden wie man diese ermitteln kann ( Tor- Schaltung & Reziprokefrequenzmessung)


Mein Versuch einer Tor-Schaltung:

Code: Alles auswählen

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
COUNTER = 0


def Interrupt():
    global COUNTER
    COUNTER += 1


# Interrupt-Event
GPIO.add_event_detect(27, GPIO.FALLING, callback=Interrupt)


def main():
    try:
        global COUNTER
        while True:
            start = time.time()
            while True:
                vergangene_zeit = time.time() - start
                if vergangene_zeit >= 1:
                    print("Es wurden", COUNTER, "in", vergangene_zeit, "gemessen!")
                    break
                time.sleep(0.01)
    except KeyboardInterrupt:
        print("Messung wurde abgebrochen!")


if __name__ == "__main__":
    main()
Ich habe die ermittelte Frequenz mit einem kalibrierten Messgerät gegen gepürft und augenscheinlich funktioniert es ( nächste Woche lege Ich nochmal eine Frequenzgenerator an den Pi und habe dann ein Aussagekräftiges Ergebnis ( Die Frequenz hier sind von 0Hz - ca 500Hz )



Mein Zweiter Versuch die Frequenz zu messen via Reziproke-Verfahren klappt leider nicht:

Code: Alles auswählen

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
COUNTER = 0
STARTZEIT = 0


def Interrupt():
    global COUNTER
    COUNTER += 1


# Interrupt-Event
GPIO.add_event_detect(27, GPIO.FALLING, callback=Interrupt)


def main():
    try:
        global COUNTER
        global STARTZEIT
        while True:
            if COUNTER == 1:
                STARTZEIT = time.time()
            if COUNTER == 5:
                endzeit = time.time() - STARTZEIT
                frequenz = 1 / endzeit
                COUNTER = 0
    except KeyboardInterrupt:
        print("Messung wurde abgebrochen!")


if __name__ == "__main__":
    main()

Die gemessene Zeit ist leider falsch Ich weiß nicht ob es ein Fehler von mir ist oder das das System ( Linux mit Python) auf dem Pi zu träge ist als Beispiel messe Ich bei 12Hz real Frequenz mit dieser Methode ca 2-3Hz ( 0,3256 .... sekunden) hat hier jemand eine Idee) Auch wenn Ich extra noch ein Time.sleep in die While Schleife einbaue von 0.001 Sekunden ?


Vorhaben:

Generell würde Ich gerne eure Meinung zu dem Projekt hören Ich weiß das viele die Sensordaten lieber mit einem Arudino auslesen und dann an den Pi übertragen ( da die Taktzahl den Pics deutlich höher ist als die des Pis) :

Meine Idee ist es im Prinzip 1 min Mittelwerte zu ermitteln also per I2C Temperatur mehrmals in der Minute zu messen sowie die Feuchte .Und natürlich die Windgeschwindigkeit falls es in einem Skript nicht klappen sollte dachte Ich an mehrere Threads.

Ich bin auf eurer Feedback gespannt und danke euch.
Eine Vision ohne Aktion bleibe eine Illusion
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

`as` ist dazu da, dass man den Import umbenennt. GPIO wird aber gar nicht umbenannt, das `as` ist daher Unsinn.
Konstanten werden komplett gross geschrieben, COUNTER ist aber gar keine Konstante. Sehr verwirrend. global sollte man auch erst gar nicht verwenden.

Code: Alles auswählen

import time
from collections import deque
from RPi import GPIO

PIN = 27

def main():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(PIN, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
    times = deque(maxlen=1000)
    GPIO.add_event_detect(PIN, GPIO.FALLING, callback=lambda: times.append(time.time()))
    try:
        while True:
            times.clear()
            time.sleep(1)
            print(f"Es wurden {len(times)} in 1s gemessen!")
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
    print("Messung wurde abgebrochen!")


if __name__ == "__main__":
    main()
Bei deinem zweiten Code hast Du ja die Zeit von 4 Countern gezählt.

Code: Alles auswählen

import time
from collections import deque
from RPi import GPIO

PIN = 27

def main():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(PIN, GPIO.IN, pull_up_down=GPIO.PUD_OFF)
    times = deque(maxlen=5)
    GPIO.add_event_detect(PIN, GPIO.FALLING, callback=lambda: times.append(time.time()))
    try:
        while True:
            time.sleep(0.1)
            data = list(times)
            frequency = (len(data) - 1) / (data[-1] - data[0])
            print(f"{frequency}Hz")
    except KeyboardInterrupt:
        pass
    finally:
        GPIO.cleanup()
    print("Messung wurde abgebrochen!")


if __name__ == "__main__":
    main()
Bl3nder
User
Beiträge: 139
Registriert: Freitag 3. Januar 2020, 17:07

Ich danke dir für die schnelle Antwort
Eine Vision ohne Aktion bleibe eine Illusion
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Statt dem wirklich schlechten RPi.GPIO benutzt man fuer alles, bei dem es einem auf Ereigniszeitpunkte ankommt, pigpio. Denn das sampelt die IO-Ereignisse mittels DMA und uebergibt dann praezise Tick-Zeitstempel, dank derer man auch wenn das eigene Programm gerade mal vom Kernel kurz angehalten worden ist, weil irgendwas wichtiges wie ein Netzwerkdatenpaket dazwischengekommen ist.

Und dann fehlt deiner Drehzahlberechnung natuerlich noch die Faehigkeit, auch gegen Null zu konvergieren, wenn das Windrad stillsteht. Mit deinem Ansatz bekommst du auf ewig immer nur den letzten Messwert. Um das vernuenftig umzusetzen bietet sich eine Klasse an, die man sowohl mit Trigger-Zeitpunkten fuettert, als auch eine rpm-Abfrage, die mit groessere zeitlicher Entfernung zum letzten Messzeitpunkt gegen 0 konvergiert.
Bl3nder
User
Beiträge: 139
Registriert: Freitag 3. Januar 2020, 17:07

Ich danke euch für die Denkanstöße und @ __deets__ hat natürlich Recht das es dann nie zu einem weiterzählen kommen würde wenn keine Impuls mehr kommen das verstehe Ich .Ich probier mal die Tage ein bisschen alleine weiter und werde mich dann melden sobald Ich ein Ergebnis habe .Und Ich werde mir die andere Bibliothek mal anschauen :)
Eine Vision ohne Aktion bleibe eine Illusion
Antworten