Steuerung mit einem pH-Meter

Hallo,

auch ich gehör jetzt zur Arduino-Gemeinde und hab auch schon das erste Problem das mich jetzt schon länger beschäftigt und ich dadurch einfach nicht weiterkomme.

ich möchte mit pH-Werten bestimmte Vorgänge steuern. z. B. wenn pH-wert < 5 dann wird eine LED eingeschaltet.
Der pH-Wert wird berechnet und funktioniert einwandfrei, da der Hersteller des pH-meters einen Sketch zur Verfügung stellt. Dieser Wert erscheint zusätzlich im seriellen Monitor angezeigt.

Ich möchte diesen Wert einfach übernehmen und damit eine LED ansteuern. Leider gelinkt es mir nicht

/*
 # This sample code is used to test the pH meter V1.0.
 # Editor : YouYou
 # Ver    : 1.0
 # Product: analog pH meter
 # SKU    : SEN0161
*/
#define SensorPin A0            //pH meter Analog output to Arduino Analog Input 0
#define Offset 0.22            //deviation compensate
#define LED 13
#define samplingInterval 20
#define printInterval 800
#define ArrayLenth  40    //times of collection
int pHArray[ArrayLenth];   //Store the average value of the sensor feedback
int pHArrayIndex=0;   
int LEDpin = 9; 
void setup(void)
{
  pinMode(LEDpin, OUTPUT);
  pinMode(LED,OUTPUT);  
  Serial.begin(9600);  
  Serial.println("pH meter experiment!");    //Test the serial monitor
}
void loop(void)
{
  static unsigned long samplingTime = millis();
  static unsigned long printTime = millis();
  static float pHValue,voltage;
  if(millis()-samplingTime > samplingInterval)
  {
      pHArray[pHArrayIndex++]=analogRead(SensorPin);
      if(pHArrayIndex==ArrayLenth)pHArrayIndex=0;
      voltage = avergearray(pHArray, ArrayLenth)*5.0/1024;
      pHValue = 3.5*voltage+Offset;
      samplingTime=millis();
  }
  if(millis() - printTime > printInterval)   //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
  {
  Serial.print("Voltage:");
        Serial.print(voltage,2);
        Serial.print("    pH value: ");
  Serial.println(pHValue,2);
        digitalWrite(LED,digitalRead(LED)^1);
        printTime=millis();
  }
}
double avergearray(int* arr, int number){
  int i;
  int max,min;
  double avg;
  long amount=0;
  if(number<=0){
    Serial.println("Error number for the array to avraging!/n");
    return 0;
  }
  if(number<5){   //less than 5, calculated directly statistics
    for(i=0;i<number;i++){
      amount+=arr[i];
    }
    avg = amount/number;
    return avg;
  }else{
    if(arr[0]<arr[1]){
      min = arr[0];max=arr[1];
    }
    else{
      min=arr[1];max=arr[0];
    }
    for(i=2;i<number;i++){
      if(arr[i]<min){
        amount+=min;        //arr<min
        min=arr[i];
      }else {
        if(arr[i]>max){
          amount+=max;    //arr>max
          max=arr[i];
        }else{
          amount+=arr[i]; //min<=arr<=max
        }
      }//if
    }//for
    avg = (double)amount/(number-2);
  }//if
  float pHValue, voltage;
  pHValue = 3.5*voltage+Offset;
  
  
  if(pHValue > 5)
  {
    digitalWrite(LEDpin, HIGH);
  }
  else
  {
    digitalWrite(LEDpin, LOW);
  }
  
  return avg;
}

Ich habe am unteren Ende eine if-else-funktion hinzugefügt wobei ich den ph-Value als Variable verwende. Leider reagiert die LED nicht darauf. ich vermute dass der Wert so nicht gelesen oder verarbeitet werden kann. Bei Temperatursensoren hat diese vorgehensweise funktioniert, aber wahrscheinlich ist es überhaupt nicht vergleichbar. Vielleicht hat jemand einen Tipp für mich :wink:

Seit nicht zu hart mit mir, ich bin blutiger Anfänger.

Gruß Noodles

  float pHValue, voltage;
  pHValue = 3.5*voltage+Offset;

Was sollen pHValue und voltage sein? Das ist gar nichts. Das sind lokale Variablen die einen mehr oder weniger zufälligen Wert haben.

Das gehört hier hin in loop():

  if(millis()-samplingTime > samplingInterval)
  {
      pHArray[pHArrayIndex++]=analogRead(SensorPin);
      if(pHArrayIndex==ArrayLenth)pHArrayIndex=0;
      voltage = avergearray(pHArray, ArrayLenth)*5.0/1024;
      pHValue = 3.5*voltage+Offset;
      samplingTime=millis();

      //<--- hier LED schalten --->
  }

Super hat funktioniert

Ich hab mir zwar gedacht dass es nur eine kleine Sache ist, ab das es so einfach ist...

das nenn ich mal ne schnelle Hilfe.
Ich danke dir!

Eine Frage hätte ich noch zum Verständnis.

An der gezeigten Stelle funktioniert die LED-Steuerung, sogar eine zusätzliche Motor- und Relaissteuerung ist mir gelungen.

Da die pH-Wert-messung aber nur ein Teil eines Gesamtsketches wird, stellt sich mir die Frage warum das nur an dieser Stelle funktioniert oder ob man das ändern kann, weil ich will ja jetzt nicht meine gesamte Prozesssteuerung an dieser Stelle Programmieren.

Hat das evtl. was damit zu tun, dass an dieser Stelle pHValue definiert ist und die Steuerung innerhalb der geschweiften Klammern stattfinden muss?
betseht vielleicht die Möglichkeit den pHValue-Wert am Anfang des Sketches zu definieren damit man ihn überall anwenden kann?

Es geht darum dass das pH-Meter nur eines von vielen Sensoren und Motoren ist und ich nicht die ganze Programmierung innerhalb des fertigen pH-Meter-Sketches machen will (ehrlich gesagt weiss ich nicht was dagegen spricht;-) ) aber ich könnte mir vorstellen, dass das auch zu Problemen führen kann.

Vielleicht kann mir das jemand erläutern und hat einen Tipp für mich. Danke

Das funktioniert theoretisch auch an anderer Stelle. Aber du musst schon auf die korrekten Variablen zugreifen. Und diese existieren nur in der entsprechenden if-Abfrage. Du wolltest "pHValue" ausgeben und der wird nunmal dort berechnet.

Du hast aber einfach in einer anderen Funktion zwei Variablen pHValue und voltage deklariert und dann irgendwie gedacht dass die mit den anderen zusammenhängen. Das sind zwei völlig unterschiedliche Variablen die nur gleich heißen.

betseht vielleicht die Möglichkeit den pHValue-Wert am Anfang des Sketches zu definieren damit man ihn überall anwenden kann?

Natürlich. Das nennt man globale Variablen und die sind dann überall verfügbar. Aber auch da musst du dann auf diese Variablen zugreifen und darfst nicht irgendwo noch mal lokale Variablen gleichen Namens erstellen. Jedenfalls nicht wenn du erwartest, dass diese dann irgendeinen Zusammenhang mit den globalen Variablen haben. Das kann man machen, aber die überdecken dann die globalen Variablen.

Ansonsten kannst du auch Variablen per Parameter an Funktionen übergeben:

void func1()
{
    int value = ....;

    func2(value);
}

void func2(int value)
{
    Serial.println(value);
}

So kann man schön Eingabe, Verarbeitung und Ausgabe trennen. Es ist nämlich keine gute Idee das alles an einer Stelle zu machen, sei es in loop() oder in einer Funktion. Normal schreibt man sich getrennte Funktionen für alles und ruft die dann nacheinander auf. Das geht auch mit globalen Variablen:

int value;

void loop()
{
   eingabe();
   verabreitung();
   ausgabe();
}

void eingabe()
{
   value = ...;
}

void verarbeitung()
{
   ...
}

void ausgabe()
{
   Serial.println(value);
}

Vereinfacht. Ausgabe würde man da z.B. zeitverzögert machen so wie das auch bei dir ist.

So kannst du auch den Code von ph-Meter und Motor trennen indem du alles in getrennte Funktionen packst. z.B. eine Funktion phMeter() schreiben, die dann alles weitere erledigt.

Du kannst in der Arduino IDE übrigens verschiedene Tabs mit mehreren .ino Datei anlegen. So kann man Code etwas organisieren ohne gleich mit Klassen anzufangen. Du musst allerdings beachten dass die in alphabetischer Reihenfolge bearbeitet werden. Deshalb kann es zu Problemen mit der Sichtbarkeit von Variablen kommen, wenn die Namen nicht passen. Funktionen und Variablen müssen bekannt sein bevor sie verwendet werden. Also z.B. alle globalen Variablen in eine Datei namens aGlobal.ino packen.

Das ging ja wieder schnell;-)

Diese Antwort ist sehr ausführlich, aber ich glaube ich hab noch nicht das Hintergrundwissen um diese Vorschlägu wirklich zu verstehen (ich bin ganz ehrlich). ich werde es jetzt und die folgenden Tage mal versuchen und gucken wie es klappt.
Ich gespannt ob mein Projekt mal fertig wird.

Nochmals vielen Dank