一、项目和设计思路
酸奶、醪糟都是我爱吃的美食。做这类美食并不复杂,都是利用微生物发酵,改善食物风味,产生的美食。微生物在发酵过程中需要维持生产菌的生长和产物合成的适当发酵条件,其中之一就是温度。温度是保证各种酶活性的重要条件,微生物的生长和产物合成均需在其各自适合的温度下进行。因此,在发酵过程中必须保证稳定和最适宜的温度环境。
喜欢自己动手,所以就想自己制作一个恒温箱,用来发酵食物。箱子不需要太大,能够很好地隔绝温度就好。大多数发酵温度都是略高于环境温度,但又不会太高,所以恒温箱内部使用发热元件,功率不需要太大。需要很好地控制温度的上下波动,所以需要使用温度传感器来进行反馈,做到温度控制的闭环管理。
二、硬件的选择
恒温箱整体就使用了一个15L的保温箱,作为个人使用,15升的容积,能应对大多数场景了。
主控使用ESP32-S3_SMART_DIAL。M5Dial是一款多功能的嵌入式开发板,配备1.28寸圆形TFT触摸屏,以M5StampS3为主控(ESP32-S3@Xtensa LX7 ,8M-FLASH,WIFI,OTG\CDC功能),内置旋转编码器,可精确记录旋钮位置。此外,板载RFID检测模块,RTC电路,板载蜂鸣器以及屏下按键用于设备互动和提醒唤醒等功能。供电方面,产品设计支持宽电压6-36V直流电输入,并预留了锂电池接口和充电电路,以提供不同需求。
温度传感器使用了DS18B20数字温度传感器。DS18B20通过单总线(1-Wire)通信,只需要一条数据线 (和地线) 即可与处理器进行数据传输。器件可以工作在-55°C至+125°C范围,在-10°C至+85°C范围内测量精度为±0.5°C。每个DS18B20具有唯一的64位序列号,从而允许多个DS18B20挂接在同一条1-Wire总线。
为了均衡保温箱内个点温度,DS18B20温度传感器我使用了3个,一颗放置在加热器件上,防止加热器件温度过高,引起危险。另外两个放置在恒温箱内不同的地方,用来测量不同地方的温度。并且加装了两个风扇,用来快速平衡保温箱内温度。
发热器件,使用了普通的12V加热片,功率不大,面积较大,方便加热,并且尽量避免热量的聚集,毕竟恒温箱材质是塑料的,经受不起高温。设计时是使用了一片发热片,测量12v时功率大概是15W,加热速度太慢了,后来有添加了两片碳纤发热片,两片碳纤发热片是5V电压的,将其串联进12v内使用,在全额12v电压下功率约为28W。
三、方案框图和硬件实现
整个方案工作流程并不复杂,通过主控M5Dial读取温度传感器的值,去驱动发热板和风扇工作。目前自己需要制作的只有酸奶和醪糟两种食物,所以只设计了两种食物的发酵环境。酸奶需要的温度为40~42度,醪糟则是为30度。设计系统工作流程图:
M5Dial自带一个1.28寸圆形TFT触摸屏,用这块屏幕来展示用户界面,M5Dial还带了一个旋转编码器和按键,用户使用他们来选择菜单和确定选择。M5Dial提供的管脚很有限,好在DS18B20温度传感器是单总线模式,多个温度传感器只占用一个GPIO。
加热板和风扇选择的是12v电压输入。M5Dial支持宽电压(6v~36v),所以恒温箱电源我就是用一个12V电源作为输入电源,M5Dial的接口处有将输入电源转换为5V电源,用这个5V电源为DS18B20温度传感器供电。风扇和加热板属于功率器件了,M5Dial是无法直接驱动他俩了。所以就使用MOS管来进行驱动,这里选的MOS管型号为SI2302S。按这个思路绘制了电路图。
制作PCB遇到的坑。PCB与M5Dial连接是通过两组2.0排母连接,使用螺丝牢牢固定在PCB上。但是M5Dial有一个按键在底部螺丝孔中央。写程序遇到M5Dial写死的情况时,需要按住这个按键再去烧写就能解决。在这里PCB将这个按键完全遮住了,导致M5Dial无法烧写程序时,只能拆掉螺丝,将M5Dial整个拆下来处理,非常麻烦。后来实在是没办法了,就在这个PCB中间钻了个洞来解决这个问题。
硬件制作完成后,才发现购买的发热模块功率太小了,大概只有15W。盖上恒温箱盖子后,空箱满功率运行,大概需要90分钟才能将空箱内的温度上升到42度。这样以后到了冬天,估计很难将温度上升到制作酸奶合适的温度了。于是又找来了两片碳纤维发热材料,不过是5V驱动的发热布,将两片串联起来,和原来的发热模块并联在一起,满负荷发热功率上升到了28W。恒温箱升温的速度也快了很多。
四、软件设计实现
软件使用arduino编程。编程工具Vscode+platformio。arduino编程非常方便,有大量的库可以参考使用。温度传感器部分使用了单总线(OneWire)库,可以通过DS18B20的地址去读取每一个温度传感器的温度。
byte board_addr[8] = {0X28, 0X75, 0XAC, 0X84, 0X00, 0X00, 0X00, 0XA8}; //板载板子上的DS18B20用于测量环境温度
byte box_addr1[8] = {0X28, 0XE2, 0X99, 0X43, 0XD4, 0XBE, 0X09, 0XB0}; //短线
byte box_addr2[8] = {0X28, 0XD, 0X18, 0X49, 0XF6, 0XAE, 0X3C, 0X16}; //短线
byte box_addr3[8] = {0X28, 0X13, 0X18, 0X6B, 0X00, 0X00, 0X00, 0X5A}; //长线
OneWire ds(13);
//读取DS18B20温度,入口,传感器地址,出口:温度,浮点数
float readSesonTemp(byte *addr)
{
byte data[9];
ds.reset();
ds.select(addr);
ds.write(0x44, 1);
delay(5);
ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for (byte i = 0; i < 9; i++)
{ // we need 9 bytes
data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00)
raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20)
raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40)
raw = raw & ~1; // 11 bit res, 375 ms
// default is 12 bit resolution, 750 ms conversion time
return (float)raw / 16.0;
}
温度控制部分,使用了PID算法。使用PID算法来计算需要给加热板输出的功率值,使用PWM方式控制着输出功率。加热板功率比较小,所以热惯性也不大,PID参数几乎不用怎么调整就能很好地控制温度了。
#include "tempturepid.h"
PID pid;
void PID_Init()
{
pid.Kp = 270;
pid.ki = 0.125;
pid.kd = 0.05;
}
void PID_Calc() // pid计算
{
float DelEk;
float ti, ki;
float td;
float kd;
int out;
pid.Ek = pid.Sv - pid.Pv; //得到当前的偏差值
pid.Pout = pid.Kp * pid.Ek; //比例输出
pid.SEk += pid.Ek; //历史偏差总和
DelEk = pid.Ek - pid.Ek_1; //最近两次偏差之差
pid.Iout = pid.ki * pid.SEk; //积分输出
pid.Dout = pid.kd * DelEk; //微分输出
Serial.printf("EK=%.1F , Ek_1=%.1f , SEK=%.1f \r\n", pid.Ek, pid.Ek_1, pid.SEk);
out = pid.Pout + pid.Iout + pid.Dout;
if (out > MAXOUTVAL)
{
pid.OUT = MAXOUTVAL;
}
else if (out <= 0)
{
pid.OUT = 0;
}
else
{
pid.OUT = out;
}
pid.Ek_1 = pid.Ek; //更新偏差
}
风扇部分设计之初也是想用PID来控制转速的。但是风扇购买回来后测试发现,这个风扇驱动电压要上到9V以上才会旋转,这样PID算法意义不大了,就直接使用开关量的方式来控制风扇了。
五、效果展示
主界面,通过编码器选择制作酸奶,或是醪糟。
摆入添加好白糖和菌种的牛奶,酸奶发酵需要隔绝氧气。我这里直接使用牛奶原装的包装,使用漏斗将白糖和菌种加入牛奶,白糖加入的比例为10%,原包装能够很好滴密封。
制作酸奶开始。发热板100%的功率工作,电流约为2.4A,功率约为29W。
工作中,温度已达设定温度。功率为维持功率,电流约为0.9A,功率11W。
成品,粘稠的酸奶。
六、心得体会
感谢电子森林举办的FastBond活动。通过参加这次活动,将脑海中的想法制作成实物了,即体会到了学习制作中的快乐!又能自己制作美食了!