def measurestep(self, value=None): if value == None: stdinput = stdin("", exitevent=self.fanctrl.exitevent, mutex=self.fanctrl.mutex, displaylater=False, background=False) print("Enter PWM value for step response") inptxt = "Enter PWM: " inp = stdinput.input(inptxt) if inp: value = self.fanctrl.gettype(inp, False) if value == None: print("Invalid input!") del stdinput return None del stdinput print("Measuring fan step response (PWM = {:.2f}%)".format(value)) self.fanctrl.fanoutput.set(0) self.fanctrl.exitevent.wait(2 * LIN_SLEEP) tm = [] rpm = [] self.fanctrl.fanoutput.set(value) starttime = time() nowtime = starttime while nowtime - starttime <= STEP_LENGTH and not self.fanctrl.exitevent.is_set( ): self.fanctrl.exitevent.wait(STEP_SLEEP) nowtime = time() nowrpm = self.fanctrl.rpm.get() tm.append(nowtime - starttime) rpm.append(nowrpm) self.fanctrl.fanoutput.set(0) print("Finished measuring fan step response") return (tm, rpm)
def testPID(self, Kp, Ki): print("Test PID parameters") self.fanctrl.start(Kp=Kp, Ki=Ki) stdinput = stdin() value = 0 step = 500 # check pwm < 1, don't count nowpwm = 0 rpms = [] r2 = [] while nowpwm < 100 and not self.fanctrl.exitevent.is_set(): self.fanctrl.set(value) self.fanctrl.exitevent.wait(LIN_SLEEP) nowrpm = self.fanctrl.rpm.get() nowpwm = self.fanctrl.fanoutput.get() if (nowpwm > 1.0) and (nowpwm < 99.0): rpms.append(value) r2.append(pow(nowrpm - value, 2)) #print("{:.2f}\t{:.2f}\t{:.2f}".format(value,nowrpm,pow(nowrpm - value,2))) value += step if len(r2) > 1: r = sqrt(sum(r2) / (len(r2) - 1)) else: r = 1 if len(rpms) > 0: avg = sum(rpms) / len(rpms) else: avg = 1 perc = 100 * r / avg #print(r,avg,perc) self.fanctrl.stop() self.fanctrl.exitevent.wait(LIN_SLEEP / 5) print("Finished test PID parameters") return perc
def determine(self): stdinput = stdin("", exitevent=self.fanctrl.exitevent) print("Determining Pgain and Igain") Kp = ((self.fanctrl.max() - self.fanctrl.min()) / (self.tempfull - self.tempstart)) * 0.9 Ki = Kp * 0.1 / (150.0) print("Results: Pgain = {:.3f}, Igain = {:.3f}".format(Kp, Ki)) Ok = stdinput.yn_choice("Store results?", "Y") return Ok, round(Kp, 3), round(Ki, 3)
def plotstep(self, sr): print("Fan step response plot") stdinput = stdin() stdinput.eprint("Time [ms]\tRPM [1/min]") for i in range(0, len(sr[0])): stdinput.eprint("{:.2f}\t{:.2f}".format(sr[0][i], sr[1][i])) del stdinput print("Finished fan step response plot") return
def plotlinear(self): print("Fan linear plot") stdinput = stdin() value = 0 step = 5 stdinput.eprint("Linear step: " + str(step)) stdinput.eprint("PWM [%]\tRPM [1/min]") while value <= 100: self.fanctrl.fanoutput.set(value) self.fanctrl.exitevent.wait(LIN_SLEEP) nowrpm = self.fanctrl.rpm.get() stdinput.eprint("{:.2f}\t{:.2f}".format(value, nowrpm)) value += step del stdinput print("Finished fan linear plot") return
def tune(self): sp = 50 exit = False Ok = False ans = 'n' auto = True stdinput = stdin("", exitevent=self.fanctrl.exitevent) while not exit and not self.fanctrl.exitevent.is_set(): correctResults = False while not correctResults and not self.fanctrl.exitevent.is_set(): if auto: Kp = 0 Ki = 0 sr = self.measurestep(sp) if sr: #self.plotstep(sr) Kp, Ki = self.calcparams(sr, sp) print("Results: Pgain = {:.3f}, Igain = {:.3f}".format(Kp, Ki)) if (Kp == 0 or Kp > GAINMAX or Ki == 0 or Ki > GAINMAX) and not self.fanctrl.exitevent.is_set(): correctResults = stdinput.yn_choice( "Incorrect autotuning results. Try again?", 'y') else: correctResults = True if correctResults: r = self.testPID(Kp, Ki) Ok = r < 1 print("RMS error = {:.2f}%, Ok (< 1% is Ok): {}".format(r, Ok)) if not self.fanctrl.exitevent.is_set(): ans = 'n' if Ok else 'y' exit = not stdinput.yn_choice("Retry tuning?", ans) else: exit = True if not exit and not self.fanctrl.exitevent.is_set(): auto, Kp, Ki, sp = self._tuneMenu(stdinput, Kp, Ki, sp) if not self.fanctrl.exitevent.is_set(): ans = 'Y' if Ok else 'n' Ok = stdinput.yn_choice("Store results?", ans) del stdinput if self.fanctrl.exitevent.is_set(): Ok = False Kp = 0 Ki = 0 return Ok, round(Kp, 3), round(Ki, 3)
def manualCalibrate(self): print("Manual calibration") self.mutex.acquire() pwmlevel = MINPWM - MANUALPWMDELTA choice = False stdinput = stdin("", exitevent=self.exitevent) while not choice and pwmlevel < MAXPWM and not self.exitevent.is_set(): pwmlevel += MANUALPWMDELTA self.fanoutput.set(pwmlevel) choice = stdinput.yn_choice( "Is the fan running? (PWM = {})".format(pwmlevel), 'n') if not self.exitevent.is_set(): self.valuemin = pwmlevel self.fanoutput.set(MINPWM) self.mutex.release() print("Manual calibration finished, minimum PWM: {}".format( self.valuemin)) return self.valuemin