stampare una variabile con telnet

salve devo stampare tramite telnet una variabile intera ecco il codice:

#include <SPI.h>

#include <Client.h>
#include <Ethernet.h>
#include <Server.h>
#include <Udp.h>





//Arduino uses digital pins 10, 11, 12, and 13 (SPI) to communicate with the W5100 on the ethernet shield
int ledPIN = 9;
int PIN_TEMP=5; //Assegniamo alla variabile il pin di ingresso analogico scelto
int temp; //Dichiariamo la variabile che conterrà il valore della temperatura

byte mac[] = {
 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//byte ip[] = { 10, 0, 0, 4};
byte ip[] = { 192,168,1,15 };
byte gateway[] = {192,168,1,1};
byte subnet[] = {255,255,255,0};

Server server(77);

void setup()
{
 // setta come output
 pinMode(ledPIN, OUTPUT);
 // initialize the ethernet device
 Ethernet.begin(mac, ip, gateway, subnet);
 // start listening for clients
 server.begin();
 Serial.begin(9600);
 Serial.println("Accetto");
 server.write('inizio!!');
 blink (5);
}

void loop()
{
 
 Client client = server.available();
 // il client si collega con il comando:
 // telnet 192.168.1.15 77
 if (client) {
   int rcv = client.read();
   // echo vs il client:
   server.write(rcv);
   // Serial.print(rcv);

   // comandi accettati:
   // 1=acceso, 0=spento, B=blink
   switch (rcv) {
   case '1':
  server.write("scelta1");
    digitalWrite(ledPIN, HIGH);
     Serial.println("CMD 1 received");
     break;
   case '0':
     server.write("scelta2");
     digitalWrite(ledPIN, LOW);
     Serial.println("CMD 0 received");
     break;
   case 'B':
     server.write("sceltab");
     blink(2);
     Serial.println("CMD B received");
     break;
     case 'T':
     //server.write("sceltab");
     Serial.println("temperatura richiesta");
     temp= analogRead(PIN_TEMP)*0.5; //Assegniamo alla variabile temp il valore restituito dalle lettura del pin 5
     server.write(temp);
     //delay(100); //Aspettiamo 100 mS prima di leggere un nuovo valore
     
     break;
   }
 }
}


void blink (int times)
{
 for (int cnt=times; cnt>0; cnt--)
 {
   digitalWrite(ledPIN, HIGH);   // set the LED on
   delay(200);
   digitalWrite(ledPIN, LOW);    // set the LED off
   delay(200);
 }
}

il problema è qui:

 case 'T':
     
     Serial.println("temperatura richiesta");
     temp= analogRead(PIN_TEMP)*0.5; //Assegniamo alla variabile temp il valore restituito dalle lettura del pin 5
     server.write(temp);
     break;

non riesco a leggere il valore è uno scarabocchio come lo converto a stringa?
poi come faccio...

server.write("sceltab");

a fare andare a capo la risposta?
server.writeln da errore...
grazie in anticipo!

allora, credo che l'arduino stampi il carattere corrispondente al valore temp nella tabella ascii...
prova con un Server.write(temp+'0'); (ovvero, a temp sommi il valore del carattere '0'. però funziona se la lettura è un numero solo...
pre più cifre puoi provare

char risposta[10];
sprintf(risposta, "%d", temp);

oppure

int temp2=temp;
do{
   int cifra=temp2%10; //prendo l'ultima cifra di temp2
   temp2/=10; //tolgo a temp2 l'ultima cifra (che ho estratto in cifra)
   Server.write(cifra+'0'); //stampo la cifra
}while(temp2>=0); //continua finchè ci sono numeri. uso un do{}while(); perchè se temp è 0 sono sicuro di stampare '0'

per andare a capo è un pò un casino:
in windows \r\n
in linux \n
in mac \n\r
quindi dire i che il modo in assoluto migliore è \r\n\r ;D
benvenuto nell'informatica :slight_smile:

edit: studiati la differenza tra int e char, le varie conversioni e cos'è e come si usa la tabella ascii. Questa volta la pappa è pronta :stuck_out_tongue:

grazie per il benvenuto! ;D
ma arduino non implementa dei parser? quella delle 0 l'ho gia provata devo provare la seconda... ma scusa \r\n\r dove vanno?

sul secondo esempio va tutto in loop...

ho provato a scrivere questo...
server.print(char(temp));
ma non va...
con la seriale è molto più semplice:
Serial.println(temp,DEC);
e viene stampato in modo corretto!
poi chi ha idea di come passare un parametro ad un metodo tramite telnet?

Adesso c'è anche l'oggetto String:

:wink:

interessante!
ho scritto questo:

String valore = String (temp);  //temp è int..
server.write(valore);

da errore sul write forse le librerie ethernet non riconoscono ancora le stringhe?

@braibooster: per favore, non complichiamo la vita con gli oggetti se ancora non sa fare un listato sequenziale... IMHO :-X

sul secondo esempio va tutto in loop...

quindi il BUG nel secondo esempio è nella condizione del while... infatti dvrebbe essere:

while(temp2>0);

perché quando avremo terminato di stampare la stringa temp2 sarà == 0
Attento: questo codice NON gestisce i numeri negativi... è facile da fare, quindi in caso ti serva te lo lascio come compito casa ;D

server.print(char(temp));

già che la funzione ritorni char (quindi UNA sola lettera) dovrebbe metterti in guardia...come fai a scrivere 10 con una sola lettera?

poi chi ha idea di come passare un parametro ad un metodo tramite telnet?

se intendi che il parametro dovrà essere eseguito sul pc inviato dall'arduino o viceversa, devi implementare un tuo protocollo, tipo "numeroFunzioneparametro1parametro2."
a questo punto il pc/arduino "smonta"il messaggio, con uno switch sceglie la funzione da eseguire e gli passa i parametri...
Non è difficile, è tutto gioco di char :wink:

qui:

Server.write(cifra+'0'); //stampo la cifra

concateno 0 alla destra? non mi è chiaro devo capirlo perche devo invertire il valore in uscita..
per i numeri negativi so che in ascii il simbolo "-" è in decimale 45...mi ci sono avvicinato? ::slight_smile:

Code:

server.print(char(temp));

già che la funzione ritorni char (quindi UNA sola lettera) dovrebbe metterti in guardia...come fai a scrivere 10 con una sola lettera?

ero convinto di lavorare con le stringhe!
poi lo trovato scritto:
char myStr[] = "this is a test";
ogni elemento del vettore contiene una lettera giusto?

concateno 0 alla destra? non mi è chiaro devo capirlo perche devo invertire il valore in uscita..

No, al valore sommi il valore del carattere '0' in ascii...
il valore di '0' in ascii è 48, se cifra vale 0 viene 0+48 =48(carattere '0' appunto), se cifra vale 1 viene 1+48=49(carattere '1') e così via fino al 9, infatti se ci hai fatto caso sono in fila nella tabella ascii...
Con lo stesso principio, se hai una lettera minuscola, fai carattere-('a'-'A') e la trasformi maiuscola(al posto di 'a'-'A' potevi usare 32, ovvero la distanza tra una lettera maiuscola e la sua corrispondente minuscola, esattamente come al posto di '0' puoi usare 48... però con 'a' e '0' il codice è molto più comprensibile...

per i numeri negativi so che in ascii il simbolo "-" è in decimale 45...mi ci sono avvicinato?

No, non puoi estrarre il meno come se fosse una cifra. Come accennato prima non ti serve sapere il valore decimale, la tabella ascii serve per capire come funzionano i trucchetti che ti ho spiegato sopra.
In pratica prima che vengano stampate le cifre dovrai verificare se il numerò è negativo, in caso lo sia stampare '-'. Però essendo poi il tuo numero < 0 usciresti subito dal while, quindi ne prendi il valore assoluto (funzione abs() o moltiplichi i numeri negativi per -1), tanto il meno ce l'hai già e le cifre non cambiano.

ero convinto di lavorare con le stringhe!
poi lo trovato scritto:
char myStr[] = "this is a test";
ogni elemento del vettore contiene una lettera giusto?

Esatto. "Piccolo" particolare di cui non abbiamo ancora discusso... come fai a sapere che una stringa è finita? esiste un carattere speciale lo '\0'(sembrano 2 caratteri ma in realtà lo \ vuol dire:occhio, il prossimo è il corrispondente di un carattere speciale, lo 0 corrisponde a "fine stringa", lo '\r' al "Torna a inizio riga", lo '\n' al "vai a capo", lo '\' stampa \ ;))
In questo caso lo '\0' viene aggiunto in automatico a fine array (quindi l'array sarà lungo stringa+1)... ma nell'esempio sopra manca! Quindi non sapresti dove inizia una cifra e dove finisce, a meno che non trovi un meno.
esempio, leggi 256 poi 541 poi 10 poi -345... senza '\0' leggeresti:
25654110-345(umm un numero con dentro un meno, verrebbe un bel macello, dipende come fai a leggerlo...ben che ti vada otterresti 2 numeri, 25654110 e -345)
con lo '\0' dividi con esattezza i numeri:
256\0451\0-345\0

Secondo mè vale la pena di imparare ad usare String, visto che c'è..
IMHO sarebbe più semplice :slight_smile:

preso tutti i tuoi consigli ho scritto un metodo..

void StampaInt (int val)
{
    int val2=val;
    char contrario[sizeof(val2)];//vettore che uso per ribaltare le cifre
    int cont = sizeof(val2); 
   
do{
   int cifra=val2%10; //prendo l'ultima cifra di temp2
   val2/=10; //tolgo a temp2 l'ultima cifra (che ho estratto in cifra)
   if (val2<0){//se il numero è negativo stampo il carattere"-"
   server.write('-'); //stampo il carattere negativo
   val2=val2*-1;//lo porto in valore positivo per evitare di bloccare il ciclo do
   }  
   cont = cont--;
   //server.write(cifra+'0'); //stampo la cifra
   contrario[cont] = cifra+'0';//tolto il carattere vai a capo..
}while(val2>0); //continua finchè ci sono numeri. uso un do{}while(); perchè se temp è 0 sono sicuro di stampare '0'
 
 for (int c=0; c<sizeof(contrario); c++) //ora stampo tutti i caratteri in formato corretto
 {
    server.write(contrario[c]); //stampo la cifra
 }  
    server.write('\n'); //stampo vai a capo
}

per i numeri positivi ok per i numeri negativi ovvero temperature sotto lo 0... (spero mai di doverle misurare! ;D)
scrivendo cosi:

 int val2=val*-1;

mi stampa come carattere ,+2 invece di -25 forse non ho considerato qualche cosa?

sfruttando la particolarità di arduino dei caratteri speciali \n \r ecc...

non posso passargli una stringa cosi:

parametro\rvalore1\rvalore2

prendo questo char lo metto nel vettore e ho già i 3 caratteri separati...idea sbagliata?

:-[

allora la funzione stampaInt funziona bene(per i numeri positivi ovvio)? do per scontato di sì.
Per i numeri negativi il tuo errore è semplice: prendi il numero ad esempio -59 e fai così: su un foglio di carta segui il tuo programma passo passo.
Ogni volta che crei una variabile, scrivi il suo nome in una riga vuota, affianco segni i valori che assume. Ti accorgerai subito del tuo errore! Piano piano questa operazione ti verrà naturale addirittura mentre pensi al codice...

sfruttando la particolarità di arduino dei caratteri speciali \n \r ecc...

non posso passargli una stringa cosi:

Certo che puoi! ti consiglio però di usare il carattere speciale "\t" che equivale al TAB... questo perché sarà più facile debuggare il codice, \r non si vede, invece il tab è uno spazio e spesso bello lungo :slight_smile:

si ma con i numeri negativi mi esce una virgola e un + poi il numero non capisco questa cosa..per quanto riguarda il carattere speciale \t ho provato a scrivere cosi: (usando /r...)
char prova[] = "comando\rvalore1\rvalore2"
però devo sempre scandire tutta la variabile e dividerla per il carattere speciale...

ok, per scandire e dividere in automatico ogni variabile usa \0...

si ma con i numeri negativi mi esce una virgola e un + poi il numero non capisco questa cosa

l'unica è fare debug del codice come ti ho spiegato... l'errore è semplice da individuare