Go Down

Topic: Naam van mijn functie niet goed?? foutmelding op verwijzing (Read 463 times) previous topic - next topic

FTMZ

Hallo mensen,

Ik heb in mijn programma een verwijzing naar een functie staan, waar ik data laat wegschijven naar mijn externe EEPROM.
 writeEEPROM (eeprom, EPMaddress, 0x90);  

En dan even verderop:
VOID writeEEPROM {doe wat}

Om een voor mij onduidelijke reden, krijg ik de foutmelding dat "writeEEPROM" "not declared in this scope" is.
Wat kan daar de oorzaak van zijn?
Ik heb al vanalles geprobeerd. Ik heb een paar werkende voorbeeld sketches erbij gepakt ter vergelijking, maar ik weet niet waar ik fout ga hierin.

Iemand suggesties?


Koepel

Kun je de sketch laten zien ? Tussen code-tags. De </> knop geeft die code-tags.
Eventueel de hele foutmelding er bij, met de regelnummer en zo.

De compiler is bezig met compileren. Op de plek waar de compiler aan het compileren is, is de functie "writeEEPROM" niet bekend.

Arduino heeft een pre-compiler. Je hoeft zelf geen prototyping te doen. Je kunt meteen de functie ergens neerzetten.

sterretje

Quote
VOID writeEEPROM {doe wat}
Ziet er niet uit als een functie definitie.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

FTMZ

Code: [Select]

#include <Adafruit_BMP085.h>  //Bibliotheek voor de druksensor
#include <Wire.h>             //Bibliotheek voor de I2C verbinding.
#include <Servo.h>
//#define EEprom 0x50 //het adres van de EEprom is 50 HEX. en wordt voortaan "EEprom" genoemd.

Servo myservo;  // create servo object to control a servo
Adafruit_BMP085 bmp;  //object

int EPMaddress = 0;  //Adreswaarde EEprom begint op 0
float ijkwaarde;
float hoogteref;     //referentiehoogte
int pos(0);              //servopositie
int hoogte(0);        //hoogte op nul
int apogee(0);        //max geregistreerde hoogte
byte downcount;         //teller die waarneemt hoevaak de voorgaande hoogte hoger is, maw wanneer er wordt gedaald 
int ingang = 8;
int buzzer = 9;
  
void setup() {
  Wire.begin(); //creates a Wire object
  
  Serial.begin(9600);
  pinMode (ingang,INPUT_PULLUP);
  pinMode (buzzer, OUTPUT);  
  myservo.attach(10);  // attaches the servo on pin 10 to the servo object
  if (!bmp.begin()) { //als de module geen verbinding heeft...
   Serial.println("Geen verbinding met de BMP module");
   while (1) {}//in oneindige loop komen
   }
   ijkwaarde = (bmp.readAltitude(101500)) -4 ; //basiswaarde BMP zo verrekenen dat dit altijd op 4 uit komt bij het opstarten
   Serial.println(ijkwaarde);
   delay (2000);

   
   
//hier begon eerder de VOIDLOOP

    hoogte = (bmp.readAltitude(101500)-ijkwaarde);//hoogte, verrekend naar "geijkte" hoogte thuis (NAP + 4); (FLOAT ivm decimalen achter de komma (nu niet))
    myservo.write(0);
    
    Serial.print("Real altitude = ");
    Serial.print(hoogte);
    Serial.println(" meters");
    Serial.println(hoogteref);
    Serial.println(downcount);
    writeEEPROM (0x50, EPMaddress, 0x90);// verwijzing naar de VOID "writeEEprom" tbv het schrijven van de actuele hoogte naar de EEprom
    EPMaddress++;                            //verhoogt het EEprom adres.
    delay (500);
    
    if (hoogte > hoogteref){   //zolang de hoogte hoger is dan de voorgaande meting...
      hoogteref = hoogte;      //het resultaat van de vorige meting overnemen.
      downcount = 0;           //de downcount resetten
    }
     else {
      downcount++;         //het aantal opeenvolgende momenten van een dalende waardes registreren.
      if (downcount >5) {    //wanneer daling na 5 metingen door is gezet, 
        downcount = 0;     //teller resetten
        //start servo      //parachute deployen
        apogee = hoogteref;
        Serial.print ("Apogee = ");
        Serial.println (apogee);
        if (hoogte < 10){
             Serial.println ("No deploy. Undershoot Hight!");
             myservo.write(90);
        }
        else Serial.println ("Parachute deploy");
        
        delay (5000);
        hoogteref = 0;
        
        }
     }
     
      
   // delay(2000);
}

  
void loop() {} //loop nu even hier...
    
    

//---------------------------hieronder een gecopieerd stuk. Betreft de fukties voor het EEprom schrijven en lezen---------------------------------------
//defines the writeEEprom function
void writeEEPROM(0x50, int EPMaddress, byte data ) {
  Wire.beginTransmission(EEprom);
  Wire.write((int)(EPMaddress >> 8));      //writes the MSB
  Wire.write((int)(EPMaddress & 0xFF));    //writes the LSB
  Wire.write(data); //laadt de aangeleverde data
  Wire.endTransmission();       //einde transmissie naar EEprom
  Serial.print (EEprom); //noemt het adres van de EEprom (80)
  Serial.print ("\t");          //tab
  Serial.print (EPMaddress);    //benoemt het adres van de EEprom waar de data is opgeslagen
  Serial.print ("\t");          //tab
  Serial.println (data);        //toont de aangeleverde data. (hoogte in meters)

  }

//defines the readEEprom function
byte readEEPROM(int deviceaddress,  int eeaddress ) 
 {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));      //writes the MSB
  Wire.write((int)(eeaddress & 0xFF));    //writes the LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
                      
 rdata = Wire.read();

 Serial.print (rdata, HEX);
 Serial.print ("\t");
 return rdata;
                           
  }


Het is wat spelerij hoor. Ik wil het wat in de vingers krijgen, maar hier lukt het even niet.
@Sterretje, wat bedoel je precies? Ik hoop dat de code hierboven wat verheldering biedt.
In grote lijnen komt het er op neer dat ik in het programma een verwijzing maak naar een funktie waar ik geen waarde uit terug hoef te krijgen. Een VOID dus, als ik de materie goed heb begrepen, met de naam writeEEPROM.

Oja, hieronder de foutmelding(en)
Code: [Select]

Arduino:1.8.13 (Windows 10), Board:"Arduino Leonardo"
C:\Users\Eigenaar\Documents\Arduino\Hoofd_Sketch_Raket\Hoofd_Sketch_Raket.ino: In function 'void setup()':

Hoofd_Sketch_Raket:47:5: error: 'writeEEPROM' was not declared in this scope

     writeEEPROM (0x50, EPMaddress, 0x90);// verwijzing naar de VOID "writeEEprom" tbv het schrijven van de actuele hoogte naar de EEprom

     ^~~~~~~~~~~

C:\Users\Eigenaar\Documents\Arduino\Hoofd_Sketch_Raket\Hoofd_Sketch_Raket.ino:47:5: note: suggested alternative: 'readEEPROM'

     writeEEPROM (0x50, EPMaddress, 0x90);// verwijzing naar de VOID "writeEEprom" tbv het schrijven van de actuele hoogte naar de EEprom

     ^~~~~~~~~~~

     readEEPROM

C:\Users\Eigenaar\Documents\Arduino\Hoofd_Sketch_Raket\Hoofd_Sketch_Raket.ino: At global scope:

Hoofd_Sketch_Raket:86:17: error: variable or field 'writeEEPROM' declared void

 void writeEEPROM(0x50, int EPMaddress, byte data ) {

                 ^

Hoofd_Sketch_Raket:86:24: error: expected primary-expression before 'int'

 void writeEEPROM(0x50, int EPMaddress, byte data ) {

                        ^~~

Hoofd_Sketch_Raket:86:45: error: expected primary-expression before 'data'

 void writeEEPROM(0x50, int EPMaddress, byte data ) {

                                             ^~~~

Meerdere bibliotheken gevonden voor "Adafruit_BMP085.h"

Gebruikt: C:\Users\Eigenaar\Documents\Arduino\libraries\Adafruit-BMP085-Library-master

Niet gebruikt: C:\Program Files (x86)\Arduino\libraries\Adafruit-BMP085-Library-master

Meerdere bibliotheken gevonden voor "Servo.h"

Gebruikt: C:\Users\Eigenaar\Documents\Arduino\libraries\Servo

Niet gebruikt: C:\Program Files (x86)\Arduino\libraries\Servo

exit status 1

'writeEEPROM' was not declared in this scope



Dit rapport zou meer informatie bevatten met
"Uitgebreide uitvoer weergeven tijden compilatie"
optie aan in Bestand -> Voorkeuren.

FTMZ

wellicht ter overvloede, maar die #define EEprom 0x50, die ik nu heb uitgeschakeld gaf in eerste instantie problemen.
daarom heb ik die "EEprom" tijdelijk vervangen voor 0x50 in het programma, zodat ik die verwijzing kon omzeilen.
Dit hielp niet. 

MAS3

Ok, dat is weer een stukje dat niet helemaal goed is verwoord door mij in de andere thread.
Je verwacht niets terug, en geeft er daarom een VOID aan.
Dus dan word het zoiets als "Hier komt niets: chipAdres, GeheugenCelAdres, teVerwerkenWaarde".
Dat klopt niet helemaal he, je gooit die data ergens heen waar niets word verwacht.

Dus, een VOID geeft niet alleen niets terug, je kunt er ook niets aan meegeven want wat je in de leegte gooit, gooi je voor goed weg.
Dat is je probleem hier dus.

Feitelijk gebeurt er hier exact hetzelfde als in je vorige thread, alleen is het een stukje van een andere code.
Het blijft het schrijven van een enkele geheugencel van je EEPROM.
Dus verandert er ook niets aan de aanpak.

In je vorige thread definieer je geen variabele voor je naar de functie gaat, en daarmee geef je ook aan dat je niets terug verwacht.
Maar omdat je niet zegt dat het een leegte (void) is, kun je er dus wel iets heen sturen.

Wanneer je raket meer dan 255 meter omhoog moet kunnen, dan heb je dus ook meer dan 1 cel nodig, en moet je daar je code ook op aanpassen.
Maar je hebt gezien hoe je dat kunt doen in de andere thread.

Ik zie nu dat je daar al mee aan de slag bent gegaan, maar het is niet af omdat de code buiten loop() staat en dus maar 1 keer een waarde naar de EEPROM stuurt.


Verder ga je de apogee missen als je zoveel delays gebruikt, ik zou ze er uit slopen na het testen van de code.
En de apogee op een bepaalde positie in je EEPROM vast te zetten, terwijl de andere waarden achtereenvolgens worden opgeslagen in de EEPROM, zodat je niet alleen je apogee ziet, maar ook een mooie grafiek kunt maken van de hoogtes tegenover de tijd/de baan van je raket.
Ligt er natuurlijk wel aan hoeveel ruimte je hebt en kunt gebruiken in je EEPROM.
Ik heb geen idee hoe snel je je hoogte kunt ophalen uit je sensor, maar wanneer je in vaste tijdsintervallen een waarde opslaat (2 maal per seconde, of 10, bedenk een goede en passende interval), dan krijg je zo een mooi beeld.


Dit is ook anders dan ik zo snel even las.
De 5 seconden delay komt pas nadat je aan het parachutekoord hebt getrokken, en de 2 seconden zijn commentaar en staan daarmee uit.

Ik betwijfel wel of het schrijven naar de EEPROM een halve seconde pauze per keer nodig heeft, ik vind dat erg veel.
En je servo word pas op z'n vroegst 2 seconden na start van de Arduino op nul gezet.
Ik zou dat eerder doen, meteen nadat je 'm geïnitieerd hebt.
Het lijkt me wat teleurstellend als de parachute per ongeluk deployed blijkt tijdens lancering.

Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

FTMZ

Hoi MAS3.
Allereerst bedankt dat je er serieus op in gaat en dat je het doel van het programma niet veroordeelt. :)

Het is zoals ik eerder aangaf een rauwe code waar ik nog aan moet schaven hoor!
Ik heb mijn goal om floats te registreren in mijn EEPROM al overboord gezet omdat ik daarvoor steeds 4 bytes per schrijfcyclus moet zien te verwerken en het overpeinzen daarvan schoot zijn doel voorbij (pardon my choice of words).

Ik wil elke x milisecondes de waarde (hoogte) vastleggen, zodat ik uiteindelijk een grafiek kan laten weergeven hoe het verloop is gegaan. (just for fun). Ik verwacht niet over de 255m te gaan. En anders kan ik wel wat gaan spelen met de codes tijdens het uitlezen. Voor latere zorg.

Die Chute deploy heeft wat voorwaarden ingeprogrammeerd gekregen. 
Hij moet minimaal 10m hoog zijn geweest (volgens mij had ik 10m aangegeven).
Verder had ik dat al getest met een programma incl servo. Pas als opeenvolgende metingen (op dit moment 5) onder een van de voorgaande waardes komt, zal de servo de parachute bay openen.
Als de metingen snel achter elkaar komen, zal ik er nog een waarde van minimaal 2m oid in vrotten. Dat is geen probleem.

Terug naar het programma...
Ik heb een stukje code wat ik werkend heb gekregen, volledig uitgekleed, waarbij het registreren van waarden nog steeds bleef bestaan.
Dát stuk heb ik vertaalt naar mijn huidige programma. Maar daar werkt het dus niet.
De VOID om puur een waarde weg te zetten en niets terug te verwachten komt daar ook vandaan.
Hij lijkt me daarom ook niet fout. :smiley-confuse:


Code: [Select]

#include "Wire.h"

#define eeprom 0x50 //defines the base address of the EEPROM

void setup()  {
  delay(5000);

  Wire.begin(); //creates a Wire object
  Serial.begin(9600);

  int address = 0; //first address of the EEPROM
  Serial.println("We write the zip code 22222, at location: ");
  for(address = 0; address< 10; address++){
    writeEEPROM(eeprom, address, 0x70 );// Writes Hex 70 to the EEPROM
    delay (5); }
  Serial.println();
 

  for(address = 0; address< 10; address++) {
    byte wappie  = (readEEPROM(eeprom, address));    
    Serial.println (wappie, BIN);            
    delay (5);
    }
  }
  

void loop() {
  //Serial.println ("test");
  /*there's nothing in the loop() function because we don't want the arduino to
  repeatedly write the same thing to the EEPROM over and over.
  We just want a one-time write, so the loop() function is avoided with EEPROMs.*/
}

//defines the writeEEPROM function
void writeEEPROM(int deviceaddress, int eeaddress, byte data ) {
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));      //writes the MSB
  Wire.write((int)(eeaddress & 0xFF));    //writes the LSB
  Wire.write(data); //ipv data
  Serial.print (deviceaddress);
  Serial.print ("\t");
  Serial.print (eeaddress);
  Serial.print ("\t");
  Serial.println (data, HEX);
  Wire.endTransmission();
  }

//defines the readEEPROM function
byte readEEPROM(int deviceaddress,  int eeaddress )
 {
  byte rdata = 0x99;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8));      //writes the MSB
  Wire.write((int)(eeaddress & 0xFF));    //writes the LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
                            

 rdata = Wire.read();

 Serial.print (rdata, HEX);
 Serial.print ("\t");
 return rdata;
                            
  }

MAS3

OK, ik probeer het nog een keer.

Eerder heb ik inderdaad gezegd dat een VOID zo heet omdat het een leegte voorstelt die niets terug kan geven.
Maar je kunt er ook niets in stoppen, want een oneindige leegte maakt alles wat je er in stopt kwijt.
(Zie het als iemand die in de ruimte (space) gaat schreeuwen; het geluid kom er wel uit, maar niemand zal het horen (tenzij ie direct naast de schreeuwer is en de lucht uit diens longen meteen in z'n oren krijgt).)
Dus je kunt 'm niet VOID noemen.
Als je zowel het woord VOID als een te vullen variabele weglaat, dan roep je ook een functie aan die niets terug geeft, maar wel wat kan ontvangen.
En dat is wat je wil, want je wil aan de functie doorgeven welke EEPROM (0x50) je aanspreekt, op welk adres (cel) de data terecht moet komen, en wat dan die data is.

Zo werkt het ook in de sketch van je vorige vraag.

Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

sterretje

Het hangt af van de functie declaratie waarin je vertelt dat de functie nul of meer parameters verwacht.

Code: [Select]
void add()
{
  int c = aa + bb;
  Serial.println(c);
}
Een functie die geen parameters verwacht en ook niets terug geeft; aa en bb zijn globale parameters

Code: [Select]
int add()
{
  int c = aa + bb;
  return c;
}
Een functie die geen parameters verwacht en een int terug geeft; aa en bb zijn globale parameters

Code: [Select]
void add(int a, int b)
{
  int c = a + b;
  Serial.println(c);
}
Een functie die twee parameters van type int verwacht en niets terug geeft.

Code: [Select]
int add(int a, int b)
{
  int c = a + b;
  return c;
}
Een functie die twee parameters van type intverwacht en een int terug geeft.

Als je een functie schrijft die niets verwacht (eerste voorbeeld) en vervolgens in de aanroep parameters mee geeft, zal de compiler daar over klagen.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

sterretje

Bedankt, copy-and-paste error. Zal het even verbeteren.
If you understand an example, use it.
If you don't understand an example, don't use it.

Electronics engineer by trade, software engineer by profession. Trying to get back into electronics after 15 years absence.

FTMZ

OK, dank voor de uitleg en het verschil benoemen, Sterretje.
Met dat in het achterhoofd ga ik weer die twee sketches naast elkaar leggen.
De tweede sketch (die ik ergens had gekopieerd om mee te rommelen) werkte wel, waar de eerste dat niet deed.
Daar is wat mee te doen.

[edit]
Quote
Quote from: MAS3 Tue Jan 26 2021 00:50:57 GMT+0100 (Midden-Europese standaardtijd)

OK, ik probeer het nog een keer.

Als je zowel het woord VOID als een te vullen variabele weglaat, dan roep je ook een functie aan die niets terug geeft, maar wel wat kan ontvangen.
Ah... Dit, met de bovenstaande uitleg/vergelijking van Sterretje, maakt het een stuk duidelijker.
[/edit]
Dank zover voor jullie reacties!

shooter

en eerst definieeren dus eerst de functie maken en daarna pas gebruiken, uiteraard moet het aantal wat je gebruikt ook kloppen met wat je opgeeft bij de functie. en de types moeten ook gelijk zijn dus een int is geen float etc.

paul deelen
shooter@home.nl
making controls with codesys PLC and arduino

FTMZ

OK, Guys...

Ik ben al wat verder gekomen en ik heb in ieder geval geen compilatieerrors meer, maar ik heb nog wat vragen.
Vooral het "waarom" zo? 

Ik maak een verwijzing naar die funktie om wat weg te schrijven.:

Code: [Select]
writeEEPROM (EPMaddress, data, EEprom)

Deze verwijzing stuurt me naar: 

Code: [Select]
void writeEEPROM(int EPMaddress, byte data, int i2caddress)

Op een later tijdstip krijg ik de verwijzing om de data weer op te halen, waarna ik naar de volgende funktie ga:


Code: [Select]
byte readEEPROM(int EPMaddress, int i2caddress)

nu is die "int i2caddress"  het I2C adres van de geheugenchip. Dat is 0x50
Waarom is dat bij de schrijfopdracht dan "EEprom", maar in de funktie "i2caddress"??

Want het i2c adres zal niet veranderen, lijkt me.
Ik had daar ipv "EEprom" "i2caddress" waardoor ik steeds compile errors kreeg omdat die i2caddress niet "in de scoop" stond. 

Waarom kunnen die "vaste" variabelen in de verwijzing en in de functie niet gelijk zijn aan elkaar?
OK... Dan komt hij niet voor in de scoop. Maar waarom is dat?

NB... Ik weet niet of ik het nu allemaal goed heb gedaan tav een VOID (tov Byte) om zaken weg te schrijven, dus schiet me daar nu even niet op af. Ik heb alles vergeleken met een werkend programma, en zo de fout ontdekt.

Erik_Baas

Waarom kunnen die "vaste" variabelen in de verwijzing en in de functie niet gelijk zijn aan elkaar?
Dat was het probleem niet, dat kan namelijk gewoon wél.
Code: [Select]

int X = 5;

void setup() {
 Serial.begin(115200);
}

void loop() {
 test(X);
}

void test(int X) {
 Serial.println(X);
}

De parameter X in test() is een andere dan de varabele X in de sketch, en de scope is lokaal voor die functie, dwz. dat hij na het verlaten van die functie niet meer bestaat.

Quote
OK... Dan komt hij niet voor in de scoop. Maar waarom is dat?
Omdat de variablele niet gedeclareerd was in de sketch.

MAS3

Een functie is dus een apart stukje code met lokale variabelen.
Daarmee bespaar je op geheugen.

Uit jouw vraag is de inhoud van EEprom geldig in je loop.
Die geef je als eerste mee aan je functie.
In je functie geef je 'm ook een naam, maar het kan verwarrend zijn als je daar dezelfde naam gebruikt.
Ik zie dat je met EPMaddress en data tijdens het schrijven naar de EEPROM ook zo doet, en daar werkt het ook.
Overigens, staat er voor de naam ook nog welk type variabele (int) het is, dan geef je daarmee ook aan dat het een nieuw aan te maken variabele is.

De waarde uit EEprom word dus tijdens het aanroepen overgeheveld naar (volgens jouw vraag) i2caddress die alleen binnen die functie geldt.
Wanneer je die naam nog een keer gebruikt binnen een andere functie, zal het wel werken, maar kan er dus verwarring gaan ontstaan.
Alleen al omwille van het overzicht is het wat mij betreft dus een goede reden dit zo te doen.




Je moet wel goed opletten dat een en ander klopt, en dat is dus ook wat shooter riep over het definiëren.
Eerst vul je het in bij de functie, en daarna zorg je er voor dat het ook klopt tijdens het aanroepen.
Ik vind dat een logische en goede aanpak.
Bij je eerdere getoonde codes was het volgens mij steeds eerst het I2C adress van de chip, dan het adres van wat ik steeds de geheugencel noemde, en dan de data die daar in moest.
Nu heb je schijnbaar die laatste 2 omgedraaid.
Dat maakt niet uit, zolang je het maar bij de definitie en bij het aanroepen op dezelfde manier doet.
Zelf vind ik de eerst gebruikte manier meer intuïtief.




Verder is het niet een scoop (je brengt geen hot news als eerste), maar scope.
Scope vertaalt in dit geval naar zoiets als blikveld (letterlijk reikwijdte).
Als je in een functie een variabele uit een andere functie wil gebruiken, moet je 'm overhevelen op de manier die nu besproken word.
Of, zoals Erik_Baas al aangeeft, wanneer de variabele als globaal gedefinieerd is kun je 'm overal gebruiken.

Dus het blikveld beslaat alleen globale variabelen of die die binnen je functie gedefinieerd werden.
Variabelen daarbuiten vallen ook buiten het blikveld / bereik, en vertaald naar het Engels is dat dan dus "out of scope".
Have a look at "blink without delay".
Did you connect the grounds ?
Je kunt hier ook in het Nederlands terecht: http://arduino.cc/forum/index.php/board,77.0.html

Go Up