Bagaimana saya menerima seluruh string sebagai lawan 1 karakter pada suatu waktu di Arduino?

11

Saya berhasil mengikuti instruksi di situs web ini:

http://www.doctormonk.com/2012/04/raspberry-pi-and-arduino.html

dan saya bisa mendapatkan komunikasi antara pi dan mega arudino saya persis seperti yang ditentukan situs web.

Namun, alih-alih mengirim bilangan bulat yang mewakili berapa kali LED berkedip, saya ingin mengirim teks ASCII seperti:

"MOVE 5 METER FORWARD", "TURN LEFT", "MOVE 10 METER BACKWARD" ke arduino dari pi.

Saya menulis kode berikut:

char inData[64];
char inChar=-1;

void setup(){
   Serial.begin(9600);
   Serial.begin("Waiting for Raspberry Pi to send a signal...\n");
}


void loop(){
    byte numBytesAvailable= Serial.available();

    // if there is something to read
    if (numBytesAvailable > 0){
        // store everything into "inData"
        int i;
        for (i=0;i<numBytesAvailable;i++){
            inChar= Serial.read();
            inData[i] = inChar;
        }

        inData[i] = '\0';


        Serial.print("Arduino Received: ");
        Serial.println(inData);
    }
}

Saya mem-flash kode di atas dengan sukses ke Arduino Mega 2560 saya.

Saya beralih ke terminal python saya di Raspberry Pi dan di konsol saya mengetik:

import serial
ser = serial.Serial('/dev/ttyACM1',9600)
ser.write("MOVE")

Apa yang ditampilkan pada Monitor Seri Arduino saya adalah sebagai berikut:

Arduino Received: M
Arduino Received: O
Arduino Received: V
Arduino Received: E

Tapi yang saya inginkan adalah:

Arduino Received: MOVE

Bagaimana cara mengubah kode di atas untuk memasukkan semua karakter ke buffer inData?

pengguna1068636
sumber
Apakah Anda yakin telah menyalin kode Anda dengan benar? Cara saya melihat kode Anda, terlepas dari apa yang ada di data, baris "Arduino Received" hanya akan pernah dicetak sekali. Anda yakin itu semua dalam fungsi setup () Anda?
NickHalden
Kamu benar. Saya memperbaikinya sekarang. Tapi masalahnya masih ada.
user1068636

Jawaban:

23

Masalahnya adalah bahwa Arduino berputar-putar begitu cepat, itu akan mengeksekusi if (numBytesAvailable > 0)garis beberapa kali antara setiap karakter yang datang melalui port serial. Jadi begitu sebuah karakter tiba, ia mengambilnya, berputar dari nol ke satu, dan mencetak satu karakter.

Yang harus Anda lakukan adalah mengirim karakter garis akhir ('\ n') setelah setiap perintah dari program Python Anda. Kemudian minta buffer kode Arduino Anda masing-masing karakter yang diterimanya dan hanya bertindak pada pesan setelah menerima karakter end-of-line.

Jadi jika Anda mengubah kode Python Anda jangan mengirim karakter garis akhir, seperti:

import serial
ser = serial.Serial('/dev/ttyACM1',9600)
ser.write("MOVE\n")

Maka kode Arduino Anda bisa seperti ini:

// Buffer to store incoming commands from serial port
String inData;

void setup() {
    Serial.begin(9600);
    Serial.println("Waiting for Raspberry Pi to send a signal...\n");
}

void loop() {
    while (Serial.available() > 0)
    {
        char recieved = Serial.read();
        inData += recieved; 

        // Process message when new line character is recieved
        if (recieved == '\n')
        {
            Serial.print("Arduino Received: ");
            Serial.print(inData);

            inData = ""; // Clear recieved buffer
        }
    }
}
Phil
sumber
1
Juga, potensi twist pada ini untuk penggunaan yang lebih umum (seperti pada C lurus di mana Anda tidak memiliki kelas String yang nyaman) adalah Anda mengintip apa yang ada di buffer untuk melihat apakah Anda telah menerima \ n. Dengan cara ini Anda menyimpan semuanya di buffer internal sebelum Anda membuat salinannya. Kelemahan di sini adalah bahwa buffer internal harus cukup besar untuk memungkinkan Anda menangkap satu baris terpanjang Anda. Kalau tidak, Anda berpotensi memperoleh kecepatan pemrosesan karena Anda menghindari suka seperti String (mungkin, yaitu) mengkomputasi ulang dan mengalokasikan memori untuk memperluas dirinya.
Toby Lawrence
Kode Anda berhasil! Saya harus mengubah beberapa baris seperti inData = "" dan inData + = diterima. Saya tidak berpikir kompiler menyukainya.
user1068636
6

Python naskah Anda mengirimkan empat byte, M, O, V, dan E. Bagaimana Arduino seharusnya tahu bahwa itu adalah string tunggal? Pertimbangkan bahwa kode Python:

ser.write("MOVE")

adalah benar-benar identik dengan

ser.write("MO")
ser.write("VE")

dari sudut pandang Arduino. Port serial mentransfer karakter, bukan string.

Dalam kode Anda, Arduino cepat (dibandingkan dengan baud rate 9600), jadi setiap kali dipanggil Serial.available(), ia hanya melihat satu dari empat karakter itu. Itu sebabnya Anda mendapatkan hasil yang Anda lakukan.

Yang perlu Anda lakukan adalah membuat beberapa cara untuk membatasi string, yaitu menandainya dengan beberapa cara dari Python sehingga Arduino dapat menambahkan karakter individu yang diterimanya ke dalam konsep string tingkat tinggi Anda .

Menggunakan garis sangat mudah: kirim setiap string yang diakhiri dengan karakter baris baru ( '\n'). Di Arduino, baca karakter dan tambahkan ke string Anda. Ketika Anda melihat '\n', string sudah berakhir dan Anda dapat mencetaknya.

Jim Paris
sumber
Tidak menambahkan karakter individu ke string lebih lambat daripada hanya menunggu karakter baris baru, dan membaca seluruh urutan karakter sekaligus ketika karakter baris baru diterima.
The Vivandiere
2
Tidak yakin apa yang Anda usulkan - Anda tidak dapat "menunggu" untuk karakter baris baru kecuali dengan membacanya, dan pada saat Anda membacanya, Anda harus membaca semua karakter sebelumnya juga (yang berarti mereka harus telah disimpan dalam beberapa cara - apakah itu "menambahkan string" atau metode lain untuk menyimpannya terserah Anda).
Jim Paris
2
  if(Serial.available() > 0) {
     str = Serial.readStringUntil('\n');
     Serial.println(str);

Kode di atas berfungsi sempurna pada koneksi saya antara Pi dan Arduino

Douglas
sumber
1

Gunakan .readlinesebagai ganti.read

Saya memiliki masalah yang sama dan ini segera diperbaiki. Semoga ini bisa membantu!

sam_trudgian
sumber
Ini agak tipis untuk jawaban pada EE.SE. Terutama mengingat bahwa ini adalah utas berusia 2 tahun. Tolong jelaskan.
Nick Alexeev
Selamat datang di tumpukan, sam. Kami senang Anda bergabung. Ini tidak seperti banyak forum lain, karena kami berusaha keras untuk menjadi sejelas dan serinci mungkin, sehingga setiap orang yang menemukan tulisan kami di masa depan dapat memperoleh manfaat maksimal dari pengetahuan itu. Apakah Anda memiliki masalah yang sama persis ? Dengan komponen yang tepat itu ? Dan kode yang tepat itu ? Kondisi apa dalam pengaturan ini yang membuat kode Anda berfungsi, dan mengapa tidak berfungsi sebelumnya? Komunitas menginginkan bantuan Anda, dan wawasan Anda.
Sean Boddy
0

Ini adalah bagaimana saya melakukannya dari contoh pertama:

String readString;

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

void loop()
{
    char incomingByte;
    while (Serial.available() > 0)
    {
        delay(10); // if the data came
        incomingByte = Serial.read(); // read byte
        //Serial.println(incomingByte);
        readString += incomingByte;
    }

    if(readString != "")
    {
        Serial.print("arduino recived this : ");
        Serial.println(readString);
    }
    readString = "";
}
karim
sumber