以下介绍一个使用digispark制作的voc在线监测仪,最终产品如图1所示。
图 1 最终产品
1.硬件部分
1.1 包含设备
设备端包括如下设备:
图 2 Digispark1个
图 3 12832IIC0.91寸OLED屏幕1个
图 4 IIC接口voc传感器(KQM2801A)1个
1.2 接口连线
各设备接线如下表所示:
Digispark |
12832 OLED |
VOC IIC接口传感器(KQM2801A) |
5V |
VCC |
5V |
GND |
GND |
GND |
P0 |
SDA |
A |
P2 |
SCL |
B |
2.软件部分
采用arduino IDE,使用digispark库编译。由于digispark可用内存只有6K,因此必须考虑程序的体积。为减少最终编译程序的体积,采用如下措施:
1)将digispark的OLED库进行了修改使用,删除不需要的字符和函数减少内存使用量;
2)使用digiusb而没用采用digicdc。
2.1 VOC IIC接口传感器(KQM2801A)数据的读取
根据淘宝卖家提供的资料,KQM2801A地址为0x2F,数据格式如下表所示。
BYTE1 |
BYTE2 |
BYTE3 |
BYTE4 |
地址码 |
输出高位 |
输出低位 |
校验值 |
由于返回数据只有BYTE2和BYTE3两个byte类型构成一个int类型值,简单起见定义一个联合体完成数据的读取:
1 2 3 4 5
| typedef union { int ivalue; byte bvalue[2]; }VOCDATA;
|
利用tinywire库完成IIC接口的数据读取,关键代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| VOCDATA KQM2801A::get_data(void) { byte data[3]; byte state = 0; byte q = 0; byte dat; VOCDATA retval; Wire.beginTransmission(0x2F); Wire.requestFrom(KQM2801AADDRESS , 4); while (Wire.available()) { dat = Wire.read(); if (dat == 0x5f) { state = 1; data[0] = dat; q = 1; continue; } if (state == 1) { data[q] = dat; q++; } if (q > 3) { Wire.endTransmission(); if (data[1] == 0xff && data[2] == 0xff) { retval.ivalue = -1; return retval; } else if ((byte)(data[0] + data[1] + data[2]) == data[3]) { retval.bvalue[1] = data[1]; retval.bvalue[0] = data[2]; retval.ivalue = (retval.ivalue + 5) / 10; return retval; } else { retval.ivalue = -2; return retval; } } } retval.ivalue = -3; return retval; }
|
2.2 digiusb传输数据
DigiUSB每次向上位机上传读取到传感器的数据,主要代码如下:
1 2 3 4
| DigiUSB.refresh(); DigiUSB.write(value.bvalue[0]); DigiUSB.write(value.bvalue[1]); DigiUSB.refresh();
|
2.3 12832 oled屏显示
digiusb已占用约4k的内存,使用DigisparkOLED库内存导致整个项目内存超标。故精简了DigisparkOLED库中本项目不需要的函数,特别是将font8x16.h中小写字母等内容删除。
oled屏显示voc数据关键代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
| oled.begin(); oled.print(F("SENSOR")); oled.setCursor(0, 2); oled.print(F("INITIALIZING"));
oled.setCursor(0, 0); oled.print(F("VOC(PPM):")); oled.setCursor(90, 0); oled.print(value.ivalue); oled.setCursor(0, 2); oled.print(F(" IMI OF HFUT"));
|
由于传感器初始化时间较长,约2~3分钟
,长期停留在初始化界面严重影响用户体验,故本项目采用在屏幕上有一点闪烁的方式提醒用户程序正在启动,其关键代码如下:
1 2 3 4 5 6 7 8 9 10 11
| oled.setCursor(118, 0); if (zai_1 == 0) { zai_1 = 1; oled.print(F(".")); } else { zai_1 = 0; oled.print(F(" ")); }
|
至此设备端程序完成,完整项目代码可在coding.net下载。