Example #1
0
class Motor(object):
    # 1440 ticks per rev, 150 rev per min 60 sec per minute
    MAX_SPEED = float(1440 * 150 / 60.)
    MAX_ACCELERATION = MAX_SPEED / 10  # Max speed achieved in 10 iterations
    MAX_CMD = 400.

    def __init__(self):
        self.pid_speed = PID(0.01, 0.9, 0, Motor.MAX_CMD)
        self.target_speed = 0

    @staticmethod
    def convert_command_to_speed(x):
        if x > 1:
            x = 1
        if x < -1:
            x = -1
        return x * Motor.MAX_SPEED

    def set_speed(self, target_speed):
        if abs(target_speed) > 1:
            print(target_speed)
            raise ValueError(
                "The absolute value of target_speed "
                "cannot be greater than 1, was: {}".format(target_speed))

        self.target_speed = self.convert_command_to_speed(target_speed)

    def get_speed_command(self, speed_measurement, time_of_measurement):
        speed_cmd = self.pid_speed.get_output(self.target_speed,
                                              speed_measurement,
                                              time_of_measurement)

        if self.target_speed == 0 and abs(speed_cmd) < 30:
            self.reset_pids()
            speed_cmd = 0

        return speed_cmd

    def reset_pids(self):
        self.pid_speed.reset()
Example #2
0
class HeatPlatform():
    """
    加热平台控制主类
    """

    def __init__(self, config_dict, OLED_Status=True):
        self.cfg = config_dict  # 配置文件信息
        self.pwm_out = PWM(Pin(2), freq=5, duty=1023)

        self.max6675 = MAX6675(None, None, None, Pin(16, Pin.OUT))
        # max6675使用的是硬件SPI,会设置GPIO13引脚,若使用GPIO13(蜂鸣器)请后初始化

        self.beep = Pin(13, Pin.OUT)    # 蜂鸣器引脚
        self.beep.value(1)      # 关闭蜂鸣器
        self.beep_flag1 = True
        self.beep_flag2 = False	# 只当编码器值改变时才置为True
        # 安全温度阈值,当 实际温度-与设定温度>self.max_error_temperature 触发报警
        self.max_error_temperature = 30

        self.buf_len = 3
        self.buf_index = 0
        self.temperature_err_flag = True
        self.temperature_buf = [20] * self.buf_len
        self.buf_sum = 20 * self.buf_len

        self.temp_now = self.max6675.read_temperature()
        self.temp_target = 50
        # 进行PID控制的阈值(以致于前期可以持续快速升温)
        self.temp_DValue = 20
        self.pid_enable = False
        self.pid_dt = 300 # PID的调整时间ms
        gc.collect()

        # 创建OLED显示器
        # construct an I2C bus,软件i2c所有接口都适用
        self.interface = Interface(self, Pin(1), Pin(3), OLED_Status)
        self.interface.temperature_now = self.temp_now
        self.interface.temperature_target = self.temp_target
        self.interface.opt_deal()

        # 创建编码器控制对象
        self.knobs = EC11(4, 5, 0)

        # 创建pid控制对象
        # self.pid_contorller = PID(6.0, 18.0, 6.0, self.pid_dt/1000)
        # self.pid_contorller = PID(6.0, 3.0, 10.0, self.pid_dt/1000)
        self.pid_contorller = PID(1.0, 0.3, 6.0, self.pid_dt/1000)

        # 创建蜂鸣器的定时器
        self.beep_start_timer = Timer(-1)  # periodic with 100ms period
        # mode: Timer.ONE_SHOT / Timer.PERIODIC
        self.beep_start_timer.init(period=1000, mode=Timer.PERIODIC,
                             callback=self.start_beep)

        # 创建温度读取的定时器
        self.temperature_timer = Timer(-1)  # periodic with 100ms period
        # mode: Timer.ONE_SHOT / Timer.PERIODIC
        self.temperature_timer.init(
            period=200, mode=Timer.PERIODIC, callback=self.get_temperature)

        # 创建按键检测的定时器
        self.knobs_timer = Timer(-1)  # periodic with 100ms period
        # mode: Timer.ONE_SHOT / Timer.PERIODIC
        self.knobs_timer.init(
            period=200, mode=Timer.PERIODIC, callback=self.check_knobs)

        # 创建pid调节的定时器
        self.adjust_timer = Timer(-1)
        # mode: Timer.ONE_SHOT / Timer.PERIODIC
        self.adjust_timer.init(
            period=self.pid_dt, mode=Timer.PERIODIC, callback=self.adjust_temperature)

        gc.collect()

    def get_temperature(self, timer):
        temperature = self.max6675.read_temperature()
        if temperature == 4095:
            self.temperature_err_flag = True
            return None
        else:
            self.temperature_err_flag = False
        self.buf_sum = self.buf_sum - self.temperature_buf[self.buf_index]
        self.temperature_buf[self.buf_index] = temperature
        self.buf_sum = self.buf_sum + self.temperature_buf[self.buf_index]
        self.buf_index = (self.buf_index+1) % self.buf_len

    def check_knobs(self, timer):
        # increase为一个长度为2的元组 编码脉冲+按键是否按下
        increase = self.knobs.get_data()
        # 跳转到界面里处理按键触发的指令
        self.interface.opt_deal(increase[0], increase[1])

    def start_beep(self, timer):
        """
        蜂鸣器报警
        """
        if self.beep_flag1 == True and self.beep_flag2 == True \
			and self.beep.value() == 1:
            self.beep_flag1 = False
            self.beep_flag2 = False
            self.beep.value(0)
            # 创建蜂鸣器的关闭定时器
            self.beep_end_timer = Timer(-1)  # periodic with 100ms period
            # mode: Timer.ONE_SHOT / Timer.PERIODIC
            self.beep_end_timer.init(
                period=700, mode=Timer.ONE_SHOT, callback=self.end_beep)

    def end_beep(self, timer):
        """
        蜂鸣器报警
        """
        self.beep.value(1)
       

    def adjust_temperature(self, timer):
        if self.temperature_err_flag == True:
            str_temp_now = "XXXX"
            self.pwm_out.duty(1023)
            self.interface.temperature_now = str_temp_now
            self.interface.pwm = 1023
            self.interface.show()
            return None

        self.interface.temperature_now = int(self.buf_sum/self.buf_len)
        self.temp_now = self.interface.temperature_now
        str_temp_now = str(self.temp_now)
        pwm_val = None  # 输出的PWM值
        if self.temp_target - self.temp_now > self.temp_DValue:
            pwm_val = 0
            #self.pid_enable = False
            self.beep_flag1 = False
            self.pid_contorller.set_data(self.temp_DValue, 0)
        elif self.temp_now > self.temp_target:
            pwm_val = 1023
            #self.pid_enable = False
            if self.temp_now-self.max_error_temperature > self.temp_target:
                # 当温度高于安全温度差,立即报警
                self.beep_flag1 = True  # 蜂鸣器报警标志
                self.beep_flag2 = True  # 蜂鸣器报警标志
            self.pid_contorller.set_data(0, 0)
        else:
            if self.temp_target == self.temp_now:
                self.beep_flag1 = True  # 蜂鸣器报警标志
            #if self.pid_enable == False:
            #    self.pid_enable = True
            out_val = self.pid_contorller.get_output(
                self.temp_target, self.temp_now)

            pwm_val = int(out_val)
            if pwm_val > 0:
                if pwm_val > 1020:
                    pwm_val = 0
                else:
                    pwm_val = 1023-pwm_val
            else:
                pwm_val = 1023
        self.pwm_out.duty(pwm_val)

        self.interface.pwm = pwm_val
        self.interface.show()

    def __del__(self):
        self.temperature_timer.deinit()
        self.knobs_timer.deinit()
        self.adjust_timer.deinit()
        self.temperature_timer.deinit()