Raar gedrag bij seriële communicatie met Arduino.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • nephilimcrt
  • Registratie: Juni 2011
  • Laatst online: 09-09 18:12

nephilimcrt

Mad Scientist

Topicstarter
Hoi iedereen,

Ik ervaar wat onverwacht gedrag wanneer ik mijn Arduino een ontvangen string terug wil laten sturen over de seriële poort. Ik zal hier de code en het resultaat posten. Ik hoop dat iemand een idee heeft wat er fout gaat en/of wat ik verkeerd doe.

Zoals je ziet leest de Arduino een ontvangen string en knalt deze dan terug met een Serial.println:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
* This sketch is a test for sending strings back and forth via the serial port.
*/

void setup() {
    // initialize the serial communication:
  Serial.begin(9600);

}

void loop() { 
 
   char rxbyte;
   String rxstring;


  // check if data has been sent from the computer:
  while (Serial.available()!= 0) 
   {
    // read the most recent byte:
    rxbyte = Serial.read();
    // add the most recent byte to the string:
    rxstring = rxstring + rxbyte;
    //send the received string back over the serial port:
   }
   if (rxstring != "")
   {
     Serial.println(rxstring);
     Serial.println("break"); //test to see what's going wrong
   }
   rxstring = "";
   
}


Je zou verwachten dat de string in z'n geheel in één keer terugkomt, maar dat blijkt niet het geval. Op de één of andere manier hakt ie 'm in stukjes. Je kunt dit zien doordat ik de tekst 'break' ertussen heb geknutseld. Die regel zou ie volgens mij helemaal niet mogen bereiken voordat deze hele rxstring 'op de lijn' is gezet.

Onderstaande is wat er in de serial monitor verschijnt:
code:
1
2
3
4
5
6
7
8
9
10
d
break
eze zin w
break
ordt in kleine stuk
break
jes gehakt en ik snap niet waar
break
om kan iemand me dit uitleggen?
break


Alle hulp wordt op prijs gesteld!

Tapping progress on the shoulder and saying: "More forwards, please!".


Acties:
  • 0 Henk 'm!

  • Sphere-
  • Registratie: November 2003
  • Laatst online: 28-08 19:53
http://www.arduino.cc/en/Serial/Available

Serial.Available() geeft terug hoeveel bytes er ontvangen zijn op je serial port en nog in de buffer staan.
Als jij wat in je terminal typt kan het zijn dat je niet snel genoeg typt en dus niet constant wat op de seriele poort zet. Op een moment dat er niks meer in de buffers is geeft die functie 0 terug. Omdat je programma in een loop draait zal die uiteindelijk de hele string wel terug sturen in stukjes.

Als je perse een hele string wilt ontvangen alvorens hem door te sturen zal je moeten checken op een newline karakter (\n of \r of beide afhankelijk van instellingen) en dan pas hetgene wat je gebuffert hebt terug sturen.

[ Voor 21% gewijzigd door Sphere- op 06-11-2011 23:22 ]


Acties:
  • 0 Henk 'm!

  • nephilimcrt
  • Registratie: Juni 2011
  • Laatst online: 09-09 18:12

nephilimcrt

Mad Scientist

Topicstarter
Maar ik type gewoon de zin in en druk dan pas op 'Send'. Dus zou het toch in één keer op de lijn gezet moeten worden?

Overigens krijg ik met andere constructies wel gewoon de hele zin terug, maar dat waren nogal onhandige constructies. Het probleem lijkt dus te zitten in de manier van terugsturen. Het zou toch niet zo mogen zijn dat hij die "break" al stuurt voordat de hele 'rxstring' verstuurd is?

Misschien moet ik m'n vraag anders formuleren: Kan iemand me een goeie methode laten zien voor het ontvangen en versturen van strings met een Arduino?

Tapping progress on the shoulder and saying: "More forwards, please!".


Acties:
  • 0 Henk 'm!

  • Sphere-
  • Registratie: November 2003
  • Laatst online: 28-08 19:53
Die vraag start met wat jij ziet/gebruikt als een string.

Voor mij is dat een reeks karakters afgesloten met een newline karakter.
Dan kan je zoiets doen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
void loop() { 
 
   char rxbyte;
   String rxstring;
   
  
  while (true) 
  {   
    // check if data has been sent from the computer:
    if (Serial.available()!= 0) {
   
      // read the most recent byte:
      rxbyte = Serial.read();
      // add the most recent byte to the string:
      rxstring = rxstring + rxbyte;
      //send the received string back over the serial port:
      
      // check if end of string
      if (rxbyte == '\n') {
        break; // break out of the while loop
      }
    }
  }
  
  if (rxstring != "")
  {
     Serial.println(rxstring);
     Serial.println("break"); //test to see what's going wrong
  }
  
  rxstring = "";
  
  // ready to receive a new string
   
}

[ Voor 4% gewijzigd door Sphere- op 06-11-2011 23:51 ]


Acties:
  • 0 Henk 'm!

  • nephilimcrt
  • Registratie: Juni 2011
  • Laatst online: 09-09 18:12

nephilimcrt

Mad Scientist

Topicstarter
Ik heb je voorbeeld een beetje moeten aanpassen omdat ie '\n' niet als char accepteert natuurlijk. Ik heb voor het gemak maar even een tilde gepakt als EOL karakter en het resultaat is veelbelovend:

code:
1
2
3
4
5
6
7
8
Eens kijken wat er gebeurt als ik nu deze regel afsluit met een tilde~
break
En nu een hele lange zin om heel zeker te weten dat er geen rare dingen gebeuren~
break
Verdorie, volgens mij werkt het nog ook~
break
Vette shizzle!~
break


Ik begrijp niet helemaal wat er nu zo anders is geworden, maar ik ben blij dat het werkt. Mijn dank is groot.

Tapping progress on the shoulder and saying: "More forwards, please!".


Acties:
  • 0 Henk 'm!

  • Sphere-
  • Registratie: November 2003
  • Laatst online: 28-08 19:53
'\n' zou gewoon moeten werken hoor, is hetzelfde als rxbyte == 0x0A of rxbyte == 10. '\n' is een zogenaamde escape sequence
Heb je het wel geprobeerd? Je zal wellicht in je terminal in moeten stellen wat hij moet verzenden bij een enter (\n, \r of beide)

[ Voor 63% gewijzigd door Sphere- op 07-11-2011 00:10 ]


Acties:
  • 0 Henk 'm!

  • nephilimcrt
  • Registratie: Juni 2011
  • Laatst online: 09-09 18:12

nephilimcrt

Mad Scientist

Topicstarter
Ja, ik heb het geprobeerd en de compiler vond het niet grappig op de één of ander manier. Dus meteen maar een enkel karakter gepakt en dat ging wel.

Geeft verder niet, als het maar werkt.

Tapping progress on the shoulder and saying: "More forwards, please!".


Acties:
  • 0 Henk 'm!

  • Ibex
  • Registratie: November 2002
  • Laatst online: 10:01

Ibex

^^ met stom.

Je zegt dat je eerst de hele string typt, en dan pas op send drukt. Dan nog zal je pc (of wat je ook gebruikt) de string karakter per karakter doorsturen. Als er ook maar een iets te lange pauze - hoe klein dan ook - is tussen twee karakters, zal je initiele code een lege buffer krijgen, en denken dat de string volledig is ontvangen.

De correcte werkwijze is inderdaad een end-of-line karakter definieren, en dan je programma laten luisteren tot dat karakter is ontvangen. Nu zal wellicht je buffer ook af en toe leeg raken, maar het programma weet dat hij nog moet blijven luisteren, tot dat het EOL karakter is ontvangen.

I.v.m. de \n; probeer eens "\n" met dubbele quotes? Of anders kan je gewoon 0x0A of 10 nemen zoals hierboven is gemeld. Uiteindelijk is het toch een nummer :).

Archlinux - Rode gronddingetjes zijn lekker - Komt uit .be


Acties:
  • 0 Henk 'm!

  • nephilimcrt
  • Registratie: Juni 2011
  • Laatst online: 09-09 18:12

nephilimcrt

Mad Scientist

Topicstarter
Bedankt voor je input. Wat je zegt is natuurlijk waar. Echter, ik weet nu zeker dat de code werkt (met tilde als EOL karakter) want ik krijg inmiddels in m'n VB applicatie ook de juiste data terug en niet alleen in de Serial Monitor.

Ik zal nog wat gaan proberen met "\n" of 0x0A, maar ik ga er niet al teveel moeite in steken. Ik kan prima leven met een zelf gedefiniëerd EOL karakter

Tapping progress on the shoulder and saying: "More forwards, please!".


Acties:
  • 0 Henk 'm!

  • _ferry_
  • Registratie: Januari 2002
  • Niet online

_ferry_

Moderator Tweaking

Nipple Tweaker

Heb je toevallig ook getest met serial.print ipv serial.println?
Pagina: 1