zurück

Serielle Schnittstelle des Arduino

19.01.2018

Der Arduino ist in der Lage, über seine eingebaute serielle Schnittstelle Daten zu empfangen und zu senden.

Aufbau

Für den Aufbau benötigt man nur den Arduino UNO und eine Verbindung zum PC. Die Kommunikation zwischen PC und dem Arduino kann über den "Seriellen Monitor" der Arduino-IDE über auch über ein beliebiges Terminal-Programm, wie z.B. PuTTY erfolgen.

Ex 1: Interne LED steuern

In diesem Experiment wird die interne LED des Arduino (auf PIN 13) mittels Befehlen gesteuert, die vom PC über die serielle Schnittstelle empfangen werden.

Sketch

#define LED_PIN 13

// rxChar holds the received command.
char rxChar = 0;

void printHelp(void)
{
    Serial.println("--- Command list: ---");
    Serial.println("? -> Print this HELP");
    Serial.println("a -> LED On \"activate\"");
    Serial.println("d -> LED Off \"deactivate\"");
    Serial.println("s -> LED \"status\"");
}

void setup()
{
    pinMode(LED_PIN, OUTPUT);

    // Open serial port (9600 bauds).
    Serial.begin(9600);

    // Clear receive buffer.
    Serial.flush();
}

void loop()
{
    // Check receive buffer.
    if (Serial.available() > 0) {
        rxChar = Serial.read(); // Save character received.
        Serial.flush(); // Clear receive buffer.

        switch (rxChar) {
            case 'a':
                if (digitalRead(LED_PIN) == LOW) {
                    digitalWrite(LED_PIN, HIGH);
                    Serial.println("LED turned On");
                } else {
                    Serial.println("LED already On!");
                }
            break;

            case 'd':
                if (digitalRead(LED_PIN) == HIGH) {
                    digitalWrite(LED_PIN, LOW);
                    Serial.println("LED turned Off");
                } else {
                    Serial.println("LED already Off!");
                }
            break;

            case 's':
                if (digitalRead(LED_PIN) == HIGH) {
                    Serial.println("LED status: On");
                } else {
                    Serial.println("LED status: Off");
                }
            break;

            case '?':
                printHelp();
            break;

            default:
                Serial.print("'");
                Serial.print((char)rxChar);
                Serial.println("' is not a command!");
                printHelp();
            break;
        }
    }
}
Konfiguration von PuTTY
Abb.: Konfiguration von PuTTY
Terminal-Ausgabe in PuTTY
Abb.: Terminal-Ausgabe in PuTTY

Grafische Ausgabe von seriellen Daten

Es ist auch möglich mit spezieller Software über Zeit Daten als Graph darzustellen, die von der seriellen Schnittstelle empfangen werden.
Versuchsaufbau zum Empfangen der Daten sind drei verschiedenfarbige LEDs, welche Messdaten der Helligkeit an den Arduino weitergeben sollen.
Die graphische Auswertung erfolgt hier mit dem Programm Serial Port Plotter, welches die Daten ähnlich wie PuTTY im obigen Versuch über den COM-Port empfängt und grafisch aufbereitet.

Schaltplan
Abb.: Schaltplan
Aufbau der Schaltung
Abb.: Aufbau der Schaltung

Sketch

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.print("$");

    Serial.print(analogRead(0));
    Serial.print(" ");

    Serial.print(analogRead(1));
    Serial.print(" ");

    Serial.print(analogRead(2));
    Serial.print(";");

    delay(100);
}
Ausgabe des Serial Port Plotter
Abb.: Ausgabe des "Serial Port Plotter" mit den drei Messwerten der LEDs

Mit dem folgenden selbstgeschriebenen simplen Programm "SerialGraph" (Windows/.NET) kann ein Wert (getrennt mit Linefeeds) graphisch über die serielle Schnittstelle beobachtet werden.

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    Serial.println(random(1000));
    delay(250);
}
Code: Beispielcode zur Demonstration von SerialGraph
Beispiel-Ausgabe von SerialGraph
Abb.: Beispiel-Ausgabe von SerialGraph
SerialGraph laden [6 kB]
Source von SerialGraph laden (.NET/C#) [305 kB]

"Serial event"

Arduino (und Genuino) triggern in loop() die Funktion serialEvent(), auf die wir im Code reagieren können. Jedesmal, wenn über RX Daten empfangen werden, wird dieses event ausgelöst.
Der Aufbau benötigt lediglich einen Arduino Uno und eine USB-Verbindung zum PC. Der Code ist vom Standard-Beispiel der Arduino-IDE leicht modifiziert übernommen worden.

Sketch

String inputString = "";         // a string to hold incoming data
bool stringComplete = false;  // whether the string is complete

void setup()
{
    Serial.begin(9600);

    // reserve 200 bytes for the inputString
    inputString.reserve(200);
}

void loop()
{
    // print the string when a newline arrives:
    if (stringComplete) {
        Serial.println(inputString);
        inputString = "";
        stringComplete = false;
    }
}

/**
 * SerialEvent occurs whenever a new data comes in the hardware serial RX.
 * This routine is run between each time loop() runs, so using delay inside
 * loop can delay response.  Multiple bytes of data may be available.
 */
void serialEvent()
{
    while (Serial.available()) {
        // get the new byte:
        char inChar = (char)Serial.read();
        // add it to the inputString:
        inputString += inChar;
        // if the incoming character is a newline, set a flag
        // so the main loop can do something about it:
        if (inChar == '\r') {
            stringComplete = true;
        }
    }
}

Binäre Daten vom Arduino senden

Es können auch binäre Daten vom Arduino an den PC oder umgekehrt übertragen werden.
(Siehe dazu den entsprechenden Sketch im GIT Repository)

Sketch

int incomingByte = 0;   // for incoming serial data

void setup()
{
    Serial.begin(9600);

    int testValue = 100;
    byte testValue2 = 0xFF;

    Serial.print(testValue);
    Serial.print('\n');

    Serial.write(testValue);
    Serial.print('\n');

    Serial.write(lowByte(testValue));
    Serial.write(highByte(testValue));
    Serial.print('\n');

    Serial.print(byte(testValue2));
    Serial.print('\n');

    Serial.write(testValue2);
    Serial.print('\n');
}

void loop()
{
    // send data only when you receive data:
    if (Serial.available() > 0) {
        incomingByte = Serial.read(); // read one incoming byte

        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
    }
}

Daten auf dem PC mit Python empfangen

Zunächst muss Python für Windows installiert werden. Dannach die Python-Module für den seriellen Port. Dafür öffent man die Windows PowerShell oder eine Eingabeaufforderung cmd:
pip3 install pyserial
pip3 install serial

(Da ich die Python v3.7.3 verwende, wird pip3 statt pip benutzt!)
Das folgende Python-Programm speichert man am besten in eine Datei "list-serial.py" und es gibt dann alle verfügbaren seriellen Port aus, wenn man es auf der Konsole mit python list-serial.py startet:

import serial.tools.list_ports as port_list
ports = list(port_list.comports())
for p in ports:
    print (p)

Baurate und Port-Nummer müssen im folgenden Code natürlich noch angepasst werden:

import serial
ser = serial.Serial("COM1", 9600, timeout=5)
ser.flushInput()
ser.flushOutput()
while True:
    data_raw = ser.readline()
    print(data_raw)