|
本帖最后由 cometsky 于 2014-11-7 13:56 编辑
先露个脸
在那群密密麻麻的线后面还藏着一个LM35的温度传感器,主要用来计算DN7C3的温度补偿。
线路图就不画了,连线很简单,和前代GP2Y1010是完全一样的,这货基本上就一外壳包着GP2Y1010外加风扇,价格可是x4了。
测试的串口屏幕
左边的一列是analogRead()后的换算电压(还取了1000次平均),那叫一个飘。中间是减掉基准参考电压后,第三列是PM2.5
PDF附上:
说说经验:
1 这东西几乎完全是模拟器件,至少接口是,Vo电压差不多有10mV左右的漂移,上图中最后一列是PM2.5读数(单位手误了),前半部分是走到楼梯间测的,后半部分是室内测的(有空气净化器)。
2 打开风扇会让读数稳定些,应该是大灰尘都按惯性走了旁边的通道,没有进入传感器,为了防止电机对电源的干扰,电机的供电单独设置。
3 外壳上QRCode里面的参考电压就是一个摆设,我在较洁净的室内实测电压低于参考电压将近130mV,应该是LED串联的电阻阻值略高(153欧),并且加上面包板上各个插针的接触电阻导致LED亮度不够,另外所有器件的电源都从Arduino板上取,会稍微的拉低电压。
4 温度漂移要考虑,参考电压是在25度下的读数,每摄氏度有6mV的漂移。相当于3.6ug的颗粒物。
5 模拟口不同针脚连续读取好像有干扰(不确定),反正代码里读DN7C3和LM35分开了200us。
6 analogRead()函数执行大概需要100us多一点,但是采样的延时应该没有那么多(有一种说法是可以设置ADCH连续采样,间隔是26us),前后的时间应该是开关ADC的耗时,我感觉应该在60-80us后是读数时点。所以arduino的delayMicroseconds我取值220。
7 除非能有校准的手段,否则这东西就是一准玩具。我准备去美帝使馆附近校准。
8 脉冲必须按时发出,无论你读取与否,间断的脉冲会导致错误读数。
9 通过USB传进来的电压必须准确,我用山寨充电宝当电源,结果Arduino的5v针脚就变成5.2v了。
上代码:(大概10s之后才有读数,这是稳定期,每秒的读数是和前10秒的平均值,否则跳跃太大) - // My QRcode: 1491800B82 1.23 **** 24.9
- // 14918 is produce at 2014-09-18 (WTF!)
- // 1.23 is reference voltage
- // 24.9 is temperature of reference voltage
- #include <LiquidCrystal.h>
- // LCD_VSS pin to ground
- // LCD_VDD pin to 5V
- // LCD_VO pin to ground with 10K resistor
- int LCD_RS = 6;
- // LCD_RW pin to ground
- int LCD_E = 7;
- int LCD_D4 = 8;
- int LCD_D5 = 9;
- int LCD_D6 = 10;
- int LCD_D7 = 11;
- // LCD_A pin to 5V
- // LCD_K pin to ground
- LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
-
- int count = 0;
- float valueP = 0; // reading of DN7C3
- float valueT = 0; // reading of LM35
- float averageP = 0;
- float averageT = 0;
- float historyP = 0;
- unsigned long timer = 0;
- unsigned long A = 0;
- unsigned long B = 0;
- void setup() {
- pinMode(A5, INPUT); // DN7C3 Vo Pin
- pinMode(A2, INPUT); // LM35 input
- pinMode(4, OUTPUT);
- digitalWrite(4, HIGH);
-
- lcd.begin(16, 2);
- lcd.print("Sharp DN7C3");
-
- Serial.begin(115200);
- Serial.println("Sharp DN7C3 PM2.5 Sensor");
-
- for(int i = 0; i < 1000; i++) {
- delayMicroseconds(9680);
- digitalWrite(4, LOW);
- delayMicroseconds(320);
- digitalWrite(4, HIGH);
- }
- timer = micros();
- }
- void loop() {
- if ((micros() - timer) >= 10000) { // per 10ms
- timer = micros();
-
- digitalWrite(4, LOW); // turn on led
- A = micros(); // measure pulse begin time
- delayMicroseconds(230); // Arduino ADC need about 100us
- valueP = analogRead(A5); // PM2.5 reading
- B = micros(); // measure pulse end time
- digitalWrite(4, HIGH); // turn off led
-
- delayMicroseconds(200); // wait to read Temperature
- valueT = analogRead(A2); // Temperature reading
-
- count++;
- averageP = (averageP * (count - 1) + valueP * (5000.0 / 1024.0)) / count;
- averageT = (averageT * (count - 1) + valueT * (5000.0 / 1024.0)) / count;
-
- if (count >= 100) { // 100 times average, 1 second
- float temp = averageT / 10; // get Temperature
- float diffrent = averageP - (1100 + (temp-24.9)*6); // 1100 is ture reference voltage base on my circuits
- float pm25ug = diffrent * 0.6;
-
- if (historyP == 0) {
- historyP = pm25ug;
- }
- else {
- historyP = (historyP * 9 + pm25ug) / 10;
- }
-
- // post to Serial
- Serial.print("T: ");
- Serial.print(temp, 2);
- Serial.print(" C\tV: ");
- Serial.print(averageP, 2);
- Serial.print(" mV\t P: ");
- Serial.print(pm25ug, 2);
- Serial.print(" ug/m3\t avgP: ");
- Serial.print(historyP, 2);
- Serial.print(" ug/m3\t Pulse: ");
- Serial.println(B - A);
-
- // show on 1602
- lcd.clear();
- lcd.setCursor(0,0);
- lcd.print("PM25: ");
- lcd.print(historyP); // averaged
- lcd.setCursor(14,0);
- lcd.print("ug");
- lcd.setCursor(0,1);
- lcd.print("Temp: ");
- lcd.print(temp);
- lcd.setCursor(15,1);
- lcd.print("C");
-
- // clear for next time
- count = 0;
- valueP = 0;
- valueT = 0;
- averageP = 0;
- averageT = 0;
- }
- }
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|