生物化学(仪器设备)PocketPCR:超便携口袋式设计、全部开源、可3D打印的 聚合酶链式反应设备

PocketPCR简介

  • PocketPCR 是由 GaudiLabs 发起的一个开源项目,旨在提供一种 袖珍型、低成本、USB供电的 PCR 热循环仪(Thermal Cycler)。它允许生物实验者在桌面或野外环境中进行基础的 DNA 扩增实验。
链接地址用途说明
http://gaudi.ch/PocketPCR/官方介绍页面(GaudiLabs 官网)
https://github.com/GaudiLabs/PocketPCRGitHub 项目主页,包含源代码、电路图、说明文档等
Essential Biochem Lab Equipment: PCR MachineHow To Assemble PocketPCR详细的使用教程(包括加矿物油防止蒸发)PocketPCR 使用演示视频(YouTube)

在这里插入图片描述

PocketPCR 结构展示

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

硬件部分

加热头部分

在这里插入图片描述

PCB

  • 官方代码在硬件部分提供了每个板子的GERBER的zip文件,直接上传到PCB平台就能进行打板。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 使用的主控为:SAMD21G18B-A (changed from SAML21),通过arduino进行编程:
    在这里插入图片描述

BOM

  • 核心元器件与主芯片
设计ator数量名称封装订货号
U21SAMD21G18B-A(改自 SAML21)TQFP-48 7×7mm, 0.5mm 间距556-ATSAMD21G18A-AUT
U11TLV1117-33 稳压器SOT-223595-TLV1117LV33DCYR
Y11晶振 32.765 kHzSMD_3215-2pin_3.2x1.5mm520-ECS-327-12.5-34B / 449-LFXTAL009678REEL
NTC1热敏电阻 10K 0.5% 04020402810-NTCG103JX103DTDS
  • 显示、连接与接口
设计ator数量名称封装/说明订货号
S11OLED 显示连接器-649-SFV30R-1STE1HLF
S11OLED 显示屏OLED_096_1_Flip-
J31USB Type-C 插座Amphenol_12401610E4-2A523-12401610E4#2A
J112 针接头1x02 PinHeader-
J20调试接头(未装)2x5, SMD, 1.27mm-
  • 有源/无源元件
设计ator数量名称封装订货号
Q1, Q2, Q33N-MOS 管(GSD)SOT-23863-NTR3C21NZT1G
LED1, LED22指示灯0805-
  • 电容、电阻
设计ator数量封装订货号
C31100uF, 6.3V1206JMK316ABJ107ML-T
C2, C5210uF, 6.3V1206JMK107ABJ106MA-T
C1, C4, C12, C14, C1651uF0805810-C2012X7R1C105M-3 / 603-CC805KKX7R7BB105
C6–C94100nF0805-
C10, C11222pF0805-
C15, C1722.2uF0805603-CC805KKX7R7BB225
R1, R9, R1034.7kΩ0805-
R2, R32390Ω0805-
R5, R72390kΩ0805-
R4, R624.7kΩ, 0.1% 精度-279-CPF0805B4K7E1
  • 散热、风扇、机械件
名称数量说明 / 参数订货号
Blower 风扇130×30×10mm, 5V, 2Pin3010 fan
Heat Block1Ø19.5mm, 铝合金 6082-
Spring 弹簧1线径 0.4mm / 长度 5mm 或 0.3mm / 10mm-
Feets 脚垫4硅胶脚塞,适配 6.5mm+MAKSEY Silicone Caps
Screw M3x6mm2黑色十字盘头螺钉 DIN 7985-
Screw M3x16mm4黑色十字盘头螺钉 DIN 7985-
Plastic Screw2M3 白色尼龙或黑色手拧螺钉-
X1, X22+2六角金属柱,10mm + 20mm, M3VT DI 10MM / VT DI 20MM
  • 旋转编码器相关
名称数量封装订货号
SW11带按压开关的旋转编码器Alps EC11E858-EN11-HSB1AQ15
Encoder Cap1旋钮帽,6mm 轴用套件/批量购买
Rotary Encoder Spring1与编码器弹力回弹配合-
  • PCB 列表
名称数量材质 / 特性
PCB11TopHeater 铝基板,导热率 2W,黑色,1.6mm
PCB21主控 PCB,FR4 黑色,1.6mm
PCB31盖子 PCB,FR4 白色,1.2mm
  • 其他物品
名称数量描述型号
Beutel ESD 袋1ESD 屏蔽袋 76×127 mm,可重复封口ESD BEUTEL-S 127

CODE

  • 这段 loop() 是整个 PocketPCR 热循环控制程序的核心,负责读取传感器、处理界面交互、控制温度状态转换、执行 PID 控制逻辑,并呈现不同的用户界面(主界面、设置界面、运行状态界面等)。整个状态流严格控制 PCR 各个阶段:变性、退火、延伸,并且支持用户自定义每个阶段的时间和温度。
void loop() {
  // 关闭加热与风扇,初始化状态
  setHeater(0, 0);  

  // 读取NTC热敏电阻的ADC值
  sensorValue = analogRead(analogInPin);

  // 应用当前温度与控制值设置加热/冷却输出
  setHeater(temperature_mean, TEMPcontrol);

  // 将ADC值转换为电压
  sensorVoltage = 3.3 * sensorValue / 4096;

  // 使用分压公式计算热敏电阻阻值
  sensorResistance = (sensorVoltage * NTC_R0) / (3.3 - sensorVoltage);

  // 根据 B 参数模型计算温度值(摄氏)
  temperature = 1 / (log(sensorResistance * 1000 / NTC_RN) / NTC_B + 1 / NTC_TN) - 273.15;

  // 平滑滤波温度值(加权滑动平均)
  temperature_mean = (temperature_mean * 3 + temperature) / 4;

  // 根据当前 UI 状态 caseUX 进行功能分支
  switch (caseUX) {

    // 主界面:用户在“Run PCR”与“Setup”之间选择
    case CASE_Main:
      if (counter > 1) counter = 0;
      if (counter < 0) counter = 1;
      MenuItem = counter;
      draw_main_display(); // 显示主界面

      // 用户按键触发
      if (!digitalRead(butPin)) {
        while (!digitalRead(butPin));  // 等待释放
        if (MenuItem == 0) {
          caseUX = CASE_Run;           // 进入运行界面
          casePCR = PCR_set;           // 初始化PCR状态
          PCRstate = 0;
          counter = 0;
        }
        if (MenuItem == 1) {
          caseUX = CASE_Settings;      // 进入设置界面
          counter = 0;
        }
      }
      break;

    // 设置界面:显示与编辑温度/时间设置
    case CASE_Settings:
      if (counter > 12) counter = 0;
      if (counter < 0) counter = 12;
      MenuItem = counter;

      // 判断当前设置项是否为“分钟”单位
      minuteMode = (MenuItem % 2 == 1 && settings.value[MenuItem] > 90);

      // 进入具体某一项的编辑界面
      if (!digitalRead(butPin)) {
        while (!digitalRead(butPin));
        caseUX = CASE_EditSettings;
        counter = minuteMode ? settings.value[MenuItem] / 60 : settings.value[MenuItem];
      }

      draw_setup_display(); // 显示设置界面
      break;

    // 编辑具体某项设置(温度或时间)
    case CASE_EditSettings:
      if (MenuItem % 2 == 0) { // 温度项
        if (MenuItem == 10) {
          if (counter < 1) counter = 1;
          if (counter > 99) counter = 99;
        } else {
          if (counter < 25) counter = 25;
          if (counter > 99) counter = 99;
        }
      } else { // 时间项
        if (minuteMode) {
          if (counter < 2) { minuteMode = false; counter = 90; }
        } else {
          if (counter > 90) { minuteMode = true; counter = 2; }
          if (counter < 0) counter = 0;
        }
      }

      // “保存设置”或“恢复默认”
      if (MenuItem == 11) {
        caseUX = CASE_Main;
        my_flash_store.write(settings); // 保存
      }
      if (MenuItem == 12) {
        caseUX = CASE_Main;
        settings = my_flash_store.read(); // 恢复
      }

      // 保存当前值到 EEPROM 缓存结构
      if (MenuItem < 11) {
        settings.value[MenuItem] = minuteMode ? counter * 60 : counter;
      }

      // 返回设置页面
      if (!digitalRead(butPin)) {
        while (!digitalRead(butPin));
        caseUX = CASE_Settings;
        counter = MenuItem;
      }

      draw_setup_display(); // 显示设置项
      break;

    // PCR 运行状态机
    case CASE_Run:
      // 温差与积分项更新(用于 PID 控制)
      TEMPdif = TEMPset - temperature_mean;
      TEMPi += TEMPdif;

      // 每200ms 计算一次微分项(TEMPd)
      if (millis() - TEMPclick > 200) {
        TEMPclick = millis();
        TEMPd = TEMPdif_a[4] - TEMPdif;
        TEMPdif_a[4] = TEMPdif_a[3];
        TEMPdif_a[3] = TEMPdif_a[2];
        TEMPdif_a[2] = TEMPdif_a[1];
        TEMPdif_a[1] = TEMPdif_a[0];
        TEMPdif_a[0] = TEMPdif;
      }

      // PCR 流程控制状态机
      switch (casePCR) {
        case PCR_set:
          // 设置当前阶段目标温度和时间
          TEMPset = settings.value[PCRstate * 2];
          TIMEcontrol = settings.value[PCRstate * 2 + 1];
          PIDIntegration = false;
          casePCR = PCR_transition; // 进入加热阶段
          break;

        case PCR_transition:
          runPID(); // PID控制
          draw_run_display();
          // 达到目标温度后进入计时状态
          if (abs(TEMPset - temperature_mean) < temperature_tollerance) {
            PIDIntegration = true;
            TEMPi = 0;
            TIMEclick = millis();
            casePCR = PCR_time;
          }
          break;

        case PCR_time:
          runPID(); // PID控制
          // 倒计时
          TIMEcontrol = settings.value[PCRstate * 2 + 1] - (millis() - TIMEclick) / 1000;
          draw_run_display();

          // 阶段结束后判断下一个状态
          if (TIMEcontrol <= 0) {
            if (PCRstate == 4) caseUX = CASE_Done; // Final结束
            else if (PCRstate == 3) { // Extension -> Denature (下一轮)
              PCRstate = 1;
              PCRcycle++;
              if (PCRcycle > settings.value[10]) PCRstate = 4; // 到达循环上限,进入 Final
            } else {
              PCRstate++; // 正常流程进入下一阶段
            }
            casePCR = PCR_set; // 开始下一阶段
          }
          break;

        default:
          break;
      }
      break;

    // PCR 完成界面
    case CASE_Done:
      TEMPcontrol = 0;
      setHeater(temperature_mean, TEMPcontrol); // 停止加热

      display.clearDisplay();
      display.setFont(&FreeSans9pt7b);
      display.fillRect(10, 10, 100, 40, 1);
      display.setCursor(15, 30);
      display.setTextColor(0);
      display.println("PCR Done"); // 显示完成信息
      display.display();
      display.setFont();

      if (!digitalRead(butPin)) {
        while (!digitalRead(butPin));
        caseUX = CASE_Main;
        counter = MenuItem;
      }
      break;

    default:
      break;
  } // end switch
}

温度控制原理

  • 系统通过 热敏电阻 + PID 算法 + 加热器 + 风扇 实现高精度闭环温控。

控制流程概述

  1. 温度测量

    • 通过热敏电阻(NTC)采集当前温度(使用 analogRead())。
    • 使用热敏电阻的阻值换算公式与 B 参数模型将电压转换为温度。
  2. 设定目标温度

    • 根据当前的 PCR 状态(如变性、退火、延伸等),读取 EEPROM 里保存的目标温度 TEMPset
  3. 误差计算与 PID 控制

    • 计算当前温度与目标温度之间的差值 TEMPdif
    • 调用 runPID() 函数,根据 PID 算法(比例P + 微分D + 积分I)计算出控制量 TEMPcontrol
  4. 执行加热或冷却

    • 调用 setHeater(),根据 TEMPcontrol 的正负:

      • 正值表示加热:启用加热器(加热电阻),关闭风扇。
      • 负值表示冷却:启用风扇,关闭加热器。

PID 控制runPID()

TEMPcontrol = PIDp * TEMPdif + PIDd * TEMPd + (int)PIDIntegration * PIDi * TEMPi;
  • PIDp, PIDi, PIDd 是比例/积分/微分系数。
  • TEMPdif:当前目标温度与实际温度差。
  • TEMPi:积分项(误差累加)。
  • TEMPd:微分项(温差变化速率)。
  • TEMPcontrol 是一个浮点值,代表“应该加热多少”或“应该冷却多少”。

风扇控制:setHeater(float temperature, float power)

  • 风扇配合加热器,实现了主动降温机制,使温控反应速度更快、更加精准,尤其适合 PCR 中快速温变需求(例如从 95°C 降至 55°C)。
if (TEMPcontrol > 0)
{
  // 加热控制(风扇停)
  heatPower = power_heating(temperature, power);
  analogWrite(fanPin, 0);
  analogWrite(heaterPin, heatPower);
}
else
{
  // 冷却控制(关闭加热,风扇开启)
  heatPower = power_cooling(temperature, power);
  analogWrite(fanPin, heatPower);
  analogWrite(heaterPin, 0);
}
  • 根据 TEMPcontrol 的正负,决定启用加热器或风扇。
  • 调用 power_heating() / power_cooling() 计算合适的 PWM 占空比。
情况风扇状态作用说明
需要升温(TEMPcontrol > 0关闭风扇防止风扇带走热量,集中加热
需要降温(TEMPcontrol < 0开启风扇加快冷却速率,迅速降温
温控关闭(如 PCR 结束)风扇关闭节能,系统静止

CG

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值