anologe arduino calibratie opslaan in eeprom

Goedenmiddag,

Om met de deur in huis te vallen:

op het moment bezit een programmatje van mij een druksensor die op waardes 30 gram en 200 gram gecalibreerd worden.
dit volgens het preciepe van de standart tuturial die op de website van arduino te vinden is.

Nu is dit een werkend concept aleen ik zoek meer.
elke keer als de arduino spanningsloos is geweest moet ik opnieuw een calibratie uitvoeren,

Het is mogelijk om bepaalde waardes in de eeprom op te laten slaan,
en daar komt mijn probleem dus.
Ik krijg dit niet voor elkaar,
het geheel moet als volgt zijn:

arduino start op -> leest van eprom de correcties en gebruikt deze in zijn programma -> als een knop wordt ingedrukt (voor het gemakt ingang 13) moet deze in "calibratiemode" gaan -> laagste waarde moet worden toegebracht en dit wordt dmv een knop bevestig (dit moet dus ook opslaan in de eprom) -> hoogste waarde wordt gemeten en door een knop bevestig (ook dit moet worden opgeslagen in de eeprom) en als de calibratie is gelukt moet de led 2 keer knipperen.

Heeft iemand ervaring met het eeprom gedeelte van de arduino?
na enkele uuren gegoogeld, en nog meer uuren geprobeert te hebben komt er een / door mijn

bijgevoegd is de "standart"code can de arduino website, over wat hun caibratie noemen.

edit:
code vervangen door de link

https://www.arduino.cc/en/Tutorial/Calibration

[Bericht gewijzigd door Piet potlood op zondag 13 maart 2016 19:08:06 (43%)

c code:

const int sensorPin = A0;    // pin that the sensor is attached to
#include <EEPROM.h>     

     
int knopje1 = 2;
int knopje2 = 3;




// variables:
int sensorValue = 0;         // the sensor value

int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value
int sensorEEPROMmin = EEPROM.read(256);                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax = EEPROM.read(156);                 // waarde uit de eprom over maximale druk



void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
sensorValue = analogRead(sensorPin);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);

}

void loop() {
  // put your main code here, to run repeatedly:
if (knopje1 = HIGH) {
    // record the maximum sensor value
     (sensorValue > sensorMax);                     // calibratie van maximale druk
      sensorMax = sensorValue;
      EEPROM.write(156,sensorValue);
      delay(1000);
    }
    
if (knopje2 = HIGH) {
    // record the minimum sensor value
     (sensorValue < sensorMin);                     // calibratie van minimale druk
      sensorMin = sensorValue;
      EEPROM.write(256, sensorValue);
      delay(1000);
      }


  

   // read the sensor:
  sensorValue = analogRead(sensorPin);                    
 
  // apply the calibration to the sensor reading
  sensorValue = map(sensorValue, sensorEEPROMmin, sensorEEPROMmax, 0, 255);
  
  // in case the sensor value is outside the range seen during calibration
  sensorValue = constrain(sensorValue, 0, 255);
 
 
}

Dit was een beetje mijn idee.

maar ik weet niet goed of dit nu wel verstandig is/ werkt.

mijn grootste punt is: wordt nu bij elke cycel de eeprom gelezen? (dit moet natuurlijk niet) 1 maal de waarde eruit trekken bij opstarten en daarna die waarde in systeem laten staan.

Calibratie houd hier schaling in.

Je input gaat van 0..1024, en hij pakt daarvan de laagste en hoogste waarde die hij in 5 sec ziet.

Dus als je sensor van (omgezet) 60 tot 1010 loopt, wordt dat geschaald (map functie) naar 0..255

Het opslaan in de eeprom is toch niet moeilijk? Zie https://www.arduino.cc/en/Tutorial/EEPROMWrite

Let op dat dit niet oneindig kan (iedere locatie 1000x max ofzo), dus niet in een lus de waarde wegschrijven.

GMT+1

hallo, progger

dank voor de reactie. ik denk dat u mijn laatste bericht niet heeft gezien.
ik weet gelukkig dat het niet een echte calibratie is, maar ik gebruik het ook voor de map functie.

hopelijk kunt u wel antwoord geven op mijn vraag hiervan (eeprom) :)

mvg
piet

[Bericht gewijzigd door Piet potlood op zondag 13 maart 2016 19:22:15 (25%)

je code klopt niet helemaal.

normaal zet je voor de setup de vaste waarden.

dingen zoals "lees 1maal uit eeprom" moet je in de setup() plaatsen. dan wordt het enkel tijdens het opstarten uitgevoerd.

het is wel goed van je dat je de delay heb gebruikt. als je de knop nu een goeie seconde indrukt, wordt de waarde maximaal 2x weggeschreven.

(je moet wel een DigitalRead toevoegen, nu bevat de waarde knopje1 het nummer van je ingang, niet de waarde van die ingang)

GMT+1

dus meer in de richting van dit?

btw: dit is natuurlijk een proefsketch,

c code:

const int sensorPin = A0;    // pin that the sensor is attached to
#include <EEPROM.h>     

     
int knopje1 = 2;
int knopje2 = 3;




// variables:
int sensorValue = 0;         // the sensor value

int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value
int sensorEEPROMmin = EEPROM.read(256);                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax = EEPROM.read(156);                 // waarde uit de eprom over maximale druk


void setup() {
  // put your setup code here, to run once:
EEPROM.read(256);                 // waarde uit de eprom over minimale druk 
EEPROM.read(156);                 // waarde uit de eprom over maximale druk
Serial.begin(9600);
sensorValue = analogRead(sensorPin);
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);


}

void loop() {
  // put your main code here, to run repeatedly:
if ( digitalRead(knopje1 = HIGH)) {
    // record the maximum sensor value
     (sensorValue > sensorMax);                     // calibratie van maximale druk
      sensorMax = sensorValue;
      EEPROM.write(156,sensorValue);
      delay(1000);
    }
    
if ( digitalRead(knopje2 = HIGH)) {
    // record the minimum sensor value
     (sensorValue < sensorMin);                     // calibratie van minimale druk
      sensorMin = sensorValue;
      EEPROM.write(256, sensorValue);
      delay(1000);
      }


  

   // read the sensor:
  sensorValue = analogRead(sensorPin);                    
 
  // apply the calibration to the sensor reading
  sensorValue = map(sensorValue, sensorEEPROMmin, sensorEEPROMmax, 0, 255);
 
  // in case the sensor value is outside the range seen during calibration
  sensorValue = constrain(sensorValue, 0, 255);
 
 
}

Even wat dingetjes aangepast, verder niet getest:

c code:


#include <EEPROM.h>     
const int sensorPin = A0;    // pin that the sensor is attached to
const int knopje1 = 2;
const int knopje2 = 3;


// variables:
int sensorValue = 0;         // the sensor value
int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value
int sensorEEPROMmin = 0;                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax = 0;                 // waarde uit de eprom over maximale druk


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(knopje1, INPUT);
  pinMode(knopje2, INPUT);
  pinMode(sensorPin, INPUT);
  sensorEEPROMmin = EEPROM.get(256);                 // waarde uit de eprom over minimale druk 
  sensorEEPROMmax = EEPROM.get(156);                 // waarde uit de eprom over maximale druk
  // sensorValue = analogRead(sensorPin);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (digitalRead(knopje1) == HIGH) {
    // record the maximum sensor value
    sensorValue = analogRead(sensorPin);
    if (sensorValue <> sensorMax) {                   // calibratie van maximale druk
      sensorMax = sensorValue;
      EEPROM.put(156,sensorValue);
      Serial.print("SensorMax gewijzigd naar:"); Serial.println(sensorValue);
    }
    delay(1000);
  }
	
  if (digitalRead(knopje2) == HIGH) {
    // record the minimum sensor value
    sensorValue = analogRead(sensorPin);
    if (sensorValue <> sensorMin) {                   // calibratie van minimale druk
      sensorMin = sensorValue;
      EEPROM.put(256, sensorValue);
      Serial.print("SensorMin gewijzigd naar:"); Serial.println(sensorValue);
    }
    delay(1000);
  }
}


  
int readSensor() {
  sensorValue = analogRead(sensorPin);   // read the sensor:                  
  return map(sensorValue, sensorEEPROMmin, sensorEEPROMmax, 0, 255);// apply the calibration to the sensor reading
  // sensorValue = constrain(sensorValue, 0, 255); // in case the sensor value is outside the range seen during calibration <-- kan niet gebeuren na map(x,x,x,0,255)
}
 

Al vraag ik me wel af wat je precies wilt bereiken met deze 4 variabelen:

c code:

int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value
int sensorEEPROMmin = 0;                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax = 0;                 // waarde uit de eprom over maximale druk

Edit: typo bij digitalRead's

kleine wijzigingen:
-inlezen naar setup
-pinmode naar input
-correct gebruik digitalRead
dingen die je nog moet oplossen:
-na het calibreren wordt de waarde wel opgeslagen, maar neit in het programma gebruikt. je zal dus moeten herstarten.
-beveiliging tegen onjuiste waarden.

c code:



const int sensorPin = A0;    // pin that the sensor is attached to
#include <EEPROM.h>     
 
 
int knopje1 = 2;
int knopje2 = 3;
 
 
 
 
// variables:
int sensorValue = 0;         // the sensor value
 
int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value
int sensorEEPROMmin = 1;                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax = 0;                 // waarde uit de eprom over maximale druk
 
 
void setup() {
  // put your setup code here, to run once:
sensorEEPROMmin = EEPROM.read(256);                 // waarde uit de eprom over minimale druk 
sensorEEPROMmax = EEPROM.read(156);                 // waarde uit de eprom over maximale druk
Serial.begin(9600);
sensorValue = analogRead(sensorPin);
pinMode(2,INPUT);                                  // je leest de INgang
pinMode(3,INTPUT);
 
 
}
 
void loop() {
  // put your main code here, to run repeatedly:
if ( digitalRead(knopje1) == HIGH) {                //correcte manier
    // record the maximum sensor value
     (sensorValue > sensorMax);                     // calibratie van maximale druk
      sensorMax = sensorValue;
      EEPROM.write(156,sensorValue);
      delay(1000);
    }
 
if ( digitalRead(knopje2) == HIGH) {
    // record the minimum sensor value
     (sensorValue < sensorMin);                     // calibratie van minimale druk
      sensorMin = sensorValue;
      EEPROM.write(256, sensorValue);
      delay(1000);
      }
 
 
 
 
   // read the sensor:
  sensorValue = analogRead(sensorPin);                    
 
  // apply the calibration to the sensor reading
  sensorValue = map(sensorValue, sensorEEPROMmin, sensorEEPROMmax, 0, 255);
 
  // in case the sensor value is outside the range seen during calibration
  sensorValue = constrain(sensorValue, 0, 255);
 
 
}
GMT+1

hartelijk bedankt!!

idd ik zag ook de input/output fout ;) (en u heeft daar ook een spelfout gemaakt :P)
de rest is een slimme oplossing.

wat bedoelt u met "beveiliging tegen onjuiste waarden."

over de sensor waarde heen?
of meer in de richting als waarde onder x is of over x dan error?

ik bedoel, als er een keer wat kapot gaat, pak je een nieuwe processor, dan kan het geheugen van alles bevatten (meestal 0xff = 255).

je programma moet ertegen kunnen dat je min en max bijvoorbeeld gelijk zijn. of je min is groter dan je max.

dit kun je afvangen en omdat dit het resultaat is van een verkeerde kalibratie of lege processor, eerst een kalibratie forceren.

(de gemiddelde gebruiker klikt net zo lang op ok tot hij werkt, ook al staat er duidelijk dat de meting niet klopt)

GMT+1

Begrijpelijk,
ik heb een opzetje in mijn programma dat ervoor zorgt dat dit niet voor kan komen/ tegen gaat komen.

nu heb ik nog een probleem.

er zijn 2 sensors waarvan het gemiddelde moet worden gepakt.
bijde moeten worden gecalibeert etc.

totzover niet bar interessant en moeilijk.

Aleen wil ik het gemiddelde van de bijde pakken
door "sensorValue = (sensorValue1+sensorValue2)/2 "

maar in de erialread op de pc komt sensor 1 niet boven de 200 (van de 1024) terwijl sensor 2 dit wel behaald, ookal wissel ik om blijven de waardes zo op de pinnen.
dus het gemiddelde klopt van geen kant.

die ik iets simpels verkeerd, of is hetniet mogelijk om het op deze manier op te lossen/ hebben jullie een betere tip waarmee ik kan gaan werken?

mvg
piet

zijn sensor 1 en sensor 2 van hetzelfde type? kun je de code plaatsen?

GMT+1

jazeker het zijn iditieke sensors.

Het opzetje dat ik gemaakt heb.

c code:


#include <EEPROM.h>     
 
 
int knopje1 = 2;
int knopje2 = 3;
int knopje3 = 4;
int knopje4 = 5;

const int sensorPin1 = A0;    // pin that the sensor is attached to
const int sensorPin2 = A1; 
 
 
// variables:
int sensorValue = 0;                     // the sensor value (gemiddeld)
int sensorValue1 = 0;
int sensorValue2 = 0;

  
int sensorMin = 1023;                    // minimum sensor value
int sensorMax = 0;                       // maximum sensor value
int sensorEEPROMmin1 = 1;                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax1 = 0;                 // waarde uit de eprom over maximale druk
int sensorEEPROMmin2 = 1;                 // waarde uit de eprom over minimale druk 
int sensorEEPROMmax2 = 0;                 // waarde uit de eprom over maximale druk 

 
void setup() {
  // put your setup code here, to run once:
sensorEEPROMmin1 = EEPROM.read(30);                    // waarde uit de eprom over minimale druk 
sensorEEPROMmax1 = EEPROM.read(60);                    // waarde uit de eprom over maximale druk
sensorEEPROMmin2 = EEPROM.read(90);                    // waarde uit de eprom over minimale druk 
sensorEEPROMmax2 = EEPROM.read(120);                    // waarde uit de eprom over maximale druk

Serial.begin(9600); 
sensorValue1 = analogRead(sensorPin1);
sensorValue2 = analogRead(sensorPin2);
pinMode(2,INPUT);                                      // je leest de INgang
pinMode(3,INPUT);
pinMode(4,INPUT);                                      
pinMode(5,INPUT); 
 
}
 
void loop() {
  // put your main code here, to run repeatedly:
if ( digitalRead(knopje1) == HIGH) {                   //correcte manier
    // record the maximum sensor value
     (sensorValue1 > sensorMax);                        // calibratie van maximale druk
      sensorMax = sensorValue;
      EEPROM.write(30,sensorValue1);
      delay(1000);
    }
 
if ( digitalRead(knopje2) == HIGH) {
    // record the minimum sensor value
     (sensorValue1 < sensorMin);                        // calibratie van minimale druk
      sensorMin = sensorValue;
      EEPROM.write(60, sensorValue1);
      delay(1000);
      }

if ( digitalRead(knopje3) == HIGH) {                   //correcte manier
    // record the maximum sensor value
     (sensorValue2 > sensorMax);                        // calibratie van maximale druk
      sensorMax = sensorValue2;
      EEPROM.write(90,sensorValue2);
      delay(1000);
    }

if ( digitalRead(knopje4) == HIGH) {
    // record the minimum sensor value
     (sensorValue2 < sensorMin);                        // calibratie van minimale druk
      sensorMin = sensorValue2;
      EEPROM.write(120, sensorValue2);
      delay(1000);
      }
  
 
 
 
   // read the sensor:
  sensorValue1 = analogRead(sensorPin1);
  sensorValue2 = analogRead(sensorPin2);                    
 
  // apply the calibration to the sensor reading
  sensorValue = map(((sensorValue1 + sensorValue2)/2) , ((sensorEEPROMmin1 + sensorEEPROMmin1)/2), ((sensorEEPROMmax1+sensorEEPROMmax1)/2), 0, 255);
 
  // in case the sensor value is outside the range seen during calibration
  sensorValue = constrain(((sensorValue1+sensorValue2)/2) , 0, 255);
 
 

je kan dit natuurlijk testen door een sensor op beide ingangen aan te sluiten (tegelijk), je zou dan identieke waarden moeten krijgen.

waarschijnlijk ben je tegen deze bug aangelopen:
https://github.com/arduino/Arduino/issues/3064

als je 2 verschillende kanalen direct achter elkaar wil uitlezen, dan kan het even duren voordat de meetwaarde intern 'doorkomt'

als je een delay(10) toevoegt, zou het kunnen werken.

GMT+1

Op 15 maart 2016 11:38:39 schreef Piet potlood:
maar in de erialread op de pc komt sensor 1 niet boven de 200 (van de 1024) terwijl sensor 2 dit wel behaald, ookal wissel ik om blijven de waardes zo op de pinnen.

Als je dit kunt constateren, dan heb je dus een werkend stukje code. Waarom post je dat dan niet? Dat wat je tot nu toe post krijg je met geen 10 paarden gecompileerd.

En een int lezen en schrijven met EEPROM.read en EEPROM.write gaat ook niet zo, een int is 2 bytes, en zo lees en schrijf je maar 1 van de 2 bytes.

Edit: Gek genoeg compileerd het na toevoegen van een } aan het eind nog ook.

Maar wat is dit:

c code:

(sensorValue2 < sensorMin);                        // calibratie van minimale druk

De compiler klaagt er niet over, maar moet dat niet zoiets zijn:

c code:

if (sensorValue2 < sensorMin) {                        // calibratie van minimale druk
buckfast_beekeeper

Golden Member

Op 13 maart 2016 19:03:31 schreef Progger:
....

Het opslaan in de eeprom is toch niet moeilijk? Zie https://www.arduino.cc/en/Tutorial/EEPROMWrite

Let op dat dit niet oneindig kan (iedere locatie 1000x max ofzo), dus niet in een lus de waarde wegschrijven.

Valt wel mee. Een ATmega644 geeft in zijn datasheet volgende waarde

Write/Erase cyles: 10,000 Flash/100,000 EEPROM

Van Lambiek wordt goede geuze gemaakt.

code:


(sensorValue2 < sensorMin);   

Is op zich correcte code. Het vergelijkt 2 variabelen en levert een boolean result (true/false). Vervolgens wordt er niets met dat result gedaan. Dus uiteindelijk heeft de code geen effect. Grote kans dat de compiler het zelfs gewoon weg optimaliseert.

Dus in het volgende stukje

code:


if ( digitalRead(knopje1) == HIGH) {                   //correcte manier
    // record the maximum sensor value
     (sensorValue1 > sensorMax);                        // calibratie van maximale druk
      sensorMax = sensorValue;
      EEPROM.write(30,sensorValue1);
      delay(1000);
    }

Hier wordt bij het indrukken van knopje1 altijd de sensorValue naar sensorMax gecopieerd, en vervolgens wordt sensorValue1 naar Eeprom geschreven. Maar waarschijnlijk wil je alleen de Eeprom schrijven als de SensorValue1 groter is dan SensorMax.
Dat zou dan zo moeten, zoals BVZ ook al had laten zien:

code:


if ( digitalRead(knopje1) == HIGH)                    //correcte manier
{   // record the maximum sensor value
    if (sensorValue1 > sensorMax)                          // calibratie van maximale druk
    {    sensorMax = sensorValue;
         EEPROM.write(30,sensorValue1);
         delay(1000);
    }
}

Maar dan nog gaat het fout. De sensorValue1 heeft een bereik van 0 .. 1023, recht van de A/D converter terwijl sensorMax een veel kleiner bereik heeft tgv de map en constrain funkties. Dus dan heeft het niet veel nut om die te gaan vergelijken (iets met appels en peren) ;-)

En dan is het niet erg logisch om in de loop eerst de waarde van de sensor te gaan gebruiken, en pas daarna de sensor te gaan lezen.
Normaal gesproken ga je eerst de sensorwaarde inlezen, en dan direct de gelezen waarde gebruiken.

En de EEPROM read en write functies werken inderdaad met bytes. Dus de getallen die je wegschrijft en terughaalt in/uit de Eeprom hebben een bereik van 0 .. 256. Dus als je 400 wegschrijft, en je leest die waarde weer terug, dan krijg je 144! Dat is vast niet de bedoeling.

Dat kan je oplossen door de Value op te splitsen in 2 delen:

code:


void EepromWriteInt(int address, int Value)
{  EEPROM.write(address    , Value / 256);  //< High byte first
   EEPROM.write(address + 1, Value % 256);  //< Then Low byte
}

int EepromReadInt(int Address)
{  return EEPROM.read(Address) * 256)       //< Read High byte 
        + EEPROM.read(Address + 1);         //< REad Low byte 
}

Als je die functies hebt dan kun je die gebruiken om je data in de Eeprom te schrijven:

code:


...
   EepromWriteInt(30,sensorValue1);
...
en
... 
   sensorEepromMin1 = EepromReadInt(30);

hallo!,

Maar wat is dit:
c code:
(sensorValue2 < sensorMin); // calibratie van minimale druk

De compiler klaagt er niet over, maar moet dat niet zoiets zijn:
c code:
if (sensorValue2 < sensorMin) { // calibratie van minimale druk

Geen zorgen, in de kladversie klopte het idd niet hellmaal, maar in mijn "goede code" klopte dit wel ;)

Maar dan nog gaat het fout. De sensorValue1 heeft een bereik van 0 .. 1023, recht van de A/D converter terwijl sensorMax een veel kleiner bereik heeft tgv de map en constrain funkties. Dus dan heeft het niet veel nut om die te gaan vergelijken (iets met appels en peren) ;-)

okee, mijn bedoeling hier was het om te zetten in een andere eenheid die gelijk staat aan de ohmseweestand. en hiervan deze waarde een "if" voorwaarde te maken.

Misschien heeft hier een betere tip voor?!?

En beide hebben helemaal gelijk met de EEPROM!.
Ik kreeg soms hele gekke waardes uit de eeprom terug geschreven.

hartelijk dank voor de oplossing hiervan!!!!
eerlijk gezegd. heb ik hier geen momend bij stil gestaan :3.
Ik heb ook wat geprobeerd met de code. maar dat werdt 1 groote ramp met veel problemen in de compiler..

hartelijk dank voor dit stukje WERKENDE code :D

De 0 en 2(nog iets)
Zouden dan bijv gram zijn.
En dan bij de if funcites gewoon kunnen aangeven tussen 40-60 gram .... Etc..