|
通过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回调函数中。 - VCPXpress_API_CALLBACK(myAPICallback)
- {
- uint32_t API_InterruptCode;
- //get the code that indicates the reason for the interrupt
- API_InterruptCode = Get_Callback_Source();
- //if the USB connection was just opened
- if (API_InterruptCode & DEVICE_OPEN)
- {
- //start the first USB read procedure
- Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesRcvd);
- /*we will process the received bytes when we get
- a callback with an RX_COMPLETE interrupt code*/
- }
- if (API_InterruptCode & RX_COMPLETE) //USB read complete
- {
- //'C' tells the EFM8 to begin or resume PID control
- if(USBRxPacket[0] == 'C')
- {
- PID_ACTIVE = TRUE;
- }
- //'H' tells the EFM8 to halt PID control
- else if(USBRxPacket[0] == 'H')
- {
- PID_ACTIVE = FALSE;
- /*The heater-drive voltage is held at 0 V
- * while PID control is halted.*/
- UpdateDAC(DAC_HEATER, 0);
- }
- //'S' indicates that the host is sending the setpoint
- else if(USBRxPacket[0] == 'S')
- {
- /*The setpoint temperature is restricted to
- * positive integers not greater than 100
- * degrees C. Scilab sends the setpoint as a
- * normal binary number, not as ASCII characters,
- * so that the EFM8 doesn't have to convert
- * from ASCII to binary.*/
- Setpoint_Temp = USBRxPacket[1];
- }
- //continue with the next USB read procedure
- Block_Read(USBRxPacket, USB_PACKET_SIZE, &USBBytesRcvd);
- }
- }
复制代码
PID流量 主while循环中的PID例程现在通过检查PID_ACTIVE标志开始,该标志初始化为FALSE。此时执行仍然存在,直到Scilab的“C”命令导致EFM8将此标志更改为TRUE。另一个重要的区别是测量的温度在每次迭代开始时被发送到Scilab。在之前的项目中,Scilab首先通过USB命令请求数据,然后EFM8将数据作为对请求的响应发送。在这个项目中,Scilab不必询问数据; EFM8在每次迭代期间发送一个三字节的测量温度数据包,Scilab只接收并显示数据。这减少了USB流量和EFM8处理器的负担,因此我们应该减少更高的更新速率,以改善受控变量变化的可视化。当前固件使用两秒的更新间隔,这似乎提供了足够的控制和可视化,而不会使EFM8或Scilab GUI负担过重。以下代码摘录涵盖了主while循环的PID部分: - while (1)
- {
- /*First, we check PID_ACTIVE.The following while statement
- * suspends PID functionality until the EFM8 is commanded by
- * Scilab to begin or resume PID control.*/
- while(PID_ACTIVE == FALSE);
- GatherMAX31855Data();
- while(TEMP_DATA_READY == FALSE); //wait until the SPI transaction is complete
- Measured_Temp = ConvertMAX31855Data_to_TempC();
- //send measured temperature to Scilab
- TransmitUSB_TempData();
- Error = Setpoint_Temp - Measured_Temp;
- /*We don't want the integral error to get
- * way too large. This is a standard problem
- * referred to as integral windup. One solution
- * is to simply restrict the integral error to
- * reasonable values.*/
- Error_Integral = Error_Integral + Error;
- if(Error_Integral > 50)
- Error_Integral = 50;
- else if(Error_Integral < -50)
- Error_Integral = -50;
- Error_Derivative = Error - Previous_Error;
- Previous_Error = Error;
- PID_Output = (K_proportional*Error) + (K_integral*Error_Integral) + (K_derivative*Error_Derivative);
- /*We need to restrict the PID output to
- * acceptable values. Here we have limited it
- * to a maximum of 200, which corresponds
- * to about 780 mA of heater-drive current, and
- * a minimum of 0, because we cannot drive
- * less than 0 A through the heating
- * element.*/
- if(PID_Output > 200)
- PID_Output = 200;
- else if(PID_Output < 0)
- PID_Output = 0;
- //here we convert the PID output from a float to an unsigned char
- Heater_Drive = PID_Output;
- UpdateDAC(DAC_HEATER, Heater_Drive);
复制代码
发光二极管 虽然LED反馈本身不足,但它仍然是监控系统运行的便捷方式。 它也有助于确认Scilab显示的数据与EFM8中的实际情况一致。 为了使LED反馈更适合第二个目的,我们将在项目的这个阶段采取不同的方法:如果测量的温度在设定点的±2°C范围内,我们只打开绿色LED。 如果测得的温度低于设定值2°C以上,我们只打开蓝色。 如果测得的温度高于设定值2°C以上,我们只打开红色。 所以,绿色=好,蓝色=太冷,红色=太热。 当测量温度在设定点附近振荡时,该方案的优点将是显而易见的,因为LED颜色的变化将与GUI中显示的温度变化同步。 LED控制代码包含在主while循环的第二部分中。 - /*LED visualization: If the measured temperature is within
- * plus/minus 2 degrees C of the setpoint, we turn on the
- * green LED. If the measured temperature is more than
- * 2 degrees below the setpoint, we turn on the blue LED.
- * If the measured temperature is more than 2 degrees
- * above the setpoint, we turn on the red LED.*/
- if(Measured_Temp >= (Setpoint_Temp-2) && Measured_Temp <= (Setpoint_Temp+2))
- {
- UpdateDAC(DAC_RGB_R, 0);
- UpdateDAC(DAC_RGB_B, 0);
- UpdateDAC(DAC_RGB_G, 100);
- }
- else if(Measured_Temp < (Setpoint_Temp-2))
- {
- UpdateDAC(DAC_RGB_R, 0);
- UpdateDAC(DAC_RGB_B, 100);
- UpdateDAC(DAC_RGB_G, 0);
- }
- else if(Measured_Temp > (Setpoint_Temp+2))
- {
- UpdateDAC(DAC_RGB_R, 100);
- UpdateDAC(DAC_RGB_B, 0);
- UpdateDAC(DAC_RGB_G, 0);
- }
- /*Here we wait until the PID interval has expired,
- * then we begin a new iteration. The interval is
- * currently set to 2 seconds.*/
- PID_WAIT = TRUE;
- while(PID_WAIT == TRUE);
- }
复制代码
SCILAB 以下是GUI处于非活动状态时的样子:
它是在GUI Builder工具箱的帮助下设计的,您可以通过Scilab的ATOMS模块管理器下载该工具箱:、
首先,使用“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控制)命令的方式:
Setpoint值取自文本输入框,如下所示:
当PID控制处于活动状态时,Scilab会反复检查虚拟COM端口接收缓冲区。收到三个字节后,它会读取三个字节,将它们转换为温度值,然后将它们添加到一个数组中,该数组包含自上次单击“激活PID控制”以来收到的所有测量温度值:
显示测量温度的图也有一条绿色虚线,对应于设定值。以下代码用于生成设定值行:
结果 在上一篇文章中,我们研究了仅比例系统和比例积分系统的(基于LED和oscope的)结果。在这两种情况下,控制任务是将加热元件从30°C带到50°C的设定点。我们能够确定1)P-only系统从未达到设定点,2)PI系统确实达到了设定值,但有一些超调量。现在让我们看看同一控制任务的基于GUI的结果。首先是P-only系统:
我们可以看到,P-only系统实际上非常接近设定值,但没有积分增益,温度会有所降低,并达到比设定值低约2°C的稳态值。正如我们在前一篇文章中提到的那样,P-only系统因其对显着稳态误差的敏感性而闻名。
以下是PI系统的图表:
我们在这里可以看到PI系统实际上比我们想象的更糟糕。它确实达到了设定值,但它不仅仅导致过冲 - 这种特殊配置实际上导致了设定点周围的持续(或至少是长期)振荡。
总结 我们用于此项目的PCB实际上有两个USB连接器,一个用于电源,另一个用于数据。典型的USB端口不能提供超过500 mA的电流。因此,为了获得加热元件所需的更高电流,电路板包括从单独的连接器获取电源的选择。因此,其中一根USB线连接到USB充电器,可以提供1200 mA的电流,另一根连接到PC上的USB端口。
在下一篇文章中,我们将使用我们精美的新GUI来探索不同的P、I和D增益如何影响系统的性能。 |