Forum: PC-Programmierung Raspi telnet SPI Schnittstelle


von Marcus (Gast)


Lesenswert?

Nachdem die Ansteuerung einer LED über telnet gut funktioniert

Beitrag "RasPi telent LED blnken"

versuche ich mein eigentliches Ziel, die Fernsteuerung der 
SPI-Schnittstelle über telnet zu realisieren. Ich habe hierzu diesen 
neuen Thread aufgemacht, weil die Überschrift für die Forensuche ja 
wichtig ist.

Mein Code sieht momentan so aus:
1
#!/usr/bin/python             
2
# how to use the SPI
3
# http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_SPI.html
4
5
import socket                 # Import socket module
6
import time
7
import RPi.GPIO as GPIO
8
import spidev
9
10
#pin definitions
11
RST_N = 25
12
ARDUINO_LED = 4 # Raspberry GPIO 4
13
14
GPIO.setmode(GPIO.BCM)  # set board mode to Broadcom
15
16
GPIO.setup(RST_N, GPIO.OUT)  # RST_N as output
17
GPIO.setup(ARDUINO_LED, GPIO.OUT)  
18
19
spi = spidev.SpiDev()
20
spi.open(0,0)
21
spi.max_speed_hz=4000000
22
23
24
def led_blink(msg):
25
    print "got msg", msg         # Debug msg
26
    
27
    spidata=spi.xfer(msg)
28
29
    GPIO.output(ARDUINO_LED, GPIO.HIGH)
30
    time.sleep(0.1)
31
    GPIO.output(ARDUINO_LED, GPIO.LOW)
32
33
s = socket.socket()           # Create a socket object
34
host = ''                     # all interfaces
35
port = 5006                   # Port
36
s.bind((host, port))          # Bind to the port
37
s.listen(5)                   # Now wait for client connection.
38
print "Listening"
39
c, addr = s.accept()          # Establish connection with client.
40
41
while True:
42
    msg = c.recv(1024)
43
    print map(ord,msg)
44
    print 'Got connection from', addr
45
    if msg[0:4] == "Exit":
46
        print "EXIT !!"
47
        break
48
    led_blink(msg)
49
50
c.close()
51
spi.close()

Die SPI habe ich zuvor getrennt getestet und sie lässt sich von Python 
aus ansprechen.
Allerdings funktioniert das Ganze wohl nicht wenn ich den SPI-Befehl

    spidata=spi.xfer(msg)

in den Server einbaue. Sobald der Sever eine Anfrage erhält, beendet er 
sich kommentarlos.

Woran könnte das wohl liegen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was für eine Art von Daten kann spi.xfer verarbeiten? Kann das mehr als 
ein einzelnes Byte bzw. Word verarbeiten?

Bedenke, daß SPI eine synchrone serielle Schnittstelle ist, die 
gleichzeitig(!) sendet und empfängt.

Was für Daten erwartest Du in spidata?

von Marcus (Gast)


Lesenswert?

>Was für eine Art von Daten kann spi.xfer verarbeiten?

Das ist eine gute Frage, besonders weil in Python ja Typen nicht 
ersichtlich sind.
Das Ur-Beispiel habe ich von hier:
http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_SPI.html

dort steht:
1
spi.xfer([array of bytes])  Sendet ein Byte-Array, CEx wird vor jedem Byte aktiv und dann wieder inaktiv

und tatsächlich, dank Deiner Anmerkung habe ich einfach mal testweise 
die Zeile
1
    spi.xfer([1,2,3])

eingesetzt. Mit dem Logikanalysator geprüft werden jetzt die 3 bytes 
gesendet und der Server beendet sich nicht mehr.
Es sieht also so aus, als wenn die xfer-Funktion sich an dem Text 
verschluckt.

von Marcus (Gast)


Lesenswert?

Damit ich die SPI-Schnittstelle steuern kann, müssen Daten zum 
SPI-Server übertragen werden und die Empfangsdaten vom Server abgeholt 
werden.
Das Senden funktioniert eigentlich. Ich kann via telnet zum obigen 
Server senden, kann aber keine Daten empfangen.

Als Test für das zurücksenden habe ich folgendes probiert ( es wird 
einfach nur ein ">" zurück gesendet ). Wenn ich das tue, bleibt der 
Server aber wieder hängen, wenn ich ihn mit telnet anspreche. Woran 
könnte das liegen?
Hier ist der funktionierende Code für das beschreiben der 
SPI-Schnittstelle. Das Zurücksenden, welches nicht funktioniert, habe 
ich auskommentiert.

1
#!/usr/bin/python             
2
# how to use the SPI
3
# http://www.netzmafia.de/skripten/hardware/RasPi/RasPi_SPI.html
4
5
import socket                 # Import socket module
6
import time
7
import RPi.GPIO as GPIO
8
import spidev
9
10
#pin definitions
11
RST_N = 25
12
ARDUINO_LED = 4 # Raspberry GPIO 4
13
14
GPIO.setmode(GPIO.BCM)  # set board mode to Broadcom
15
16
GPIO.setup(RST_N, GPIO.OUT)  # RST_N as output
17
GPIO.setup(ARDUINO_LED, GPIO.OUT)  
18
19
spi = spidev.SpiDev()
20
spi.open(0,0)    #message=raw_input(">")
21
    #c.send(message);
22
spi.max_speed_hz=4000000
23
24
25
def toggleLed():
26
  if not hasattr(toggleLed, "state"):
27
     toggleLed.state = 0  # it doesn't exist yet, so initialize it
28
  if toggleLed.state==1:
29
    GPIO.output(ARDUINO_LED, GPIO.HIGH)
30
    toggleLed.state=0
31
  else:
32
    GPIO.output(ARDUINO_LED, GPIO.LOW)
33
    toggleLed.state=1
34
35
def transfer(msg):
36
    print "got msg", msg         # Debug msg
37
    data=map(ord,msg)
38
    if len(data)>0:
39
      data=spi.xfer(data)
40
    toggleLed()
41
    return str(data)
42
43
s = socket.socket()           # Create a socket object
44
host = ''                     # all interfaces
45
port = 5007                   # Port
46
s.bind((host, port))          # Bind to the port
47
s.listen(5)                   # Now wait for client connection.
48
print "Listening"
49
c, addr = s.accept()          # Establish connection with client.
50
51
while True:
52
53
    msg = c.recv(1024)
54
    print map(ord,msg)
55
    print 'Got connection from', addr
56
    if msg[0:4] == "Exit":
57
        print "EXIT !!"
58
        break
59
    print "data", transfer(msg)
60
61
    #Zurücksenden zu telnet geht nicht
62
    #message=raw_input(">")
63
    #c.send(message);
64
65
c.close()
66
spi.close()

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Marcus schrieb:
> Woran könnte das liegen?

Hat denn die spi.xfer-Funktion überhaupt einen Rückgabewert? Der von Dir 
zitierten Dokumentation zufolge nicht, das Ding scheint eine 
Einbahnstraße zu sein, nur senden, aber nichts empfangen.

Andererseits gibts da ja dieses Beispiel
1
# Einleseschleife
2
while True:
3
  # Lese ADC-Kanal 1
4
  rcv = spi.xfer2 ([1, 8 << 4, 0])
5
  adcval = ((rcv[1] & 3) << 8) + rcv[2]
6
  # Wert ausgeben 
7
  Print "ADC = ", adcval
8
  # etwas warten
9
  time.sleep(1)
10
# Ende Schleife

demzufolge spi.xfer(2) einen Rückgabewert hat. Und der ist wohl auch 
vom Typ "array of byte".

Erzeugt denn die von Dir verwendete Funktion "str" aus diesem Datentyp 
was lesbares?

von imonbln (Gast)


Lesenswert?

Marcus schrieb:
> #Zurücksenden zu telnet geht nicht
>     #message=raw_input(">")
>     #c.send(message);

Der Server sendet hier nichts, weil er auf eingaben wartet. raw_input 
wartet das du dinge (TM) auf stdin deines Pi Eingibst nach dem return 
werden die auch gesendet.
1
 raw_input(...)
2
    raw_input([prompt]) -> string
3
    
4
    Read a string from standard input.  The trailing newline is stripped.
5
    If the user hits EOF (Unix: Ctl-D, Windows: Ctl-Z+Return), raise EOFError.
6
    On Unix, GNU readline is used if enabled.  The prompt string, if given,
7
    is printed without a trailing newline before reading.

generell würde ich dir empfehlen deinen Server auf einen TCPServer 
socketserver umzubauen. der nimmt dir das kümmern ums Netzwerk etwas ab 
und solltest du feststellen das UPD oder ein Threading server oder so 
brauchst kannst du dann einfach ein paar Klassen wechseln und das ding 
ist fertig umgestellt.

>def toggleLed():
>  if not hasattr(toggleLed, "state"):
>     toggleLed.state = 0  # it doesn't exist yet, so initialize it
>  if toggleLed.state==1:

hier würde ich vorschlagen das toggleLed.state zu einen bool zu machen
1
 if toogle.stateHigh is True:
 ließt sich einfach schöner im Code.

von Marcus (Gast)


Lesenswert?

imonbln (Gast)
>Der Server sendet hier nichts, weil er auf eingaben wartet. raw_input

Du hast Recht. Das war der Fehler.
Ich habe schon ewig nichts mehr mit Python gemacht und versuche den 
Syntax wieder in die vorderen Speicherbereiche meines Gehirns zu bringen 
..

Ob es wohl besser wäre eher UDP für's lokale Netzwerk zu nutzen?

von Rolf M. (rmagnus)


Lesenswert?

Gibt's heutzutage eigentlich noch sowas wie den (x)inetd? Da konnte man 
einfach Programme, die über stdin/stdout kommunizieren, in Server 
verwandeln. Das Programm brauchte sich dann gar nicht um irgendwelche 
Netzwerksachen kümmern.

Marcus schrieb:
> Ob es wohl besser wäre eher UDP für's lokale Netzwerk zu nutzen?

Kommt letztendlich darauf an, wie du es verwenden willst. Mit TCP hast 
du eher den Charakter einer "Session". Du baust eine Verbindung auf und 
kannst darüber nun wie in einer Kommandozeile arbeiten. Wenn du fertig 
bist, schließt du die Verbindung wieder.
Bei UDP hast du eher nach dem Prinzip "fire and forget" die Möglichkeit, 
ohne den ganzen Verbindungskram einfach Nachrichten hinzuschicken. Wenn 
du aber auch in der anderen Richtung übertragen willst, muss dein rpi 
irgendwoher wissen, wohin er die Daten schicken muss.

von seho85 (Gast)


Lesenswert?

Hey,

Rolf M. schrieb:
> Gibt's heutzutage eigentlich noch sowas wie den (x)inetd? Da
> konnte man
> einfach Programme, die über stdin/stdout kommunizieren, in Server
> verwandeln. Das Programm brauchte sich dann gar nicht um irgendwelche
> Netzwerksachen kümmern.

netcat (nc)


Ein Lösung wäre evtl. der Einsatz von netcat und dem Linux "spidev" 
Kernel Modul.

Mit nc einen Server zu starten, der seine Daten an ein "spidev" piped.

Damit sollte ein einfacher "TCPtoSPI-Proxy" möglich sein.
1
nc -l 22 > /dev/spidev0.0


Gruß,
Sebastian

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.