Ankündigung

Einklappen
Keine Ankündigung bisher.

[Konnekting] Idee: BodenfeuchteSensor

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #46
    Ok, klar. Aber theoretisch kann ich ja gar nicht messen während die Pins umgeschaltet werden, da der Arduino nur einen Thread hat. Andererseits benötigt das umschalten ja sicher eine Zeit >0. Das war meine Sorge.
    Das Umschalten geht sehr fix. Das ständige umpolen machst du ja um die Elektroden des Sensors länger leben zu lassen, und nicht um einen Messwert zu erhalten.


    Was etwas unschön und anstrengend ist:
    -Ständiges umstecken von Seriell für's Programmieren und Debuggen
    Das wird mit späteren Geräten hoffentlich einfacher. Die UUPS von Eugen bringt ja einen USB Port mit... Und der Reg-Controller der gerade entsteht, hat dafür einen separaten/umschaltbaren seriellen Anschluss. Da dürfte das auch egal sein.

    Ein weiteres Gerät das gerade in Planung ist hat einen physikalischen Umschalter... Muss man nur noch den Schalter in die passende Endposition schieben um entweder KNX oder den Programmieradapter am µC zu haben.

    -Trennen vom KNX für einige Sekunden nach dem Programmieren der Applikation (via FTDI)
    Versteh ich nicht. Kannst du näher erläutern "warum?"

    -Parametrieren via Suite funktioniert nicht wirklich zuverlässig:
    Oha, das sollte nicht sein. Bisherige Tests waren äußerst stabil. Nicht nur bei mir.

    -Problem des Netzwerk-Interface
    Du meinst die Sache mit den vielen Netzwerkinterfaces, die man aktuell am besten abschaltet? Das wird in beta4 besser, versprochen.

    -Selbst via Lan funktioniert das Programmieren nicht immer (und nie, wenn ich nicht den roten Knopf (=alles) nehme
    Das programmieren erfordert den Empfang eines Telegramms am Arduino. Ist das Problem nur bei deinem Sketch akut, oder ist das ebenfalls mti dem Demo-Sketch zu sehen? Wenns nur in deinem Sketch ist: Check mal die loop() Methode... Da muss alle paar µSekunden Knx.task() aufgerufen werden, sonst ist nicht sicher gestellt dass alle telegramme sauber gelesen werden. Und dann können Programmier-Telegramme verloren gehen.

    Zeig mal deine aktuelle loop() Methode...

    -Programmieren 'im Garten' geht nicht. Aber ich nutze da auch kein KNX-konformes Kabel. Mir scheint da aber noch etwas Robustheit zu fehlen
    Läuft der Sensor vollkommen Autark vom Bus versorgt? Oder hängt in irgend einer Weise eine zweite Spannugsquelle dran?

    Hatte mal ein ähnliches Phänomen mit einer tasterschnittstelle in der Garage: Da hatte ich ein Relais mit einem Transistor als Treiber angeschlossen. problem war: Zusätzliche Spannungsquelle die über die tasterschnittstelle den gleichen GND benutzt hat. Somit wurde der Bus auf der schwarzen Ader hart auf Masse gezogen. Vieles ging noch, aber beim programmieren ging's gehörig in die Hose.

    Ergo: Wenn eine separate Spannungsquelle zum Einsatz kommt: Galvansich trennen.

    Was noch nice to have wäre, ein Export aus der Suite in den Arduino-Sketch. Man könnte automatisch ein CodeGerüst mit dem einlesen der Parameter und KOs etc. erstellen in dem alle im XML defnierten Parameter und KOs enthalten wären. Aber das wäre Luxus.
    Hmm, da muss ich mal drüber schlafen... Ist keine sooo schlechte Idee. Man könnte aus der XML eine Art "Param Init" Methode generieren die man dann per copy&paste in den Sketch ziehen kann. Die Methode kann man dann in setup() eintüten und damit direkt beim start alle Parameter vom EEPROM holen. Und natürlich auch die KO-Liste sowie Param-Länge-Liste. Aber zumindest bei der KO-Liste müsste man die XML noch um die notwendigen Flags erweitern.

    Muss ich mal schauen. Da lässt sich aber sicherlich etwas zusammenzimmern das einem das Leben leichter macht.
    [update]
    Hab da mal ein Ticket angelegt, damit die Idee nicht in Vergessenheit gerät:
    https://github.com/KONNEKTING/KonnektingSuite/issues/10





    Zuletzt geändert von tuxedo; 16.06.2016, 07:14.

    Kommentar


      #47
      Zitat von tuxedo Beitrag anzeigen
      Hmm, da muss ich mal drüber schlafen... Ist keine sooo schlechte Idee. Man könnte aus der XML eine Art "Param Init" Methode generieren die man dann per copy&paste in den Sketch ziehen kann. Die Methode kann man dann in setup() eintüten und damit direkt beim start alle Parameter vom EEPROM holen. Und natürlich auch die KO-Liste sowie Param-Länge-Liste. Aber zumindest bei der KO-Liste müsste man die XML noch um die notwendigen Flags erweitern.

      Muss ich mal schauen. Da lässt sich aber sicherlich etwas zusammenzimmern das einem das Leben leichter macht.
      [update]
      Hab da mal ein Ticket angelegt, damit die Idee nicht in Vergessenheit gerät:
      https://github.com/KONNEKTING/KonnektingSuite/issues/10
      Ergänzung zu Idee: nicht copy&paste, sondern separata init.ino datei (o.ä.) die man dann einfach in den Sketchordner hinzufügen muss. Arduino IDE fasst es dann zusammen.

      Kommentar


        #48
        Zitat von Eugenius Beitrag anzeigen

        Ergänzung zu Idee: nicht copy&paste, sondern separata init.ino datei (o.ä.) die man dann einfach in den Sketchordner hinzufügen muss. Arduino IDE fasst es dann zusammen.
        Magst du deine Ergänzung vllt. direkt im Ticket formulieren?

        Kommentar


          #49
          Hallo,

          ich möchte diesen alten Thread noch einmal aufleben lassen. Leider schaffe ich es nicht, vernünftige Werte von meinem Sensor zu erhalten. Ich erhalte nur Rauschen, siehe hier (link).

          Da der Thread schon sehr alt ist, wiederhole ich mal das Wesentliche:
          Die Schaltung:

          Ich muss den Widerstand messen.
          In den Unterlagen zum Sensor wird angegeben, dass dieser nicht kontinuierlich einen Strom sehen darf. Daher pole ich die Spannung regelmäßig um.
          Hier der Code (loop)
          Code:
          void loop() {
              Knx.task();
              unsigned long currentTime = millis();
          
              // only do measurements and other sketch related stuff if not in programming mode
              if (!Tools.getProgState()) {
                  i=i+1;
                  if (i==100) {
                     i=0;
                #ifdef DEBUG  
                     int d=-(lastTime-currentTime);
                     float  h=(float) d;
                     float c=d/100;
                     lastTime=millis() ;
                     DEBUG.print("average cycle time ");
                     DEBUG.println(c);
                #endif   
                  }  
                  // Get temperature
                  if ((currentTime - previousTimeTemp) >= intervalTempUser) {
          
                      long start = micros();
                      currentTemp = htu.readTemperature();
                      long end = micros();
          #ifdef DEBUG  
          //            DEBUG.print("currentTemp: ");
          //           DEBUG.println(currentTemp);
          //           DEBUG.print("time: ");
          //           DEBUG.println((end-start));
          #endif
                      if (currentTemp < 900) {
                          switch (typeTemp) {
                              case 0:
                                  Knx.write(1, currentTemp);
                                  break;
                              case 1:
                                  if (abs(currentTemp * 100 - previousTemp * 100) >= diffTempUser * 100) {//"*100" => "float to int"
                                      Knx.write(1, currentTemp);
                                      previousTemp = currentTemp;
                                  }
                                  break;
                              default:
                                  break;
                          }
                          limitReached(currentTemp, limitTempMin, limitTempMax, 2, 3, valueTempMin, valueTempMax);
                          previousTimeTemp = currentTime;
                      }
                  }
                  // Get humidity
                  if ((currentTime - previousTimeHumd) >= intervalHumdUser) {
                      long start = micros();
                      currentHumd = htu.readHumidity();
                      long end = micros();
          
          #ifdef DEBUG 
          //            DEBUG.print("currentHumd: ");
          //            DEBUG.println(currentHumd);
          //           DEBUG.print("time: ");
          //           DEBUG.println((end-start));
          #endif
                      if (currentHumd < 900) {
          
                          switch (typeHumd) {
                              case 0:
                                  Knx.write(4, currentHumd);
                                  break;
                              case 1:
                                  if (abs(currentHumd * 100 - previousHumd * 100) >= diffHumdUser * 100) {
                                      Knx.write(4, currentHumd);
                                      previousHumd = currentHumd;
                                  }
                              default:
                                  break;
                          }
                          limitReached(currentHumd, limitHumdMin, limitHumdMax, 5, 6, valueHumdMin, valueHumdMax);
                          previousTimeHumd = currentTime;
                      }
                  }
          //Bodenfeuchte
          // ********** Get Bodenfeuchte***********
                  if (cyclecounter > toggleVoltageCycle ) {
                    cyclecounter=0;
                    //first half of Interval: invert voltage
                         if (measureReady) { // only change if needed, i.e. if not WatermarkPin=HIGH already ; We store this in a variable in order to prevent a read.
                                #ifdef DEBUG 
                                    DEBUG.println("Toggle Voltage; NOT ready to measure"); 
                                #endif
                                    readyToMeasureCounter=0;                       
                                    digitalWrite(WatermarkPin, HIGH);
                                    digitalWrite(ResistorPin,   LOW);
                                  measureReady=0;
                                 }
                          else {  // only change if needed, i.e. if not WatermarkPin=LOW already
                              #ifdef DEBUG 
                                  DEBUG.println("Toggle Voltage; READY to measure"); 
                              #endif                   
                                readyToMeasureCounter=0;
                                digitalWrite(WatermarkPin, LOW);
                                digitalWrite(ResistorPin, HIGH);
                                measureReady=1;
                          }
                  }
                  cyclecounter=cyclecounter+1;
                  if (measureReady) {
                    readyToMeasureCounter=readyToMeasureCounter+1;
                  }
                  #ifdef DEBUG 
                  //DEBUG.println("readyToMeasureCounter, cyclecounter, measureReady");
                  //DEBUG.println(readyToMeasureCounter);
                  //DEBUG.println(cyclecounter);
                  //DEBUG.println(measureReady); 
                  #endif       
                  if (   (readyToMeasureCounter > waitCyclesAfterReadyToMeasure) && (measureReady==1) ) {    // 
                      long start = micros();
                      int currentVoltage_int = analogRead(sensorPin);
                      a=b;
                      b=c;
                      c=currentVoltage_int;
                      currentVoltage_int=(a+b+c)/3;
          
                    if ((currentTime - previousTimeBF) >= intervalBFUser ) {
                      Knx.write(10, currentVoltage_int);
          
                    #ifdef DEBUG  
                        DEBUG.print("Watermarkpin: ");
                        DEBUG.println(digitalRead(WatermarkPin));
                        DEBUG.print("Resistorpin: ");
                        DEBUG.println(digitalRead(ResistorPin));
                        DEBUG.print("currentVoltage_int (also sent via KNX): ");
                        DEBUG.println(currentVoltage_int);
                    #endif
                        if (currentVoltage_int < 1023 && currentVoltage_int > 0 ) {
                            //float currentVoltage = currentVoltage_int*Uref/1023;
                            float currentVoltage_float = (float) currentVoltage_int; //needed for the devision
                            //convert Voltage to Resistance
                            unsigned int   R=18; //kOhm
                            float currentR  = R/(1023/currentVoltage_float-1);  // current resistance of Watermark Sensor in kOhm (kOhm needed later)
                            //convert Resistance to Feuchtigkeit
                            float soilTemp=10;  // FIXME  Connect to parameter later; or measure.
                            float currentBF=-10*((4.093+3.213*currentR)/(1-0.009733*currentR-0.01205*soilTemp));  //unit hPa, convert to positive Values
                    #ifdef DEBUG 
                            DEBUG.print("currentR: ");
                            DEBUG.println(currentR);
                            DEBUG.print("currentBF: ");
                            DEBUG.println(currentBF);
                    #endif
                            switch (typeBF) {
                            case 0:
                                Knx.write(7, currentBF);
                                break;
                            case 1:
                                if (abs(currentBF * 100 - previousBF * 100) >= diffBFUser * 100) {
                                    Knx.write(7, currentBF);
                                    previousBF = currentBF;
                                }
                            default:
                                break;
                            }
                            limitReached(currentBF, limitBFMin, limitBFMax, 8, 9, valueBFMin, valueBFMax);
                            previousTimeBF = currentTime;
                        }
                        else
                        {
                        #ifdef DEBUG 
                            DEBUG.println("Sensor ERROR ");  // FIXME: Connect to object
                        #endif      
                        }  
                    }
              } 
          //End Bodenfeuchte
              }
          }
          Ich würde mich sehr freuen, wenn jemand über den Code schauen würde und mir mit Ideen helfen würde.

          Gruß,
          Hendrik

          Kommentar


            #50
            Ohne jetzt den kompletten Thered zu lesen, gleich ein paar Fragen:
            warum nutzt du immer noch beta3?
            warum muss du umpollen und nicht einfach ab und zu die Spannung zuschalten und abschalten?
            hast du schon diesen Sensor ohne KNX zum laufen gebracht?
            ich würde Spannung zuschalten, x ms warten, dann 3-10 mal messen, mit kleinem Abstand, so um 10ms, dann mittelwert bilden und die Spannung wieder abschalten.
            Code:
             
             currentVoltage_int < 1023
            soll
            Code:
            currentVoltage_int < 1024
            heissen.

            Kommentar


              #51
              Moin,
              vielen Dank für deine Hilfe.

              Zitat von Eugenius Beitrag anzeigen
              Ohne jetzt den kompletten Thered zu lesen, gleich ein paar Fragen:
              Das solltest du auch gar nicht ;-) Daher habe ich versucht das Wesentliche zusammenzufassen.

              warum nutzt du immer noch beta3?
              Ich hab seit der Beta3 nichts geändert. Für Änderungen würde ich upgraden. Dafür muss ich wohl aber auch an den code :-( Ich glaube, da werde ich ne Weile für brauchen.

              warum muss du umpollen und nicht einfach ab und zu die Spannung zuschalten und abschalten?
              Wenn ich es richtig verstanden habe -und mich richtig entsinne- dann soll verhindert werden, dass sich der Sensor auflädt.

              hast du schon diesen Sensor ohne KNX zum laufen gebracht?
              Jain. Ich kann einen Widerstand messen. Der Schwankt nicht.

              ich würde Spannung zuschalten, x ms warten, dann 3-10 mal messen, mit kleinem Abstand, so um 10ms, dann mittelwert bilden und die Spannung wieder abschalten.
              Ich sehe jetzt nichts, was dagegen spricht. Außer dass ich da noch das Umpolen hinzufügen muss. Aber ich sehe auch nicht, warum das -im Gegensatz zu meinem aktuellen Vorgehen- funktionieren sollte.

              Code:
              currentVoltage_int < 1023
              soll
              Code:
              currentVoltage_int < 1024
              heissen.
              Aber das ist nicht das Problem, richtig?

              Gruß,
              Hendrik

              Kommentar


                #52
                Hi,

                ich habe da mal schnell was geschrieben, ungetestet! Aber so stelle ich mir das vor:
                Code:
                unsigned long bodenfeuchtePrev = 0;
                int bodenfeuchteIntervall = 10000;//10 sek
                int bodenfeuchteWarteXms = 100; //100ms warten
                int bodenfeuchteWarteMessungen = 10; //10ms warten zwischen Messungen
                unsigned long bodenfeuchteWartePrev = 0;
                unsigned long bodenfeuchteWarteMessungenPrev = 0;
                bool messunggestartet = false;
                bool warenVorbei = false;
                bool polarity = false;//true = + auf Watermark, false = + auf Widerstand
                byte anzahlMessungenGesamt = 10;
                byte anzahlMessungen = 0;
                int messungen = 0;
                
                //ab hier in die Loop-Schleife
                unsigned long bodenfeuchteCurr = millis();
                //gehe in die schleife wenn die Zeit verstrichen ist oder wenn die Messeung angefangen wurde
                if (((bodenfeuchteCurr - bodenfeuchtePrev) >= bodenfeuchteIntervall)) || messunggestartet) {
                    messunggestartet = true;
                    if(polarity){
                        digitalWrite(WatermarkPin, HIGH);
                        digitalWrite(ResistorPin,   LOW);
                        polarity = false;
                    }
                    if(((bodenfeuchteWartePrev - bodenfeuchteCurr) >= bodenfeuchteWarteXms) && !wartenVorbei){
                        //warte 100ms nach dem die Spg umgepollt wurde
                        wartenVorbei = true;
                        bodenfeuchteWartePrev = millis();
                    }
                    //warte 10ms zwischen Messungen        
                    if(((bodenfeuchteWarteMessungenPrev - bodenfeuchteCurr) >= bodenfeuchteWarteMessungen) && wartenVorbei){
                        //mache 10 Messungen alle 10ms
                        if(anzahlMessungen < anzahlMessungenGesamt){
                            //addiere alle Werte um spätter einen Mittelwert zu bilden
                            messungen =+ analogRead(sensorPin);
                            anzahlMessungen++;
                        }
                        if(anzahlMessungen >= anzahlMessungenGesamt){
                            anzahlMessungen = 0;
                            wartenVorbei = false;
                            messunggestartet = false;
                            digitalWrite(WatermarkPin, LOW);
                            digitalWrite(ResistorPin, HIGH);
                            polarity = true;
                            //Mittelwert berechnen
                            messungen = (int)(messungen / anzahlMessungen); 
                            /*
                             * hier Formel anwenden und Wert senden... 
                             */
                        }
                        bodenfeuchteWarteMessungenPrev = millis();
                    }     
                }
                Im groben:
                die erste Schleife wird entweder alle 10sek aufgerufen oder wenn die Messung gestartet wurde.
                dann werden zuerst 100 ms abgewartet,
                dann alles 10ms Messung gemacht
                nach 10 Mal wird ein Mittelwert gebildet und der Rest berechnet.

                Ich habe angenommen, dass man nur misst, wenn Watermark auf Plus geht. Wenn Widerstand auf Minus geht, dann muss ja den festen Widerstand nicht messen.

                Kommentar


                  #53
                  Moin,

                  ganz herzlichen Dank!
                  Dann werde ich mal die neuste IDE und Suite laden.

                  Wenn ich den Code richtig verstehe, wird zwar umgepolt, aber nicht dafür gesorgt, dass beide Polaritäten gleich häufig/lange vorkommen, oder?

                  Gruß,
                  Hendrik

                  Kommentar


                    #54
                    Genau, das ist asynchron. Du kannst statt 10sek 1100ms einstellen, dann wird es synchron. Der Code ist ja nur ein Ausschnitt. Kannsz auch mit beta3 in deinen Sketch einfügen.

                    Kommentar


                      #55
                      Hallo,

                      das erste Ergebnis sieht nicht gut aus.
                      Der Sensor sendet nur null. Ich kann den Fehler aber nicht finden. Magst du nochmal einen Blick darauf werfen?

                      Ich sehe das Problem nicht.

                      Ich habe die Hardware jetzt mit einem Widerstand von 19k in Betrieb. Die Spannung am Widerstand ist konstant bei -0.13V.
                      Ich habe es danach mit 8k versucht. Da war die Spannung erst kurz bei 1V und ist dann auf -0.17V gesunken. Vermutlich ist das vorher bei den 19k auch passiert.
                      Es scheint mir, als würde nur einmal umgepolt.

                      Gruß und v.a. Danke,
                      Hendrik
                      Angehängte Dateien
                      Zuletzt geändert von henfri; 18.06.2017, 13:28.

                      Kommentar


                        #56
                        Hallo,

                        wäre jemand so lieb nochmal über meinen Code zu schauen? Ich finde den Fehler nicht :-(

                        Gruß&Danke,
                        Hendrik

                        Kommentar


                          #57
                          Hi, ich hatte noch keine Möglichkeit den code anzuschauen, aber ich habe versucht den DB von dem Sensor zu verstehen. Ich habe, ehrlich gesagt, immer noch nicht verstanden warum man den Sensor umpolen muss. Da steht zwar das man nicht lange an Strom hängen soll, aber nicht, das man entladen oder so soll.

                          Kommentar


                            #58
                            Hallo,

                            vielleicht habe ich das auch aus einer anderen Quelle als dem Datenblatt. Ich hatte damals einiges recherchiert.

                            Gruß,
                            Hendrik

                            Kommentar


                              #59
                              Ich würde an deiner Stelle mit ganz kleinem Sketch und Setup versuchen:
                              nur analogRead, Serielle Console und Sensor an VCC und Ax anschließen und Widerstand an Ax und GND.
                              Dann schauen ob es was sinnvolles anzeigt. Die Abfrage ein Mal in 10 - 60 Sekunden machen, damit sich der Sensor nicht viel zu sehr auflädt...
                              Erst dann würde ich schauen was passiert wenn man VCC mit GND tauscht. Bei gleicher Feuchte soll dann der Wert nicht bei X sondern bei 1023-X liegen...
                              Und erst dann mit der automatischer Umpolung anfangen.

                              Kommentar


                                #60
                                Danke, mache ich.

                                Kommentar

                                Lädt...
                                X