ฉันจะรับสายอักขระทั้งหมดได้อย่างไรเมื่อเทียบกับอักขระ 1 ตัวในแต่ละครั้งใน arduino


11

ฉันทำตามคำแนะนำในเว็บไซต์นี้เรียบร้อยแล้ว:

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

และฉันสามารถรับการสื่อสารระหว่าง pi และ mega arudino ของฉันตรงตามที่เว็บไซต์ระบุ

อย่างไรก็ตามแทนที่จะส่งจำนวนเต็มแทนจำนวนครั้งที่ LED กระพริบฉันต้องการส่งข้อความ ASCII เช่น:

"ย้าย 5 เมตรไปข้างหน้า", "เลี้ยวซ้าย", "ย้าย 10 เมตรด้านหลัง" ไปยัง arduino จาก pi

ฉันเขียนรหัสต่อไปนี้:

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);
    }
}

ฉันส่งโค้ดด้านบนไปยัง Arduino Mega 2560 ของฉันสำเร็จแล้ว

ฉันเปลี่ยนไปใช้ terminal ของหลามบน Raspberry Pi และในคอนโซลที่ฉันพิมพ์:

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

สิ่งที่แสดงบน Serial Monitor ของ Arduino คือ:

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

แต่สิ่งที่ฉันต้องการคือ:

Arduino Received: MOVE

ฉันจะเปลี่ยนรหัสด้านบนเพื่อรับตัวละครทั้งหมดในบัฟเฟอร์ inData ได้อย่างไร


คุณแน่ใจว่าคุณได้คัดลอกรหัสของคุณถูกต้องหรือไม่ วิธีที่ฉันเห็นรหัสของคุณโดยไม่คำนึงถึงสิ่งที่อยู่ในข้อมูลบรรทัด "Arduino Received" จะถูกพิมพ์ครั้งเดียวเท่านั้น คุณแน่ใจหรือว่านั่นคือทั้งหมดที่อยู่ในการตั้งค่า () ฟังก์ชั่นของคุณ?
NickHalden

คุณถูก. ฉันแก้ไขมันตอนนี้ แต่ปัญหายังคงอยู่
user1068636

คำตอบ:


23

ปัญหาคือว่า Arduino กำลังวนรอบอย่างรวดเร็วมันจะดำเนินการif (numBytesAvailable > 0)บรรทัดหลายครั้งระหว่างตัวละครแต่ละตัวที่เดินทางมาถึงพอร์ตอนุกรม ดังนั้นทันทีที่ตัวละครมาถึงมันคว้าตัวมันวนจากศูนย์หนึ่งไปยังอีกตัวหนึ่งแล้วพิมพ์อักขระตัวเดียวออกมา

สิ่งที่คุณควรทำคือส่งอักขระสิ้นสุดบรรทัด ('\ n') หลังจากแต่ละคำสั่งจากโปรแกรม Python ของคุณ จากนั้นให้บัฟเฟอร์รหัส Arduino ของคุณอักขระแต่ละตัวที่ได้รับและดำเนินการกับข้อความเมื่อได้รับอักขระสิ้นสุดบรรทัดแล้วเท่านั้น

ดังนั้นหากคุณเปลี่ยนรหัส Python ของคุณอย่าส่งอักขระสิ้นสุดบรรทัดเช่น:

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

จากนั้นโค้ด Arduino ของคุณอาจเป็นดังนี้:

// 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
        }
    }
}

1
นอกจากนี้ความเป็นไปได้ที่จะเกิดขึ้นนี้สำหรับการใช้งานทั่วไปที่มากขึ้น (เช่นใน C ตรงที่คุณไม่มีคลาส String ที่สะดวก) คือคุณมองสิ่งที่อยู่ในบัฟเฟอร์เพื่อดูว่าคุณได้รับ \ n หรือยัง วิธีนี้คุณเก็บทุกอย่างไว้ในบัฟเฟอร์ภายในก่อนที่จะทำสำเนา ความหายนะที่นี่คือบัฟเฟอร์ภายในจะต้องมีขนาดใหญ่พอที่จะให้คุณจับบรรทัดเดียวที่ยาวที่สุด มิฉะนั้นคุณอาจได้รับความเร็วในการประมวลผลในขณะที่หลีกเลี่ยงไลค์อย่าง String (สมมุติว่าคือ) คำนวณและจัดสรรหน่วยความจำเพื่อขยายตัวเอง
Toby Lawrence

รหัสของคุณใช้งานได้! ฉันต้องเปลี่ยนสองบรรทัดอย่าง inData = "" และ inData + = ที่ได้รับ ฉันไม่คิดว่าคอมไพเลอร์ชอบมัน
user1068636

6

สคริปต์ Python ของคุณจะถูกส่งสี่ไบต์M, O, และV EArduino ควรรู้ได้อย่างไรว่าเป็นสายเดี่ยว? พิจารณาว่ารหัส Python:

ser.write("MOVE")

เป็นสมบูรณ์เหมือนกันไป

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

จากมุมมองของ Arduino อักขระการถ่ายโอนพอร์ตอนุกรมไม่ใช่สตริง

ในโค้ดของคุณ Arduino นั้นรวดเร็ว (เมื่อเทียบกับอัตราบอด 9600) ดังนั้นทุกครั้งที่มีการโทรSerial.available()มันจะเห็นเพียงหนึ่งในสี่ตัวอักษรเท่านั้น นั่นเป็นเหตุผลที่คุณได้รับผลลัพธ์ที่คุณทำ

สิ่งที่คุณจะต้องทำคือมาด้วยวิธีของ delimiting สตริงคือเครื่องหมายพวกเขาในทางใดทางหนึ่งจากงูหลามเพื่อให้ Arduino สามารถผนวกบุคคลบางตัวละครที่ได้รับเข้าไปในแนวความคิดระดับสูงของคุณของสตริง

การใช้เส้นตรงไปตรงมา: ส่งทุกสายที่ลงท้ายด้วยอักขระขึ้นบรรทัดใหม่ ( '\n') บน Arduino อ่านตัวอักษรและต่อท้ายสตริงของคุณ เมื่อคุณเห็นก'\n'สตริงจะจบและคุณสามารถพิมพ์ได้


ไม่ได้ต่อท้ายอักขระแต่ละตัวกับสตริงช้ากว่าการรออักขระขึ้นบรรทัดใหม่และการอ่านตามลำดับอักขระทั้งหมดในครั้งเดียวเมื่อได้รับอักขระขึ้นบรรทัดใหม่
Vivandiere

2
ไม่แน่ใจว่าคุณกำลังเสนออะไร - คุณไม่สามารถ "รอ" สำหรับอักขระขึ้นบรรทัดใหม่ยกเว้นการอ่านและเมื่อคุณอ่านแล้วคุณจำเป็นต้องอ่านอักขระก่อนหน้าทั้งหมดด้วยเช่นกัน (ซึ่งหมายความว่าพวกเขาต้องการ ได้รับการบันทึกในบางวิธี - ไม่ว่าจะเป็น "การต่อท้ายสตริง" หรือวิธีการบันทึกอื่น ๆ นั้นขึ้นอยู่กับคุณ)
จิมปารีส

2
  if(Serial.available() > 0) {
     str = Serial.readStringUntil('\n');
     Serial.println(str);

โค้ดด้านบนทำงานได้อย่างสมบูรณ์แบบในการเชื่อมต่อระหว่าง Pi และ Arduino


1

ใช้.readlineแทน.read

ฉันมีปัญหาเดียวกันและสิ่งนี้แก้ไขได้ทันที หวังว่านี่จะช่วยได้!


นี่เป็นคำตอบเล็กน้อยสำหรับ EE.SE โดยเฉพาะอย่างยิ่งการพิจารณาว่านี่เป็นด้ายอายุ 2 ปี กรุณาอธิบายอย่างละเอียด
Nick Alexeev

ยินดีต้อนรับสู่สแต็ค เราดีใจที่ได้คุณอยู่บนเรือ นี่ไม่เหมือนฟอรัมอื่น ๆ มากมายซึ่งเราพยายามอย่างหนักเพื่อให้ชัดเจนและละเอียดที่สุดเท่าที่จะเป็นไปได้เพื่อให้ทุกคนที่ค้นหางานเขียนของเราในอนาคตสามารถได้รับประโยชน์สูงสุดจากความรู้นั้น คุณมีปัญหาเดียวกันที่แน่นอน ? ด้วยองค์ประกอบที่แน่นอนเหล่านั้น? และรหัสที่แน่นอน ? เงื่อนไขใดในการตั้งค่านี้ทำให้รหัสของคุณใช้งานได้และทำไมมันไม่ทำงานมาก่อน ชุมชนต้องการความช่วยเหลือและความเข้าใจของคุณ
ฌอน Boddy

0

นี่คือวิธีที่ฉันทำจากตัวอย่างแรก:

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 = "";
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.