跳转到内容

教程:模拟CO2传感器

最短的完整可编程传感器:一个从400到5000 ppm的滑块, 一个引脚上的电压,以及一个Arduino读取它。从头到尾十分钟, 之后每个模拟传感器你都会复制这个形状。

[ CO2传感器芯片 ] [ Arduino Uno ]
VCC o------------------------o 5V
GND o------------------------o GND
OUT o------------------------o A0
滑块 400..5000 ppm -> OUT 0..5 V -> analogRead(A0)

从编辑器的文件资源管理器中添加一个自定义芯片。一个对话框提供 内置模板以及Start from blank(从空白开始);选择空白模板来 跟随操作。无论哪种方式,你最终都会得到两个文件:清单 (chip.json)和源代码(chip.c)。

三个引脚,一个属性,一个控件。控件的id和 属性的name必须匹配;这就是将它们绑定在一起的方式。

chip.json
{
"schema": "velxio-chip/v1",
"name": "CO2 Sensor",
"description": "Analog CO2 sensor with a live ppm slider. OUT maps 400-5000 ppm to 0-5 V.",
"pins": ["VCC", "GND", "OUT"],
"attributes": [
{ "name": "ppm", "label": "CO2 (ppm)", "type": "int",
"default": 1000, "min": 400, "max": 5000, "step": 10 }
],
"controls": [
{ "id": "ppm", "label": "CO2 (ppm)", "type": "range",
"min": 400, "max": 5000, "step": 10, "unit": "ppm" }
]
}

一个重复的定时器将ppm转换为电压并驱动引脚。注意 vx_attr_read 的位置:在回调内部,这样每次滴答都能看到 滑块的当前位置。

chip.c
#include "velxio-chip.h"
#define PPM_MIN 400.0
#define PPM_MAX 5000.0
#define VOLTS_MAX 5.0
typedef struct {
vx_pin out;
vx_attr ppm;
vx_timer timer;
} chip_state_t;
static chip_state_t S;
static void on_tick(void *user_data) {
(void)user_data;
double ppm = vx_attr_read(S.ppm); /* live slider value */
if (ppm < PPM_MIN) ppm = PPM_MIN;
if (ppm > PPM_MAX) ppm = PPM_MAX;
double volts = (ppm - PPM_MIN) / (PPM_MAX - PPM_MIN) * VOLTS_MAX;
vx_pin_dac_write(S.out, volts);
}
void chip_setup(void) {
S.out = vx_pin_register("OUT", VX_ANALOG);
S.ppm = vx_attr_register("ppm", 1000);
S.timer = vx_timer_create(on_tick, 0);
vx_timer_start(S.timer, 50000000ULL, true); /* 50 ms, in nanoseconds */
on_tick(0); /* drive the initial level */
vx_log("co2 sensor ready");
}

三个重要的细节:

  • 引脚上的VX_ANALOG。数字引脚不能承载中间 电压,对其调用vx_pin_dac_write不会达到你想要的效果。
  • vx_timer_start接受纳秒。50000000ULL是50毫秒。这是 第一个芯片中最常见的拼写错误。
  • 返回前直接调用on_tick(0)。没有它,引脚将保持在0 V 直到第一个定时器触发,而一个快速的草图会将其读取为虚假的 400 ppm。

按下Compile(编译)。

将芯片拖到画布上,放在Arduino Uno旁边,并连接VCC到 5V,GND到GND,以及OUT到A0。

CO2传感器芯片连接到Arduino Uno:VCC到5V,GND到GND,OUT到A0

sketch.ino
void setup() {
Serial.begin(115200);
}
void loop() {
int raw = analogRead(A0);
float volts = raw * (5.0f / 1023.0f);
float ppm = 400.0f + volts / 5.0f * 4600.0f;
Serial.print("raw="); Serial.print(raw);
Serial.print(" ppm="); Serial.println(ppm, 0);
delay(500);
}

按下Run(运行),然后点击芯片。滑块面板打开:

芯片在模拟运行时的实时面板:一个以ppm为单位的CO2滑块

拖动它,串行输出在一个delay(500)内跟随:

串行监视器跟踪滑块:ppm读数从1000跳到3000

这就是整个循环:滑块写入属性,定时器每秒读取 20次,引脚电压改变,analogRead看到它。

你看到的现象 几乎总是
点击芯片没有任何反应 模拟已停止:面板仅在运行时打开
滑块出现但读数从不变化 vx_attr_read在chip_setup()中被调用并缓存,而不是在on_tick内部
analogRead只返回0或1023 引脚被注册为数字模式而不是VX_ANALOG
值更新一次然后冻结 vx_timer_start被调用时repeat为false,或者间隔以毫秒为单位写入,因此下一次滴答在50000秒之后
串行显示400 ppm持续片刻 缺少初始的on_tick(0)调用