array: da serie a gruppi

Ciao a tutti, sono nuovo del forum anche se lo leggo da un po.
Sto cercando di programmare una keypad dalla quale pilotare una radio trasmittente.
Il problema che sto trovando è come passare da una serie di numeri (array) a un gruppo di numeri.
Mi spiego meglio:
se io immetto da tastiera e/o da keypad 14550000 per settare 145.500.00 MHz prima di poterla mandare alla radio devo scomporla in 14 55 00 00,
perchè la radio accetta istruzioni a 5 byte (aggiungo il comando alla fine).
Al momento ho creato questo scketc ma non ne vengo fuori...
Please help me =(
se immetto il dato l'array mi restituisce quello che inserisco ma come faccio a dividerlo come serve a me?

char valore[8];
  char inByte;
  uint32_t risultato= 0 ;
  int c=0;
     
void setup() {
  Serial.begin(9600);
}

void loop() {
  if (Serial.available() > 0) {

  inByte =  Serial.read();
  Serial.print("seriale ");
  Serial.println(inByte);
  
  if (inByte != '#') {
   if (c >= 8 ) {c= 0 ;goto RES;}
    valore[c] = inByte;
    c= c+1;
 } else{
   RES:
    valore[8]=0;
    uint32_t risultato = atof(valore);
      
   Serial.println("MMM.kkk.hh");
   Serial.print(valore[0]);
   Serial.print(valore[1]);
   Serial.print(valore[2]);
   Serial.print(".");
   Serial.print(valore[3]);
   Serial.print(valore[4]);
   Serial.print(valore[5]);
   Serial.print(".");
   Serial.print(valore[6]);
   Serial.print(valore[7]);
   Serial.println(" MHz");
   
   for(c=0;c<8;c++){valore[c]=0;}
   c=0;
 }
}
     delay(10);

}

da quello che ho capito tu da un char lo vuoi trasformare in int?

secondo la tabella ascii i numeri partono da 48 quindi potresti trasformare il valore in int e sottrarre 48.

oppure usi la funzione atoi() (mi pare sia questa) che dovrebbe ritornare il valore espresso.

comunque siccome l'hai già scomposto forse il primo metodo è più comodo.

poi fai una somma semplicissima (mi raccomando il primo numero *100 il secono *10 e l'ultimo invariato) :wink:

beh, forse mi esprimo non correttamente e per questo chiedo scusa, ma mi avvicino da poco al mondo arduino e sicuramente commetto degli errori o omissis:

con il codice che ho postato succede che dal monitor seriale io scrivo 14550000# e quei serial print mi restituiscono la forma che io voglio xxx.xxx.xx
uno per ogni valore che assume "valore

", vorrei sapere come porter raggruppare valore[1] e valore [2] etc etc
a me in realtà serve che i valori che io immetto come12345678# diventino 12 34 56 78 per poterli poi inviare tramite seriale alla radio.

Un esempio di come invio alla radio è questo:

[code]
void PLL_W() {
int val[5];
val[0]= 14; // valore della frequenza
val[1]= 55; // 
val[2]= 00; //
val[3]= 00; //
val[4]= 01; // codice di comando per la scrittura della frequaenza
    
    Serial.write(val[0]);
    delayMicroseconds (200);
    Serial.write(val[1]);
    delayMicroseconds (200);
    Serial.write(val[2]);
    delayMicroseconds (200);
    Serial.write(val[3]);
    delayMicroseconds (200);
    Serial.write(val[4]);
    
}
[/code]
Che sia char o int non credo sia molto differente... o almeno credo...

nono ho capito bene ma mi sono espresso male :stuck_out_tongue:

per ottenere ciò che vuoi puoi fare una cosa simile:

Serial.println("MMM.kkk.hh");
   Serial.print(valore[0]);
   Serial.print(valore[1]);
   Serial.print(valore[2]);
   Serial.print(".");
   Serial.print(valore[3]);
   Serial.print(valore[4]);
   Serial.print(valore[5]);
   Serial.print(".");
   Serial.print(valore[6]);
   Serial.print(valore[7]);
   Serial.println(" MHz");

  // Lo trasformiamo in 3 numeri

  val[0]= atoi(valore[0]+valore[1]+valore[2]); // valore della frequenza
  val[1]= atoi(valore[3]+valore[4]+valore[5]); // 
  val[2]= atoi(valore[6]+valore[7]); //
  val[3]= 00; //
  val[4]= 01; // codice di comando per la scrittura della frequaenza


  // li inviamo al tuo apparecchio

  Serial.write(val[0]);
  delayMicroseconds (200);
  Serial.write(val[1]);
  delayMicroseconds (200);
  Serial.write(val[2]);
  delayMicroseconds (200);
  Serial.write(val[3]);
  delayMicroseconds (200);
  Serial.write(val[4]);

dovrebbe funzionare...

l'altro metodo che intendevo era quello per cui ad ogni numero compreso tra 0 e 255 corrisponde un carattere (secondo una tabella chiamata ascii) e siccome il valore viene salvato come numero nella variabile e poi convertito in carattere (non è esattamente così ok ma è per capire) e sapendo che secondo le tabelle ascii i numeri sono divisi così:
(n° ascii) 48 -> 0 (carattere)
(n° ascii) 49 -> 1 (carattere)
(n° ascii) 50 -> 2 (carattere)
(n° ascii) 51 -> 3 (carattere)
(n° ascii) 52 -> 4 (carattere)
(n° ascii) 53 -> 5 (carattere)
(n° ascii) 54 -> 6 (carattere)
(n° ascii) 55 -> 7 (carattere)
(n° ascii) 56 -> 8 (carattere)
(n° ascii) 57 -> 9 (carattere)

in teoria atoi() dovrebbe già restituirti il valore del carattere (insomma scrivi 1 lo trasformi con atoi e rimane 1) però non vorrei che 1 lo convertisse in ascii e quindi nella variabile vi sarebbe il valore 50.
in caso fosse così devi convertire ogni singola cifra e sottrarre 48 per avere l'effettivo valore che ti serve.

allora, ho inizializzato val così:
int val[4];

poi ho aggiunto

val[0] = atoi(valore[0] + valore [1]); // serve così la divisione.
val[1] = atoi(valore[2] + valore [3]);
val[2] = atoi(valore[4] + valore [5]);
val[3] = atoi(valore[6] + valore [7]);

se provo a compilare mi restituisce questo errore:

testarrayfreq.cpp: In function 'void loop()':
testarrayfreq:39: error: invalid conversion from 'int' to 'const char*'
testarrayfreq:39: error: initializing argument 1 of 'int atoi(const char*)'

se inizializzo val come: char val[4];
l'errore è lo stesso.
cmq confermo che con atoi mi restituiva 50, mentre con atof mi restituisce il valore corretto, ossia 1.

dove sto sbagliando?

mrboss:
allora, ho inizializzato val così:
int val[4];

poi ho aggiunto

val[0] = atoi(valore[0] + valore [1]); // serve così la divisione.
val[1] = atoi(valore[2] + valore [3]);
val[2] = atoi(valore[4] + valore [5]);
val[3] = atoi(valore[6] + valore [7]);

se provo a compilare mi restituisce questo errore:

testarrayfreq.cpp: In function 'void loop()':
testarrayfreq:39: error: invalid conversion from 'int' to 'const char*'
testarrayfreq:39: error: initializing argument 1 of 'int atoi(const char*)'

se inizializzo val come: char val[4];
l'errore è lo stesso.
cmq confermo che con atoi mi restituiva 50, mentre con atof mi restituisce il valore corretto, ossia 1.

dove sto sbagliando?

sostituisci i miei atoi con atof :wink:

Il codice postato non è corretto! Fare questo:

val[0] = atoi(valore[0] + valore [1]);

vuol dire passare un valore intero alla funzione quando lei si aspetta un array di caratteri (una stringa)! Inoltre usare l'operatore + vuol dire sommare i due numeri contenuti in valore[0] e valore[1] e non concatenarli.
L'errore di cast che ti riporta è proprio per questi motivi, ti conviene usare un approccio diverso, come quello già consigliato di usare la tabella ascii :slight_smile:

Grazie, in effetti la funzione atoi con i valori sommati non mi portava a nulla, l'avevo già provata.
Invece ho risolto in parte con le stringhe.
Ora il problema è trasformare una stringa in un int per passarla al Serial.write

il codice è questo:

String readKeyPad;
String f1;
String f2;
String f3;
String f4;
String ft;


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

void loop() {
while (Serial.available()) {
     delay(10);

     if (Serial.available() >0) {
     char c = Serial.read();
     readKeyPad += c;}}
     

   if (readKeyPad.length() >0) {
  
        f1 = (readKeyPad.substring(0,2));
        f2 = (readKeyPad.substring(2,4));
        f3 = (readKeyPad.substring(4,6));
        f4 = (readKeyPad.substring(6,8));
        ft = (readKeyPad.substring(0,8));
        Serial.println(f1);
        Serial.println(f2);
        Serial.println(f3);
        Serial.println(f4);
        Serial.println(ft);
 
   readKeyPad="";
   }
   }

così ottengo la divisione che mi serve ma se provo a scrivere f1, ad esempio Serial.write(f1);
l'errore è:
string_freq.cpp: In function 'void loop()':
string_freq:35: error: no matching function for call to 'HardwareSerial::write(String&)'

sto cercando di capire come trasformare la stringa in int ma purtroppo non riesco a capire come gestirla.
E' lo scotto del novellino... :frowning: :frowning: :frowning:

dancol90:
Il codice postato non è corretto! Fare questo:

val[0] = atoi(valore[0] + valore [1]);

vuol dire passare un valore intero alla funzione quando lei si aspetta un array di caratteri (una stringa)! Inoltre usare l'operatore + vuol dire sommare i due numeri contenuti in valore[0] e valore[1] e non concatenarli.
L'errore di cast che ti riporta è proprio per questi motivi, ti conviene usare un approccio diverso, come quello già consigliato di usare la tabella ascii :slight_smile:

no aspetta in teoria essendo 2 char vado a sommare non il valore ma a concatenare i caratteri un questo caso no? :cold_sweat:

comunque aspetta un minuto che cerco un mio vecchio codice e vedo come avevo risolto XD

no io dovevo fare il contrario..

allora non ho modo di provarlo ma in teoria il codice dovrebbe essere una cosa così:

val[0] = (atoi(valore[0])-48)*10 + (atoi(valore [1])-48);
val[1] = (atoi(valore[2])-48)*10 + (atoi(valore [3])-48);
val[2] = (atoi(valore[4])-48)*10 + (atoi(valore [5])-48);
val[3] = (atoi(valore[6])-48)*10 + (atoi(valore [7])-48);

solo che non avendo arduino sotto mano ammetto che sto andando per tentativi..

se non va così prova

val[0] = (valore[0]-48)*10 + (valore [1]-48);
val[1] = (valore[2]-48)*10 + (valore [3]-48);
val[2] = (valore[4]-48)*10 + (valore [5]-48);
val[3] = (valore[6]-48)*10 + (valore [7]-48);

naturalmente val[] deve essere inizializzato come int mentre valore (nel primo caso per certo) deve essere un char*

superlol:
no aspetta in teoria essendo 2 char vado a sommare non il valore ma a concatenare i caratteri un questo caso no? :cold_sweat:

nono...sono dichiarati come int! e anche se fossero stati char, per il c/c++ sono numeri anche quelli :wink:

superlol:

val[0] = (valore[0]-48)*10 + (valore [1]-48);

val[1] = (valore[2]-48)*10 + (valore [3]-48);
val[2] = (valore[4]-48)*10 + (valore [5]-48);
val[3] = (valore[6]-48)*10 + (valore [7]-48);

questo è quello che dicevo anch'io! è il metodo migliore senza dover usare la classe String...

@mrboss:
Per capire meglio il codice sopra dai un'occhiata qui ASCII - Wikipedia, nota che i "glifi" da '0' a '9' sono contigui e hanno valore fra 48 e 57. Dentro valore troverai proprio un numero fra 48 e 57, basta sottrarre 48 o '0' (per il C un carattere dentro apici singoli corrisponde al suo codice ASCII) per ottenere la cifra che interessa a te!

Magari controlla prima che tutti i caratteri dentro valore siano compresi fra '0' e '9' (notare gli apici, sono caratteri non cifre!!)
Per risparmiare un po' di spazio in ram ti conviene dichiarare valore come un array di char o di byte (occupano la metà di un int, che può tenere numeri molto più grandi ma che in questo caso non ci servono :slight_smile: )

Grazie a tutti per l'aiuto.
Ieri poi ho provato con String.substring e sono riuscito nel mio intento.
Poi ho convertito la CHAR in INT e da li è stato facile.
Oggi, con l'aiuto di un amico, ho riscritto tutta la funzione e l'ho resa "universale" nel senso che posso utilizzarla come call per altri comandi.
Appena posso posto il codice, magari può tornare utile a qualcuno...

posto un altro metodo che ho usato per ridefinire la stringa di byte che mi serviva.
Se può tornare utile a qualcuno:

char inFreq;
unsigned char YaesuCatBuffer [5];
int i;
int FreqStringUsed = 0;
void freq()
{
               
        inFreq = keypad.getKey();
        
	if (inFreq != NO_KEY){
            if(inFreq !='#'){
                beep();
                if (FreqStringUsed < FREQ_STRING_LEN){
                   FreqString [FreqStringUsed] = inFreq;
		   FreqStringUsed = FreqStringUsed + 1;
         }}else{
         tone(buzzer, notes[1], 100);  
         for (i=0; i<4; i++) {YaesuCatBuffer [i] = ((FreqString [i*2]-'0') << 4) | ((FreqString [i*2+1]-'0'));}
	 YaesuCatBuffer [4] = 0x01;
	 Serial.write (YaesuCatBuffer, 5);

         for (i=0; i<FREQ_STRING_LEN; i++) FreqString [i]='0';
         FreqStringUsed = 0;

         keyvar=0; }}}