Salve a tutti, in questi giorni ho tentato di creare una libreria per arduino che non fa' altro che dare dei valori a dei sensori fittizi, e avente un metodo che crea una stringa con dentro tutti i valori.. e qui il problema! Perché se uso questo metodo in un loop non fa assolutamente nulla.
codice header "Sensori.h":
#ifndef SENSORI_H_
#define SENSORI_H_
#include <Arduino.h>
class Sensori {
//sensori da leggere
float light;
int humidity;
int pressure;
float temperature;
float altitude;
bool rain;
static int cont;
public:
Sensori();
static int getCont();
String getSensori();
String getTemperatureS();
String getAltitudeS();
String getLightS();
};
#endif /* SENSORI_H_ */
questo il codice vero e proprio "Sensori.cpp":
#include "Sensori.h"
#include <Arduino.h>
int Sensori::cont = 0;
Sensori::Sensori() {
temperature=20+cont;
light=12+cont;
humidity=3+cont;
pressure=1000+cont;
altitude=120+cont;
rain= (cont%2)==0 ? true : false;
cont++;
}
String Sensori::getTemperatureS(){
char tmp[5];
return dtostrf(temperature, 2, 1, tmp);
}
String Sensori::getAltitudeS(){
char tmp[5];
return dtostrf(altitude, 2, 1, tmp);
}
String Sensori::getLightS(){
char tmp[5];
return dtostrf(light, 2, 1, tmp);
}
String Sensori::getSensori(){
String s = "temp=";
s+=getTemperatureS();
s+=" lum=";
s+=getLightS();
s+=" hum=";
s+=humidity;
s+=" pres=";
s+=pressure;
s+=" alt=";
s+=getAltitudeS();
s+=" rain=";
s+=rain;
return s;
}
int Sensori::getCont(){
return cont;
}
ed infine lo sketch per arduino:
#include "Sensori.h"
void setup()
{
Serial.begin(9600); //stabilisco una connessione con il pc
Serial.println("Inizializzazione");
delay(1000);
}
void loop()
{
Sensori obj;
Serial.println(obj.getSensori());
delay(3000);
}
il risultato è solo una riga di monitor con scritto "inizializzazione" e poi il nulla più totale..
avete dei suggerimenti per creare una stringa con tutti i valori nella libreria?
Primo, hai dichiarato Sensori obj; nella loop()
La loop() viene eseguita di continuo. Essendo l'oggetto dichiarato in quella funzione, ogni volta che la loop() viene eseguita l'oggetto nasce e muore.
Secondo, usi dtostr() e fai dei return con funzioni il cui valore di ritorno li dichiari String. dtostr() e String non c'entrano nulla l'una con l'altra. dtostr() ritorna un char* e non un String (che è un oggetto della classe String, molto pesante per una MCU con soli 2Kb di SRAM)
http://www.atmel.no/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1ga060c998e77fb5fc0d3168b3ce8771d42.html
nid69ita:
Primo, hai dichiarato Sensori obj; nella loop()
La loop() viene eseguita di continuo. Essendo l'oggetto dichiarato in quella funzione, ogni volta che la loop() viene eseguita l'oggetto nasce e muore.
Secondo, usi dtostr() e fai dei return con funzioni il cui valore di ritorno li dichiari String. dtostr() e String non c'entrano nulla l'una con l'altra. dtostr() ritorna un char* e non un String (che è un oggetto della classe String, molto pesante per una MCU con soli 2Kb di SRAM)
http://www.atmel.no/webdoc/AVRLibcReferenceManual/group__avr__stdlib_1ga060c998e77fb5fc0d3168b3ce8771d42.html
so' perfettamente che ho creato l'oggetto nel loop, è proprio quello che volevo fare: se vedi gli attributi della classe ne ho messo uno statico che aumenta ogni volta che viene creato un oggetto di quella classe, e lo sommo agli altri attributi facendoli cambiare ogni volta che il loop viene eseguito, un po' come una lettura di sensori, che voglio infatti simulare (perchè ora non li ho disponibili).
Come secondo punto hai ragione e ne ero consapevole, dici che il problema si risolve cambiando il tipo del metodo in char*? (ora cmq provo e ti dico)
edit: ok ho cambiato il tipo di ritorno dei 3 metodi di conversione in char* ed ora il risultato è:
Inizializzazione
temp=L ÛÜ lum=L ÛÜ hum=3 pres=1000 alt=L û rain=1
e si impianta qui senza fare altri loop.. idee?
Ripeto, hai solo 2Kb di SRAM, stai usando MALE i puntatori e per quello che vorresti fare dovresti usare l'allocazione dinamica di stringhe (array di char e NON String object). Ma ha SOLO 2Kb di SRAM.
Quando fai questo:
char* Sensori::getAltitudeS()
{ char tmp[5];
return dtostrf(altitude, 2, 1, tmp);
}
Stai restituendo il char* restituito dalla dtostr() ovvero il puntatore a tmp, che essendo locale dopo la return viene distrutto.
Dovresti lasciare che le varie getxxx() ad esempio getTemperatureS() ritornino il valore numerico (non stringa).
Poi eventualmente fai una funzione che da quella frase lunga ma non con return ma modifica un parametro char[] passato dall'esterno, ovvero un buffer stampabile.
#ifndef SENSORI_H_
#define SENSORI_H_
#include <Arduino.h>
class Sensori
{ //sensori da leggere
float light;
float temperature;
float altitude;
//int humidity; int pressure; bool rain;
static int cont;
public:
Sensori();
void getSensori(char buf[],byte bufsize);
float getTemperature() { return temperature; }
float getAltitude() { return altitude; }
float getLight() { return light; }
int getCont() { return cont; }
};
#endif /* SENSORI_H_ */
int Sensori::cont = 0;
Sensori::Sensori()
{ temperature=20+cont;
light=12+cont;
//humidity=3+cont; pressure=1000+cont; rain= (cont%2)==0 ? true : false;
altitude=120+cont;
cont++;
}
void Sensori::getSensori(char buf[],byte bufsize)
{ char tmpt[5],tmpa[5],tmpl[5];
dtostrf(altitude , 2, 1, tmpa);
dtostrf(temperature, 2, 1, tmpt);
dtostrf(light , 2, 1, tmpl);
snprintf(buf,bufsize,"temp=%s lum=%s alt=%s",tmpt,tmpl,tmpa);
}
void setup()
{ delay(1000);
Serial.begin(9600); //stabilisco una connessione con il pc
Serial.println("Inizializzazione");
}
void loop()
{ char buffer[40];
Sensori obj;
obj.getSensori(buffer,sizeof(buffer));
Serial.println(buffer);
delay(3000);
}
Inizializzazione
temp=20.0 lum=12.0 alt=120.012.0
temp=21.0 lum=13.0 alt=121.013.0
temp=22.0 lum=14.0 alt=122.014.0
temp=23.0 lum=15.0 alt=123.015.0
temp=24.0 lum=16.0 alt=124.016.0
Una classe può essere resa printable grazie alla classe Printable del core di Arduino, un esempio è la classe IPAddress() della libreria Ethernet.
Un esempio sciocco:
#include <Printable.h>
class IGOR : public Printable {
public:
IGOR();
virtual size_t printTo(Print& p) const; // necessary to be "Printable"
private:
int num;
};
IGOR::IGOR() { num=123; }
size_t IGOR::printTo(Print& p) const
{ size_t n = 0;
char buf[10];
snprintf(buf,10,"%05d",num);
for (int i =0; i < 5; i++)
{ n += p.print(buf[i]);
}
return n;
}
IGOR objIgor;
void setup()
{ delay(1000);
Serial.begin(9600);
Serial.println("go");
Serial.println(objIgor);
}
void loop() {}
La tua classe ora Printable:
#ifndef SENSORI_H_
#define SENSORI_H_
#include <Arduino.h>
#include <Printable.h>
class Sensori : public Printable
{ //sensori da leggere
float light;
float temperature;
float altitude;
//int humidity; int pressure; bool rain;
static int cont;
public:
Sensori();
float getTemperature() { return temperature; }
float getAltitude() { return altitude; }
float getLight() { return light; }
int getCont() { return cont; }
virtual size_t printTo(Print& p) const;
};
#endif /* SENSORI_H_ */
int Sensori::cont = 0;
Sensori::Sensori()
{ temperature=20+cont;
light=12+cont;
//humidity=3+cont; pressure=1000+cont; rain= (cont%2)==0 ? true : false;
altitude=120+cont;
cont++;
}
size_t Sensori::printTo(Print& p) const
{ size_t n = 0;
byte nc;
char buf[40],tmpt[5],tmpa[5],tmpl[5];
dtostrf(altitude , 2, 1, tmpa);
dtostrf(temperature, 2, 1, tmpt);
dtostrf(light , 2, 1, tmpl);
nc=snprintf(buf,sizeof(buf),"temp=%s lum=%s alt=%s",tmpt,tmpl,tmpa);
for (int i =0; i < nc; i++)
{ n += p.print(buf[i]);
}
return n;
}
void setup()
{ delay(1000);
Serial.begin(9600); //stabilisco una connessione con il pc
Serial.println("Inizializzazione");
}
void loop()
{ Sensori obj;
Serial.println(obj);
delay(3000);
}
Grazie mille! con i buffer mi hai aperto un mondo! 
ora la mia classe funziona a meraviglia 