Wert/e Speichern [Loop-Schleife]



  • UPDATE:(Runterscrollen)

    Hallo Leute,
    ich bastle gerade an einem großen Arduino-Projekt und möchte meinen Code optimieren.
    Den Code habe ich von anderen Sachen extrahiert und hier ausgeführt damit das Problem besser verstehen werden kann. In dem arduino.cc Forum haben Leute versucht mir zu helfen aber es scheint ein Code spezifisches Problem zu sein.

    (https://forum.arduino.cc/index.php?topic=348278.0)

    Das Problem:
    In dem Code bzw. bei der Loop-Schleife werden die Werte für den nächsten Loop-Durchgang nicht gespeichert.

    Wenn ich den „serial Monitor öffne, dann sehe ich das da permanent das „PWM-Signal „gesendet wird. Ich will, dass nur dann der PWM-Signal gesendet wird, wenn am POTI gedreht wird“

    Der Aufbau:
    Ein Arduino, mit einem Poti, und einem LED

    Die Funktion:
    Man dreht an dem Poti und die LED wird gedimmt.

    CODE:
    Ich habe 2 Möglichkeiten ausprobiert:
    Ich will, dass der Wert getauscht wird (siehe Code) und für den nächsten Loop Durchlauf gespeichert wird (Zeile 25)

    Der Code (Versuch 1):

    int ledPin = 9;      // LED an Pin nr 9 
    
    int analogPin = 1;   // potentiometer an analogPin1
    
    int valNEW = 0;         // variable 
    int valOLD = 0;         // variable  
    
    void setup()
    
    {
    pinMode(ledPin, OUTPUT);   // Pin 9 als ausgang
    Serial.begin(9600);    // opens serial port, sets data rate to 9600 bps
    }
    
    void loop()
    {
      valNEW = analogRead(analogPin);   // Liest den aktuelen Analogwert
      if (valNEW != valOLD)              // verleicht die Werte valNEW und valOLD
    		{
    			int pwm = (valNEW / 4); //PWM-Signal wird berechnet
    			analogWrite(ledPin, pwm);  // PWM-Signal wird an LED-Pin gesendet
    			Serial.println(pwm); //PWM-Signal kann man an den serial-Monitor sehen       
    
    			valOLD = valNEW;  // valNEW wird zu valOLD gemacht und sollte für den nächsten Loop-durchgang gespecihert werden
    		}
    }
    

    Der Code (Versuch 2):
    Hier wurde mit Array Felder erstellt
    entscheidende Zeile: 17

    const byte ledPin = 9;      // LED connected to digital pin 9
    const byte anaPin = A1;  // potentiometer connected to analog pin 1
    byte val[2];
    
    void setup()
    {
    pinMode(ledPin, OUTPUT);   // sets the pin as output
    Serial.begin(9600);        // opens serial port, sets data rate to 9600 bps
    }
    
    void loop()
    {
      val[0] = analogRead(anaPin);
      val[1] = analogRead(anaPin);
      if (val[0] != val[1])
        {
         int pwm = (val[1]>>2);
         analogWrite(ledPin, pwm); 
         Serial.println(pwm);       
        }
    }
    

    Für Jegliche Hilfe bin ich dankbar 🙂

    UPDATE:
    UPDATE (kurz und knapp):
    Mit diesen Code Funktioniert die Schaltung. Man muss beachten, dass die Messung von dem Poti-Signal schwankt. Man tut einfach eine Mittelwert-funktion einbauen und der Code funktioniert.

    Danke an DirkB und Furble Wurble 👍 👍 👍

    int ledPin = 9;      // LED an Pin nr 9 
    int analogPin = 5;   // potentiometer an analogPin1 
    float pwmOLD = 0;         // variable 
    float pwmNEW = 0;         // variable   
    
    void setup()   
    { 
    pinMode(ledPin, OUTPUT);   // Pin 9 als ausgang 
    Serial.begin(9600);    // opens serial port, sets data rate to 9600 bps 
    } 
    
    void loop() 
    { 
        pwmNEW=0;
          for(int i=0;i<100;i++)
          {
    
            pwmNEW+=(analogRead(analogPin)/4);
          }
          pwmNEW=trunc(pwmNEW/100);
    
          if (pwmNEW != pwmOLD)              // verleicht die Werte valNEW und valOLD 
                {             
                   analogWrite(ledPin, pwmNEW);  // PWM-Signal wird an LED-Pin gesendet 
                   Serial.print("                     PWM-Signal:");
                   Serial.println(pwmNEW); //PWM-Signal kann man an den serial-Monitor sehen       
                   pwmOLD = pwmNEW;  // valNEW wird zu valOLD gemacht und wird für den nächsten Loop-durchgang gespecihert 
                } 
      Serial.print("Analogsignal:");
      Serial.println(analogRead(analogPin));
      delay(100);
    }
    


  • Der ADC wird rauschen.
    Du bekommst nicht dauerhaft dieselben Werte.

    Teil mal die ADC-Werte durch 10 (oder 8 oder 16)

    Code zwei ist Müll, da die beiden Werte zu schnell hintereinander gelesen werden.



  • Ich denke DirkB hat recht.
    In dem von Dir verlinkten thread wurde Dir das auch schon geraten:

    aarg schrieb:

    The analog value jumps around a little bit due to noise. So the value is never the same. You need to introduce some hysteresis.

    Es böte sich z.B. an nicht die gelesenen Werte auf Gleichheit zu prüfen, sondern die durch 4 geteilten.



  • UPDATE (kurz und knapp):
    Mit diesen Code Funktioniert die Schaltung. Man muss beachten, dass die Messung von dem Poti-Signal schwankt. Man tut einfach eine Mittelwert-funktion einbauen und der Code funktioniert.

    Danke an DirkB und Furble Wurble 👍 👍 👍

    int ledPin = 9;      // LED an Pin nr 9 
    int analogPin = 5;   // potentiometer an analogPin1 
    float pwmOLD = 0;         // variable 
    float pwmNEW = 0;         // variable   
    
    void setup()   
    { 
    pinMode(ledPin, OUTPUT);   // Pin 9 als ausgang 
    Serial.begin(9600);    // opens serial port, sets data rate to 9600 bps 
    } 
    
    void loop() 
    { 
        pwmNEW=0;
          for(int i=0;i<100;i++)
          {
    
            pwmNEW+=(analogRead(analogPin)/4);
          }
          pwmNEW=trunc(pwmNEW/100);
    
          if (pwmNEW != pwmOLD)              // verleicht die Werte valNEW und valOLD 
                {             
                   analogWrite(ledPin, pwmNEW);  // PWM-Signal wird an LED-Pin gesendet 
                   Serial.print("                     PWM-Signal:");
                   Serial.println(pwmNEW); //PWM-Signal kann man an den serial-Monitor sehen       
                   pwmOLD = pwmNEW;  // valNEW wird zu valOLD gemacht und wird für den nächsten Loop-durchgang gespecihert 
                } 
      Serial.print("Analogsignal:");
      Serial.println(analogRead(analogPin));
      delay(100);
    }
    


  • Zeile 20 bringt nichts.
    Das hätte einen Effekt, wenn pwmNEW ein int -Typ wäre.

    Wenn das /4 in Zeile 18 nicht reicht, dann nimm /8 oder /10.
    Das spart die Schleife

    Wenn du darauf nicht verzichten willst:
    Die ADC-Werte sind (soweit ich mich erinnere) alle positiv, dann wäre unsigned der bessere Datentyp.
    Wenn du dnoch eine Zweierpotenz (16, 32, 64) als Anzahl der Schleifendurchläufe nimmst, wird die Division einfacher.

    Achte aber auf den Wertebereich.



  • Die Teilung durch 4 ist deshalb gemacht weil:
    maximaler gemessener Analog wert ist 5 Volt = 1023,
    dies muss ins PMW-Signal (maximal 255) umgewandelt werden.
    Daher ist 1023/4 = 255,75. Das heist wenn der Poti zb. in einer Richtung bis zum Anschlag gedreht ist, dann fließen volle 5 Volt(also es wird 1023 gemessen).

    Soweit die Erklärung für das dividieren durch 4, es sei denn ich habe deine Frage falsch vesrtanden



  • LLucas schrieb:

    es sei denn ich habe deine Frage falsch vesrtanden

    Hast du.

    Im Augenblick machst du 100 Divisionen. Das kostet Zeit.
    Wenn du die hast, oder sogar benötigst (um zwischen den AD-Wandlungen etwas Zeit zu haben), ist es ok.

    Sonst macht man dies aber am Schluss, nach der Schleife.

    unsigned int pwmNEW = 0;
    
          for(int i=0;i<64;i++)  // mehr als 64 sollten es bei 16-Bit int nicht sein
          {     
            pwmNEW+=analogRead(analogPin);
            // evtl sleep
          }
          pwmNEW=pwmNEW/(4*64);  // Nur eine Division. Die kann der Compiler als Rechts-Shift optimieren.
    

Log in to reply