Sida 5 av 5

Re: konsolmeny till arduino

Postat: 31 januari 2012, 00:02:43
av lillmange
>Rimligtsvis borde mottagna tecken samlas "på hög" i någon buffert (normalt
>implementerat som en "array", inte bara summeras ihop då ju allt tappas bort.

Det var vad jag försökte förklara för min kompis, tydligen så misslyckades jag totalt

När jag skriver "30[ENTER]" i putty skickas tecknen till mitt arduino kort via serieporten (som ofs är en fejkad serieport eftersom det går över usb)

Detta vill jag spara för att använda till att styra pwm utgången med.

men än så länge vet jag bara hur jag tar emot ett tecken (numeriskt eller ej)

sen vill jag kolla om det är en 0 (nolla) eller 1-99 (ett till nittio nio) eller något annat som inte hör hemma här(kanske en bokstav eller ett för högt tal).

Jag är fullt medveten att 1 är ett tecken och 99 är två tecken. men det spelar ingen roll, jag måste fortfarande ta emot dom och spara dom för "framtida" användning.

Formatet är så som jag skriver in det?
Skriver jag en 1 (etta) kommer det väl en 1 till arduino?
Än så länge har arduino iaf tolkat min nedtryckning av 1 på tangentbordet som en 1... och skickat mig till den undermeny som jag har valt att kalla 1. (OBS, denna kod var ej med i den lilla snutt som jag tidigare lagt in i tråden)

Hoppas jag rett ut en del nu iaf.

/Magnus

Re: konsolmeny till arduino

Postat: 31 januari 2012, 08:46:33
av Kaggen
> Skriver jag en 1 (etta) kommer det väl en 1 till arduino?

Om du skriver en etta i konsollen så kommer ASCII koden för tecknet '1' till Arduinon, dvs värdet 49 decimalt (enligt ASCII tabellen Sodjan länkade till tidigare i tråden http://www.asciitable.com/).

Dock borde du väl kunna använda funktionen atoi() eller motsvarande för Arduino? Denna funktion konverterar x-antal ASCII-tecken (eller en sträng om man så vill) till en integer som du kan lagra i en variabel för framtida bruk.

Kom ihåg felhanteringen bara. Användare kan mata in allt tänkbart och otänkbart.

Re: konsolmeny till arduino

Postat: 31 januari 2012, 09:17:32
av lillmange
Jag förstod inte mycket av det du skrev om atoi men ang felhantering så var det just därför jag ville kolla om det var 0, 1-99 eller något annat som hade matats in.

Om man nu ska göra enklaste mottagandet av okänt antal siffror via serieporten (från putty) och som ska avslutas med /n, hur skriver man då?

/Magnus G

Re: konsolmeny till arduino

Postat: 31 januari 2012, 09:27:54
av Bosen
Siffror är ju egentligen tecken i acshii och ett tecken är en byte. Om du sätter dig framför en acshii teckenkods-tabell och tittar lite hur det är uppbyggt så kommer du nog på lite ;)

Re: konsolmeny till arduino

Postat: 31 januari 2012, 10:16:24
av sodjan
> Skriver jag en 1 (etta) kommer det väl en 1 till arduino?

Det kommer "1" till Arduinon. Du måste skillja på 1 och "1". :-) :-)

> Än så länge har arduino iaf tolkat min nedtryckning av 1 på tangentbordet som en 1...

OK, men då har du väl någon test på värdet 0x31 (eller 49 decimalt, eller "1"), eller hur ?
Det är ju inte värdet 1 som skickas utan (ASCII-) tecknet "1".

Re: konsolmeny till arduino

Postat: 31 januari 2012, 10:20:55
av lillmange
Jo jag vet att det är skillnad på ascii och "vanliga" tecken men om man tar exemplet:

Kod: Markera allt

      if (Serial.available() != 0) {
       inByte = Serial.read();    //läs av serieporten och spara till inByte
      }
    }      
        switch (inByte) {
        case '1':    
                    Serial.print("1");
        case '2':    
                    Serial.print("2");
        case '3':    
                    Serial.print("3");
...
Här fattar ju arduino att det är en vanlig siffra jag skickat...
Jag förstår inte riktigt varför jag då måste konvertera från ascii när jag vill läsa av 2 eller fler tecken?

Kan någon förklara så jag förstår?

Sodjan:

OK, så hur vet man att det är "1" jag tar emot och inte 1... vad nu skillnaden är?

/Magnus G

Re: konsolmeny till arduino

Postat: 31 januari 2012, 10:39:08
av sodjan
> att det är skillnad på ascii och "vanliga" tecken

ASCII *är* "vanliga" tecken!

> om man tar exemplet:

Jo visst, där i koden jämför du inläst tecken med ASCII tecken '1', '2' o.s.v. Helt OK!
Om inByte have varit en rent numerisk variabel så hade det stått:

Kod: Markera allt

        switch (inByte) {
        case 1:   
                    Serial.print("1");
        case 2:   
                    Serial.print("2");
        case 3:   
                    Serial.print("3");
> Jag förstår inte riktigt varför jag då måste konvertera från ascii när jag vill läsa av 2 eller fler tecken?

Ville du inte skicka värden mellan 0 och 99 ?
Det kan du skickas som "0" - "99". Fördelen med det är att det är lätt att felsöka
och det är lätt att testköra från t.ex PuTTY eftersom allt skickas som ASCII.

Antag att du skickar "56", detta kommer då fram som två tecken 0x35, 0x36, alltså ASCII koderna
för tecknen "5" och "6". Men det du vill ha i Arduinon är *värdet* 56 !

Har du ens läst på vad atoi() gör !?

> OK, så hur vet man att det är "1" jag tar emot och inte 1..

Det bestämmer *du*. Det är ju du som skickar i från andra änden (t.ex PuTTY).

> .... vad nu skillnaden är?

"1" = 0x31
1 = 0x01

Stor skillnad... :-)

På samma sätt som :

1 = 0x01
"ett" = 0x65, 0x74, 0x74

:-)

Re: konsolmeny till arduino

Postat: 31 januari 2012, 13:50:40
av jesse
Det är alldeles för många grundläggande frågor om hur programspråket fungerar för att du ska kunna ta till dig allt på en gång, tror jag. Sedan att vi inte vet hur arduino-funktionerna verkligen fungerar är ju ytterligare ett problem. Antagligen finns det redan en buffert, som de inlästa tecknen lagras i, men om man inte vet hur man kommer åt dom så spelar det ju ingen roll :roll:

Och då får du kanske bygga en buffer själv, om du inte kör 'fulhack' och tolkar indata när de kommer.
Jag vet inte vilket som är enklast för dig just nu.

Observera att C-kompilatorn skiljer på "1" och '1' !!!
Jag får 18 bytes längre programkod med "1" än med '1', så skilj noga på det. Det är inte ens säkert att det blir som avsett om man skriver "1".

"1" är en textsträng som innehåller ett tecken och ett slut-tecken. Precis som "HELLO" innehåller 5 tecken och ett slut-tecken. Dessa är arrayer av char eller unsigned char.

exempel:
char ABC[] = "ABC"; är detsamma som att skriva
char ABC[] = {65,66,67,0}; eftersom 'A' = 65, 'B' = 66, 'C' = 67

char etta[] = "1" ; är detsamma som
char etta[] = {49,0}; eftersom '1' = 49

Dessa är alltså arrayer med ett eller flera tecken följt av en nolla (inte tecknet '0' - det har värdet 48).

'1' däremot är ett heltal som motsvarar acsii-värdet av tecknet innanför '-tecknen. ASCII för '1' är 49.

exempel:
char tecken = '0'; är samma sak som
char tecken = 48;

Eftersom arrayen ABC innehåller tecken av typen char så kan man plocka ut ett sådant och jämföra med ett annat char:
exempel:

if (ABC[1] == 'B') { ... }
ABC[0] = '1'; // sätt dit '1' istället för 'A' på position 0 i arrayen ABC.

----------------------------------------------

Åter till ditt problem / fråga:
Vad du ska göra är följande:

1) se till att du fått in alla tecken i en buffert - dvs en array med char:

Kod: Markera allt

char inbuffer[20];
Du fyller på den med tecken tills ett tecken är '\n' - då påbörjar du avkodningen av arrayen.

Eventuellt kan du ersätta '\n'-tecknet i arrayen med 0x00 som betyder att strängen är slut / sista tecknet.

Gör en separat funktion (eller använd atoi) för att läsa in talet. Du skickar t.ex. en pekare till arrayen som argument.

Kod: Markera allt

int value = atoi(inbuffer);
Talet finns nu i din variabel 'value' (jag kan inte exakt syntaxen för atoi - jag har alltid gjort mina egna sådana funktioner.)

Men det bästa , tycker jag, är att du inte bara skickar ett tal från 'putty' utan du börjar med en 'kod' - på så vis kan du lätt mata in olika parametrar till din arduino:
t.ex.

V20 (enter) = ange varvtal till 20 v/min
T34 = ange maxtemperatur till 34 grader
A+ = aktivera larm
A- = avaktivera larm

Det enda du behöver göra är att du börjar med att läsa av första tecknet i bufferten, och gör en switch sats med de olika bokstäverna i var sin case-sats. (kolla inlägg 7 igen :) )

Re: konsolmeny till arduino

Postat: 31 januari 2012, 20:15:04
av Bosen
Jag slängde ihop ett snabbt exempel på hur man kan göra.
Jag är inte någon van C-programmerare och hade aldrig programmerat i C innan jag började med Arduino, så det finns nog mycket att förbättra ;)

Kod: Markera allt

int IncommingByte;
int ValueChar[]={0,0,0};    // En array av int som används som buffer
int ValueCounter=0;         // Räknare för att hålla reda på buffern
int Value=0;                      // Det slutgiltiga värdet

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

void loop(){
  
  if (Serial.available() > 0) {
    IncommingByte=Serial.read();    

    if (IncommingByte > 47 && IncommingByte < 58 && ValueCounter < 3){ // Kontrollera om tecknet är en siffra
                                                                            // och om alla tre siffrorna redan är inmatade?
      ValueChar[ValueCounter]=(IncommingByte);     // Lägg inkommande byte i buffern   
      ValueChar[ValueCounter]-=48;                 // Gör om byten till en siffra
      ValueCounter++;                              // Öka räknaren
      if (ValueCounter > 3){ ValueCounter=3; }     // Räkna inte till mer än 3
    }
    
    else if (IncommingByte==13){                  // [Enter] är mottaget
      ValueCounter--;                             // Räkna bakifrån ValueCounter är aldrig mer än 3
        Value = ValueChar[ValueCounter];          // Ental
        ValueCounter--;                           // Ett steg bakåt
      
      if (ValueCounter > -1){                     // Är det mer än en siffra inmatad?
        Value += (ValueChar[ValueCounter] * 10);  // Tiotal
        ValueCounter--;
      }
     
      if (ValueCounter > -1){                      // Är det mer än 2 siffror inmatade?
        Value += (ValueChar[ValueCounter] * 100);  //Hundratal
        ValueCounter--;
      }
    ValueCounter=0;                                // Nollställ räknaren
    ValueChar[0]=0;                                // Nollställ buffern
    ValueChar[1]=0;
    ValueChar[2]=0;
    
    Serial.print("Value: ");                       // Visa värdet
    Serial.println(Value);
      
    }
  }
}
Koden är fungerande och det är bara att skicka in den i din arduino.
Koden omvandlar ett inmatat numeriskt värde på max 3 siffror till en integer kallade "Value".
Matar man in mer än 3 siffror så använder den bara de 3 första.
Matar man in andra tecken än siffror i strängen så använder den bara siffrorna och struntar i dom andra tecknen.
Hoppas att du får någon hjälp av den iallafall ;)

Re: konsolmeny till arduino

Postat: 31 januari 2012, 20:42:01
av BEEP
Det här kanske kan vara till någon nytta i framtiden.
String Comparison Operators

Re: konsolmeny till arduino

Postat: 18 februari 2012, 00:10:45
av Rohan
Prova skriva ut 20 blankrader. Testa decimalt 10 om det ger blankrader (kolla engelska Wikipedia på ASCII).

Re: konsolmeny till arduino

Postat: 18 februari 2012, 10:28:16
av jesse
BEEP skrev:Det här kanske kan vara till någon nytta i framtiden.
String Comparison Operators
Det finns väl en del resurser i de normala C standardbiblioteken när det gäller strängar?
De 'strängoperatorer' man talar om i länken ovan är väl specifikt enbart för Arduino?

<stdlib.h>
atof, atoi, atol

<string.h>
strcpy, strncpy (kopiering)
strcat, strncat (lägga till i slutet)
strcmp, strncmp (jämför)
strlen (beräkna längd)
strspn, strcspn (leta tecken i sträng?)
strchr, m.fl (sök i sträng)

Jag har aldrig använt dem men undrar hur effektiva de är för en 8-bitars AVR?
Bättre än att försöka göra liknande/samma funktioner själv?

Re: konsolmeny till arduino

Postat: 18 februari 2012, 14:43:27
av BEEP
"De 'strängoperatorer' man talar om i länken ovan är väl specifikt enbart för Arduino?"
Jag har ingen aning men jag tror att Arduino kör sitt lilla egna race när det gäller namn på funktioner men själva funktionen borde väl vara lika?

"Jag har aldrig använt dem men undrar hur effektiva de är för en 8-bitars AVR?"
Varför bråka med en massa kommando jämförelser när man kan skriva värden och flaggor direkt till ett minnesområde på µC.

Re: konsolmeny till arduino

Postat: 6 mars 2012, 10:28:29
av lillmange
Hej

Jag tappade fart när det jag trodde skulle bli en ganska lätt match blev något helt annat, vilket jag inte riktigt har tid med just nu.

Jag tackar för all hjälp och jag ska försöka ta in allt ni skrivit så kanske det blir ett menysystem någon gång i framtiden.

Till dess kommer jag (troligtvis) köra på ursprungstanken med en encoder och menyn på en liten display.

/Magnus G