【龙印】以程序员的角度整定3d打印机的pid实现控温

本文为在用龙芯1c做3D打印机过程中的笔记。龙芯1c做的3d打印机简称“龙印”,Git地址“https://gitee.com/caogos/marlin_ls1c”


网上pid的资料很多,但展示整定全过程的视频不多。这里以龙芯1c的智龙开源主板+ramps1.4扩展板实现的3D打印机用pid控温为例,以程序员的角度整定pid,在大致确定温度采样周期和控制加热装置的pwm周期后,主要通过调节比例项、积分项、微分项和维持功率项的系数来将温度控制在指定范围。

温度采样周期的选择:以在温度快速变化时,相邻两次或三次采集的温度有变化,变化又不至于太大为宜。这句话怎么理解,首先温度变化从微观上讲并不是曲线,而是梯形,这个不会随温度采样周期的大小而改变。如果采用周期太小,则会看到连续采样几次的值都是一样的,采样周期太大,则会发现相邻两次的温度变化太大,这个根据实际情况选择一个合适的值。比如,我把温度采集周期设置为500ms,即每秒采集两次。

加热装置的pwm周期的选择:加热装置的pwm周期最好不要大于温度采集周期,否则温度采集后,计算得到的pid值,不能很好的传递给加热装置执行。即加热装置还未执行完上一次pid计算得到的结果,又有一个新的pid值需要执行。个人认为加热装置的pwm周期小于或等于温度采集周期的一半比较合适。比如,我把加热头的pwm周期设为200ms。

温度采集周期一旦确定,那么pid的微分时间就确定了。

pid的积分时间通常由代码确定,即当前温度与目标温度相差n度时才开始积分,当温度超过这个限定后将积分项清零,待又回到区间内时重新积分。还可以为积分作用加些保护措施。

所以本文主要调节pid系数,而非积分时间,微分时间。但是以正确温度采集周期和加热装置的pwm周期为前提,一旦温度采集周期或加热装置的pwm周期改变了,应该重新检查之前的pid系数是否还合适。

硬件

cpu:龙芯1c

主板:智龙

扩展板:开源3d打印机扩展板ramps1.4(主要用了其中的STP55NF06L控制加热头)

温度采集:热敏电阻+AD芯片TM7705

源码

在linux上实现的。其中TM7705+NTC热敏电阻采集温度的文章之前已经写了,控制加热头的pwm也是linux驱动中的软件定时器模拟的,这里重点关注pid算法和整定过程。完整的代码在http://git.oschina.net/caogos/marlin_ls1c

加热头和风扇驱动

/*
 * include\linux\ls1c_3dprinter_heater_fan.h
 * 3d打印机加热头和风扇(散热)驱动的头文件
 */

#ifndef MY_LS1C_3DPRINTER_HEATER_FAN_H
#define MY_LS1C_3DPRINTER_HEATER_FAN_H


// 挤出机加热头的gpio
#define PRINTER_EXTRUDER_HEATER_PIN     (90)    // I2S_BCLK/GPIO90
// 挤出机散热风扇的gpio
#define PRINTER_EXTRUDER_FAN_PIN        (91)    // I2S_MCLK/GPIO91


struct platform_3dprinter_heater_fan_data {
    unsigned char extruder_heater_gpio;         // 挤出机加热头的gpio
    unsigned char extruder_fan_gpio;            // 挤出机散热风扇的gpio
};


#endif


/*
 * drivers\misc\ls1c_3dprinter_heater_fan.c
 * 3d打印机加热头和风扇(散热)驱动
 * 用linux内核定时器模拟pwm
 */

 
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/time.h>
#include <linux/timer.h>
#include <linux/errno.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/ls1c_3dprinter_heater_fan.h>


// pwm周期(ms)
#define HEATER_FAN_PWM_TIME_MS              (200)   // 200ms

enum
{
    HEATER_NOT_WORK = 0,    // 不加热(加热装置不工作)
    HEATER_WORK = 1,        // 加热(加热装置正常工作)
};
enum
{
    FAN_NOT_WORK = 0,       // 不散热(风扇不工作)
    FAN_WORK = 1,           // 散热(风扇正常工作)
};


// 一个pwm周期内,工作的时长,单位ms
// 由于驱动中不能进行浮点计算
// 所以在应用程序中将pid的占空比直接换算为一个周期内加热头和散热的风扇工作的时长
typedef struct{
    unsigned int extruder_heater_ms;        // 挤出机加热的时长(ms)
    unsigned int extruder_fan_ms;           // 挤出机风扇工作的时长(ms)
}heater_fan_work_time_t;


static heater_fan_work_time_t heater_fan_work_time = {0};
static struct platform_3dprinter_heater_fan_data *heater_fan_data = NULL;

// 用于模拟pwm的定时器
static struct timer_list extruder_heater_timer;         // 挤出机加热的定时器
static struct timer_list extruder_fan_timer;            // 挤出机散热风扇的定时器
static DEFINE_MUTEX(heater_fan_lock);



// 给挤出机加热
static void extruder_heater_enable(void)
{
    gpio_direction_output(heater_fan_data->extruder_heater_gpio, HEATER_WORK);
}


// 挤出机不加热
static void extruder_heater_disable(void)
{
    gpio_direction_output(heater_fan_data->extruder_heater_gpio, HEATER_NOT_WORK);
}


// 给挤出机散热
static void extruder_fan_enable(void)
{
    gpio_direction_output(heater_fan_data->extruder_fan_gpio, FAN_WORK);
}


// 不给挤出机散热
static void extruder_fan_disable(void)
{
    gpio_direction_output(heater_fan_data->extruder_fan_gpio, FAN_NOT_WORK);
}


// 挤出机加热定时器中断(模拟pwm)
void extruder_heater_timer_timeout_fn(unsigned long arg)
{
    static int level = 0;
    
    // 判断是否需要加热
    if (0 == heater_fan_work_time.extruder_heater_ms)
    {
        // 不需要加热
        extruder_heater_disable();
        mod_timer(&extruder_heater_timer, jiffies + HEATER_FAN_PWM_TIME_MS);
        level = 0;
        return ;
    }

    // 是否在整个pwm周期内一直加热
    if (HEATER_FAN_PWM_TIME_MS <= heater_fan_work_time.extruder_heater_ms)
    {
        // 一直加热
        extruder_heater_enable();
        mod_timer(&extruder_heater_timer, jiffies + HEATER_FAN_PWM_TIME_MS);
        level = 0;
        return ;
    }

    // 模拟pwm
    if (0 == level)
    {
        level = 1;
        extruder_heater_enable();
        mod_timer(&extruder_heater_timer, 
                  jiffies + heater_fan_work_time.extruder_heater_ms);
    }
    else
    {
        level = 0;
        extruder_heater_disable();
        mod_timer(&extruder_heater_timer, 
                  jiffies + (HEATER_FAN_PWM_TIME_MS - heater_fan_work_time.extruder_heater_ms));
    }
    
    return ;
}


// 挤出机散热风扇定时器中断(模拟pwm)
void extruder_fan_timer_timeout_fn(unsigned long arg)
{
    static int level = 0;
    
  
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值