Arduino'da aynı anda 1 karakter yerine tüm bir dizeyi nasıl alabilirim?


11

Bu web sitesindeki talimatları başarıyla izledim:

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

ve tam olarak web sitesinin belirttiği gibi pi ve arudino mega arasında iletişim alabildim.

Ancak, LED'in yanıp sönme sayısını temsil eden bir tam sayı göndermek yerine, ASCII metnini aşağıdaki gibi göndermek istiyorum:

"5 METRE İLERİ HAREKET", "DÖNÜŞ SOL", "10 METRE GERİ HAREKET" i pi'den arduino'ya taşıyın.

Aşağıdaki kodu yazdım:

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'ımın kodunu başarıyla geçtim.

Raspberry Pi'deki python terminalime geçtim ve yazdığım konsolda:

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

Arduino'nun Seri Monitöründe görüntülenen şu şekildedir:

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

Ama istediğim şu:

Arduino Received: MOVE

Tüm karakterleri inData arabelleğine almak için yukarıdaki kodu nasıl değiştirebilirim?


Kodunuzu doğru kopyaladığınızdan emin misiniz? Kodunuzu nasıl gördüğümde, inData'da ne olursa olsun, "Arduino Alındı" satırı yalnızca bir kez yazdırılır. Tüm bunların setup () işlevinizde olduğundan emin misiniz?
NickHalden

Haklısın. Şimdi düzelttim. Ama sorun hala devam ediyor.
user1068636

Yanıtlar:


23

Sorun, Arduino'nun bu kadar hızlı dönmesi, if (numBytesAvailable > 0)seri bağlantı noktasından gelen her karakter arasındaki satırı birkaç kez yürütmesidir . Yani bir karakter gelir gelmez onu yakalar, sıfırdan bire döngüler ve tek bir karakter basar.

Yapmanız gereken Python programınızdaki her komuttan sonra bir satır sonu karakteri ('\ n') göndermektir. Ardından, Arduino kodunuzun aldığı her karakteri arabelleğe almasını ve yalnızca satır sonu karakterini aldıktan sonra iletiyi etkinleştirmesini sağlayın.

Python kodunuzu değiştirirseniz, aşağıdaki gibi bir satır sonu karakteri gönderin:

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

O zaman Arduino kodunuz şöyle olabilir:

// 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
Ayrıca, daha genel kullanımlar için bu konuda potansiyel bir bükülme (uygun bir String sınıfına sahip olmadığınız düz C'de olduğu gibi), henüz bir \ n alıp almadığınızı görmek için arabellekte ne olduğuna göz atmanızdır. Bu şekilde, kopyasını çıkarmadan önce her şeyi dahili arabellekte tutarsınız. Buradaki düşüş, dahili tamponun en uzun tek çizginizi yakalayabilmeniz için yeterince büyük olması gerektiğidir. Aksi takdirde, String'i (muhtemelen, yani, kendini genişletmek için yeniden hesaplama ve bellek ayırma gibi) beğenmediğiniz için işlem hızı kazanırsınız.
Toby Lawrence

Kodunuz işe yaradı! Ben inData = "" ve inData + = alınan gibi birkaç satır değiştirmek zorunda kaldı. Derleyicinin hoşuna gittiğini sanmıyorum.
user1068636

6

Kişisel Python komut dört bayt gönderiyor, M, O, V, ve E. Arduino'nun bunun tek bir ip olduğunu nasıl bilmesi gerekiyor? Python kodunun:

ser.write("MOVE")

bir tamamen aynı için

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

Arduino'nun bakış açısından. Seri bağlantı noktaları karakterleri aktarır, dizeleri değil.

Kodunuzda Arduino hızlıdır (9600 baud hızıyla karşılaştırıldığında), bu yüzden her aradığında Serial.available()bu dört karakterden yalnızca birini görür. Bu yüzden çıktınız çıktı.

Yapmanız gereken, dizeleri sınırlamanın bir yolunu bulmaktır, yani Arduino'nun aldığı bireysel karakterleri bir dize kavramınıza ekleyebilmesi için bunları Python'dan bir şekilde işaretlemek .

Çizgileri kullanmak basittir: yeni satır karakteri ( '\n') ile sonlandırılmış her dizeyi gönderin . Arduino'da karakterleri okuyun ve dizenize ekleyin. Bir gördüğünüzde '\n', dize bitti ve yazdırabilirsiniz.


Bir karaktere yeni satır karakterini beklemekten daha yavaş bir karakter eklemek ve satırsonu karakteri alındığında tek seferde tüm karakter sırasını okumak değildir.
Vivandiere

2
Ne önerdiğinizden emin değilsiniz - bir satırsonu karakteri okumak dışında "bekleyemezsiniz" ve okuduğunuz zaman, önceki tüm karakterleri de mutlaka okursunuz (yani, bir şekilde kaydedilmişse - bu "bir dizeye ekleniyor" veya bunları kaydetmenin başka bir yöntemi size kalmış olsun).
Jim Paris

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

Yukarıdaki kod Pi ve Arduino arasındaki bağlantımda mükemmel çalışıyor


1

Yerine .readlinekullanın.read

Ben de aynı sorunu vardı ve bu hemen düzelttim. Umarım bu yardımcı oldu!


Bu, EE.SE'ye cevap vermek için biraz incedir. Özellikle bu 2 yaşındaki bir iplik olduğunu düşünüyor. Lütfen detaylandırın.
Nick Alexeev

Yığına hoş geldin, sam. Sizi aramızda görmekten mutluluk duyuyoruz. Bu, diğer forumlara pek benzemiyor, çünkü mümkün olduğunca açık ve ayrıntılı olmaya çalışıyoruz, böylece gelecekte yazımızı bulan herkes bu bilgiden maksimum fayda sağlayabilir. Eğer var mıydı tam olarak aynı sorunu? Tam olarak bu bileşenlerle mi? Ve tam olarak bu kod mu? Bu kurulumdaki hangi koşullar kodunuzu çalıştırdı ve neden daha önce çalışmadı? Topluluk yardımınızı ve görüşünüzü istiyor .
Sean Boddy

0

İlk örnekten böyle yaptım:

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 = "";
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.