Meetfout?

Software die niet past in bovenstaande onderwerpen
Berichten: 313
Geregistreerd: 23 Okt 2016, 20:29

Re: Meetfout?

Berichtdoor benvo » 18 Feb 2018, 11:48

Even een opmerking en vraag om het voor mij duidelijk te maken. De vermenigvuldiging en deling met 100 haal ik weg en alles zit vast! Zoek ik nog verder naar. Dan de vraag: Wanneer je jezelf afvraagt waarom de schrijver van de middelingsketch de readings als Int aangeeft dan zit daar wel een logica in. Immers analogRead geeft toch een Int waarde tussen 0 en 1023, afhankelijk van het gemeten voltage. Waarom dan de Array naar float wijzigen? Zie wat Arduino cc aangeeft hieronder. Hoe zit dit nu precies?

analogRead()
[Analog I/O]


Description


Reads the value from the specified analog pin. The Arduino board contains a 6 channel (8 channels on the Mini and Nano, 16 on the Mega), 10-bit analog to digital converter. This means that it will map input voltages between 0 and 5 volts into integer values between 0 and 1023. This yields a resolution between readings of: 5 volts / 1024 units or, .0049 volts (4.9 mV) per unit.

Natuurlijk staat mijn pHvalue wél op float om die redenen kunnen/moeten de readings ook op float? En natuurlijk het gemiddelde, de average. De readings worden afgetrokken/opgeteld in een total, dus ook float. De readindex is een int en kan zo blijven? Is mijn redenatie zo juist? Hopelijk kun je de vraag ook nog even beantwoorden?

Advertisement

Gebruikers-avatar
Berichten: 4861
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Meetfout?

Berichtdoor nicoverduin » 18 Feb 2018, 12:22

analogRead speelt bij jou niet omdat die PH class dat uitvoert en een float waarde teruggeeft. Dus wat er in die library gebeurt is feitelijk totaal irrelevant. Je hebt een controle uitgevoerd waarbij je de float waardes vergelijkt met jouw meter. Die waren goed dus kun je stellen dat:
a) De sensor goed is
b) de PH library goed werkt
Dus die kun je uitsluiten als oorzaak van afwijkingen. De movingAverage moet dus inderdaad werken met float getallen. Ik heb ooit een library geschreven voor de MovingAverage (zie: https://github.com/nicoverduin/MovingAverage). Daar kun je verschillende moving averages gebruiken. Je hoeft alleen te definiëren (zie het voorbeeld) of je met floats of ints wil werken. De lib zorgt voor de rest. Tevens houd hij rekening met het aantal gelezen elementen. Stel je wilt de MA over 10 waarden maar je hebt er pas 5 gelezen, dan krijg je het gemiddelde over die 5 waarden.
Docent HBO Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 313
Geregistreerd: 23 Okt 2016, 20:29

Re: Meetfout?

Berichtdoor benvo » 18 Feb 2018, 14:37

We zijn een aantal stappen verder. Floats zijn gezet. De *100 en /100 zijn verwijderd. De smoothing procedure gaat nu goed, zo lijkt het. Ook heb ik de meting zelf geïsoleerd van de rest van het programma maar daar is niets uit te halen, ook niet met Serial.print omdat alles zo op en neer vliegt dat er geen touw aan vast is te knopen. Het is dan niet af te lezen of de waardes boven of naar beneden gaan. Na toevoeging van het smoothing deel blijkt dan dat alles nog steeds omgekeerd werkt! Hierbij het totale programma met de wijzigingen, zoals je eerder vroeg.


[code2=cpp][/
Code: Alles selecteren

#include <Nextion.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <RTClib.h>
#include <ChannelManager.h>
#include <EEPROM.h>
#include <AnalogPHMeter.h>


//Data aansluiting is aangesloten op pin 7 on the Arduino.
#define ONE_WIRE_BUS 7

// Legt een oneWire aan om te communiceren met elk oneWire apparaat.
OneWire oneWire(ONE_WIRE_BUS);

// Verbind onze oneWire referentie aan Dallas Temperature.
DallasTemperature sensors(&oneWire);

AnalogPHMeter pHSensor(A0);


//Zet de meters in NexGauge pointer

NexGauge lichtrood = NexGauge(0, 1, "z0");
NexGauge lichtblauw = NexGauge(0, 2, "z1");
NexGauge lichtwit = NexGauge (0, 3, "z2");
NexGauge pH = NexGauge(0, 4, "z3");
NexGauge temp = NexGauge(0, 5, "z4");





// ----------------------- Constanten -----------------------

const int MaxChannels = 3;       // Maximaal te gebruiken kanaalnummers, indien nodig te wijzigen naar meer of minder
const int MaxPoints = 25;        // Maximaal te gebruiken en in te voeren licht intensiteits punten, indien nodig te wijzigen in meer of minder
const int TxPin = 16;            //Tx ledPin op 16
const int numReadings = 20;      //aantal afgelezen monsters van de pH sensor/electrode.

// RTC
RTC_DS3231 rtc;

// Time
DateTime CurrentTime;
unsigned int pHCalibrationValueAddress = 0;

unsigned long temperatuurMillis;
unsigned long tijdMillis;
unsigned long updateMillis;


// ----------------------- Variabelen -----------------------

int phInt = 0;                             //wordt gebruikt voor omrekening naar ronde meter.
float readings [numReadings];              //aflezingen van analoge ingang A0.
int readIndex = 0;                       //Arraypositie van de huidige pH sensor aflezing.
float total = 0;                           //het lopende totaal aantal aflezingen.
int pHsensorPin = A0;                  //pin nummer verbonden met de Po uitgang van de pH sensormodule.

float average = 0;                         //het gemiddelde van de pH sensor aflezingswaarden.


int relaisPin = 8;                      //relais uitgang

float maxPH = 7.05;                    // Waarde hierboven zet de magneetklep open

float minPH = 6.95;                    //waarde hieronder sluit de magneetklep

float x = 0;                           //Wordt gebruikt om temperatuurmetingswaarde in op te slaan.



// ----------------------- Licht -----------------------

// Invul wijze (Uur, Minuut, Intensiteit)
// De verschillen in intensiteit tussen de ingegeven punten zullen gradueel toenemen of afnemen.


Channel Channels[MaxChannels];
Point Points[MaxChannels][MaxPoints];


void InitializeChannels(int channels) {


  // Channel 0:
  int channelNo = 0;                               // Kanaal 0 wordt in gebruik genomen
  int redPin = 9;                                      // Kanaal 0 gebruikt  pin 9 voor de wit-rode balk
  Channels[channelNo] = Channel(redPin, MaxPoints, fademode_linear, Points[channelNo]);      // Initialiseerd kanaal en kiest de FadeMode
  Channels[channelNo].AddPoint(8, 30, 0);           // Voeg punt toe (Kunt ook decimale waarden gebruiken van 0 tot 1 als dat de voorkeur heeft)
  Channels[channelNo].AddPoint(9, 0, 76);
  Channels[channelNo].AddPoint(9 , 30, 204);
  Channels[channelNo].AddPoint(18, 30, 204);
  Channels[channelNo].AddPoint(20, 0, 76);
  Channels[channelNo].AddPoint(20, 30, 25);
  Channels[channelNo].AddPoint(21, 0, 10);
  Channels[channelNo].AddPoint(23, 0, 0);




  // Channel 1:In te voeren
  channelNo = 1;                                // Kanaal 1 wordt in gebruik genomen
  int bluePin = 10;                                     // Kanaal 1 gebruikt pin 10 voor de wit-blauwe balk
  Channels[channelNo] = Channel(bluePin, MaxPoints, fademode_linear, Points[channelNo]);
  Channels[channelNo].AddPoint(9, 0, 0);
  Channels[channelNo].AddPoint(9, 15, 76);
  Channels[channelNo].AddPoint(9, 30, 204);
  Channels[channelNo].AddPoint(18, 30, 204);
  Channels[channelNo].AddPoint(19, 30, 127);
  Channels[channelNo].AddPoint(20, 30, 51);
  Channels[channelNo].AddPoint(22, 0, 25);
  Channels[channelNo].AddPoint(23, 0, 0);



  // Channel 2:
  channelNo = 2;                              // Kanaal 2 wordt in gebruik genomen
  int whitePin = 11;                                   // Kanaal 2 gebruikt pin 11 voor de witte balk
  Channels[channelNo] = Channel(whitePin, MaxPoints, fademode_linear, Points[channelNo]);
  Channels[channelNo].AddPoint(9, 0, 0);
  Channels[channelNo].AddPoint(9, 15, 102);
  Channels[channelNo].AddPoint(9, 30, 204);
  Channels[channelNo].AddPoint(17, 30, 204);
  Channels[channelNo].AddPoint(17, 45, 102);
  Channels[channelNo].AddPoint(18, 00, 10);
  Channels[channelNo].AddPoint(18, 15, 0);




}

// ----------------------- Functies -----------------------


long lastUpdateTime = 0;

// Update licht intensiteit waarden

void UpdateLights(DateTime CurrentTime)
{
  long now = Seconds(CurrentTime.hour(), CurrentTime.minute(), CurrentTime.second());         // Zet de huidige tijd naar seconden sinds middernacht
  if (now != lastUpdateTime)                                                                 // Geeft alleen een update als er een duidelijk waarneembaar verschil in tijd.
  {
    for (int channel = 0; channel < MaxChannels; channel++)                                    // Voor elk kanaal
    {
      analogWrite(Channels[channel].GetPin(), Channels[channel].GetLightIntensityInt(now));   // Krijgt de geupdate licht intensiteit en schrijft de waarde naar de desbetreffende pin
      // update wordt uitgevoerd wanneer de waarde ingelezen wordt




      //Bereken  het percentage output gebaseerd op de huidige licht intensiteit.

      {

        int channel = 0;
        float intensityNow = Channels[channel].GetLightIntensityInt(now);
        float maxIntensity = 255;
        float a = intensityNow / maxIntensity;
        float currentPercent = a * 100;

        //omrekening lichtwaarde naar naar graden voor lichtschaal
        // licht in percentage is linear
        //licht uit (0) angle=-45 degrees
        //licht 100% aan angle=+225degrees
        //range light % is 100
        //range of angle is 270(225+45)
        //float intensity
        float angle = (currentPercent / 100.0 * 270.0) - 45.0;
        if (angle < 0)                          //Als de stand lager is dan 0 en dus negatief wordt.
        {
          angle += 360;                         //maak een positief aantal graden voor de meter
        }
        int rood = int(angle);
        lichtrood.setValue(rood);
      }

      {
        int channel = 1;
        float intensityNow = Channels[channel].GetLightIntensityInt(now);
        float maxIntensity = 255;
        float a = intensityNow / maxIntensity;
        float currentPercent = a * 100;


        //omrekening lichtwaarde naar naar graden voor lichtschaal
        // licht in percentage is linear
        //licht uit (0) angle=-45 degrees
        //licht 100% aan angle=+225degrees
        //range light % is 100
        //range of angle is 270(225+45)
        //float intensity
        float angle = (currentPercent / 100.0 * 270.0) - 45.0;
        if (angle < 0)                            //Als de stand lager is dan 0 en dus negatief wordt.
        {
          angle += 360;                           //maak een positief aantal graden voor de meter
        }
        int blauw = int(angle);
        lichtblauw.setValue(blauw);
      }

      {
        int channel = 2;
        float intensityNow = Channels[channel].GetLightIntensityInt(now);
        float maxIntensity = 255;
        float a = intensityNow / maxIntensity;
        float currentPercent = a * 100;

        //omrekening lichtwaarde naar naar graden voor lichtschaal
        // licht in percentage is linear
        //licht uit (0) angle=-45 degrees
        //licht 100% aan angle=+225degrees
        //range light % is 100
        //range of angle is 270(225+45)
        //float intensity
        float angle = (currentPercent / 100.0 * 270.0) - 45.0;
        if (angle < 0)                               //Als de stand lager is dan 0 en dus negatief wordt.
        {
          angle += 360;                              //maak een positief aantal graden voor de meter
        }
        int wit = int(angle);
        lichtwit.setValue(wit);
      }
    }
  }
  lastUpdateTime = now;
}


// Converteerd de uren:minuten naar seconden sinds middernacht

long Seconds(int hours, int minutes, int seconds) {
  return ((long)hours * 60 * 60) + (minutes * 60) + seconds ;
}

//-------------------- pagina 1 -------------------------------

NexButton b0 = NexButton(0, 6, "b0");                 //knop Instellingen
NexButton b2 = NexButton(1, 2, "b2");                 //knop plus maximum pH
NexButton b3 = NexButton(1, 3, "b3");                 //knop min maximum pH
NexButton b4 = NexButton(1, 4, "b4");                 //knop plus minimum pH
NexButton b5 = NexButton(1, 5, "b5");                 //knop min minimum pH
NexButton for_c = NexButton(1, 6, "b6");              //knop "Clear"
NexButton for_l = NexButton(1, 7, "b7");              //knop "pH 4.0"
NexButton for_m = NexButton(1, 8, "b8");              //knop "pH 7.0"
NexButton for_h = NexButton(1, 9, "b9");              //knop "pH 10.0"
NexButton for_s = NexButton(1, 10, "b10");            //knop "Save"



//Declaratie tekstvelden

//Op de homepagina 0

NexText t0 = NexText(0, 11, "t0");                     //uren, minuten en seconden
NexText t1 = NexText(0, 12, "t1");                     //dag, maand en jaar


//Op pagina 1

NexText t11 = NexText(1, 11, "t11");                    //maximum pH
NexText t12 = NexText(1, 12, "t12");                    //minimum pH
NexText t13 = NexText(1, 13, "t13");                    //pH kalibratie waarde


//buffer definities

char buffer_pHtemp[10];                                  //buffer pH sensor
char buffer_maxPH[10];                                   //buffer pH maximum instel waardes
char buffer_minPH[10];                                   //buffer pH minimum instel waardes

// Registeer een button object op de touch event lijst.

NexTouch *nex_listen_list[] =
{
  &b0,
  &b2,
  &b3,
  &b4,
  &b5,
  &for_c,
  &for_l,
  &for_m,
  &for_h,
  &for_s,
  &t0,
  &t1,
  &t11,
  &t12,
  &t13,
  NULL
};





//------------ pagina 1 Instellingen en kalibratie pH ----------------
void b0PopCallback(void*ptr)
{
  dtostrf(maxPH, 5, 2, buffer_maxPH);                  //drukt maxPH af.
  t11.setText(buffer_maxPH);

  dtostrf(minPH, 5, 2, buffer_minPH);                   //drukt minPH af.
  t12.setText(buffer_minPH);
}

void t11PopCallback(void*ptr)
{
  dtostrf(maxPH, 5, 2, buffer_maxPH);                  //drukt maxPH af.
  t11.setText(buffer_maxPH);
}

void t12PopCallback(void*ptr)
{
  dtostrf(minPH, 5, 2, buffer_minPH);                  //drukt minPH af.
  t12.setText(buffer_minPH);
}

void b2PopCallback(void*ptr)
{
  maxPH += 0.01;
  dtostrf(maxPH, 5, 2, buffer_maxPH);
  t11.setText(buffer_maxPH);
}

void b3PopCallback(void*ptr)
{
  maxPH -= 0.01;
  dtostrf(maxPH, 5, 2, buffer_maxPH);
  t11.setText(buffer_maxPH);
}

void b4PopCallback(void*ptr)
{
  minPH += 0.01;
  dtostrf(minPH, 5, 2, buffer_minPH);
  t12.setText(buffer_minPH);
}

void b5PopCallback(void*ptr)
{
  minPH -= 0.01;
  dtostrf(minPH, 5, 2, buffer_minPH);
  t12.setText(buffer_minPH);
}

void PopCallback_c(void*ptr)
{
  pHSensor.calibrationClear();                           //Clear
}

void PopCallback_l(void*ptr)
{
  pHSensor.calibrationLow(4.000f);                       //pH 4
}

void PopCallback_m(void*ptr)
{
  pHSensor.calibrationMid(7.000f);                       //pH 7
}

void PopCallback_h(void*ptr)
{
  pHSensor.calibrationHigh(10.000f);                     //pH 10
}

void PopCallback_s(void*ptr)
{
  EEPROM.put(pHCalibrationValueAddress, pHSensor.getCalibrationValue());  //slaat Calibratiewaarde op in EEPROM
}








// ----------------------- Setup -----------------------
void setup()
{
  Wire.begin();

  // Klok
  rtc.begin();


  //Zet de baudrate nodig voor de communicatie met het Nextion scherm
  nexInit();
  //merkt de tekstvensters op.

  t11.attachPop(t11PopCallback, &t11);
  t12.attachPop(t12PopCallback, &t12);

  //Merkt de losgelaten knop op.

  b0.attachPop(b0PopCallback, &b0);
  b2.attachPop(b2PopCallback, &b2);
  b3.attachPop(b3PopCallback, &b3);
  b4.attachPop(b4PopCallback, &b4);
  b5.attachPop(b5PopCallback, &b5);

  for_c.attachPop(PopCallback_c, &for_c);
  for_l.attachPop(PopCallback_l, &for_l);
  for_m.attachPop(PopCallback_m, &for_m);
  for_h.attachPop(PopCallback_h, &for_h);
  for_s.attachPop(PopCallback_s,  &for_s);




  //Pin is uitgang
  pinMode(TxPin, OUTPUT);                                   //TxPin wordt als uitgang gebruikt.
  pinMode(relaisPin, OUTPUT);                               //relaisPin wordt als uitgang gebruikt


  sensors.begin();                                          //Start de Temperatuurlibrary/sensor

  struct PHCalibrationValue pHCalibrationValue;
  EEPROM.get(pHCalibrationValueAddress, pHCalibrationValue);
  pHSensor.initialize(pHCalibrationValue);                                    //Start de pH sensor

  for ( int thisReading = 0; thisReading < numReadings; thisReading ++)   //initialiseer alle aflezingen op 0
  {
    readings[thisReading] = 0;
  }
  //Initialiseer de kanaal schema's
  InitializeChannels(MaxChannels);

  // rtc.adjust(DateTime(2018,2,15,12,45,0));               // Stelt de RTC tijd in op de sketch samenstelling, wordt gebruikt voor één run. De tijd wordt gereset op het moment dat een apparaat wordt gereset!


}


// ----------------------- Loop -----------------------


void loop(void)
{

  nexLoop(nex_listen_list);


  // Stelt in op de huidige tijd

  CurrentTime = rtc.now();

  //------------- temperatuurmeting -----------------

  unsigned long huidigeTemp = millis();
  if (huidigeTemp - temperatuurMillis >= 6000)
  {
    sensors.requestTemperatures();                            // Zend het commando om de temperatuurmeting te halen.
    x = sensors.getTempCByIndex(0);                           //Zet de verkregen waarde in x



    //Omrekening waarde naar graden voor de temperatuurschaal
    // Temperature (linear)
    // temperature = 0, angle = -45 degrees
    // temperature = 50, angle = +225 degrees.
    // range of temperature is 50
    // range of angle is 270 (225 + 45)
    //float temperature;
    float angle = (x / 50.0 * 270.0) - 45.0;
    int degrees = int(angle);
    temp.setValue(degrees);
    if (angle < 0)                                             //Als de stand lager is dan 0 en dus negatief wordt.
    {
      angle += 360;                                            //maak een positief aantal graden voor de meter
    }
    temperatuurMillis = huidigeTemp;
  }



  //--------------------- pH waarden meting  --------------------------

  static unsigned long t = millis();
  if (millis() - t > 1000)
  {

    total = total - readings[readIndex];                       //Trek van de laatste pH sensor aflezing af.
    float pHvalue = (pHSensor.singleReading().getpH());        //aflezen van de sensor


    readings[readIndex] = pHvalue;                      //Leest de pH waarde in.
    total = total + readings[readIndex];                       //Voeg de pH sensor aflezing toe aan het totaal.
    readIndex = readIndex + 1;                                 //Vooruit naar de volgende positie in de array.

    if ( readIndex >= numReadings)                             //Als we aan het einde van de array staan...
    {
      readIndex = 0;                                           //...ga terug naar het begin.
    }
    average = total / numReadings;                             //Bereken het gemiddelde.
    pHvalue = average;



    dtostrf(pHvalue, 5, 2, buffer_pHtemp);                     //conversie pH value naar een string
    t13.setText(buffer_pHtemp);

    if (pHvalue >= maxPH)                                     //Als de gemeten pH waarde groter is dan de maxPH waarde
    {
      digitalWrite(relaisPin, LOW);                           //relais is aangetrokken, magneetklep open. CO2 toevoer.
    }

    if (pHvalue <= minPH)                                     //Als de gemeten pH waarde kleiner is dan de minPH waarde
    {
      digitalWrite(relaisPin, HIGH);                          //relais is open, magneetklep gesloten. Geen CO2 toevoer.
    }


    //omrekening naar ronde meter

    phInt = pHvalue * 100;                                   // alles met 100 vermenigvulden om een heel getal te hebben
    signed int graden = map (phInt, 600, 850, -45, 225);     // nu heb je de graden

    if (graden < 0)                                          // Als de stand lager is als nul en dus negatief wordt.
    {
      graden += 360;                                        // maak een positief aantal graden voor de meter
    }

    pH.setValue(graden);                                    //zet de meternaald
    t = millis();
  }


  // Tijd en datum update
  unsigned long huidigetijdMillis = millis();
  if (huidigetijdMillis - tijdMillis > 1000)
  {
    DateTime now = rtc.now();
    char tijdString[9];
    static char vorigeTijd[9];

    sprintf(tijdString, "%02d:%02d:%02d", now.hour(), now.minute(), now.second());

    if (strcmp(tijdString, vorigeTijd) != 0)
    {
      t0.setText (tijdString);                              //Tijd update
      strcpy(vorigeTijd, tijdString);                       //Bewaar vorigeTijd voor de volgende vergelijking
    }



    char datumString[9];
    static char vorigeDatum[9];

    sprintf(datumString, "%02d-%02d-%02d", now.day(), now.month(), now.year());

    if (strcmp(datumString, vorigeDatum) != 0)
    {
      t1.setText (datumString);                            //Datum update
      strcpy(vorigeDatum, datumString);                    //Bewaar vorigeDatum voor de volgende vergelijking
    }
    tijdMillis = huidigetijdMillis;
  }

  // Update lights
  unsigned long huidigeupdateMillis = millis();
  if (huidigeupdateMillis - updateMillis > 10000)
  {
    UpdateLights(CurrentTime);
    updateMillis = huidigeupdateMillis;
  }
}
code2]

Gebruikers-avatar
Berichten: 4861
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Meetfout?

Berichtdoor nicoverduin » 18 Feb 2018, 14:51

Met serial print kun je de laatst gelezen waarde parallel printen met de moving average. Als dat goed loopt lijkt het mij tegenstrijdig met je eerdere opmerking dat serial print van alleen de ph waarde en jouw meter
En als je handig bent maak je onderscheid tussen phvalue en dan bijv avgphvalue
Docent HBO Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 313
Geregistreerd: 23 Okt 2016, 20:29

Re: Meetfout?

Berichtdoor benvo » 18 Feb 2018, 17:59

Even iets duidelijk maken:

Twee foto's. De foto met de PH controller met de rode cijfers is de gekochte controller. Daar vergelijk ik dus mee. De andere foto laat het zelfgemaakte scherm zien waarin het programma draait. Rechtsbovenin worden de gemeten waardes getoond. Nu staat er 11.73 in. Toen de foto gemaakt is was deze niet aangesloten dus let even niet op die waarde, dit terzijde. Zodra ik een Serial.print maak lees ik dus altijd dezelfde waarde als die in dit zelfgemaakte (calibratie-)scherm verschijnt. De tip om een deel van de pHvalue aan te geven als avgPHvalue is een goeie. Hieronder laat ik de gemaakte wijziging in dit programma deel nog even zien.


Afbeelding

Afbeelding


[code2=cpp][/
Code: Alles selecteren

 //--------------------- pH waarden meting  --------------------------

  static unsigned long t = millis();
  if (millis() - t > 1000)
  {

    total = total - readings[readIndex];                       //Trek van de laatste pH sensor aflezing af.
    float pHvalue = (pHSensor.singleReading().getpH());        //aflezen van de sensor


    readings[readIndex] = pHvalue;                             //Leest de pH waarde in.
    total = total + readings[readIndex];                       //Voeg de pH sensor aflezing toe aan het totaal.
    readIndex = readIndex + 1;                                 //Vooruit naar de volgende positie in de array.

    if ( readIndex >= numReadings)                             //Als we aan het einde van de array staan...
    {
      readIndex = 0;                                           //...ga terug naar het begin.
    }
    average = total / numReadings;                             //Bereken het gemiddelde.
    float avgPHvalue = average;







    dtostrf(avgPHvalue, 5, 2, buffer_pHtemp);                     //conversie pH value naar een string
    t13.setText(buffer_pHtemp);

    if (avgPHvalue >= maxPH)                                     //Als de gemeten pH waarde groter is dan de maxPH waarde
    {
      digitalWrite(relaisPin, LOW);                           //relais is aangetrokken, magneetklep open. CO2 toevoer.
    }

    if (avgPHvalue <= minPH)                                     //Als de gemeten pH waarde kleiner is dan de minPH waarde
    {
      digitalWrite(relaisPin, HIGH);                          //relais is open, magneetklep gesloten. Geen CO2 toevoer.
    }


    //omrekening naar ronde meter

    phInt = avgPHvalue * 100;                                   // alles met 100 vermenigvulden om een heel getal te hebben
    signed int graden = map (phInt, 600, 850, -45, 225);     // nu heb je de graden

    if (graden < 0)                                          // Als de stand lager is als nul en dus negatief wordt.
    {
      graden += 360;                                        // maak een positief aantal graden voor de meter
    }

    pH.setValue(graden);                                    //zet de meternaald
    t = millis();
  }

code2]

Gebruikers-avatar
Berichten: 4861
Geregistreerd: 13 Mei 2013, 20:57
Woonplaats: Heemskerk

Re: Meetfout?

Berichtdoor nicoverduin » 18 Feb 2018, 18:50

Ik ben het ff kwijt :)
Je zegt dat als je de phValue rechtstreeks op de Serial zet, dan is deze goed. Dus zou de PH meting goed zijn.
Ik stel voor om gelijk zowel de phValue als de avgPHValue op de serial te zetten. dan kun je zien (en zelfs narekenen) of deze goed is.
Wat jij op jouw scherm laat zien vind ik niet zo boeiend op dit moment. Je moet eerst weten of de waardes die je hebt goed zijn. Ik zit nog niet in de stand (gezien het verleden) dat ik blind vertrouw op jouw code. Dus moet je stap voor stap met Serial.print controleren of het nog steeds goed gaat of niet. Desnoods maak je een simpel programmatje die alleen die PH meet en een gemiddelde en meet bijv een keer per seconde of halve seconde. Zet je de resultaten op de Serial en zet maar eens de output van een regel of 20 hier neer.
Docent HBO Software Engineering, Embedded ontwikkelaar & elektronicus
http://www.verelec.nl

Berichten: 313
Geregistreerd: 23 Okt 2016, 20:29

Re: Meetfout?

Berichtdoor benvo » 18 Feb 2018, 19:29

Je bent het inderdaad kwijt, :-). Hetgeen zeer begrijpelijk is, je zit op een afstand de zaak te bekijken. Niet raar dus.

In grote lijnen meet mijn programma wel, het werkt dus. Maar de waardes werken, alleen voor het PH deel, verkeerd om!
Een eindje terug liet ik al zien dat ik getest heb met alleen het ph programma, wat jij noemt een simpel programmaatje, ik drukte het zelfs af een eindje terug. Ik sprak toen over een geïsoleerd programmadeel. Wanneer ik dat doe, dus alleen het PH deel gebruik vliegen de waardes op en neer, zodanig dat niet is te zien of de waardes stijgen of zakken in vergelijk met de gekochte meter. Ik heb niet verteld dat de serial goed is. Wel zei ik dat de serial klopt met wat ik op mijn eigengemaakte scherm rechtsboven zie. Ik weet dus dat mijn waardes niet goed zijn, in elk geval zijn ze niet goed in het vergelijk met het gekochte scherm. Wanneer de waardes op het gekochte scherm getalmatig naar boven gaan gaat de meting, de getallen dus, in mijn programma naar beneden. Mijn programma werkt dus niet goed. Daar heb je het probleem, alleen ik zie niet waardoor dit veroorzaakt wordt.
Mijn PH sensor zit gekoppeld aan een PHmodule die weer aan de Arduino zit. Bovendien is het hele programma ook aangepast aan een Nextion scherm. Ik moet dus even bekijken hoe ik je vraag aangaande de serial afdrukken kan beantwoorden.

Berichten: 313
Geregistreerd: 23 Okt 2016, 20:29

Re: Meetfout?

Berichtdoor benvo » 19 Feb 2018, 17:09

Denkelijk heb ik de oplossing.

Ik heb het kale programma ingevoerd en via Serial print waardes ingelezen. Je ziet dan dat er, wanneer je bijvoorbeeld de "m" indrukt er een blijvende waarde van 6.99 tevoorschijn kom staande voor PH 7.00. Zie het screenshot. Daaruit blijkt dat het programma alleen zorg kan dragen voor calibratie, niet meer, niet minder. Nu moet er dus een deel toegevoegd worden dat verder gaat en de nu gecalibreerde sensor gebruikt om binnengekomen waardes te meten. Deze laatste waardes moeten dan afgevlakt worden met het dus wel goede smoothing deel. Hoe ik dat nieuwe deel moet toevoegen weet ik nog niet, jij wel?

screenshot en het kale, zoals ik nu weet, calibratie programma.

Afbeelding

[code2=cpp][/
Code: Alles selecteren

#include <AnalogPHMeter.h>
#include <EEPROM.h>

AnalogPHMeter pHSensor(A0);
unsigned int pHCalibrationValueAddress = 0;

void setup(void) {
  Serial.begin(9600);

  struct PHCalibrationValue pHCalibrationValue;
  EEPROM.get(pHCalibrationValueAddress, pHCalibrationValue);
  pHSensor.initialize(pHCalibrationValue);

  Serial.println("Analog PH Meter Calibration");
  Serial.println("The value will be saved on EEPROM");
  Serial.println("Procedure:");
  Serial.println(" - Put pH on pH 7 solution");
  Serial.println(" - Wait until stable");
  Serial.println(" - Press 'm' to calibrate");
  Serial.println(" - Same process for pH 4 and/or pH 10,");
  Serial.println("   except press 'l' for pH 4, and 'h' for pH 10");
  Serial.println();
  Serial.println("All calibration value will be reset after restart.");
  Serial.println("In this example, press 's' to save the value to EEPROM");
  Serial.println("You can freely change the storage.");
  Serial.println("It is not limited to EEPROM only");
  Serial.println();
  Serial.println("*to clear calibration value press 'c'");
  delay(3000);
}

void loop(void) {
  static unsigned long t = millis();
  if (millis() - t > 1000) {
    Serial.println(pHSensor.singleReading().getpH());
    t = millis();
  }

  if (Serial.available()) {
    char c = Serial.read();
    if (c == 'm') {
      pHSensor.calibrationMid(7.000f);
    } else if (c == 'l') {
      pHSensor.calibrationLow(4.000f);
    } else if (c == 'h') {
      pHSensor.calibrationHigh(10.000f);
    } else if (c == 'c') {
      pHSensor.calibrationClear();
    } else if (c == 's') {
      EEPROM.put(pHCalibrationValueAddress, pHSensor.getCalibrationValue());
    }
  }

code2]

Berichten: 313
Geregistreerd: 23 Okt 2016, 20:29

Re: Meetfout?

Berichtdoor benvo » 23 Feb 2018, 17:29

Mijn programma werkt!

Wellicht is de oplossing die ik vond ook interessant voor anderen. Misschien ook zijn er mensen die vinden dat mijn oplossing helemaal fout is of voor verbetering vatbaar. In dat geval hoor ik het graag. Hieronder het gewijzigde deel.
cpp code
Code: Alles selecteren

//--------------------- pH waarden meting  --------------------------

  static unsigned long t = millis();
  if (millis() - t > 1000)
  {

    total = total - readings[readIndex];                       //Trek van de laatste pH sensor aflezing af.
    float pHvalue = (pHSensor.singleReading().getpH());        //aflezen van de sensor



    pHvalue = pHvalue * 100;                                   // Alles met 100 vermenigvuldigen om een heel getal te hebben
    pHvalue = map(pHvalue, 0, 1400, 1400, 0);                  //omkering metingen
    pHvalue = pHvalue / 100;                                   //Delen door 100 om weer een floatwaarde te krijgen

    readings[readIndex] = pHvalue;                             //Leest de pH waarde in.
    total = total + readings[readIndex];                       //Voeg de pH sensor aflezing toe aan het totaal.
    readIndex = readIndex + 1;                                 //Vooruit naar de volgende positie in de array.

    if ( readIndex >= numReadings)                             //Als we aan het einde van de array staan...
    {
      readIndex = 0;                                           //...ga terug naar het begin.
    }
    average = total / numReadings;                             //Bereken het gemiddelde.
    float avgPHvalue = average;



    dtostrf(avgPHvalue, 5, 2, buffer_pHtemp);                     //conversie pH value naar een string
    t13.setText(buffer_pHtemp);

    if (avgPHvalue >= maxPH)                                     //Als de gemeten pH waarde groter is dan de maxPH waarde
    {
      digitalWrite(relaisPin, LOW);                           //relais is aangetrokken, magneetklep open. CO2 toevoer.
    }

    if (avgPHvalue <= minPH)                                     //Als de gemeten pH waarde kleiner is dan de minPH waarde
    {
      digitalWrite(relaisPin, HIGH);                          //relais is open, magneetklep gesloten. Geen CO2 toevoer.
    }


    //omrekening naar ronde meter

    phInt = avgPHvalue * 100;                                   // alles met 100 vermenigvulden om een heel getal te hebben
    signed int graden = map (phInt, 600, 850, -45, 225);     // nu heb je de graden

    if (graden < 0)                                          // Als de stand lager is als nul en dus negatief wordt.
    {
      graden += 360;                                        // maak een positief aantal graden voor de meter
    }

    pH.setValue(graden);                                    //zet de meternaald
    t = millis();
  }

Vorige

Terug naar Overige Software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 1 gast