Komunikacja USART (Serial Port)
USART (Universal Synchronous / Asynchronous Receiver-Transmitter) to sprzętowy moduł, który umożliwia komunikację szeregową między płytką Arduino, a innymi urządzeniami (np. komputer, moduły czujników, Bluetooth, inne mikrokontrolery) za pomocą pinów Rx i Tx.
UART realizuje transmisję i odbiór danych w sposób asynchroniczny, co oznacza, że nie wymaga dodatkowego sygnału zegarowego do synchronizacji.
Arduino posiada wbudowany moduł CP2102 (lub CH340 w przypadku chińskich zamienników) do komunikacji seryjnej z komputerem za pomocą kabla USB.
TTL (Transistor-Transistor Logic) to standard logicznego poziomu napięcia używany w wielu urządzeniach elektronicznych. W arduino korzysta się często z poziomu napięć 3.3V i 5V.
Transmisja może nastąpić tylko wtedy, kiedy obydwa urządzenia dzielą te same ustawienia:
- Szybkość transmisji (baud rate – częstotliwość pulsów zegara / ilość bitów na sekundę)
- Format ramki danych
- Warunek rozpoczęcia / zakończenia transmisji (start/stop)
Wysyłanie danych
Dane można wysyłać za pomocą metody print lub write:
print / println wysyła dane skonwertowane na znaki (ASCII)
Serial.print(12);
Serial.println("Hej");
Funkcja println wyświetla argumenty i dodaje znak przejścia do nowej linii (‘\r\n’)
Serial.print("Hej");
Serial.print('\r');
Serial.print('\n');
write wysyła dane w postaci bajta danych (liczby)
Serial.write(65);
Pobieranie danych
Wysyłanie danych do komputera powoduje ich wyświetlenie w Serial.Monitorze. W przypadku wysyłania danych między płytkami lub z komputera do płytki, należy te dane odebrać i przetworzyć.
Serial.available
Dane wysyłane do portu szeregowego są przechowywane w 64 bajtowym buforze. Pobierając dane, warto sprawdzić czy są one dostępne. Można to zrobić za pomocą metody Serial.available(), która zwraca ilość bajtów(znaków) do odczytania z Serial port (wraz z Enterem).
if (Serial.available() > 0) { }
Program odczyta dane z bufora w określonym domyślnie czasie (1s).
Czas oczekiwania można zmienić za pomocą metody:
Serial.setTimeout(1000); // czas w ms
Dane z portu Serial można pobierać za pomocą kilku dostępnych metod:
Serial.read()
Serial.read() zwraca wartości numeryczne znaków lub znak ASCII w zależności od typu danych
byte recData = Serial.read(); // zwraca wartość liczbową znaku ASCII
char recChar = Serial.read(); // zwraca znak ASCII
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
char a = Serial.read();
if (a == '1') {
digitalWrite(13, 1);
} else if (a == '0') {
digitalWrite(13, 0);
}
}
}
Serial.readString()
Serial.readString() zwraca wartość typu string
String recData = Serial.readString();
Serial.readStringUntil()
Serial.readStringUntil() zwraca wartość typu string bez znaku Enter
String recData = Serial.readStringUntil('\n');
Serial.readBytes()
Serial.readBytes() zwraca liczbę otrzymanych bajtów (bytesLength), które można przypisać do tablicy o określonej długości (BUF_SIZE)
const int BUF_SIZE = 50;
char bytesReceived[BUF_SIZE];
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available()) {
int bytesLength = Serial.readBytes(bytesReceived, BUF_SIZE);
Serial.print("Liczba bajtów: ");
Serial.println(bytesLength);
Serial.print("Otrzymane bajty: ");
for(int i = 0; i < bytesLength; i++)
Serial.print(bytesReceived[i]);
}
}
Serial.parseInt()
Serial.parseInt() parseInt zwraca z bufora pierwszą napotkaną wartość liczbową (lub 0 w przypadku przekroczenia czasu)
paresInt przyjmuje argumenty: SKIP_NONE, SKIP_ALL, SKIP_WHITESPACE
Serial.parseInt(SKIP_ALL, ’,’);
if(Serial.available()){
int a = Serial.parseInt();
Serial.print(a);
}
Serial.parseFloat()
Serial.parseFloat() zwraca kolejną liczbę rzeczywistą (lub 0 w przypadku przekroczenia czasu)
if(Serial.available()){
float b = Serial.parseFloat();
Serial.print(b);
}
serialEvent() to metoda/event, który wywoła się za każdym razem, kiedy w buforze danych pojawi się informacja do pobrania. Ważne by pobrać dane z bufora, a tym samym go wyzerować, aby event nie wykonywał się ciągle.
void serialEvent(){
if(Serial.available()){
Serial.println(Serial.read());
}
}
Line ending
Wysyłane dane mają swój początek i koniec. Istnieją specjalne znaki, które to określają.
Carriage Return '\r’
New line '\n'(w systemie windows \n zawiera obydwa znaki: \r\n)
W zależności od projektu i sposobu komunikacji, należy tę opcję odpowiednio dostosować.
Pobieranie i wyświetlanie danych z użyciem serialEvent
String inputString = "";
bool stringComplete = false;
void setup() {
Serial.begin(9600);
inputString.reserve(200);
}
void loop() {
if (stringComplete) {
Serial.println(inputString);
inputString = "";
stringComplete = false;
}
}
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
stringComplete = true;
}
}
}
Zobacz: Komunikacja Serial z modułem USB UART TTL
Zobacz: Komunikacja I2C w Arduino
Zobacz: Komunikacja SPI w Arduino