zu a)
ja, task_PID_[ABC] wird durch die allgemeine form pid_calc ersetzt.
Sinngemäss wie du auf die Elemente des Arrays zugreifst sähe so aus (ohne das ich jetzt verstehe was dein Algo macht):
Code:
void *pid_calc(void *arg) {
float aspeed, damp, PWMpwr, readold, errorold, tprop;
long readstart, cmax, cmin; // for monitoring
long starttime, runtime, clock, dtime; // timer
char regloop;
// arg nach index casten
unsigned port = (unsigned)arg;
motor[port].runstate = 0x10; // reg state: RAMPUP
motor[port].read = (MotorRotationCount(port)); // get current encoder reading
motor[port].err = motor[port].target - motor[port].read; // error to target
readstart = motor[port].read;
regloop = 1;
damp=0; // damp the integral memory
starttime= CurrentTick();
// appoach target
_Astart:
motor[port].runstate = 0x10; // run state: RUNNING
do {
pthread_testcancel();
dtime = CurrentTick() - clock;
clock = CurrentTick();
runtime = clock - starttime;
tprop = dtime/20.0;
if ((motor[port].err==errorold)&& (abs(motor[port].err)>motor[port].precis))
damp=1; // stalling
else
damp=motor[port].damp;
motor[port].integr = (damp * motor[port].integr) + motor[port].err;
if((motor[port].integr) > 3*motor[port].maxout)
motor[port].integr = 3*motor[port].maxout; // cut away
else if((motor[port].integr) <-3*motor[port].maxout)
motor[port].integr =-3*motor[port].maxout;
PWMpwr= (motor[port].P*motor[port].err) + (motor[port].I*motor[port].integr)*tprop + (motor[port].D*(motor[port].err-errorold))/tprop;
if(PWMpwr > motor[port].maxout)
PWMpwr= motor[port].maxout; // forward maxout
else if(PWMpwr < -motor[port].maxout)
PWMpwr= -motor[port].maxout; // reverse maxout
motor[port].speed= (motor[port].read-readold)*100/dtime; // rotat speed [degrees/100ms]
aspeed = abs(motor[port].speed) ;
if (aspeed > motor[port].tarpwm) {
PWMpwr = sign(PWMpwr)*motor[port].tarpwm;
}
motor[port].outp = round(PWMpwr);
//**************************************************************************
// PID regulation !
OnFwd(port, (motor[port].outp)); // action !
Wait(motor[port].regtime); // wait regulation time
//**************************************************************************
readold = motor[port].read; // save old sensor
errorold = motor[port].err; // save old error
motor[port].read = (MotorRotationCount(port)); // get new encoder value
motor[port].err = motor[port].target-motor[port].read; // new error to target
if (motor[port].read>cmax)
cmax=motor[port].read; // monitor overshooting
else if (motor[port].read<cmin)
cmin=motor[port].read; // monitor overshooting
if ((motor[port].cont)&& (abs(motor[port].err)<=motor[port].precis))
motor[port].runstate = 0x60;
else
motor[port].runstate = 0x20;
if (motor[port].cont)
continue;
if (abs(motor[port].err)<=motor[port].precis) {
regloop +=1 ;
motor[port].runstate = 0x40;
}
} while ((abs(motor[port].err)>=motor[port].precis) && (regloop<=5)); // target reached
Off(port); // finished - brake motor
motor[port].runstate = 0x40; // run state: RAMPDOWN
motor[port].outp=0;
Wait(50);
motor[port].read = MotorRotationCount(port);
regloop=1;
if (motor[port].read>cmax) cmax=motor[port].read; // detect overshooting
if (motor[port].read<cmin) cmin=motor[port].read; // detect overshooting
motor[port].err = motor[port].target-motor[port].read;
if ((abs(motor[port].err)>motor[port].precis)) {
goto _Astart;
}
motor[port].runstate=0;
Wait(1); //runstate = IDLE
}
zu b)
klar geht das, in deinem Beispiel legst du einfach fünf Threads an, die vom OS ausgeführt werden.
Was du nicht machen darfst ist zweimal ein RotatePID mit der identischen Portnummer aufzurufen ohne vorher ein StopPIDcontrol aufzurufen. Würdest du das machen hättest du zwei Threads die dann doch wieder auf einem PID rumrechnen.
Ausserdem würde ich statt Nummern für die Ports eine enum erstellen, Namen sind einfacher zu lesen, als mit 0,4,7 einen Motor zu assoziieren.
Lesezeichen