旧乡故客
发表于: 2018-8-3 14:14:43 | 显示全部楼层

通过USB通信和Scilab图形用户界面,我们可以真正看到PID控制器正在做什么。

该PID(比例 - 积分 - 微分)温度控制系统的主要组件包含EFM8微控制器、DAC和MAX31855热电偶数字转换器。该系列总共有6部分:

●    Part 1:电路原理设计

●    Part 2:板级集成

●    Part 3:实现与可视化

●    Part 4:Scilab GUI


比LED更好的显示方式

在上一篇文章中使用的LED可视化方案非常有限。事实上,几乎任何基于几个LED的可视化方案都会相当薄弱。我们需要确切地看到我们的PID控制器正在做什么 - 首先,因为它会更有趣,其次,因为我们需要有关系统性能的详细信息,以便正确设置比例、积分和增益。


在项目的这个阶段,我们将把USB功能整合到EFM8固件中,并设计Scilab图形用户界面,控制设定点并实时显示实际测量的温度。


固件 - USB命令

固件已更改,因此PID操作由Scilab管理。在Scilab告诉它之前,EFM8不会启动PID功能,然后Scilab可以随时停止并恢复PID功能。要启动或恢复PID操作,Scilab通过USB链路发送ASCII“C”,并停止PID操作,它发送ASCII“H”;这两个命令只是一个没有回车或换行或不换行的单个字符。当PID操作停止时,加热器驱动电压设置为0 V,因此请记住,在停止状态期间,加热元件的温度将逐渐降低到室温。 Scilab也可以改变设定值;这是通过发送ASCII“S”后跟一个单字节二进制(即非ASCII)数字来实现的,该数字表示以摄氏度为单位的设定值。这三个命令包含在VCPXpress回调函数中。

  1. VCPXpress_API_CALLBACK(myAPICallback)
  2. {
  3.    uint32_t API_InterruptCode;

  4.    //get the code that indicates the reason for the interrupt
  5.    API_InterruptCode = Get_Callback_Source();

  6.    //if the USB connection was just opened
  7.    if (API_InterruptCode & DEVICE_OPEN)
  8.    {
  9.            //start the first USB read procedure
  10.            Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesRcvd);
  11.            /*we will process the received bytes when we get
  12.            a callback with an RX_COMPLETE interrupt code*/
  13.    }

  14.    if (API_InterruptCode & RX_COMPLETE)   //USB read complete
  15.    {
  16.                    //'C' tells the EFM8 to begin or resume PID control
  17.                    if(USBRxPacket[0] == 'C')
  18.                    {
  19.                            PID_ACTIVE = TRUE;
  20.                    }

  21.                    //'H' tells the EFM8 to halt PID control
  22.                    else if(USBRxPacket[0] == 'H')
  23.                    {
  24.                            PID_ACTIVE = FALSE;

  25.                            /*The heater-drive voltage is held at 0 V
  26.                             * while PID control is halted.*/
  27.                            UpdateDAC(DAC_HEATER, 0);
  28.                    }

  29.                    //'S' indicates that the host is sending the setpoint
  30.                    else if(USBRxPacket[0] == 'S')
  31.                    {
  32.                            /*The setpoint temperature is restricted to
  33.                             * positive integers not greater than 100
  34.                             * degrees C. Scilab sends the setpoint as a
  35.                             * normal binary number, not as ASCII characters,
  36.                             * so that the EFM8 doesn't have to convert
  37.                             * from ASCII to binary.*/
  38.                            Setpoint_Temp = USBRxPacket[1];
  39.                    }

  40.            //continue with the next USB read procedure
  41.            Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesRcvd);
  42.    }
  43. }
复制代码

PID流量

主while循环中的PID例程现在通过检查PID_ACTIVE标志开始,该标志初始化为FALSE。此时执行仍然存在,直到Scilab的“C”命令导致EFM8将此标志更改为TRUE。另一个重要的区别是测量的温度在每次迭代开始时被发送到Scilab。在之前的项目中,Scilab首先通过USB命令请求数据,然后EFM8将数据作为对请求的响应发送。在这个项目中,Scilab不必询问数据; EFM8在每次迭代期间发送一个三字节的测量温度数据包,Scilab只接收并显示数据。这减少了USB流量和EFM8处理器的负担,因此我们应该减少更高的更新速率,以改善受控变量变化的可视化。当前固件使用两秒的更新间隔,这似乎提供了足够的控制和可视化,而不会使EFM8或Scilab GUI负担过重。以下代码摘录涵盖了主while循环的PID部分:

  1. while (1)
  2. {
  3.         /*First, we check PID_ACTIVE.The following while statement
  4.          * suspends PID functionality until the EFM8 is commanded by
  5.          * Scilab to begin or resume PID control.*/
  6.         while(PID_ACTIVE == FALSE);

  7.         GatherMAX31855Data();
  8.         while(TEMP_DATA_READY == FALSE);        //wait until the SPI transaction is complete

  9.         Measured_Temp = ConvertMAX31855Data_to_TempC();

  10.         //send measured temperature to Scilab
  11.         TransmitUSB_TempData();

  12.         Error = Setpoint_Temp - Measured_Temp;

  13.         /*We don't want the integral error to get
  14.          * way too large. This is a standard problem
  15.          * referred to as integral windup. One solution
  16.          * is to simply restrict the integral error to
  17.          * reasonable values.*/
  18.         Error_Integral = Error_Integral + Error;
  19.         if(Error_Integral > 50)
  20.                 Error_Integral = 50;
  21.         else if(Error_Integral < -50)
  22.                 Error_Integral = -50;

  23.         Error_Derivative = Error - Previous_Error;
  24.         Previous_Error = Error;

  25.         PID_Output = (K_proportional*Error) + (K_integral*Error_Integral) + (K_derivative*Error_Derivative);

  26.         /*We need to restrict the PID output to
  27.          * acceptable values. Here we have limited it
  28.          * to a maximum of 200, which corresponds
  29.          * to about 780 mA of heater-drive current, and
  30.          * a minimum of 0, because we cannot drive
  31.          * less than 0 A through the heating
  32.          * element.*/
  33.         if(PID_Output > 200)
  34.                 PID_Output = 200;
  35.         else if(PID_Output < 0)
  36.                 PID_Output = 0;

  37.         //here we convert the PID output from a float to an unsigned char
  38.         Heater_Drive = PID_Output;

  39.         UpdateDAC(DAC_HEATER, Heater_Drive);
复制代码

发光二极管

虽然LED反馈本身不足,但它仍然是监控系统运行的便捷方式。 它也有助于确认Scilab显示的数据与EFM8中的实际情况一致。 为了使LED反馈更适合第二个目的,我们将在项目的这个阶段采取不同的方法:如果测量的温度在设定点的±2°C范围内,我们只打开绿色LED。 如果测得的温度低于设定值2°C以上,我们只打开蓝色。 如果测得的温度高于设定值2°C以上,我们只打开红色。 所以,绿色=好,蓝色=太冷,红色=太热。 当测量温度在设定点附近振荡时,该方案的优点将是显而易见的,因为LED颜色的变化将与GUI中显示的温度变化同步。 LED控制代码包含在主while循环的第二部分中。

  1. /*LED visualization: If the measured temperature is within
  2.          * plus/minus 2 degrees C of the setpoint, we turn on the
  3.          * green LED. If the measured temperature is more than
  4.          * 2 degrees below the setpoint, we turn on the blue LED.
  5.          * If the measured temperature is more than 2 degrees
  6.          * above the setpoint, we turn on the red LED.*/
  7.         if(Measured_Temp >= (Setpoint_Temp-2) && Measured_Temp <= (Setpoint_Temp+2))
  8.         {
  9.                 UpdateDAC(DAC_RGB_R, 0);
  10.                 UpdateDAC(DAC_RGB_B, 0);
  11.                 UpdateDAC(DAC_RGB_G, 100);
  12.         }

  13.         else if(Measured_Temp < (Setpoint_Temp-2))
  14.         {
  15.                 UpdateDAC(DAC_RGB_R, 0);
  16.                 UpdateDAC(DAC_RGB_B, 100);
  17.                 UpdateDAC(DAC_RGB_G, 0);
  18.         }

  19.         else if(Measured_Temp > (Setpoint_Temp+2))
  20.         {
  21.                 UpdateDAC(DAC_RGB_R, 100);
  22.                 UpdateDAC(DAC_RGB_B, 0);
  23.                 UpdateDAC(DAC_RGB_G, 0);
  24.         }

  25.         /*Here we wait until the PID interval has expired,
  26.          * then we begin a new iteration. The interval is
  27.          * currently set to 2 seconds.*/
  28.         PID_WAIT = TRUE;
  29.         while(PID_WAIT == TRUE);
  30. }
复制代码

SCILAB

以下是GUI处于非活动状态时的样子:

PID4_blankGUI.jpg

它是在GUI Builder工具箱的帮助下设计的,您可以通过Scilab的ATOMS模块管理器下载该工具箱:、

RGBGUI_ATOMS.jpg


首先,使用“Open VCP Port”按钮建立与EFM8的虚拟COM端口连接。接下来,选择设定值。 Scilab将设定值限制为小于或等于100的整数。如果输入的值大于100,Scilab将自动将其减小到100并在下面的消息栏中显示“设定值降至最大允许值,即100°C” “打开VCP端口”按钮。同样,如果输入非整数,Scilab会将其舍入到最接近的整数,并显示相应的消息。现在您可以单击“激活PID控制”按钮。在单击此按钮之前,设定值实际上不会发送到EFM8,并且在PID控制处于活动状态时无法更改设定值。这很明显,因为在有效PID控制期间,设定值文本输入框显示为灰色。要更改设定值,必须单击“停止PID控制”,然后更改它,然后单击“激活PID控制”以恢复PID操作。


使用完GUI后,首先单击“停止PID控制”(除非PID控制已处于非活动状态),然后单击“关闭VCP端口”,然后关闭GUI窗口。如果您不遵循此过程,则可能需要重新启动Scilab或重置EFM8等。这很烦人,但不是灾难性的。


让我们快速浏览一下Scilab脚本的一些显着部分。首先,这是Scilab在单击“激活PID控制”后发送“S”(设定值)和“C”(启动/恢复PID控制)命令的方式:

PID4_script1_2.jpg

Setpoint值取自文本输入框,如下所示:

PID4_script2.jpg

当PID控制处于活动状态时,Scilab会反复检查虚拟COM端口接收缓冲区。收到三个字节后,它会读取三个字节,将它们转换为温度值,然后将它们添加到一个数组中,该数组包含自上次单击“激活PID控制”以来收到的所有测量温度值:

PID4_script3.jpg

显示测量温度的图也有一条绿色虚线,对应于设定值。以下代码用于生成设定值行:

PID4_script4.jpg


结果

在上一篇文章中,我们研究了仅比例系统和比例积分系统的(基于LED和oscope的)结果。在这两种情况下,控制任务是将加热元件从30°C带到50°C的设定点。我们能够确定1)P-only系统从未达到设定点,2)PI系统确实达到了设定值,但有一些超调量。现在让我们看看同一控制任务的基于GUI的结果。首先是P-only系统:

PID4_plot1.jpg


我们可以看到,P-only系统实际上非常接近设定值,但没有积分增益,温度会有所降低,并达到比设定值低约2°C的稳态值。正如我们在前一篇文章中提到的那样,P-only系统因其对显着稳态误差的敏感性而闻名。


以下是PI系统的图表:

PID4_plot2.jpg

我们在这里可以看到PI系统实际上比我们想象的更糟糕。它确实达到了设定值,但它不仅仅导致过冲 - 这种特殊配置实际上导致了设定点周围的持续(或至少是长期)振荡。


总结

我们用于此项目的PCB实际上有两个USB连接器,一个用于电源,另一个用于数据。典型的USB端口不能提供超过500 mA的电流。因此,为了获得加热元件所需的更高电流,电路板包括从单独的连接器获取电源的选择。因此,其中一根USB线连接到USB充电器,可以提供1200 mA的电流,另一根连接到PC上的USB端口。


在下一篇文章中,我们将使用我们精美的新GUI来探索不同的P、I和D增益如何影响系统的性能。

跳转到指定楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 29 | 回复: 32



手机版|

GMT+8, 2024-12-21 21:18 , Processed in 0.041702 second(s), 7 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表