gleitender Mittelwert in der laufenden loop zu langsam

Hallo Leute,

habe ein Problem mit der Performance eines (gleitenden) Mittelwertes in meiner Loop.

Folgende Situation:
Eine LED blinkt im 0,5sek Takt. Ich greife das Licht über einen Sensor ab.
Soweit kein Problem. Mittelwert zwischen blinken und aus sind deutlich.
Sobald aber meine loop läuft “stottert” das ganze.

Im ersten Versuch habe ich einen normalen Mittelwert von 10 Messungen gebildet, jedoch stoppt hier der Ablauf, was nicht schön ist.
Im zweiten Versuch habe ich einen gleitenden Mittelwert versucht, aber dieser bekommt wohl pro loop nur einen Wert.

Ich hoffe ihr könnt mir weiter helfen ?!

Die interessanten Stellen sind zu beginn der loop und ganz am ende

Gruß

Christian

// Stepper1 Hülsenmotor 5- 8
// Stepper2 Schubmotor  9-12
// D22 Magnet
// D23 Start
// D24 Load
// D26 Vibr 
// D3 Taster Hülse
// D4 Taster Schub
// D25 Schalter Produktion
// A0 LED Load 
// A1 LED Tabacco entfällt
// D2 Servo entfällt
// D49 STOP
// D28 Taster Vibr entfällt


#include <Wire.h>

#include <Adafruit_RGBLCDShield.h>
#if defined(ARDUINO_ARCH_SAMD)
#endif


Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7


#include <AccelStepper.h> // 
#include <Servo.h>


AccelStepper stepper1(AccelStepper::FULL4WIRE, 5, 6, 7, 8);
AccelStepper stepper2(AccelStepper::FULL4WIRE, 9, 10, 11, 12);


int var=0;                                      // für 20 mal load
int var2=0;                                     // Zeit zur Berechnung für 3 Ziggis
long startTime;                                 // millis-Wert beim ersten Drücken der Taste
long duration;                                  // Variable für die Dauer




#define Rel0  23                                 //Start                   
#define Rel1  24                                //Magnet                  
#define Rel2  22                                 //Load
#define Rel3  26                                 //Vibr

//Servo myservo;  
//int pos = 0;    

int j = 0;                                      // für Mittelwert
int spannung[10];

#define anzahlMittelWerte 10                    // für gleitender Mittelwert
int werte[anzahlMittelWerte], zaehlerMittelWerte=0;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.print("  Go Fresh go  ");
  myservo.attach(2);
  stepper1.setMaxSpeed(150);
  stepper2.setMaxSpeed(270);
  stepper1.setAcceleration(3000.0);
  stepper2.setAcceleration(3000.0);
  
 
  pinMode(Rel0, OUTPUT);                            //magnet 
  pinMode(Rel1, OUTPUT);                            //start
  pinMode(Rel2, OUTPUT);                            //load
  pinMode(Rel3, OUTPUT);                          //vibr
  pinMode(3, INPUT_PULLUP);                         // Taster Hülsenmotor
  pinMode(4, INPUT_PULLUP);                         // Taster Schubmotor
  pinMode(25, INPUT_PULLUP);                         // Schalter Produktion
  pinMode(28, INPUT_PULLUP);                        // taster vibr
  pinMode(49, INPUT_PULLUP);                        // Taster Fehler
  digitalWrite(Rel0, HIGH);
  digitalWrite(Rel2, HIGH);
  digitalWrite(Rel1, HIGH);
  digitalWrite(Rel3, HIGH);
  int sensorVal1 = digitalRead(3);
  int sensorVal2 = digitalRead(4);
  int sensorVal3 = digitalRead(25);
  int sensorVal4 =  digitalRead(28);
  int sensorrel0 = digitalRead(Rel0);
  int sensorrel1 = digitalRead(Rel1);
  int sensorrel2 = digitalRead(Rel2);
  


lcd.setBacklight(WHITE);

uint8_t i=0;
 
 while(sensorVal1 == LOW) {                  // solange Schalter nicht gedrückt  
 if (stepper1.distanceToGo() == 0){          // Homing Hülsenmotor
 stepper1.move(-1);
 }
 stepper1.run();
 delay(10);
 sensorVal1 = digitalRead(3);  
 } 


while(sensorVal2 == HIGH) {                  // solange Schalter nicht gedrückt  
if (stepper2.distanceToGo() == 0){           // Homing Schubmotor
 stepper2.move(1);
 }
 stepper2.run();
 delay(10);
 sensorVal2 = digitalRead(4);  
 } 
 
 

 
 
}



void loop() {

  
  
  delay(100);
  
//myservo.writeMicroseconds(1540);
//int sensorValue1 = analogRead(A0);                 //LED Load
//int sensorValue2 = analogRead(A1);                 //LED Tabacco

if (digitalRead(25)==LOW) {                        // Schalter Produktion

//int n;                                                //für gleitender Mittelwert
//  float f;                                            //für gleitender Mittelwert
//  n=analogRead(A0);                                   //für gleitender Mittelwert
//  f= mittelWert(n);                                   //für gleitender Mittelwert
//  Serial.print("gleitender Mittelwert     ");         //für gleitender Mittelwert
//  Serial.println(f);                                  //für gleitender Mittelwert
//delay(100);                                           //für gleitender Mittelwert
  
for (j=0; j<10;j++){                     // Werte für Mittelwert sammeln
delayMicroseconds(200) ;
spannung[j] = analogRead(A0);
delayMicroseconds(50);
Serial.println(spannung[j]);
delay(100);
}

                                          //Mittelwert berechnen
long int Mittelwert = 0;
for (int j=0; j<10;j++) {
Mittelwert = Mittelwert + long(spannung[j]);
}
Mittelwert = Mittelwert / 10;
Serial.print("Mittelwert = ");
Serial.println(Mittelwert);







  
stepper1.moveTo(275);                            // fahre Hülsenmotor zur aufnahme
while (stepper1.currentPosition() != 275)
stepper1.run();
delay(170);

if (Mittelwert <800){

stepper1.moveTo(75);                             // fahre Hülsenmotor zum abwurf
while (stepper1.currentPosition() != 75)
stepper1.run();
delay(100);




 
      
digitalWrite(Rel1, HIGH);                             //löse Magnet
stepper2.setSpeed(250);
delay(100);
    
     
if (digitalRead(49)==HIGH) {                           // wenn Schalter Abbruch nicht gedrückt


var2++;                                                //Zeitvariable
if (var2 == 1){
startTime = millis();
}
var++;                                                 //Rundenvariable
lcd.setCursor(4, 1);
lcd.print("Runde  ");
lcd.println(var);


digitalWrite(Rel2, LOW);                            //aktiviere Taste load 
delay(500);
digitalWrite(Rel2, HIGH);
delay(500);
      
//stepper1.moveTo(275);                             // fahre Hülsenmotor zur aufnahme
//while (stepper1.currentPosition() != 275)
//stepper1.run(); 


if(var == 19) {
digitalWrite(Rel0, LOW);                             // aktiviere Taster start
delay(1000);
digitalWrite(Rel0, HIGH); 
delay(500);
Serial.println("Start gedrückt 19");
}

if(var == 20) {
digitalWrite(Rel0, LOW);                             // aktiviere Taster start
delay(1000);
digitalWrite(Rel0, HIGH); 
delay(500);
Serial.println("Start gedrückt 20");
var = 0;
}


if (var2 == 3){
long duration = millis() - startTime;
Serial.print("Drei Zigaretten dauern:  ");
Serial.println(duration);
var2 = 0;
digitalWrite(Rel3, LOW);
}
}                                                    //Ende Abbruch Schleife  

digitalWrite(Rel1, LOW);                             //aktiviere Magnet
delay(500);

    
stepper2.setSpeed(250);
stepper2.moveTo(760);                                 // fahre Schubmotor zum Abwurf
while (stepper2.currentPosition() != -10){
stepper2.run();}
digitalWrite(Rel1, HIGH);                             //löse Magnet
delay(10);
digitalWrite(Rel3, HIGH);
}// Ende Schleife Mittelwert
}// Ende Schleife Taste Produktion
//
//float mittelWert(int neuerWert) {
//// neuen int Wert eingeben und den Mittelwert als float zurück geben
////
//// Matthias Busse 9.2.2016 Version 1.0
//float mittel, summe=0;
//
//  werte[zaehlerMittelWerte] = neuerWert;
//  for(int k=0; k < anzahlMittelWerte; k++) summe += werte[k];
//  mittel=(float) summe / anzahlMittelWerte; 
//  zaehlerMittelWerte++;
//  if(zaehlerMittelWerte >= anzahlMittelWerte) zaehlerMittelWerte=0;
//  return mittel;
//}

}                                              // End loop

Das ist kein gleitender Mittelwert. Darunter ist gemeint, dass man die Messungen unterschiedlich gewichtet und ältere Messungen mit weniger in das Ergebnis eingehen. Du bildest nur einen einfachen Durchschnitt. Also x Messungen machen und durch x dividieren

Das ist alles sehr unsauber programmiert. Alles in loop() gepfercht statt mal was in Funktionen auszulagern. Und ständig delay(). Wenn das blockierungsfreier wäre, wäre es auch kein Problem nur eine Messung pro Durchlauf zu machen. Einfach weil es öfters drankommt. Das sieht wieder nach einer Sache aus die nach einem Zustandsautomaten schreit.

Hallo Serenifly,

ich weiß, meine Programmierung ist nicht schön. Was bitte ist ein Zustandsautomat?

https://de.wikipedia.org/wiki/Endlicher_Automat

Die einfachste Version lässt sich bequem mit einem switch/case Statement realisieren das eine Variable abfragt die den aktuellen Zustand angibt. Es geht aber auch komplexer (mit Zustandsübergangstabellen als zwei-dimensionales Array oder mit Funktionszeigern).

Anleitung z.B.: https://forum.arduino.cc/index.php?topic=328241.0

Da werden Blinklichter gezeigt die einfache Zustandsübergänge haben. Aber für die Ablaufsteuerung in Maschinen kann man natürlich auch in einem Zustand abfragen ob ein bestimmtes Ereignis eingetreten ist (z.B. ein Taster geschlossen) und dann je nachdem in verschiedene Zustände wechseln.

Warum wird die LED mit analogRead abgefragt, nicht mit digitalRead?

Zur Erkennung des nicht-blinkenden Zustand kann das Muster von Debounce verwendet werden, mit einem Intervall entsprechend der Blinkfrequenz.

IMO solltest Du Dich und Deinen Code etwas systematischer organisieren. Mit Auto Format (CTRL+T) dürfte der Code schon besser lesbar und damit verständlich sein.