Scrivere una libreria per Arduino!

Salve a tutti, sto cercando di scrivere una libreria per arduino per controllare il Wii Nunchuck. Premetto che il C++ per me è un buco nero, questi giorni sto tentando di capirci qualcosa. Avrei qualche domanda da farvi: nel mio file .h ho dichiarato come public alcune variabili, in modo che esse siano accessibili a tutte le funzioni che io andrò ad utilizzare. Ma io vorrei che queste variabili fossero utilizzabili anche nello sketch, ad esempio per stamparle sul monitor seriale con Serial.print(…); . Ma quando nello sketch le utilizzo, ho un errore di compilazione : “was not declared in this scope”. Ovviamente nello sketch ho fatto #include<nomelibreria.h>. Inoltre nel file .h ho dichiarato le mie funzioni come public e nel file .cpp le ho implementate con tutto ciò che devono fare. Per visualizzare i dati del nunchuck, nel file .cpp ho un metodo che stampa tutti i valori tramite Serial.print, ma non stampa nulla sul monitor seriale (i file X.h e X.cpp li ho messi in una cartella X che si trova nella cartella libraries di Arduino). E’ come se lo sketch e la libreria “non si parlassero”; dichiaro delle variabili public nel file .h e lo sketch non le trova, uso il Serial.print nei metodi della libreria e non lo fa!! Qualcuno può darmi qualche consiglio? Grazie mille in anticipo! :slight_smile:

Alle variabili di una “classe” si accede attraverso dei “metodi” !!!

Quindi … se hai le variabili “pippo” e “pluto” … scriverai due metodi “tuaClasse::getPippo()” e “tuaClasse::getPluto()” che ti ritornano il valore di dette variabili.

Questo è il modo corretto … poi … porcherie se ne possono sempre fare :wink:

Guglielmo

Grazie mille per la risposta! Quindi se ho capito bene: nel mio file .h dichiaro (per esempio) Public una variabile int Pippo; se voglio sapere il suo valore devo fare un metodo: int Classe::getPippo(); il quale mi restituirà il valore della variabile. Ma se questo valore lo voglio usare nel mio sketch perché voglio fare Serial.print(Pippo);??

Intanto crei un’istanza della classe, poi accedi al metodo getPippo dell’oggetto creato:

NomeClasse miaClasse;
...
Serial.print(miaClasse.getPippo());

Grazie Leo72! Questo concetto del creare un'istanza non mi è chiaro. A cosa serve? Perché devo creare un'istanza e quando? Scusa l'ignoranza e tutte queste domande, ma devo imparare :sweat_smile:

L'istanza è una copia dell'oggetto originale, che eredita tutti i metodi dell'oggetto da cui deriva. Esempi nel core di Arduino sono ad esempio le lib per accedere all'I2C, la lib Wire, o per leggere la SD. L'instanziamento permette di creare più copie dello stesso oggetto. le classi permettono di tenere il codice chiuso all'utente in modo che possa accedere solo ai metodi pubblici, cioè quelli visibili da tutti.

Ok grazie della spiegazione! Un'altra domanda: io sono nella IDE di arduino, includo la libreria che ho creato e voglio stampare sul monitor seriale il valore di una variabile che ho dichiarato come public nel file .h della mia libreria. Perché mi dice che quella variabile non è stata dichiarata?

Senza il codice non si capisce nulla. :D

P.S. una classe è solo una dichiarazione, come ad esempio "long" ; sai che è un tipo di variabile numerica ma se non dichiari una variabile di tipo long, in memoria non hai creato nulla. La classe è come il tipo di una variabile, l'istanza è la variabile (oggetto) vero e proprio, di tipo classe. Esempio:

long MyLong=0;
class MyClasse
{ ...
}
MyClass Obj1;

MyLong è una variabile di tipo long Obj1 è una istanza (oggetto) di tipo MyClass

Devi documentarti sul paradigma OO (Object Oriented) o anche genericamente detto OOP (P sta per Programming)

Un oggetto per definizioni esiste ed è istanza di un qualcosa, nel mondo reale l’automobile è oggetto istanza di classe CarFactory().

Il programmatore che vuole creare istanza di classe CarFactory non ha necessità di conosce come funziona internamente CarFactory. I membri di CarFactory sono interni e rappresentano le proprietà. Alcune proprietà potrebbero essere, Colore, Numero di sportelli, Freni Anteriori a Disco, Freni Posteriori a tamburo ecc

Io voglio la mia car e scrivo:

CarFactory ferrariDaytona(Ferrari, Daytona, Red);

ferrariDaytona è instanza oggetto di classe CarFactory, le proprietà specificate: Ferrari, Daytona, Red sono proprietà dell’oggetto e io adesso non posso cambiarle senza che l’oggetto se ne accorge, per questo motivo
le proprietà si modificano attraverso i membri funzione detti anche metodi.

ferrariDaytona.setColor(Yellow);

Ho cambiato colore all’oggetto ferrariDaytona, se la proprietà colore fosse publica potrei scrivere:

ferrariDaytona.colore = Yellow;

Ma in questo modo l’oggetto non potrebbe agire internamente per modificare il colore.

Se sei tu che devi scrivere la classe CarFactory allora devi fare in modo che il programmatore che crea istanza
oggetto lo possa usare senza conoscere come è fatta CarFactory, fornirai quindi i metodi necessari per modificare le proprietà interne, la modifica di alcune proprietà coinvolge altre proprietà e la chiamata al metodo di permette di gestire le proprietà coinvolte, in modo che l’oggetto sia sempre consistente e controllato. I colori disponibili se tu che li decidi e varieranno da modello a modella di auto. CarFactory internamente userà altre classi e altre useranno altre classe e così via fino ad arrivare alla macchina di stampaggio lamiere.

Si tratta di un esempio che non può spiegarti tutto, non puoi avere ora le idee chiare. Spero ti possa essere di aiuto e non ti confonda di più le idee. Comunque consolati che a questo livello di apprendimento è normale avere le idee confuse.

PS: Se non fosse chiaro, le variabili membro non sono mai pubbliche ma sempre private. I metodi che servono al
programmatore che creerà istanza devono essere pubblici, mentre i metodi usati internamente sono privati o protetti (protected).

Ciao.

Grazie a tutti, mi state aiutando molto e piano piano spero di riuscire a capire, per ora ho le idee un po’ confuse. Ora vi metto dei codici che, con il vostro aiuto, spero possano aiutarmi a capire. Ho allegato il file .h , .cpp e .ino! Ovviamente i file .h e .cpp li ho messi in una cartella chiamata “X” all’interno della cartella libraries di arduino. La domanda è: perché non posso utilizzare le variabili che ho dichiarato nel file .h nel mio sketch? (ci saranno quintali di errori, abbiate pazienza :sweat_smile: )
Grazie ancora!

.h (8.24 KB)

.cpp (7.63 KB)

.ino (10.8 KB)

buster009: ... La domanda è: perché non posso utilizzare le variabili che ho dichiarato nel file .h nel mio sketch?

Quindi, tutto quello che abbiamo detto ... non è servito a nulla ???

Guglielmo

Le variabili k e y sono "dentro" all'oggetto X

Puoi usarle solo cosi:

Serial.printl(X.k);

Quindi classe X che dentro ha k e y (ma non esistono ancora). Se tu dichiari due oggetti di tipo X (non dargli lo stesso nome!!!) all'inizio del programma, prima di setup()

X obj1();
X obj2();

Allora esistono "dentro" a obj1 e obj2 due coppie di variabili k e y. Capisci che non puoi riferirti a k o y perchè sarebbe ambiguo Puoi invece riferirti (si usa il punto) a obj1.k obj1.y e poi a obj2.k e obj2.y

Spero che questo possa chiarirti le spiegazioni precedenti, che forse ti hanno un pò confuso. Potrai anche chiamare la funzione ok() per aumentare i valori di k e y ma le coppie contenute nel obj giusto.

obj1.ok();

aumenta le k e y contenute in obj1. Quelle di obj rimangono a 0

Ovviamente i file .h e .cpp li ho messi in una cartella chiamata "X" all'interno della cartella libraries di arduino. La domanda è: perché non posso utilizzare le variabili che ho dichiarato nel file .h nel mio sketch? (ci saranno quintali di errori, abbiate pazienza smiley-sweat )

Il motivo è che io mi impegno al massimo per esprimermi al meglio ma evidentemente ciò non è sufficiente, questo è il vero motivo.

Ciao.

Quello che avete detto serve, ma come ho già detto per me queste cose sono un buco nero, non le ho mai fatte! E’ la prima volta che ci provo! E non funziona neanche se faccio così:

Serial.printl(X.k);

Dato che così non ne esco, vi metto i codici, potreste modificarli per far sì che funzionino per favore?

#ifndef X_h
#define X_h

#include "Arduino.h"

class X
{
  public:
   void start();
    void ok();
	int k;
	int y;
};

#endif
#include "Arduino.h"
#include "X.h"

X::start()
{
k=0;
y=0;
}

void X::ok()
{
 k++;
 y++;
}
#include<X.h>

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

void loop(){
Serial.println(X.k);
Serial.println(X.y);
void ok();
delay(500);
}
#include <X.h>

X obj1;

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

void loop() {
  Serial.println(obj1.k);
  Serial.println(obj1.y);
  obj1.ok();
  delay(500);
}

X NON ESISTE. E’ una classe, come long è un tipo di dato, non è una variabile.
Puoi nel codice fare questo ? (ovviamente no)

long=10;

obj1 ora è una variabile (oggetto) di classe X

Grazie mille!! Con esempi pratici capisco molto meglio!! Quindi creando una classe X che ha al suo interno dei metodi e delle variabili, per utilizzare questi metodi e queste variabili devo comunque creare un oggetto della classe X!! Giusto?

YES !!! :D :D

Ancora meglio dire: "devo comunque creare [u]almeno[/u] un oggetto della classe X"

Perfettooo!!! XD XD E questo oggetto può accedere a tutto ciò che nella classe è dichiarato sia come public sia come private?

Non ho capito la domanda.
Un oggetto dentro alle sue funzioni può accedere alle proprie variabili private o public.
Dall’esterno puoi solo accedere alle variabili public (ma usando la sintassi oggetto.variabileinterna )
Ricorda che come public quelle variabili possono anche essere modificate senza nessun vincolo:

obj1.k=-10;

Io creo un oggetto della classe X: X obj1; Questa è la mia classe:

#ifndef X_h
#define X_h

#include "Arduino.h"

class X
{
  public:
       void ok();
    void start();
    int a;
    int b;
        int c;
    int d;
   private:
        int z;
        int v;
};

#endif

Io facendo obj1.variabile oppure obj1.metodo, posso utilizzarli tutti? Sia quelli private sia quelli public?