Go Down

Topic: Doorgronden van de werking van een Functie. (Read 502 times) previous topic - next topic

FTMZ

Hallo mensen,

Ik heb even wat vragen over hoe een voorbeeld programma werkt, wat ik ergens heb opgevist.
Hij doet niet wat hij moet doen en ik ben het een beetje aan het ontleden.
Omdat alles in 1 topic vragen in de internationale sectie niet wordt gewaardeerd en omdat sommige problemen nou eenmaal beter uit te leggen zijn in "Native Tongue" hier even een stukje waar ik wat vragen over heb:

Ik laat even mijn opmerkingen ak reminders staan, zodat ik een beetje insights kan geven van mijn denkwijze en waar ik fout lijk te gaan.
Code: [Select]


//defines the writeEEPROM function
void writeEEPROM(int deviceaddress, unsigned 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); 
  Wire.endTransmission();
  }

//defines the readEEPROM function
byte readEEPROM(int deviceaddress, unsigned 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);
  if (Wire.available())      //als er data is opgeslagen, dan rdata update doorzetten (in dit geval 88888)
                             //maar er lijkt geen data te zijn "wire is dus niet available" want ik krijg de oorspronkelijke data 0xFF terug.
                             //Misschien omdat de voorwaarde van de IF niet tussen {} staat??
                             //update: Als ik de wire.read en return rdata in de IF statement zet, komt er een andere waarde uit. Geen FFFFF
                             //of 255255255255255 maar 229229229229229 (AAAAA) maar ook 11111 decimaal of 5050505050(HEX)
                             //als ik de IF statement met return etc helemaal weglaat, krijg ik 00000 data
    rdata = Wire.read();
    return rdata;
    
  }


Wat ik zo vreemd vind, is dat er in de laatste regels een IF statement staat, waarvan de voorwaarden niet tussen accolades staan. Hoe weet ik dan welke regels er worden uitgevoerd wanneer aan de IF voorwaarde wordt voldaan?
Ik heb wat gespeeld met die laatste regels, waarbij ik die IF statement heb weggelaten, of de return rdata ook binnen die IF statement heb gezet. Voor zover je er wat "in" kunt zetten. Er zijn geen accolades...

Een vervolgvraag daarop is wat er in die rdata hoort te zitten en waarom dit steeds het FF adres blijkt te zijn.
Ik zie ook dat hij geladen wordt met die byte rdata 0xFF.
Dat is een fixed data en als die niet veranderd wordt, blijft hij FF.
En ik zie hem niet veranderd worden. :)
Hoe zit dat nou?

Erik_Baas

#1
Jan 11, 2021, 10:02 pm Last Edit: Jan 11, 2021, 10:03 pm by Erik_Baas
Er zijn drie manieren om een if()-functie te schrijven:

Code: [Select]

1:
if (Wire.available()) rdata = Wire.read();

2:
if (Wire.available())
  rdata = Wire.read();

3:
if (Wire.available())
{
  rdata = Wire.read();
}


Deze doen alledrie precies hetzelfde. Maar: bij de eerste twee vormen kun je slechts één opdracht programmeren!

Als je jouw code even met Auto Format behandelt zie je ook dat de regel met "return rdata;" niet onder "rdata =" etc. komt, maar tegen de kantlijn. Deze wordt dan ook niet uitgevoerd onder de "if"-voorwaarde, maar altijd!

Code: [Select]

if (Wire.available())
  rdata = Wire.read();
return rdata;

MAS3

#2
Jan 11, 2021, 11:23 pm Last Edit: Jan 11, 2021, 11:27 pm by MAS3 Reason: Link gecorrigeerd
Men vergeet snel dat een regel code niet word afgesloten met een enter, zoals een regel tekst.
Een regel (C(++)) code word afgesloten met een semicolon oftewel een puntkomma ;

Als die er niet staat dan gaat de regel gewoon door.
Sommige dingen zullen dan niet helemaal gewaardeerd worden, zoals de tekst "Wire.available" die een ander kleurtje krijgt omdat het herkend word, maar niet wanneer die tekst 1 karakter per regel gemaakt word.
Maar verder gaat het gewoon door.

Verder is je beschrijving van je vraag niet gelijk aan de tekst er van.
De voorwaarden staan niet tussen accolades (nooit), de handelingen (meervoud) die van de betreffende voorwaarden afhankelijk moeten zijn wel.

Zoals Erik_Baas al aangaf: rdata word altijd terug gegeven.
Daarom moet je rdata vluchtig maken (door m alleen in de functie te definiëren en niet globaal), en/of door 'm te wissen.
Je doet beiden in deze code, 1e wat in de functie readEEPROM gebeurt, is het creëren van de variabele en 'm vullen met de waarde 0xFF.

Even voor de duidelijkheid:
Je verwacht schijnbaar 2.5 bytes terug, maar je vraagt er maar 1 op (en een halve byte kun je niet opvragen).
Code: [Select]
 Wire.requestFrom(deviceaddress,1);
Je kunt forumlid @Koepel vragen of hij je meer kan vertellen over over de wire libary, want hij heeft daar wat over gedocumenteerd.
Maar je kunt het best beginnen bij de Arduino documentatie.
Ik weet natuurlijk niet of je jouw waarde uit EEPROM niet 3 keer opvraagt, telkens met een adresje hoger of zo (ik heb het hier niet over device address) want daar is in de getoonde code niets van terug te vinden.
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 mensen,
Het blijkt dat ik dit niet had verzonden. Dat zie ik nu pas. Mijn excuses voor de ogenschijnlijk late reactie op jullie posts. Gelukkig stond dit nog onder drafts. :-)





Quote
Verder is je beschrijving van je vraag niet gelijk aan de tekst er van.
De voorwaarden staan niet tussen accolades (nooit), de handelingen (meervoud) die van de betreffende voorwaarden afhankelijk moeten zijn wel.

Als je een voorwaarde stelt, staan de handelingen in mijn optiek juist altijd tussen accolades.
Zelfs al heb je een simpele If of While voorwaarde, er staan altijd accolades onder (soms achter).
Of je moet doelen op een voorwaarde in een fuctie, waarbij (zoals ik net van Erik Baas heb geleerd) een enkele uit te voeren opdracht, direct onder de if voorwaarde komt te staan.
(met dat ik dit typ denk ik dat ik je verhaal rondom de "regels" versus de semicolom begrijp. Dat alles achter de IF statement wordt meegenomen, tot de semicolom dit afsluit.)

Quote


Quote
Zoals Erik_Baas al aangaf: rdata word altijd terug gegeven.
Daarom moet je rdata vluchtig maken (door m alleen in de functie te definiëren en niet globaal), en/of door 'm te wissen.

Dit was volgens mij niet wat Erik aanhaalde, maar ik zag hem wel staan. ;-)
Die rdata komt toch alleen voor in de functie? In ieder geval niet globaal. Want ik heb nog geprobeerd die rdata weer te geven op de serial monitor, maar dat werd niet geaccepteerd omdat hij niet in die "scoop" werd herkend.

Quote


Quote
Je doet beiden in deze code, 1e wat in de functie readEEPROM gebeurt, is het creëren van de variabele en 'm vullen met de waarde 0xFF.

Dit begrijp ik niet helemaal... rdata wordt als variabele gevuld met waarde 0xFF. Bedoel je dan de fysieke waarde 0xFF? Of de waarde die in geheugenpositie 0xFF staat?
Want de opzet van de code is een waarde (ik zal zo de complete code even plakken) opslaan, om hem later terug te halen en te printen in de serial monitor.
Komt er niets, print hij 0xFF. Zo interpreteer ik de code. Ik zal er naast zitten, maar dan weet ik niet waar. Of hoe het dan wel moet. Het is een voorbeeld code waar ik mee stoei om het te begrijpen.

Quote


Quote
Even voor de duidelijkheid:
Je verwacht schijnbaar 2.5 bytes terug, maar je vraagt er maar 1 op (en een halve byte kun je niet opvragen).
Code: [Select]

Code: [Select]
Wire.requestFrom(deviceaddress,1);


Nee, dat is niet mijn intentie...
Hoe kom je daarbij, als ik vragen mag? Ik heb wel wat zaken aangepast, maar alleen om te zien hoe ik 5x de waarde "2" kan opslaan op de EEPROM en die succesvol terug te halen.
En dat lukt maar niet. ;-)[/quote]

FTMZ

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);

  unsigned int address = 0; //first address of the EEPROM
  Serial.print("We write the zip code 22222, at location: ");
  for(address = 0; address< 5; address++)
    writeEEPROM(eeprom, address, '2'); // Writes 22222 to the EEPROM

  for(address = 0; address< 5; address++) {
    Serial.print(readEEPROM(eeprom, address), HEX);
    //Serial.print(deviceaddress);
    }
    Serial.println();
  }
  

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, unsigned 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);
  Wire.endTransmission();
  }

//defines the readEEPROM function
byte readEEPROM(int deviceaddress, unsigned 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);
  if (Wire.available())      //als er data is opgeslagen, dan rdata update doorzetten (in dit geval 88888)
                             //maar er lijkt geen data te zijn "wire is dus niet available" want ik krijg de oorspronkelijke data 0xFF terug.
                             //Misschien omdat de voorwaarde van de IF niet tussen {} staat??
                             //update: Als ik de wire.read en return rdata in de IF statement zet, komt er een andere waarde uit. Geen FFFFF
                             //of 255255255255255 maar 229229229229229 (AAAAA) maar ook 11111 decimaal of 5050505050(HEX)
                             //als ik de IF statement met return etc helemaal weglaat, krijg ik 00000 data
    rdata = deviceaddress;//Wire.read();
    return rdata;
    
  }

MAS3

#5
Jan 15, 2021, 12:24 am Last Edit: Jan 15, 2021, 12:27 am by MAS3
Sommige dingen kan ik niet duidelijker zeggen dan ik al gedaan had, sorry.
Toch ga ik nog een poging wagen.

Schijnbaar versta jij iets anders bij het woord voorwaarde, dan ik.
Voor mij is een voorwaarde datgene dat beschreven is direct na "als" of "wanneer" (ik geef zo een voorbeeld).
Bij programmeren heb je dan voorwaardelijke code, en dat is code die onder de eerder genoemde voorwaarde zal worden uitgevoerd.
Bij C (++) staat de voorwaardelijke code tussen accolades {}, en de voorwaarde misschien tussen haakjes ().

Code: [Select]
  if (x > y)  // Onder voorwaarde dat x groter is dan y
  { serial.print "X is groter"; // Word de voorwaardelijke code tussen de accolades uitgevoerd
    serial.print "Y is kleiner";
  }



Quote from: mezelf
Zoals Erik_Baas al aangaf: rdata word altijd terug gegeven.
Dat is 1 regel.
In de volgende regel zeg ik (dus niet erik) dan:
Quote
Daarom moet je rdata vluchtig maken (door m alleen in de functie te definiëren en niet globaal), en/of door 'm te wissen.
Jij hebt dit in je code staan, en dat doet dus precies wat ik hierboven al aanhaalde:
Code: [Select]
  byte rdata = 0xFF;

In deze regel maak je een lokale byte genaamd rdata, en die vul je meteen, dus tijdens het maken er van, met 0xFF.
rdata geldt dus alleen binnen de functie, en vervalt direct bij het verlaten er van.
Dat is wat er in die regel staat en ik kan er niets anders van maken.
Het is ook wat je wil doen en wat de beste wijze is.

Zou je nu rdata globaal gemaakt hebben, en niet lokaal, dan maak je 'm dus niet telkens opnieuw aan voor de functie, en kan de inhoud bewaard gebleven zijn.
Dat wil je niet want dan krijg je dus oude en daarmee foute / onbetrouwbare waarden terug.

Met andere woorden: dit doet wat jij wil en ik leg uit waarom dat (de code en wat jij wil) goed is.

Wel 1 kanttekening.
Een lege waarde uit een EEPROM is altijd 0xFF.
En natuurlijk kan je die waarde er ook zelf in zetten.
Dat is dus een waarde die je ook terug zou kunnen krijgen.
Dat geeft natuurlijk niet, zolang je dat maar weet.


Quote
alleen om te zien hoe ik 5x de waarde "2" kan opslaan op de EEPROM en die succesvol terug te halen.
Ik vraag me dan af of je de waarde 2 of het teken '2' wil opslaan en terughalen, maar dat zal aan mij liggen ;)
In jouw eerder getoonde code zie ik niets staan over 5 keer, maar wel een opmerking over FFFFF.
FFFFF zijn 2,5 bytes maar wel als je het schrijft als 0xFFFFF.
Maar dat is dus waarom ik daar over begon.

Wel zie ik in jouw eerder getoonde code staan dat je 1 byte ophaalt:
Code: [Select]
  Wire.requestFrom(deviceaddress,1);

De ",1" betekent dat je 1 byte wil ophalen, en meer past er ook niet in rdata.

Pas bij je meest recente post is te zien dat je dit 5 keer uitvoert en daarbij het adres van de geheugen cel in je EEPROM steeds ophoogt.
Maar nu komt de opmerking die ik net maakte weer naar boven (ik kijk er nu net tijdens het typen van deze regel pas naar):
Je schrijft geen 2 naar de cel in de EEPROM, maar het teken '2'.
Die heeft de waarde 50.
En dat is dus 1 van de resultaten die je genoemd hebt.
Het verschil zit 'm in de apostrof (') die om de 2 staat.
Daarmee geef je aan dat je een getal wil doorgeven dat volgens de ASCII tabel hoort bij het teken 2, en dat is dus 50.
Je kunt ook 'A' doorgeven, en dan krijg je de inhoud 65, niet te verwarren met 'a' want dat is 97.


Dit kun je op 2 manieren oplossen.
Je kunt de waarde 2 sturen in plaats van de waarde '2'.
De waardes 0 tot en met 31 zijn echter stuurtekens, en die kunnen een ongewenst resultaat opleveren.

Of je kunt naar je serial monitor de ASCII waarde schrijven.
Dan doe je in dat stukje:

Code: [Select]
    Serial.write(readEEPROM(eeprom, address), HEX);

Het verschil hier is de write in plaats van de print.

[edit]
Overigens hoop ik dat je nu ziet dat het belangrijk is dat je de hele code plaatst in plaats van zo'n snippet (een stukje knipsel uit de gehele code).
Uit zo'n snippet is het bijna niet de doen om de context van het geheel mee te krijgen.
Dus wanneer het kan, graag de gehele code tonen bij je vragen.
[/edit]
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

Sommige dingen kan ik niet duidelijker zeggen dan ik al gedaan had, sorry.
Toch ga ik nog een poging wagen.
Laat ik voorop stellen dat ik het zeer waardeer dat je dit wel doet.
De code waar het om gaat heb ik gedownload omdat ik meer inzicht wil krijgen in wat welk deel van de code doet.
Als de sketch vervolgens niet werkt, slaat bij mij de twijfel toe. Want wie zegt dat de code ook correct is?
Daarom (stukjes van) de code met de vraag of ik het goed beredeneer.
Ik wilde geen overkill neergooien door de hele code hier te deponeren. Maar ik snap je punt dat het alles overzichtelijker maakt.

Quote
Schijnbaar versta jij iets anders bij het woord voorwaarde, dan ik....
Ik denk wel dat we op 1 lijn zitten hoor! Het was me alleen te doen om de kaders van "wat te doen" als aan de voorwaarde wordt voldaan.
In mijn optiek komt het "wat te doen" deel altijd tussen accolades. In mijn code staat "wat te doen" niet tussen accolades. Vandaar mijn vraag: Hoe weet ik nu wat er gedaan wordt wanneer aan de voorwaarden wordt voldaan?
Ik begreep uit een eerdere reactie dat dat slechts de eerste regel is, na de voorwaarde.
Of dat altijd zo is, de eerste regel, of dat het alleen om code totaan de ";" gaat, is me nog wat onduidelijk.
En ik vroeg me af of dat iets was wat alleen bij functies wordt gebruikt, of dat het iets is uit C++ of juist C of zoets.
Ik weet niet beter dan dat "wat te doen" uitsluitend tussen accolades stond.
Quote
In de volgende regel zeg ik (dus niet erik) dan:
Jij hebt dit in je code staan, en dat doet dus precies wat ik hierboven al aanhaalde:
Code: [Select]
 byte rdata = 0xFF;

In deze regel maak je een lokale byte genaamd rdata, en die vul je meteen, dus tijdens het maken er van, met 0xFF.
rdata geldt dus alleen binnen de functie, en vervalt direct bij het verlaten er van.
Dat is wat er in die regel staat en ik kan er niets anders van maken.
Het is ook wat je wil doen en wat de beste wijze is.
Even vooropgesteld dat ik zelf niet weet wat "ik" wil hoor. :)
Ik weet wat een locale variabele is, denk ik. Het is een variabele die je alleen in een bepaald deel van je programma gebruikt. Als hij meer doet of kan, is dát iets wat ik niet weet.
Ik had inderdaad gezien dat de variabele gevuld werd met waarde 0xFF. Dat dit ook meteen betekent dat die byte gereset is, wist ik niet. Je zou verwachten dat alles 0x00 zou zijn. Maar dat is mijn onkunde. Het is mij duidelijk.

Waarom hij die byte 0xFF maakt weet ik niet. Want een fractie daarna wordt volgens mij een andere waarde in de EEPROM geladen.
Quote
Ik vraag me dan af of je de waarde 2 of het teken '2' wil opslaan en terughalen, maar dat zal aan mij liggen ;)
In jouw eerder getoonde code zie ik niets staan over 5 keer, maar wel een opmerking over FFFFF.
FFFFF zijn 2,5 bytes maar wel als je het schrijft als 0xFFFFF.
Maar dat is dus waarom ik daar over begon.
Nu snap ik wat je bedoelde met 2,5 Bytes. Ik moet je het antwoord schuldig blijven. Ook hier weer... Copy paste ter lering en vermaak. Vooral lering...
Ik zal zo die code nog eens doornemen.
Quote
Wel zie ik in jouw eerder getoonde code staan dat je 1 byte ophaalt:
Code: [Select]
 Wire.requestFrom(deviceaddress,1);

De ",1" betekent dat je 1 byte wil ophalen, en meer past er ook niet in rdata.

Pas bij je meest recente post is te zien dat je dit 5 keer uitvoert en daarbij het adres van de geheugen cel in je EEPROM steeds ophoogt.
Zo had ik het programma ook begrepen.
Hij zou 5x een waarde "2" schrijven en 5x terug halen.
Persoonlijk vond ik dat een wat knullige code, want als je iets goed wil uitleggen (als schrijver van de code) zou ik niet 5x hetzelfde in een EEPROM zetten. Ik had 1,2,3,4,5 oid gedaan... Daar steek je meer van op, maar goed...
Quote
Maar nu komt de opmerking die ik net maakte weer naar boven (ik kijk er nu net tijdens het typen van deze regel pas naar):
Je schrijft geen 2 naar de cel in de EEPROM, maar het teken '2'.
Die heeft de waarde 50.
Dat verklaart wel de waarden die ik terug kreeg op de Serial Monitor. Ik ken het ASCII verhaal.
Maar ook hier weer leg ik de "schuld" van de onduidelikheid bij de maker van die code.
Ik zal zo eens wat proberen naaar de EEPROM te schrijven en vervolgens te lezen.

Wat ik nog wel steeds onduidelijk vind, is dat "return" verhaal van die rdata.
Code: [Select]

   rdata = deviceaddress;//Wire.read();
   return rdata;

Als de local variable "rdata" de waarde "deviceaddress" krijgt, hoe komt dat dan terug naar búiten die functie, als rdata buiten die functie vervalt?
Als ik het goed begrijp betekent "return rdata" dat de waarde in die variabele "rdata" wordt "gereturned", uit de functie, het reguliere programma in.
Of begrijp ik die "return" niet goed? (een beetje Gosub/return uit mijn oude basic tijd.)

Kan ik ook monitoren welke data er in die "rdata" zit? Met de serial monitor oid?
Want als ik het programma goed doorgrond, wordt die oorspronkelijke waarde 0xFF veranderd in een andere waarde, wat ik echter nooit heb kunnen zien.

MAS3

Hoi.

Een goed voorbeeld / tutorial schrijven is heel veel moeilijker dan zo'n goede tutorial volgen en begrijpen wat daar gebeurt, en dat kan al een hele uitdaging zijn.
Nu zijn er natuurlijk tutorials voor beginners (die hebben daar de meeste behoefte aan en baat bij), en voor gevorderden.
Maar in beide gevallen moet het een duidelijk en gemakkelijk te volgen verhaal worden, en jij bent er nu achter gekomen dat het bij deze niet zo heel duidelijk is.
Zelf probeer ik, wanneer ik beginnende programmeurs tegen kom hier op de site, om functies te voorkomen.
Want functies zijn niet altijd even duidelijk voor een beginner en kunnen heel gecompliceerd over komen.
Maar wanneer je ze wel begrijpt en vaak genoeg hebt toegepast om er lekker mee om te gaan, merk je dat ze juist wat problemen oplossen en het overzicht een stuk kunnen  vergroten.

Een functie kan grofweg 2 smaken hebben.
Bij de meesten geeft de functie iets terug.
Bij de andere geeft de functie niets terug, en daarom word die functie dan aangemerkt als "leegte".
Leegte vertaald naar het Engels is "void", en dat zou een belletje moeten laten rinkelen bij jou.
Beginnende C++ programmeurs roepen ook vaak void wanneer ze functie bedoelen.

Een functie moet worden aangeroepen, bijvoorbeeld vanuit een andere functie.
Dat ziet er dan meestal uit als:
Code: [Select]
   waarde = functienaam(functieMeegeefWaarde);

Zo omschreven lijkt me dat vrij duidelijk.
Je verwijst met functienaam dus naar de betreffende functie.
(helemaal fout, maar heel ver weg lijkt het wat op jouw gosub).
Tijdens dat aanroepen van die functie, geef je eventueel variabelen mee tussen haakjes.
Dat is hier functieMeegeefWaarde.
Maar voor de functienaam word een variabele genoemd.
Die variabele heet hier "waarde", en er staat een = teken tussen de twee.
Dus die variabele moet schijnbaar gevuld worden.
En dat zal gedaan worden met datgene dat teruggegeven word uit functienaam.

Nu de functie.
Die word dus aangeroepen, en in jouw geval met 2 variabelen namelijk eeprom en address.
eeprom is een constante met de waarde 0x50 (of 80).
address verandert 5 keer tijdens het uitvoeren van de code.

In jouw code ziet de 1e regel van de functie er zo uit:
Code: [Select]
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) {
De functie readEEPROM verwacht 2 variabelen, achtereenvolgens (en alleen tijdens deze functie geldig) deviceaddress en eeadress.
De inhoud van die 2 variabelen worden tijdens het aanroepen gevuld met de inhoud uit eeprom (0x50) en address.
Je gaat maar met 1 byte werken, dus er hoeft ook niet meer geheugen gereserveerd te worden.

Na het verwerken van de gegevens, moet er teruggekeerd worden naar daar waar de functie werd aangeroepen.
Dat doe je met return.
Wanneer de functie geen waarde terug hoef te geven (void), staat er ook niets achter.
Maar wanneer er wel wat terug gegeven moet worden, dan moet je daar aangeven wat er dan terug moet, bij jou rdata.

Jouw voorbeeld maakt het wat lastiger te volgen, omdat er een stap word overgeslagen.
Daarmee bespaar je jezelf wat geheugen en word de code wat korter.
Ik heb het hier over dit stukje uit jouw code:
Code: [Select]
   Serial.print(readEEPROM(eeprom, address), HEX);

Je gaat wat naar Serial printen, en dat betekent altijd dat er een variabele volgt.
Dit kan er uit zien als "print mij", of als een variabelenaam.
Alleen staat hier in jouw code niet de variabele tussen de volgende haakjes, maar een verwijzing naar waar (en hoe) die waarde te vinden is.
En zelfs wat er terug te verwachten is, een HEX waarde.

Code: [Select]
   waarde = (readEEPROM(eeprom, address), HEX);
    Serial.print(waarde);


Dit zou hetzelfde doen, maar dan moet je wel "waarde" ook definiëren.

Dit is wat ik boven aan dit antwoord bedoelde met gecompliceerd in verband met functies, te gecompliceerd voor de introductie in functies als je het mij vraagt.
Al helemaal wanneer er niets is toegelicht.


Ik hoop dat dit een en ander een stukje duidelijker maakt voor je.
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

#8
Jan 17, 2021, 09:38 pm Last Edit: Jan 17, 2021, 09:39 pm by FTMZ
Ja, er zijn zeer zeker een paar dingen verhelderd.
Toch ben ik bang dat ik mijzelf niet goed heb verwoord:

Even over "wat te doen" na een If statement of een For loop:

Doen de onderstaande 2 code's
Code: [Select]

for(address = 0; address< 5; address++){
    writeEEPROM(eeprom, address, 0x19);} // Writes HEX 19 to the EEPROM

---------------- en---------------
if (Wire.available()) {
    rdata = Wire.read(); }


hetzelfde als:

Code: [Select]

for(address = 0; address< 5; address++)
    writeEEPROM(eeprom, address, 0x19); // Writes HEX 19 to the EEPROM

---------------- en---------------
if (Wire.available())
    rdata = Wire.read();

?

(bij de ene staat "wat te doen" tussen accolades, en bij de andere staan die accolades er niet.
Ik meende dat uit een eerdere reactie van je op te maken. (even los van de inhoud...))

En zo ja... tot welk punt "ziet" de "voorwaarde" wat er gedaan moet worden?
Is dat tot het ";" punt??
Je had zoiets uitgelegd, maar ik zou graag zeker willen zien dat ik het goed heb begrepen.


Een ander punt was nog even die uitleg over:
Code: [Select]

   waarde = (readEEPROM(eeprom, address), HEX);
    Serial.print(waarde);

Ik was daar even mee bezig en ik kreeg rare waardes terug en ik experimenteerde even wat,
om te kijken wat er gebeurde wanneer ik dit of dat zou aanpassen.
Het viel me op dat wanneer ik bovenstaande code aanpaste naar:
Code: [Select]

   waarde = (readEEPROM(eeprom, address));
    Serial.print(waarde, HEX);

Terwijl dit dezelfde waarden waren. Alleen de weergave is anders.


Erik_Baas

Even over "wat te doen" na een If statement of een For loop:

Doen de onderstaande 2 code's
Code: [Select]

for(address = 0; address< 5; address++){
    writeEEPROM(eeprom, address, 0x19);} // Writes HEX 19 to the EEPROM

---------------- en---------------
if (Wire.available()) {
    rdata = Wire.read(); }


hetzelfde als:

Code: [Select]

for(address = 0; address< 5; address++)
    writeEEPROM(eeprom, address, 0x19); // Writes HEX 19 to the EEPROM

---------------- en---------------
if (Wire.available())
    rdata = Wire.read();

?

(bij de ene staat "wat te doen" tussen accolades, en bij de andere staan die accolades er niet.
Ja.

Quote
En zo ja... tot welk punt "ziet" de "voorwaarde" wat er gedaan moet worden?
Is dat tot het ";" punt??
Nee.

* Als het gedeelte "wat te doen" uit één opdracht bestaat, mag die direct na de voorwaarde op dezelfde regel, óf op de volgende regel, en zijn geen accolades nodig.
* Bij meer dan één "wat te doen"-regel moeten ze samen tussen accolades.

Ik zie nu in dat dat tot verwarring leidt, dus misschien is het beter om altijd accolades te gebruiken!?

Quote
Code: [Select]

   waarde = (readEEPROM(eeprom, address), HEX);
    Serial.print(waarde);

Code: [Select]

   waarde = (readEEPROM(eeprom, address));
    Serial.print(waarde, HEX);

Terwijl dit dezelfde waarden waren. Alleen de weergave is anders.
Klopt. De toevoeging ", HEX" bij het toekennen van een waarde aan een variabele doet helemaal niets. Bij Serial.print() echter is het een optie om de weergave in een bepaald formaat te dwingen, in dit geval hexadecimaal. Zie https://www.arduino.cc/reference/en/language/functions/communication/serial/print/ , er zijn meer mogelijkheden!

MAS3

Quote from: FTMZ
Een ander punt was nog even die uitleg over:
Code: [Select]

   waarde = (readEEPROM(eeprom, address), HEX);
    Serial.print(waarde);

Ik was daar even mee bezig en ik kreeg rare waardes terug en ik experimenteerde even wat,
om te kijken wat er gebeurde wanneer ik dit of dat zou aanpassen.
Het viel me op dat wanneer ik bovenstaande code aanpaste naar:
Code: [Select]

   waarde = (readEEPROM(eeprom, address));
    Serial.print(waarde, HEX);

Terwijl dit dezelfde waarden waren. Alleen de weergave is anders.
Ja dat was een foutje van mij (toch weer iets te laat aan het reageren hier)
De ",HEX" hoort dus bij de print opdracht en heeft daarmee te maken met de uitvoer en niks met wat er binnenkomt zoals Erik_Baas al heeft toegelicht.
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

Super, Jongens!!
Dit verduidelijkt het al een heel stuk meer.

Ik ben er nog niet, maar er zit schot in. Dat wil zeggen... Dat ik het schrijven en lezen naar/uit een externe EEPROM begrijp.
Misschien een voorschotje... Maar mijn doel is om een Float naar een EEPROM te schrijven.
Ik begreep dat dit (voor mijn applicatie) 4 bytes waren (32 bits).
Als ik het ordinaire schrijven naar de EEPROM in de vingers heb, wordt dat de volgende stap.

NB
Ik zie twee verschillende manieren om een I2C Library toe te wijzen. #include <Wire.h> en #include "Wire.h".
Ze lijken hetzelfde te doen. Is dat een versie dingetje van Arduino?? Of zit er wat anders achter.
Ik kwam ze beiden tegen in enkele voorbeelden.

Erik_Baas

#12
Jan 18, 2021, 10:45 pm Last Edit: Jan 18, 2021, 10:46 pm by Erik_Baas
#include <Wire.h>; // searches default path for include files
#include "Wire.h"; // searches sketch folder first, then default path for include files

Voor het geval dat je meer dan een versie van een library hebt.

FTMZ

#13
Jan 18, 2021, 11:10 pm Last Edit: Jan 18, 2021, 11:14 pm by FTMZ
***TUSSENTIJDSE UPDATE!!***


Dat ik steeds vage waardes kreeg bij het uitlezen van de EEPROM, die iig niet strookten met de geschreven waardes, kwam omdat in mijn testprogramma er 5x achter elkaar geschreven werd, zonder een moment pauze.
Toen ik er na trial and error achter kwam dat er een fractie aan tijd voor nodig is en ik die implementeerde, begon alles goed te lopen.

Quote
Quote from: Erik_Baas Mon Jan 18 2021 22:45:49 GMT+0100 (Midden-Europese standaardtijd)

#include <Wire.h>; // searches default path for include files
#include "Wire.h"; // searches sketch folder first, then default path for include files

Voor het geval dat je meer dan een versie van een library hebt.
Dank je... Dat verklaart. :)

Go Up