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):
zu b)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 }
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