SocketCAN und Interrupt ?

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
einemark
User
Beiträge: 3
Registriert: Mittwoch 21. August 2019, 14:05

Hallo zusammen,

ich möchte gerne aufm dem Raspberry Pi Display CAN Nachrichten darstellen.
Grundsätzlich funktioniert das soweit auch schon, allerdings würde ich gerne per Interrupt (oder vergleichbare Lösungen) den CAN auslesen und nicht wie in meiner Lösung alle 1ms.

Habt ihr eine Idee für mich?

Danke im voraus.

MfG

Code: Alles auswählen

########----------import modules--------###########
from tkinter import *

from pyvit import can
from pyvit.hw import socketcan

########-------START CAN INTERFACE-----###########

dev = socketcan.SocketCanDev("can0")
dev.start()


########------------START GUI----------###########
fenster = Tk() #legt ein Fenster an
fenster.title("veh-speed") #bestimmt titel vom Fenster
fenster.geometry("400x700")

label_1 = Label(fenster, fg="black", bg="white", font="50")
label_1.pack()


########---------Define Functions-------###########

def f_veh_speed():
    global v_veh_speed
    v_veh_speed = int.from_bytes([frame.data[0],frame.data[1]], byteorder='big', signed=False)*0.01 #Factor is 0.01
    label_1.configure(text=str(v_veh_speed))
    
def read_every_1ms():
    global frame
    frame = dev.recv()
    canid = frame.arb_id # check CAN ID
    print(canid)
    if hex(canid) == '0x415':
        f_veh_speed()   
    fenster.after(1, read_every_1ms)

read_every_1ms()

fenster.mainloop()
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Eine Millisekunde ist eh ein bisschen sehr ambitioniert. In Python und mit einer GUI.

Doch davon abgesehen: mit createfilehandler https://docs.python.org/3/library/tkint ... ilehandler kannst du auf Ereignisse auf dem CAN-Bus warten, und die dann verarbeiten.
einemark
User
Beiträge: 3
Registriert: Mittwoch 21. August 2019, 14:05

Danke für die Antwort. Den File Händler gucke ich mir morgen mal genauer an.

Die 1ms war nur ein erster Versuch, der auch nicht reichen wird.
Es kommen per CAN ~5 Messages/ms.

Meine Idee wäre alle bzw. alle relevanten Daten vom CAN speichern und dann fürs Display alle x00ms updaten.

MfG
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn der mit mehreren / ms arbeitet, dann bringt der createfilehandler Ansatz nix. Dann setz einfach den timeout auf 100ms, und verarbeite 500 Nachrichten in einem Rutsch.
einemark
User
Beiträge: 3
Registriert: Mittwoch 21. August 2019, 14:05

Okay,

da ist jetzt mein Verständnis als Einsteiger in python/Linux/SocketCAN am ende.

Das Szenario ist folgendes:
Im Auto liegen super viele Infos aufm CAN und ich will bestimmte Infos lesen, in einer Variablen zwischenspeichern und diese dann aufm Display ausgeben.
Langfristig ist es sicher auch interessant die Daten dauerhaft zu speichern, also die letzte 1min. und nicht nur den letzten Wert.

Aus der C Welt kenne ich das so, dass ich per Interrupt jede einkommende Nachricht per selbst geschriebenes Script verarbeite.

Speichert der SocketCAN die "500 Nachrichten" irgendwo, wo ich die auch abgreifen kann?

MfG
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was heisst "C-Welt"? In C unter Linux hast du auch keine Interrupts. Und Scripte eigentlich auch nicht. Meinst du also die uC/MicroController-Welt?

Unter Linux (und jedem anderen halbwegs grossen OS) hast du keinen unmittelbaren Zugriff auf Interrupts. Das machen Treiber fuer dich. Und ja, die buffern einkommende Daten, und du kannst dann mehr in einem Rutsch abholen. Der Trickreiche Teil ist die Frage zu klaeren, wie viele Daten gerade da sind. Ich habe dazu in https://www.kernel.org/doc/Documentatio ... ng/can.txt nichts gefunden. Denn wenn du das nicht machst, blockiert der recv-Aufruf.

Die Loesung die ich dann waehlen wuerde: per createfilehandler sicherstellen, dass ich jede anliegende Nachricht auf dem CAN-Bus bekomme. Die aber NICHT komplett (mit GUI-update) verarbeiten, denn das ist viel zu teuer. Stattdessen die Nachrichten einfach puffern (ggf. mit einem Zeitstempel), und mit einem zweiten Timer eben alle 500ms oder was auch immer die Nachrichten verarbeiten und darstellen. Denn sonst verballerst du einfach nur die gesamte CPU-Zeit mit GUI-refresh.
__deets__
User
Beiträge: 14542
Registriert: Mittwoch 14. Oktober 2015, 14:29

Achso, was in dem von mir verlinkten Dokument beschrieben ist: Filter. Damit kannst du ggf. deine bestimmten Pakete per Filterkriterium definieren, und dadurch die Frequenz der Pakete massiv verringern. Das haengt jetzt davon ab, was genau die sind und ob die Filter-API dazu ausreichend ist. Dafuer reduzierst du dann massiv die Last, denn jeder Uebergang von User- in Kernel-Space zum lesen eines Paketes (recv), und jede Zeile Python-Code die durchlaufen wird, sind teuer.
Antworten