Closed_Loop für einen Schrittmotor

Leute ich brauch eure Hilfe :o

Wie der Titel schon sagt verusch ich einen Schrittmotoren zu regeln und ich habe gleich mehrere Fragen mit gebracht. (Im internt findet man nicht sehr viel ist das er untypisch?)

Zuerst mal das Setup:

Arduino Mega 2560,
Druck-Sensor AMS5812
Barometer
Die Ansteuerung für die 2 benutzen Schrittmotoren mittels einem Timer (ISR) steht und funktioniert auch Problem los.

Nun zu dem was ich machen will.
Ich will die Drezhal der Schrittmotoren über den Druck reglen.
Dazu hab ich ein Array in dem ich bestimmte Schwelllenwerte deklariert habe. Die Drezahl soll sich so lange erhöhen oder verringen bis der Schwellenwert erreicht wurde.
Ist der Schwellenwert erreicht worden wird das nächst Schwellenwert vom Array hergezogen und das ganze geht von vorne los. Wenn der letzte Wert vom Array heranggezogen wird, soll der Feldzähler des Arrays wieder auf das erste Feld zeigen, damit das ganze von vorn los geht.
Den Druckwert der von Sensor gelsen wird stelle ich über den Barometer ein den ich mittel Silikonschläuchen und einer Großen Sprizte einstelle. Barometer und Sensor sind mit der Sprizte parallel verzeigt verbunden, deswengen stellt sich bei beiden der gleiche Druck ein

Die Drehzahl beeinfluss über den Timer, das stimmt eigt. nicht sondern megr über die Funktion
Setspeed() der Timer zieht sich nur den Wert aus der Funktion schreibt sich den bei cih in den Regsiter rein und löst danach aus und macht dan eine Step für beide Motoren.
Der Wert den sich der Timer zieht liegt zwischen 3200 bis 22.400.

Der Code steht nocht nicht so wie oben beschreiben und befindet sich noch in der entwicklungspahse aber es gint schon erste probleme

Meine erste Frage:

Also ich lasse in der Main die unten genannte Funktion laufen. Mein Problem wenn ich am Barometer den gewünschten Druck einstelle, ziehn die motoren die Drehzahl an bis sie hangen bleiben egal on sie Unterhalb, Oberhalb oder genau im Druckberech liegen.
Wenn ich aber die ber die Auskommentierten Prints einkommentire sehe ich am Seriellem monitor das, er Arduino genau das macht was er machen soll. leigt darüber runterzählen… liegt darunter hoch zählen … …

void ReglerStellen()
{
   if(InputDruck <= (SetponitArray[Setpointzeahler]-15))         //   SetponitArray[Setpointzeahler] entspricht 100.
   {
    Steller= Steller + 50;                  // Steller wird der Funktion Setspeed() über geben.     
    //Serial.println("Hochzählen");
   }
   if(InputDruck >= (SetponitArray[Setpointzeahler]+15))         // SetponitArray[Setpointzeahler]  entspricht 100.
   {
   Steller = Steller - 50;                   // Steller wird mit 3200 deklaiert,Steller hat sollte nicht weit über unter 3200 und 22400 liegen. 
   //Serial.println("Runterzählen");
   }
   
   if( (InputDruck >= (SetponitArray[Setpointzeahler]-15) ) && (InputDruck <= (SetponitArray[Setpointzeahler]+15) ) )
   {
     //Serial.println("Eingependelt");   
   }
}

ich verstehe nicht warum das so ist ??? echt ratlos?? vlt ist es auch was einfachs und ich sehs nur net, HOFFENTLICH :slight_smile:

Meine zweite frage:

ich hab nach PID Libraries gesucht und keine passenden gefunden der von Brett Beauregard <PID_v1_h> ist zwar ginal aber der geeignet sich nicht , weil dieser ja so Funktionert das er einen Inpunt einen einliest und versucht einen Output entsprechend dem Setpoint zu reglen…
Mein Output der zu Regeln ist ist ein interner rechneter wert von Setpeed. Und so weit ich den jetzt einschätzen drufte bracht die Libraries einen PIN als Output.

An dieser Stelle wen iht eine Libraries kennt die dazu passt bitte nennen.
Oder hab ich Bertts Librarie falsch genutzt.

ich hoffe ihr könnt mir weiter helfen. Und sorry für die Schlechte Darstellung ist das erste mal das ich was hier Poste

Es ist doch nicht verwunderlich, daß der Regler davonläuft, wenn sein Output (Drehzahl) keine Rückwirkung auf seinen Input (Spritze) hat.

Nee ich seh ja wenn die SM hochfähert dan übe ich auch druck auf die Spritze aus womit der druck ebenfalls steigt.

Wie posten man hier seinen code das sieht anders aus als bei dieser beschreibung.

https://www.arduinoforum.de/attachment.php?aid=2046

Closed_Loop:
Wie posten man hier seinen code ........

z.B.
Codebereich in der Arduino IDE markieren.

Rechte Maustaste->Kontextmenue->Für Forum kopieren
Forumtextfeld->Kontextmenue->Einfügen.

#ifndef ANSTEUERUNG_H
#define ANSTEUERUNG_H
#include "CmdInterface.h"
#include "drive.h"
#include "Umwandlungsroutinen.h"
#include "AMS5812.h"
#include "Schrittgeber.h"
#include "LookupTabelle.h"
#include <avr/interrupt.h>
#include <PID_v1.h>

// Zuweisung der Arduino-Ausgänge zu den Treiber-Pins
#define X_STEP_PIN    54
#define X_DIR_PIN     55
#define X_ENABLE_PIN  38
#define Y_STEP_PIN    46
#define Y_DIR_PIN     48
#define Y_ENABLE_PIN  62

#define Poti 4
#define SCHALTERPIN 3
#define LEDPIN      13

#define HANDBETRIEB  LOW
#define AUTOMATIK    HIGH

#define POTIMIN  9600
#define POTIRUNNING 10000

// states
#define WAIT4RUN 0
#define RUNNING  1
#define STOPPING 2

////////////////// AMS5812 #Defines

#define Addr 0x78 //  Die I2C Addresse 0x78(120)
#define DigoutPmax 29491
#define DigoutPmin 3277
#define Pmax 344.7
#define Pmin 0
#define DigoutTmax 29491
#define DigoutTmin 3277
#define Tmax 85
#define Tmin -25
//////////////////

// globals
CmdInterface cmd;
int state = WAIT4RUN;  
int x;
unsigned long a = 0;
unsigned long potiwert, clk;
bool temp = 0;
COMMAND command;


bool zustand = LOW;
bool schalterwert;
bool cmdblock = true;
bool potiblock = true;
int speed;

unsigned int  Rampenzaehler = 0;
const long Zeitintervall = 100;
unsigned long VergangeZeit = 0;
unsigned long AktuelleZeit = 0;

double Setpoint, Input, Output;
int bad;
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);


int Steller;
int InputDruck;
int Setpointzeahler = 0;

    


//bool temp = 0;

Drive Antrieb(X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN);

void setup()
{
  cmd.Init(9600); // Einstellen der Übertragungsrate auf 9600 Baud
  //pinMode(Wahlschalter, INPUT);
  pinMode(SCHALTERPIN, INPUT_PULLUP);
  pinMode(LEDPIN, OUTPUT); 
  clk = millis();
  Wire.begin();
  myPID.SetMode(AUTOMATIC);

  // reset
  TCCR5A = 0; // set TCCR1A register to 0
  TCCR5B = 0; // set TCCR1B register to 0
  TCNT5  = 0; // reset counter value
  
  OCR5A = AbtastfrequenzTimer5; // compare match register

  // set prescaler
  TCCR5B |= (1 << CS12) | (1 << CS10);   
  
  TCCR5B |= (1 << WGM12); // turn on CTC mode
  TIMSK5 |= (1 << OCIE1A); // enable timer compare interrupt   
                                                                    
} 


// Interrupt service routine
ISR(TIMER1_COMPA_vect){ 
  OCR1A = Antrieb.GetDrvTicks();
 // ReglerStellen();// Count Register neu setzen 
  
  Antrieb.OneStep();
}

ISR(TIMER5_COMPA_vect,ISR_NOBLOCK) { // function which will be called when an interrupt occurs at timer 1 // ISR_NOBLOCK 

  TIMSK5 &= ~(1<<TOIE0);
  InputDruck = AMSSensor();
  TIMSK5 |= (1<<TOIE0);

}

void loop()
{


myPID.Compute();

////////////// Funktionsaufruf für den AMS5812 Sensor code

//AMSSensor();
 //Serial.print(DruckwertAMS);
 //Serial.println("Druck in MilliBar");

//////////////

  
  if(zustand != (schalterwert = digitalRead(SCHALTERPIN)))
   {
     zustand = schalterwert;
     
     potiblock = true;
     cmdblock = true;
     speed = 0;
     
     if(zustand == HANDBETRIEB) Serial.println("Handbetrieb!");
     if(zustand == AUTOMATIK)   Serial.println("Automatik!");
   }
      
   if((Antrieb.enable == !ENABLED) && (potiwert <= 10) && (zustand == HANDBETRIEB))
   { 
     potiblock = false; //Änderung: stopped zu !stopping // poti zu Potiwert
   }
   
   if((Antrieb.enable == !ENABLED) && (zustand == AUTOMATIK))
   {   
     cmdblock = false; //Änderung: stopped zu !stopping
   }
   
   // Wenn Poti nicht blockiert
   if(!potiblock && millis() - clk > 10)
   {
     speed = PotiToSpeed(readspeed());  // Potiwert einlesen
     clk = millis();       // Vergleichszeit neu setzen
   }
   
  /*if(millis() - old >= 1000)
  {
    old = millis();
   //Serial.print (NbTopsFan, DEC);
    //Serial.print (" Frequenz\n");
    Calc = ((NbTopsFan * 60) / 4.8); //(Pulse frequency x 60) / 7.5Q, = flow rate in L/hour / 
    NbTopsFan = 0;   //Set NbTops to 0 ready for calculations   // setzt die Die Variable zum aufzählen der Rechtecksignale auf null
     
    //Serial.print (Calc, DEC); //Prints the number calculated above / gibt den Wert in "Calc" als Dezimalzahl aus
    //Serial.print (" L/min\r\n"); //Prints "L/hour" and returns a  new line / Gibt was da steht aus
  }*/
     
    if(!cmdblock)
    {
       if(cmd.IsCommandAvailable()) 
         command = cmd.GetCommand();
       
       speed = CmdToSpeed(command);       
    }

 /////////////////////////////////////////// Druckkurve   
/*
  int AktuelleZeit = millis();
  if(AktuelleZeit - VergangeZeit >= Zeitintervall)
  {
    VergangeZeit = AktuelleZeit;
    Rampenzaehler = Rampenzaehler + 1;
    //Serial.println(TimerSchritt[Rampenzaehler]);
   // Serial.print(millis()); Serial.println("  Millisekunden sind vergangen");
  }

  if(Rampenzaehler>= 99)
  {
   Rampenzaehler = 0;
  }  

   Antrieb.SetSpeed(TimerSchritt[Rampenzaehler]);
*/
///////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////// Regeleinheit;



    ReglerStellen();
    Antrieb.SetSpeed(Steller);  

    if(state == WAIT4RUN){ // Motor starten? 
    if((zustand == AUTOMATIK && command.keyword == 'N') || (zustand == HANDBETRIEB && speed > POTIMIN + 40))
    {
      Serial.println("RUNNING");
      state = RUNNING; 
      Antrieb.Start();                       // asynchron (Motor fährt danach hoch)
    }
  }
  
  if(state == RUNNING){  // Motor anhalten?
    if((zustand == AUTOMATIK && command.keyword == 'S') || (zustand == HANDBETRIEB && speed <= POTIMIN + 40))
    {
      Serial.println("STOPPING");
      state = STOPPING; 
      Antrieb.Stop();
    }    // asynchron 
  }

  if(state == STOPPING && !Antrieb.enable){
    Serial.println("WAIT4RUN");
    state = WAIT4RUN; 
  }

   
  
}  


void ReglerStellen()
{
    if(InputDruck <= (SetponitArray[Setpointzeahler]-15))         //   SetponitArray[Setpointzeahler] entspricht 100.
    {
     Steller= Steller + 5;                  // Steller wird der Funktion Setspeed() über geben.     
     Serial.println("Hochzählen");
      Serial.println(Steller);
    }
    if(InputDruck >= (SetponitArray[Setpointzeahler]+15))         // SetponitArray[Setpointzeahler]  entspricht 100.
    {
    Steller = Steller - 5;                   // Steller wird mit 3200 deklaiert,Steller hat sollte nicht weit über unter 3200 und 22400 liegen. 
    Serial.println("Runterzählen");
     Serial.println(Steller);
    }
    
    if( (InputDruck >= (SetponitArray[Setpointzeahler]-15) ) && (InputDruck <= (SetponitArray[Setpointzeahler]+15) ) )
    {
    Serial.println("Eingependelt");
     Serial.println(Steller); 
    }
}


unsigned int readspeed()
{
  unsigned int speed = (analogRead(Poti));
  if((int)speed <= 0) x = 0;
  else x = 1;
  return speed;
}



#endif

Wie ich schon schrieb, der I-Regler läuft an den Anschlag sobald der Sollwert abweicht.