RaspberryGPIOSerial

Aus Hackerspace Ffm
Wechseln zu: Navigation, Suche

Man kann über die GPIO-Pins eine serielle Verbindung zu einem PC, Arduino, ... aufbauen um Daten auszutauschen oder Steuerinformationen zu übertragen.
Raspi3 GPIO Rxtx.PNG[1]

Zuerst muss die serielle login shell deaktiviert und die serielle Schnittstelle aktiviert werden.

 sudo raspi-config 
  • 5. Interfacing Options
    • P6 Serial
      • Would you like a login shell to be accessible over serial? No
      • Would you like the serial port hardware to be enabled? Yes
 sudo reboot 

Schnittstelle mittels eines Terminals testen.
Es gibt minicom oder cu und weitere.

Wenn man die beiden pins 8(TX) und 10(RX) miteinander verbindet, kann man die Schnittstelle mit sich selbst testen. Auf dem Terminal werden die Tastatureingaben als ein lokales Echo wiedergegeben.

sudo minicom -b 115200 -D /dev/ttyS0       (Verlassen über Strg+a, z, x)

oder

cu -l /dev/ttyS0 -s 115200                 (Verlassen ~.)


Da die GPIO-Pins des Raspis mit 3.3V und der PC oder Arduino mit 5V Logic Level funktionieren müssen wir die Level convertieren.
Da ein TX-Signal vom Raspi mit 3.3V im PC immer noch ein High ist brauchen wir hier nichts zu tuen.
Das 5V TX-Signal vom PC zum Raspi würde aber den Pin zerstören. Hier reicht es aber einen Spannungsteiler zwischen zu schalten.
SerialRaspiArduino.jpg

PC

Hier ein Terminalprogramm wie Terminal von Br@y verwenden.

Arduino

void setup() {
   Serial.begin(9600);
}
void loop() {
   if(Serial.available()) {
      Serial.write(Serial.read());
   }
}

Und hier ein etwas komplexerer Kommandoparser:
Die Kommandos sind a und b gefolgt von einem Integer wie z.B. a21

void receive_serial_cmd(void) {
  static uint8_t cmd[18];         // command buffer
  static uint8_t cmdcount = 0;    // position in the buffer of the received byte
  uint8_t c;                      // received byte
  while(Serial.available()) {
    c = Serial.read();
    if(c > ' ') cmd[cmdcount++] = c;
    if((c == 8) && (cmdcount > 0)) cmdcount--;                // deals with backspaces, if a person on the other side types 
    if((c == 0x0d) || (c == 0x0a) || (cmdcount > 16)) {       // end of command, gets interpreted now
      cmd[cmdcount] = 0;    // clear the last byte in cmd buffer
      if(cmdcount > 0) {    // prevent empty cmd buffer parsing
       switch(cmd[0]) {
        case 'a': 
          if((cmdcount > 2) && (cmdcount < 7)) {
            int temp = atoi((const char *)&cmd[1]);           
            Serial.print("a:");
            Serial.println(temp);                      
          }                    
          break; 
        case 'b':
          if((cmdcount > 2) && (cmdcount < 7)) {
            int temp = atoi((const char *)&cmd[1]);           
            Serial.print("b:");
            Serial.println(temp);                        
          }  
          break;                 
       }    
      }
      cmdcount = 0;
    } 
  }
}

Python

In Python gibt es die Bibliothek pySerial.

python -m pip install pyserial

Einfaches einmaliges ein und auslesen:

import serial
ser = serial.Serial('/dev/ttyS0', 9600)
data = ser.readline()
ser.write(data)
ser.close()

Einlesen von der Kommandozeile und gleichzeitiges Empfangen:

import serial
import thread

ser = serial.Serial('/dev/ttyS0', 9600)

def read():
        while True:
                data = ser.read();
                print 'from remote: ', data

def main():
        ser.flushInput()                # clears the buffer for a fresh start
        thread.start_new_thread(read, ())
        while True:
                command = raw_input('Enter: ')
                ser.write(command)

if __name__ == "__main__":
        main()