Bluetooth Real Time Plot Python/ Arduino

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
wing354
User
Beiträge: 7
Registriert: Dienstag 30. Juli 2019, 13:04

Moin,

ich habe leider keinen richtigen Ansatz, um meine Idee umzusetzen. Ich bin auch relativ neu im Programmieren von Pythonprogrammen.

Ich möchte mit Python einen Real Time Plot realisieren, in dem Python Daten von einer Bluetooth Antenne abfragt, die über die serielle Schnittstelle eines Arduino Uno mit Daten versorgt wird.

Code: Alles auswählen

import bluetooth, subprocess 
name = "HC-05"      # Device name
addr = "98:D3:91:FD:42:7E"      # Device Address
port = 1         # RFCOMM port
passkey = "1234" # passkey of the device you want to connect

# kill any "bluetooth-agent" process that is already running
subprocess.call("kill -9 `pidof bluetooth-agent`",shell=True)

# Start a new "bluetooth-agent" process where XXXX is the passkey
status = subprocess.call("bluetooth-agent " + passkey + " &",shell=True)

# Now, connect in the same way as always with PyBlueZ
try:
    s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
    s.connect((addr,port))
except bluetooth.btcommon.BluetoothError as err:
    # Error handler
    pass
Über diesen Code stelle ich eine Verbindung her, funktioniert auch prima.
Mit "s.send("G")" zum Beispiel sende ich meine Befehle und mit "s.recv(x)" möchte ich meine Daten auslesen, was an sich auch klappt.
Allerdings bekomme ich daraus keinen Liveplot gebastelt und habe keine richtigen Ansatz dafür. Hat schon mal jemand was ähnliches versucht und kann mir weiterhelfen?

Beste Grüße
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@wing354: Auf jeden Fall solltest Du diese kaputte Ausnahmebehandlung da raus nehmen und ab sofort Ausnahmebehandlung nur noch schreiben/machen wenn Du da auch tatsächlich etwas *sinnvolles* machst.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
wing354
User
Beiträge: 7
Registriert: Dienstag 30. Juli 2019, 13:04

Okay...
Ich habe folgenden Code gefunden und versuche den gerade auf meinen Fall zu münzen.

Code: Alles auswählen

# -*- coding: utf-8 -*-
"""
@author: Bernd Porr, mail@berndporr.me.uk
"""

import socket
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import threading

# read from channel 9
channel = 9

# socket connection to attys_scope
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
listen_addr = ("",65000)
s.bind(listen_addr)
f = s.makefile()

#That's our ringbuffer which accumluates the samples
#It's emptied every time when the plot window below
#does a repaint
ringbuffer = []

# for the thread below
doRun = True

# This reads the data from the socket in an endless loop
# and stores the data in a buffer
def readSocket():
    global ringbuffer
    global channel
    while doRun:
        # check if data is available
        data = f.readline()
        values = np.array(data.split(','),dtype=np.float32)
        ringbuffer.append(values[channel])
        

# start reading data from socket
t = threading.Thread(target=readSocket)
t.start()

# now let's plot the data
fig, ax = plt.subplots()
# that's our plotbuffer
plotbuffer = np.zeros(500)
# plots an empty line
line, = ax.plot(plotbuffer)
# axis
ax.set_ylim(-2, 2)


# receives the data from the generator below
def update(data):
    global plotbuffer
    # add new data to the buffer
    plotbuffer=np.append(plotbuffer,data)
    # only keep the 500 newest ones and discard the old ones
    plotbuffer=plotbuffer[-500:]
    # set the new 500 points of channel 9
    line.set_ydata(plotbuffer)
    return line,

# this checks in an endless loop if there is data in the ringbuffer
# of there is data then emit it to the update funnction above
def data_gen():
    global ringbuffer
    #endless loop which gets data
    while True:
        # check if data is available
        if not ringbuffer == []:
            result = ringbuffer
            ringbuffer = []
            yield result

# start the animation
ani = animation.FuncAnimation(fig, update, data_gen, interval=100)

# show it
plt.show()

# stop the thread which reads the data
doRun = False
# wait for it to finish
t.join()

# close the file and socket
f.close()
s.close()

print("finished")

Ich habe es wie folgt geändert, allerdings scheitert er dann ab der letzten Zeile.

Code: Alles auswählen

import socket
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import threading
import bluetooth
name = "HC-05"      # Device name
addr = "98:D3:91:FD:42:7E"      # Device Address
port = 1         # RFCOMM port
passkey = "1234" # passkey of the device you want to connect
# read from channel 9
channel = 9

# socket connection to attys_scope
#s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#listen_addr = ("",65000)
#s.bind(listen_addr)
s = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
s.connect((addr,port))
f = s.makefile()
" f = s.makefile()
Traceback (most recent call last):

File "<ipython-input-5-cfe70f3e1075>", line 1, in <module>
f = s.makefile()

File "C:\Users\hendr\Anaconda3\lib\site-packages\bluetooth\msbt.py", line 130, in makefile
raise Exception("Not yet implemented")

Exception: Not yet implemented"
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn der bluetooth-agent nur während der Ausführung des Skripts laufen soll, ist es unsinnig, ihn für immer zu starten und aber beim Start des Skripts den alten zu killen. Da Du mit dem `status` nichts machst, warum speicherst Du ihn in einer Variable?
Konstanten schreibt man nach Konvention KOMPLETT_GROSS.
Sprechendere Namen sparen dann auch die Kommentare dahinter.

Code: Alles auswählen

import bluetooth
import subprocess 
DEVICE_NAME = "HC-05"
DEVICE_ADDRESS = "98:D3:91:FD:42:7E"
RFCOMM_PORT = 1
PASS_KEY = "1234" # passkey of the device you want to connect

def main():
    try:
        # Start a new "bluetooth-agent" process where XXXX is the passkey
        bluetooth_agent = subprocess.Popen(["bluetooth-agent", PASS_KEY])

        # Now, connect in the same way as always with PyBlueZ
        socket = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
        socket.connect((DEVICE_ADDRESS, RFCOMM_PORT))
        ...
    finally:
        bluetooth_agent.kill()

if __name__ == '__main__':
    main()
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Darueber haben wir doch schon in deinem letzten Post zum exakt gleichen Thema gesprochen, und festgestellt, es geht nicht: viewtopic.php?f=1&t=46195#p350365

Wieso hakt es da schon wieder?

Und hier ist ein Server von mir, der Daten ueber OSC annimmt, und live mit Bokeh plottet, funktioniert super: https://github.com/deets/new-joy-tracke ... ter/newjoy

Das musst du natuerlich modifizieren, aber so geht's und ist ein Start.
Antworten