problema libreria

ho creato una libreria, quando la richiamo lo schetch mi dà quest'errore: error:
‘EEPROM_TCP_IP’ does not name a type

Da che dipende???

Ho provato a fare ricerche su internet e mi sembra che viene fuori quando ci sono variabili utilizzate ma non ancora dichiarate...

Boh non mi sembra che sia il mio caso

Allego i file della classe.

Quando poi nello scheck la richiamo scrivo questo:

#include <EEPROM_TCP_IP.h>
......
.....
EEPROM_TCP_IP eeprom_tcp_ip;

richiamo la funzione:

eeprom_tcp_ip.tcpSetup(ArrayTCPIP);

Ma mi genera quest'errore:

PIQ:30: error: ‘EEPROM_TCP_IP’ does not name a type
PIQ.cpp: In function ‘boolean riceve_handler(TinyWebServer&)’:
PIQ:87: error: ‘eeprom_tcp_ip’ was not declared in this scope

Ho provato a commentare le stringhe riguardanti lo skech lasciando solo l'include della libreria e cioè:

#include <EEPROM_TCP_IP.h>
...
...
//EEPROM_TCP_IP eeprom_tcp_ip;
....
....
//eeprom_tcp_ip.tcpSetup(ArrayTCPIP);

mi viene fuori i seguenti errori quindi penso che non trovi la libreria:

Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:38: error: ‘EEPROM_TCP_IP’ is not a class or namespace
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp: In function ‘void loadDefaultAdress()’:
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:40: error: ‘writeEEPROMOctet’ was not declared in this scope
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp: In function ‘void writeEEPROMOctet(int, int*)’:
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:54: error: ‘EEPROM’ was not declared in this scope
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp: At global scope:
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:60: error: ‘EEPROM_TCP_IP’ is not a class or namespace
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:137: error: ‘EEPROM_TCP_IP’ is not a class or namespace
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp: In function ‘void addressInitialize()’:
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:140: error: ‘EEPROM’ was not declared in this scope
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:146: error: ‘EEPROM’ was not declared in this scope
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp: At global scope:
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:153: error: ‘EEPROM_TCP_IP’ is not a class or namespace
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp: In function ‘void addressSet()’:
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:156: error: ‘EEPROM’ was not declared in this scope
Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.cpp:162: error: ‘EEPROM’ was not declared in this scope

edit: per favore includi il codice usando gli appositi tag altrimenti il post non è leggibile

EEPROM_TCP_IP.cpp (5.63 KB)

EEPROM_TCP_IP.h (307 Bytes)

keywords.txt (118 Bytes)

Sei sicuro di averla inserita nel posto giusto?
Pare dirti che non riconosce il tipo EEPROM_TCP_IP,, quindi come se non l'avesse caricata.
La libreria mettila in /Documenti/Arduino/libraries/nome_cartella, dove nome_cartella deve essere il nome della lib che generalmente è uguale al file .h, quindi EEPROM_TCP_IP

Si leo.....grazie per aver risposto.....quest'operazione l'ho eseguita correttamente.....ho seguito questo link come guida

Hai qualche altra idea???

Grazie mille

prima cosa: perché l'IDE di Arduino riconosca le nuove librerie devi chiuderlo e riaprirlo, l'hai fatto?

Janos:
prima cosa: perché l'IDE di Arduino riconosca le nuove librerie devi chiuderlo e riaprirlo, l'hai fatto?

L'ho provata anch'io e non funziona. Mi sfugge il motivo. Ad "occhio" pare tutto a posto, però dice sempre che EEPROM_TCP_IP non indica un tipo di dati.

Si ho provato a chiudere e riaprire arduino.....aiutatemi ragazzi!!!

Manca il costruttore, e anche il distruttore, se questo ultimo non ti serve C++ lo include di suo.

Anche se il costruttore dovrebbe mettercelo C++ almeno quello di default.

public:
     EEPROM_TCP_IPClass();
     void loadDefaultAdress();
     void tcpSetup(int array[]);
     void addressInitialize();
     void addressSet();
};

extern EEPROM_TCP_IPClass EEPROM_TCP_IP;
punta alla classe e non alla istanza.

Ti serve un oggetto solo di questa classe, cioè vuoi avere visibile questo oggetto ovunque? usarlo sempre lo stesso più volte?

Allora dovresti creare una classe singleton, solo che io so come realizzarla con i puntatori cioè lavorando con new, con arduino new non è la migliore cosa al mondo ma visto che questa istanza di classe sarà creata solo una volta e mai distrutta penso che convenga.

Cerca C++ singleton sulla rete, se non capisci come crearla e usarla fai un fischio.

Ciao.

Ma quando mai, non tenere conto di quanto scritto in precedenza.
Qui l'errore è in un file chiamato PIQ.cpp che non ha postato.

PIQ:30: error: ‘EEPROM_TCP_IP’ does not name a type /// Alla riga 30
PIQ.cpp: In function ‘boolean riceve_handler(TinyWebServer&)’: /// la funzione riceve_handler(prende un riferimento ad un tipo tinyWebServer e restituisce un boolean
PIQ:87: error: ‘eeprom_tcp_ip’ was not declared in this scope // poi eeprom_tcp_ip alla riga 87 del file PIQ e fuori scope.

Ariciao.

Prima di tutto so che i tutotia e altro parlano di libreria ma queste sono CLASSI, e infatti puoi cercare info o guide sulle classi C++ se le frasi di cui sopra non le capisci.

Passiamo al tuo problema: la classe l'hai chiamata "EEPROM_TCP_IPClass" e non "EEPROM_TCP_IP".. quest'ultimo è solo il nome del file, che centra per l'include.

Io consiglio di dare lo stesso nome a classe e file, come obbliga java, in modo da evitare questo tipo di errori. Quindi in:

EEPROM_TCP_IP.h

cambia:

class EEPROM_TCP_IPClass

in

class EEPROM_TCP_IP

oppure viceversa nel file .cpp tranne che per l'include, ovviamente.

quindi in modo più astratto i file .cpp sono così composti:

#include "nomefile.h"

tipo nomeClasse::nomeMetodo(parametri){
}

Poi sposta tutte le variabili cglobali dal .cpp al .h;

se sono nel .cpp sono globali e visibili anche dal resto del codice, e quindi possono creare collizioni con altre variabili globali in altre parti del codice; se invece le metti nel .h, più precisamente all'interno della class{}, queste variabili sono della classe e quindi NON visibili direttamente dall'esterno, ma facendo nomeClasse.nomeVariabile (se sono pubbliche, se no sono invisibili) il che è lo scopo delle classi.

Ragazzi sono stato dalle 6 fino ad adesso ha capire questa Sigleton e ho fatto prove per come utilizzarla..

Ho guardato questi link:

purtroppo non riesco a raggiungere il risultato....
non è per avere il codice pronto, ma qualcuno riesce a farmi questa classe singleton nel mio esempio in modo tale da capire bene??
Scusate ragazzi sono entrato da poco in arduino e in C

Grazie mille per il vostro aiuto!!!!!

Senti, io te l'ho trasformata in una classe da istanziare (togliendo extern ecc.... dal file .h).
Facendo così a me compila.

#include "EEPROM_TCP_IP.h"
EEPROM_TCP_IP myEEPROM;

void setup() {}
void loop() {}

EEPROM_TCP_IP.zip (2.15 KB)

uhhh quanto corri per essere agli inizi :slight_smile: (bene!)

tanto per cominciale, la correzzione di cui sopra funziona?

attento che il primo link è PHP e non C++

alloraammetto che non sapevo nemmeno dell'esistenza del Singleton, sarà che in java ci sono le classi statiche (anche se il Singleton ha il suo perchè anche in java).

dunque il singleton serve per essere certi di avere una sola istanza ed inizializzazione della classe.

per far ciò ti serve un puntatore statico alla classe

static GlobalClass *s_instance;

e una funzione (si dice metodo nel liguaggio ad oggetti mavabe), normalemnte chiamata getInstance(), che controlla, se il puntatore statico è nullo crea la classe e la inizializza, infine in ogni caso ritorna il puntatore.

Usere i Singleton in arduino non è consigliato perchè è facile finire la RAM, quindi piuttosto che un puntatore + allocazione meglio una variabile. Vedi HardwareSeriale per avere un'idea

sausim:
ho creato una libreria, quando la richiamo lo schetch mi dà quest'errore: error:
‘EEPROM_TCP_IP’ does not name a type
Da che dipende???

Brutalmente, l'errore segnalato è che usi una variabile davanti alla funzione-classe invece che il nome della classe.
Nel file .cpp hai messo

void EEPROM_TCP_IP::loadDefaultAdress()

invece che

void EEPROM_TCP_IPClass::loadDefaultAdress()

Grazie mille della risposta nid69ita lesto già mi aveva fatto notare quest'errore, ma grazie comunque del tuo intervento.

Ciao leo72, ho preso il tuo file zip con le tue correzioni ma mi dà il seguente errore:

Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.h:3:20: error: EEPROM.h: File o directory non esistente

A te non lo genera????

Grazie mille lesto adesso provo a ricercare HardwareSerial.

HardwareSerial lo trovi nella cartella di arduino, è quello che crea le classi Serial che usiamo tutti i giorni..

Insomma in quella classe di errori c'è ne a iosa.

Usere i Singleton in arduino non è consigliato perchè è facile finire la RAM, quindi piuttosto che un puntatore + allocazione meglio una variabile. Vedi HardwareSeriale per avere un'idea

In effetti Serial non dovrebbe essere istanziabile dall'utente, quindi ci sarà il costruttore privato. Comunque in merito all'esaurimento della memoria non vedo perchè debba accadere, il problema della frammentazione c'è quando allochi e liberi ripetutamente, mentre il singleton viene allocato solo la prima volta e tutte le altre a seguire getInstance si limita ritornare la precedente istanza. Non vedo controindicazioni, però c'è ci deveno essere buoni motivi per creare un sigleton, uno di questi è necessità di centralizzare un insieme di funzionalità.

Si java a le classi statiche e quindi non vedo la necessità di un sigleton, ma io di java non ci capisco nulla e quindi sicuramente avrà il suo perchè.

Se Serial è una classe preinstanziata e di questa non se ne può creare altra e questo è quello che cerchi puoi spulcire nel codice del core di Arduino al fine di apprendere come fare.

Ciao.

sausim:
Ciao leo72, ho preso il tuo file zip con le tue correzioni ma mi dà il seguente errore:

Documenti/arduino-1.0.1/libraries/EEPROM_TCP_IP/EEPROM_TCP_IP.h:3:20: error: EEPROM.h: File o directory non esistente

A te non lo genera????

Non me n'ero accorto perché avevo messo l'inclusione di EEPROM.h anche nello sketch. Poi non l'avevo copiato.
Effettivamente è vero, lo fa. Pensavo fosse un problema mio.

In effetti Serial non dovrebbe essere istanziabile dall'utente, quindi ci sarà il costruttore privato

Ma con solo il costruttore puoi istanziare più di una classe. Il sigleton invece serve proprio a fare in modo da poterne fare solo una. In pratica sopperisce alla classe statica

Comunque in merito all'esaurimento della memoria non vedo perchè debba accadere, il problema della frammentazione c'è quando allochi e liberi ripetutamente

no, se usi la prima volta un singleton all'interno di una funzione, o comunque dopo aver creato delle variabili la cui visibilità non è globale, hai creato frammentazione più o meno grave.

Non vedo controindicazioni, però c'è ci deveno essere buoni motivi per creare un sigleton, uno di questi è necessità di centralizzare un insieme di funzionalità.

è una questione di leggibilità. Arduino non usa i Signleton, si limita a inizializzare al posto tuo delle variabili di tipo classe globali (a fine del .cpp), proprio per evitare al minimo la frammentazione.

Si java a le classi statiche e quindi non vedo la necessità di un sigleton, ma io di java non ci capisco nulla e quindi sicuramente avrà il suo perchè.

in java una classe statica non può estendere o implementare una classe non statica. Con il Singleton aggiri il problema :slight_smile:

Se Serial è una classe preinstanziata e di questa non se ne può creare altra e questo è quello che cerchi puoi spulcire nel codice del core di Arduino al fine di apprendere come fare.

Invece si può fare, e faresti un sacco di casino (le due classi cercherebbero di accedere all'HW litigando tra loro, motivo per cui esitono i SO per i sistemi complessi)...
Solo che la classe si chiama HardwareSerial, ed ha un costruttore molto complesso, e quindi è improbbaile che un principiante riesca a farlo.
Includo il famoso codice, si nota bene come in base ai rgistri capisce la piattafroma target e quindi il numero di Serial da creare.
E una recente modifica che si usa al posto del nome del processore; atmel ha avuto la pensata di usare sempre gli stessi nomi di registri (salvo rarissimi casi), e quindi senza modifiche questo codice funziona anche su chip atmel che devono ancora essere creati o testati ma che seguono questo schema..

// Preinstantiate Objects //////////////////////////////////////////////////////

#if defined(UBRRH) && defined(UBRRL)
  HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR, RXEN, TXEN, RXCIE, UDRIE, U2X);
#elif defined(UBRR0H) && defined(UBRR0L)
  HardwareSerial Serial(&rx_buffer, &tx_buffer, &UBRR0H, &UBRR0L, &UCSR0A, &UCSR0B, &UCSR0C, &UDR0, RXEN0, TXEN0, RXCIE0, UDRIE0, U2X0);
#elif defined(USBCON)
  // do nothing - Serial object and buffers are initialized in CDC code
#else
  #error no serial port defined  (port 0)
#endif

#if defined(UBRR1H)
  HardwareSerial Serial1(&rx_buffer1, &tx_buffer1, &UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1, RXEN1, TXEN1, RXCIE1, UDRIE1, U2X1);
#endif
#if defined(UBRR2H)
  HardwareSerial Serial2(&rx_buffer2, &tx_buffer2, &UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2, RXEN2, TXEN2, RXCIE2, UDRIE2, U2X2);
#endif
#if defined(UBRR3H)
  HardwareSerial Serial3(&rx_buffer3, &tx_buffer3, &UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3, RXEN3, TXEN3, RXCIE3, UDRIE3, U2X3);
#endif

lesto mi aiuti a sviluppare la classe come hai in mente tu???
sono ancora lontano da te, però penso che sviluppato nel mio esempio avrò un modello da prendere spunto per la prox e sicuramente mi aiuta a capire!!

Grazie mille

Quote
Comunque in merito all'esaurimento della memoria non vedo perchè debba accadere, il problema della frammentazione c'è quando allochi e liberi ripetutamente
no, se usi la prima volta un singleton all'interno di una funzione, o comunque dopo aver creato delle variabili la cui visibilità non è globale, hai creato frammentazione più o meno grave

Qui non sono daccordo, se crei un puntatore così, questo è locale e si trova nello stack.
Qualunque blocco.
{
MyClass *myClass = MyClass::getIstance(); // myClasse è un puntatore sullo stack che cessa di esistere fuori dal blocco
}

Un puntatore locale messo sullo stack, che punta ad un oggetto messo nello heap, a me non mi pare una cosa
malvaggia, sembra un uso efficiente, specie se la prima istanza la crei nel setup() sei apposto.

Certo la memoria impegnata lo sarà sempre per tutta la durata del programma, ma accade la stessa cosa con un
variabile globale o statica.

Comunque mi sembra una cosa da provare ma costringe l'utente a lavorare con l'operatore -> anziché "." e non è cosa
buona per il principiante.

Ciao.

hai ragione, non crea garbage perchè finisce nell'heap, qu8ndi l'unico problema che può nascere è la mancanza di RAM ma questo è un altro paio di maniche