Code:
	//*************************************************************//*************************************************************
//                      motor API                              //                      motor API
//*************************************************************//*************************************************************
#define  MAXMOTORS          10    // maximum number of motors
#define  MAXMOTORSLOCAL      2    // maximum number of local motors
#define  MAXPWMRANGE       255    // maximum software-pwm range (0-255)
// motor control structure
typedef struct  {   
                // electrical motor pins
      uint8_t   pind1, pind2, pinpwm;    // dir + pwm L293 H-Bridge type
      uint8_t   pinQa, pinQb;            // rotary enc pins Qa,Qb
     
                // pwm and encoder values
      int16_t   dirpwm;     
      int32_t   motenc, oldenc;          // rotary encoder values
     
                // PID   
      pthread_t tid;
   
                // PID custom target values
      int32_t   target;                  // set target
      int16_t   tarpwm;                  // motor target speed
                // PID custom regulation parameters
      double    P;                       // P: basic propotional to error
      double    I;                       // I: integral: avoid perish
      double    D;                       // D: derivative: avoid oscillating
      double    precis;                  // error precision to target
      int32_t   regtime;                 // PID loop time
      double    damp;                    // damp the integral memory
      int8_t    cont;                    // target: continue or hit once
                // internal control variables
      int16_t   runstate;                // monitors runstate
      int16_t   outp;                    // PID control output value
      int16_t   maxout;                  // max output (max motor pwr)
      int32_t   read;                    // current sensor reading
      double    err;                     // current error
      double    integr;                  // integral of errors
      double    speed;                   // current speed
      int8_t    stopPIDcontrol;          // flag for external termination
     
} tEncMotor;
tEncMotor motor[MAXMOTORS];
#define motorLeft  motor[0]
#define motorRight motor[1]
// motor runstates:
#define OUT_REGSTATE_NULL           0
#define OUT_REGSTATE_COAST          2
#define OUT_REGSTATE_BRAKE          3
#define OUT_REGSTATE_EMERG_STOP     5
#define OUT_REGSTATE_ON             8
#define OUT_REGSTATE_RAMPUP         9
#define OUT_REGSTATE_RAMPDOWN      10
#define OUT_REGSTATE_PIDIDLE       15
#define OUT_REGSTATE_ACTIVE        16 
#define OUT_REGSTATE_PIDSTART      17
#define OUT_REGSTATE_PIDEND        18
#define OUT_REGSTATE_PIDHOLD       19
#define OUT_REGSTATE_PIDHOLDCLOSE  20
//*************************************************************
#define motorCoast(nr) motorOn(nr, 0)  // alias for motor coast
//*************************************************************
inline void motorBrake(uint nr, int dirpwm) {      // brake by pwm power
   int pwm;
   
   pwm = abs(dirpwm);
   
   digitalWrite(motor[nr].pind1, HIGH);
   digitalWrite(motor[nr].pind2, HIGH);     
   
   motor[nr].dirpwm = pwm;
   softPwmWrite(motor[nr].pinpwm, pwm);    // brake power always > 0   
   
}
//*************************************************************
inline void motorOn(uint nr, int dirpwm) { // motor On (nr, dir_pwm)
   int dir, pwm;                             // signed pwm:
   
   if(dirpwm > 0) dir = +1;                   // pwm > 0: forward
   else if(dirpwm < 0) dir = -1;              // pwm < 0: reverse
   else dir = 0;                              // pwm = 0: coast
   
   if(! _REMOTE_OK_) dirpwm=0;
   pwm = abs(dirpwm);
   
     
   if(dir> 0) {
      digitalWrite( motor[nr].pind1, HIGH);
      digitalWrite( motor[nr].pind2, LOW);     
   }
   else
   if(dir==0) {
      digitalWrite( motor[nr].pind1, LOW);
      digitalWrite( motor[nr].pind2, LOW);
   }
   else {
      digitalWrite( motor[nr].pind1, LOW);
      digitalWrite( motor[nr].pind2, HIGH);
   }
   motor[nr].dirpwm = dirpwm;
   softPwmWrite( motor[nr].pinpwm, pwm);
   
   
}
                       
                       
//*************************************************************//*************************************************************
//                       PID control                           //                       PID control
//*************************************************************//*************************************************************   
// forward: motor API functions
inline void RotatePIDtoTarget (uint nr, int32_t Target, double RotatSpeed); // approach absolute target once
inline void RotatePIDdegrees  (uint nr, int32_t Target, double RotatSpeed); // turn relative degrees
inline void RotatePIDcontinue (uint nr, int32_t Target, double RotatSpeed); // approach target continuously
inline void StopPIDcontrol    (uint nr);               
inline void PIDinit(); // P=0.4, I=0.4, D=10.0
// simple customized PID setting:
inline void SetPIDparam(uint nr, double P,double I,double D);
// extended customized parameter setting:
inline void SetPIDparamEx(uint nr, double P, double I, double D, double prec, int16_t regtime, double damp);   
//*************************************************************                   
                       
inline void PIDcleanup(uint nr) {   
        motorCoast(nr);
        motor[nr].runstate = OUT_REGSTATE_NULL;
        motor[nr].speed    = 0;
        motor[nr].outp     = 0;
        motor[nr].cont     = 0;
}                       
 
//*************************************************************                   
void * PID_calc(void *arg) {
  double  aspeed, damp, PWMpwr, readold, errorold, tprop;
  int32_t    readstart, cmax, cmin;                    // for monitoring
  int32_t    starttime, runtime, clock, dtime;         // timer
  int     regloop;
 
  // arg nach index casten
  unsigned nr = (unsigned)arg;
 
 
  motor[nr].runstate = OUT_REGSTATE_PIDSTART   ;           // reg state: RAMPUP
  motor[nr].read     = motor[nr].motenc;             // get current encoder reading
  motor[nr].err      = motor[nr].target - motor[nr].read; // error to target
  readstart      = motor[nr].read;
  regloop        = 1;
  damp=0;                                   // damp the integral memory
  starttime= millis();
  // appoach target
  _Astart:
  motor[nr].runstate = OUT_REGSTATE_ACTIVE;  // run state: RUNNING
  do {
     
    pthread_testcancel();
    if (motor[nr].stopPIDcontrol) {
        PIDcleanup(nr);
        return NULL;
    } 
    dtime    = millis() - clock;
    clock    = millis();
    runtime  = clock - starttime;
    tprop    = dtime/20.0;
   
   
    if ((motor[nr].err==errorold)&& (abs(motor[nr].err)>motor[nr].precis)) damp=1;    // stalling
    else
    damp=motor[nr].damp;
    motor[nr].integr = (damp * motor[nr].integr) + motor[nr].err;
    if((motor[nr].integr) > 3*motor[nr].maxout) motor[nr].integr = 3*motor[nr].maxout; // cut away
    else
    if((motor[nr].integr) <-3*motor[nr].maxout) motor[nr].integr =-3*motor[nr].maxout;
    PWMpwr= (motor[nr].P*motor[nr].err) + (motor[nr].I*motor[nr].integr)*tprop + (motor[nr].D*(motor[nr].err-errorold))/tprop;
    if(PWMpwr >  motor[nr].maxout) PWMpwr=  motor[nr].maxout;   // forward maxout
    else
    if(PWMpwr < -motor[nr].maxout) PWMpwr= -motor[nr].maxout;   // reverse maxout
    motor[nr].speed= (motor[nr].read-readold)*100/dtime;  // rotat speed [degrees/100ms]
    aspeed = abs(motor[nr].speed) ;
       
    if (abs(PWMpwr) > motor[nr].tarpwm )  {
        PWMpwr = sign(PWMpwr) * motor[nr].tarpwm ;
    }
    motor[nr].outp = round(PWMpwr);
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                                      // PID regulation !
    motorOn(nr, motor[nr].outp);                  // action !
    delay(motor[nr].regtime);                       // wait regulation time
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    readold     = motor[nr].read;                           // save old sensor
    errorold    = motor[nr].err;                            // save old error
    motor[nr].read  = motor[nr].motenc;                   // get new encoder value
    motor[nr].err   = motor[nr].target-motor[nr].read;  // new error to target
    if (motor[nr].read>cmax) cmax=motor[nr].read;         // monitor overshooting
    else
    if (motor[nr].read<cmin) cmin=motor[nr].read;         // monitor overshooting
    if ((motor[nr].cont)&& (abs(motor[nr].err)<=motor[nr].precis))
         motor[nr].runstate = OUT_REGSTATE_PIDSTART   ;
    else motor[nr].runstate = OUT_REGSTATE_ACTIVE;
    if (motor[nr].cont) continue;
    if (abs(motor[nr].err)<=motor[nr].precis) {
        regloop +=1 ;
        motor[nr].runstate = OUT_REGSTATE_PIDEND  ;
    }
   
    if (motor[nr].stopPIDcontrol) {
        PIDcleanup(nr);
        return NULL;
    }
  } while ((abs(motor[nr].err)>=motor[nr].precis) && (regloop<=5));  // target reached
  motorCoast(nr);                                 // finished - stop motor
  motor[nr].runstate = OUT_REGSTATE_PIDEND;       // run state: RAMPDOWN
  motor[nr].outp=0;
  delay(50);
  motor[nr].read = motor[nr].motenc;
  regloop=1;
  if (motor[nr].read>cmax) cmax=motor[nr].read;            // detect overshooting
  if (motor[nr].read<cmin) cmin=motor[nr].read;            // detect overshooting
  motor[nr].err = motor[nr].target-motor[nr].read;
  if (motor[nr].stopPIDcontrol) {
        PIDcleanup(nr);
        return NULL;
  }
  if ((abs(motor[nr].err)>motor[nr].precis))  {goto _Astart;}
  motor[nr].runstate=0;
  delay(1);                                //runstate = IDLE
  return (NULL);
}
//*************************************************************
inline void RotatePID(uint nr, int32_t Target, double RotatSpeed, int8_t cont) {
   
    if( !motor[nr].tid && motor[nr].runstate) {
        motor[nr].runstate=0; // repair
        delay(1);
    }
    if( ( motor[nr].runstate ) || ( motor[nr].tid ) ) {
       motor[nr].stopPIDcontrol = 1;
       delay(1);
       while( motor[nr].runstate || motor[nr].tid );  // wait for PID task to terminate
       delay(1);
       PIDcleanup(nr);
    }
    // init new PID structure 
    motor[nr].runstate = 1;               // set runstate: PID active
    // custom init PID [nr]   
    motor[nr].target = Target;                   // assign target
    motor[nr].tarpwm = abs(RotatSpeed);          // assign max rotation speed
    motor[nr].cont=cont;                         // cont vs. hit once
    // Reset PID control defaults
    motor[nr].outp    = 0;                // PID control output value
    motor[nr].maxout  = MAXPWMRANGE;      // absolute max possible output (max pwr)
    motor[nr].read    = 0;                // current reading
    motor[nr].err     = 0;                // current error
    motor[nr].integr  = 0;                // integral of errors
    motor[nr].speed   = 0;                // current speed
    motor[nr].stopPIDcontrol = 0;         // flag for external termination
   
    // start PID control task
    pthread_create( & motor[nr].tid,      // id speichern in dem dazugehörigen Array-Element
                    0,                    // Default Attribute (threads cancelbar)
                    PID_calc,             // Name der PID-Kalkulationsroutinge
                    (void *) nr);         // der Index des Array-Elements für eine PID Struktur,
                                          // die mit dem Motorindex gleich ist.   
   
    // run pthread task in detached mode, auto-cleanup                                   
    pthread_detach(motor[nr].tid);
}
//*************************************************************                   
inline void StopPIDcontrol (uint nr) {
  if (motor[nr].tid) { // stop PID task if already running
     motor[nr].stopPIDcontrol = 1;   
  }
}
               
//*************************************************************                         
                     
// custom PID parameters Extended
inline void SetPIDparamEx(uint nr, double P, double I, double D, double prec, int16_t regtime, double damp) {
    motor[nr].P       = P;             // P: propotional to error
    motor[nr].I       = I;             // I: avoid perish
    motor[nr].D       = D;             // D: derivative: avoid oscillating
    motor[nr].precis  = prec;          // error precision to target
    motor[nr].regtime = regtime;       // PID regulation time
    motor[nr].damp    = damp;          // damp error integral
}
//************************************************************* 
                 
// custom PID parameters
inline void SetPIDparam(uint nr, double P, double I, double D) { 
    motor[nr].P     = P;             // P: propotional to error
    motor[nr].I     = I;             // I: integral: avoid perish
    motor[nr].D     = D;             // D: derivative: avoid oscillating
}                       
   
                   
//*************************************************************                                       
                     
inline void PIDinit() {
  for (uint nr=0; nr < MAXMOTORS; ++nr) {
    SetPIDparamEx(nr, 0.40, 0.40, 10.0, 1.0, 5, 0.75); // p,i,d, precis, reg_time, damp
    delay(1);
  }
}
//*************************************************************                                       
inline void RotatePIDtoTarget(uint nr, int32_t Target, double RotatSpeed) {
   RotatePID(nr, Target, RotatSpeed, false);
   delay(1);
}
//*************************************************************                                       
inline void RotatePIDcont(uint nr, int32_t Target, double RotatSpeed) {
   RotatePID(nr, Target, RotatSpeed, true);
   delay(1);
}
//*************************************************************                                       
inline void RotatePIDdegrees(uint nr, int32_t Target, double RotatSpeed)  {
   RotatePID(nr, Target+motor[nr].motenc, RotatSpeed, false);
   delay(1);
}
//*************************************************************
//  ^^^^^^^^^^^^^^ PID end ^^^^^^^^^^^^^
//*************************************************************
 
						
Lesezeichen