Topic permanente di programmazione newbie

Sto lavorando ad un firmware piuttosto complesso nella struttura, lo devo praticamente stravolgere, alla fine ho deciso di riscriverlo, troppo disordine. Chiaramente ora vorrei rifarlo secondo le mie esigenze ma le mie conoscenze in C sono prossime allo 0 (partendo da negativo!); fondamentalmente riorganizzerò i blocchi del software precedente più altri usciti dai preziosi suggerimenti di Astrobeed e di Leo72, ma il "contorno" me lo devo riceare e lì sono usciti subito i primi problemi; ho scaricato tempo fa da un link il language reference di Arduino ma le mie scarne conscenze non mi permettono di superare ciò che lì è dato per scontato. Ho pensato allora di aprire questo Topic per porre domande che per me sono importanti e per molti di voi saranno banali, man mano che usciranno le mie esigenze. Ciò vale anche per i messaggi di errore che a volte escono e che mi fanno impazzire per trovare la soluzione. Il mio tempo è scarso quindi il vostro aiuto diventa per me prezioso. Naturalmente questo Topic potrebbe diventare un serbatoio di richieste di chiunque abbia un qualsiasi dubbio di programmazione.
Chiudo questo post qui come premessa e nel successivo pongo la prima domanda. Grazie a chiunque collaborerà.

:wink:

Ed ecco il primo quesito :
Ho necessità di creare uno switch case in cui le risposte siano "S" e "N" e non 1 e 2. Ho scritto questo

byte response = NULL;// variabile globale messa prima del setup
//il seguito si trova in loop
Serial.println("Vuoi riprogrammare i fuse di questo micro? S/N");
while(response == NULL) {
while (Serial.available() == 0); // aspetta un carattere
response = Serial.read(); // legge la risposta dell'utente

switch(response) {
case 'S':
case 's':
mode = ATMEGA;
break;
case 'N':
case 'n':
Serial.println("Togli il micro dallo zoccolo e premi il pulsante RESET");
end_programming();
break;
default:
Serial.println("Per favore premi S o N");
response = NULL; // reset response so we go thru the while loop again
break;

se premo s, S, n o N comunque mi esce il messaggio d'errore. Perché?

EDIT: falso problema, funziona, non chiedetemi cosa ho fatto, non lo so :frowning:

Perché non puoi confrontare un tipo byte con un carattere, devi usare il tipo char.
http://arduino.cc/en/Reference/Char

leo72:
Perché non puoi confrontare un tipo byte con un carattere, devi usare il tipo char.
http://arduino.cc/en/Reference/Char

How to use switch: char : Switch « Language Basics « C / ANSI-C

Ma quella del tipo char era la strada che avevo tentato di seguire creando una global:
char yesno = "" (o anche = NULL) ma mi ha preso a parolacce già su questa definizione, invece ora col tipo byte riconosce le quattro modalità e risponde correttamente, boh!?

Non mi prende a parolacce:

void loop() {
char stringa='a';
switch(stringa) {
    case 'a':
        break;
    }
}

byte è un tipo di dati di arduino che altro non è se non un unsigned char. Ma se devi fare confronti con le lettere mi pare più corretto usare il tipo di dati appropriato, cioè char, dato che byte è stato "inventato" proprio per trattare numeri.

leo72:
Perché non puoi confrontare un tipo byte con un carattere, devi usare il tipo char.

char e unsigned char (byte) sono la stessa cosa per il C, cambia solo il modo di trattarli nei calcoli, ma su i confronti non cambia nulla, un carattere ascii altro non è che un valore numerico.

leo72:
Non mi prende a parolacce:

void loop() {

char stringa='a';
switch(stringa) {
    case 'a':
        break;
    }
}




byte è un tipo di dati di arduino che altro non è se non un unsigned char. Ma se devi fare confronti con le lettere mi pare più corretto usare il tipo di dati appropriato, cioè char, dato che byte è stato "inventato" proprio per trattare numeri.

come a parolacce? ma ti sto chiedendo aiuto! Comunque, il chiarimento di Astro mi sta bene, per ora devo andare avanti, alle finezze penseremo in un secondo momento :wink:
Altro problema, solo di carattere estetico: il gruppo:

Serial.print("SIGNATURE: ");
#if (read_signature1 < 10) //serve per mostrare lo 0 iniziale per valori <16 = 10
Serial.print("0");
#endif
Serial.print(read_signature1, HEX);

nelle mie misere intenzioni doveva aggiungere uno 0 quando ho un esadecimale <16, per evitare di vedere F o A invece di 0F o 0A, invece lo zero esce inesorabilmente sempre, l'errore è nel fatto che read_signature1 contiene un valore HEX ed io lo confronto con una banale 10, avevo provato $10 ma anche qui fiumi di imprecazioni dell'IDE :blush:

astrobeed:

leo72:
Perché non puoi confrontare un tipo byte con un carattere, devi usare il tipo char.

char e unsigned char (byte) sono la stessa cosa per il C, cambia solo il modo di trattarli nei calcoli, ma su i confronti non cambia nulla, un carattere ascii altro non è che un valore numerico.

+1

menniti:

leo72:
Non mi prende a parolacce:

void loop() {

char stringa='a';
switch(stringa) {
    case 'a':
        break;
    }
}




byte è un tipo di dati di arduino che altro non è se non un unsigned char. Ma se devi fare confronti con le lettere mi pare più corretto usare il tipo di dati appropriato, cioè char, dato che byte è stato "inventato" proprio per trattare numeri.

come a parolacce? ma ti sto chiedendo aiuto! Comunque, il chiarimento di Astro mi sta bene, per ora devo andare avanti, alle finezze penseremo in un secondo momento :wink:
Altro problema, solo di carattere estetico: il gruppo:

Serial.print("SIGNATURE: ");
#if (read_signature1 < 10) //serve per mostrare lo 0 iniziale per valori <16 = 10
Serial.print("0");
#endif
Serial.print(read_signature1, HEX);

nelle mie misere intenzioni doveva aggiungere uno 0 quando ho un esadecimale <16, per evitare di vedere F o A invece di 0F o 0A, invece lo zero esce inesorabilmente sempre, l'errore è nel fatto che read_signature1 contiene un valore HEX ed io lo confronto con una banale 10, avevo provato $10 ma anche qui fiumi di imprecazioni dell'IDE :blush:

Scusa, fatti una #define che ti contiene il numero esadecimale da confrontare no ?

Scusa ma se faccio
define cfr 10
no mi assegna la sigla cfr al pin 10? Non devo comunque dirgli che 10 è un valore HEX, ma nei tipi di dati non lo vedo.

Perchè dovrebbe assegnarti il pin 10 alla sigla CRF ?
alla fine, se nel setup non metti che crf è un pin con il solito pinMode, crf resta una variabile come tante altre..
spero di essermi spiegato in maniera chiara :cold_sweat:

poi se proprio vuoi te la inizializzi solo all'interno della funzione in cui la usi così eviti altri problemi, senza contare che così facendo al termine della funzione la ram che veniva occupata dalla varibile, viene liberata.

ratto93:
Perchè dovrebbe assegnarti il pin 10 alla sigla CRF ?
alla fine, se nel setup non metti che crf è un pin con il solito pinMode, crf resta una variabile come tante altre..
spero di essermi spiegato in maniera chiara :cold_sweat:

poi se proprio vuoi te la inizializzi solo all'interno della funzione in cui la usi così eviti altri problemi, senza contare che così facendo al termine della funzione la ram che veniva occupata dalla varibile, viene liberata.

Edit:
L'ho appena provato così: #define crf = 0x10;
e compila senza problemi, alla fine è solo un numero :stuck_out_tongue:

stacco perchè mi aspetta una brutta giornata a scuola domani..

ratto93:
Perchè dovrebbe assegnarti il pin 10 alla sigla CRF ?
alla fine, se nel setup non metti che crf è un pin con il solito pinMode, crf resta una variabile come tante altre..
spero di essermi spiegato in maniera chiara :cold_sweat:

poi se proprio vuoi te la inizializzi solo all'interno della funzione in cui la usi così eviti altri problemi, senza contare che così facendo al termine della funzione la ram che veniva occupata dalla varibile, viene liberata.

Sì, hai ragione, sei stato chiarissimo, solo non capisco perché facendo il confronto diretto con 10 non va ed invece dovrebbe andare facendolo con una variabile che contiene 10, senza specificargli che è un valore hex.
Ok, provo come hai fatto tu, buonanotte e grazie.

ratto93:
L'ho appena provato così: #define crf = 0x10;

mmm ci sono alcuni errori in quella define, vedi #define - Arduino Reference
Define non fa altro che sostituire la stringa prima della compilazione, quindi niente = o ;

lucadentella:

ratto93:
L'ho appena provato così: #define crf = 0x10;

mmm ci sono alcuni errori in quella define, vedi #define - Arduino Reference
Define non fa altro che sostituire la stringa prima della compilazione, quindi niente = o ;

infatti "=" non ci vuole, comunque anche confrontantolo così non va.

Occhio che 0x10 equivale a 16 decimale se vuoi scrivere il 10 decimale in formato esa devi scrivere 0xa.

Le #define e in genere tutto quello che comincia con il simbolo # (cancelletto) riceve l'attenzione di un programma chiamato preprocessore C, che opera delle sostituzioni prima della compilazione. Per esempio:

#define crf 0x10

int somma = crf + 0x4

Viene trasformato dal preprocessore così:

int somma = 0x10 + 0x4;

Al posto del numero esa 0x10 puoi scrivere ciò che vuoi, anche F_CPU/16, il prepocessore sostituisce il segnaposto crf con quello che segue.

int somma = 16000000/16 + 0x4;

Nota però che la rappresentazione del numero in formato è da considerare cosa differente dal numero stesso, anche un'intero può essere rappresentato in esadecimale ma ciò che appare sul display o a video non è il numero reale utilizzabile ma appunto una solo rappresentazione, tanto che il calcolo viene fatto in binario.

La possibilità che il C offre è, che non importa se assegni il valore ad una variabile in formato esa oct o decimale, tanto il C trasforma tutto in binario.
La funzione della libreria avr-libc offre una printf & company che permette la formattazione tramite le stringhe di formato, se hai intenzione di usare questa fa sapere che trovo la giusta stringa di formattazione e la posto. L'unico motivo per rinunciare a queste funzione è legata all'incremento
della dimensione del programma in modo diciamo corposo, diomensione che cresce ancora se vuoi anche stampare numeri in formato float o double, ma per questo è necessario inserire un flag nella fase di linking.

Ciao.

Lasciate perdere il discorso che ho fatto tra byte e char, ci ho pensato dopo che infatti byte altro non è che un unsigned char :stuck_out_tongue:

Sulle define, la notazione di ratto è errata, non ci vuole l'uguale. Il define non è un'assegnazione come nelle variabili, ma una direttiva per il compilatore per fare ciò che dice Mauro: sostituisce all'alias indicato tutto ciò che segue.

Con #define crf = 0x10; il compilatore ogni volta che trova crf mette "= 0x10;" quindi anche l'uguale ed il punto e virgola.

Allora, se uno dei byte della signature ha un valore decimale inferiore a 16 lo 0 iniziale viene omesso nella notazione esadecimale, quindi 0F mi appare come F, quindi in sola fase di visualizzazione voglio aggiungere uno 0.
Avevo pensato a:
Serial.print("SIGNATURE: ");
#if (read_signature1 < 0x10) //serve per mostrare lo 0 iniziale per valori <16 = 10
Serial.print("0");
#endif
Serial.print(read_signature1, HEX);
ma non funziona, lo 0 esce sempre, il primo byte che è il produttore e per ATMEL è 1E mi esce come 01E.
read_signature1 contiene un dato che viene letto direttamente da un indirizzo del micro.

Ma così non funziona?

if (read_signature1 < 16) { Serial.print("0"); }

(16 è uguale a 0x10)
Poi non capisco: perché hai messo i "#" davanti all'if?

menniti:
Avevo pensato a:
Serial.print("SIGNATURE: ");
#if (read_signature1 < 0x10) //serve per mostrare lo 0 iniziale per valori <16 = 10
Serial.print("0");
#endif
Serial.print(read_signature1, HEX);
ma non funziona, lo 0 esce sempre, il primo byte che è il produttore e per ATMEL è 1E mi esce come 01E.
read_signature1 contiene un dato che viene letto direttamente da un indirizzo del micro.

Non ti funziona, ma non dovrebbe nemmeno compilarlo, perché gli "#" non ci devono essere e tantomeno ci deve essere la endif

Serial.print("SIGNATURE: ");
   if (read_signature1 < 0x10) Serial.print("0"); 
 
 Serial.print(read_signature1, HEX);