rexon 发表于 2015-4-16 13:49 
我用夏普的灰尘传感器GP2Y1010AU0F替换PPD42NS倒是可以同时上传温湿度和颗粒物密度的。因为PPD42NS获取颗 ...
因为该 Dust sensor 测量方式是:
计算 lowpulseoccupancy = LOW 的时间 ; 总共测量 30 秒
该 LOW 时间的来源是 累加 pulseIn(dustpin, LOW);
注意 duration = pulseIn(dustpin, LOW); 意思是
等待 dustpin 变 LOW, 开始计时, 如果一开始就 LOW, 则立即开始计时,
注意此时 pulseIn(dustpin, LOW) 不会回来,
会一直等到 dustin 变 HIGH 才会回来,
此时回传 pulseIn( ) 这函数停留看到 dustpin 是 LOW 的时间( 几个 ms);
依照原范例的意思是:
必须看看 30秒内 (30000 ms), 该 pin 在 LOW 的时间是几个 ms,
此即 lowpulseoccupancy,
注意该句子 lowpulseoccupancy = lowpulseoccupancy+duration; 就是在累加 dustpin 是 LOW 的时间!
然后 ratio = lowpulseoccupancy/( 30000*10.0);
换句话说,
原则上在该 30 秒内必须"相当专心" 看着 dustpin 的变化, 不可以去做别的事情,
否则你想想看,
在该 30 秒内 dustpin 可能变化了 100次, 然后你因做其他事,
只来看了一次或两次, 漏掉了其他九十九次或九十八次 dustpin 变为 LOW 的时间 !!
这样除以 ( 30000*10.0) 当然得到 0 啦 !
所以,
解决方法是, 遇到要量测 Dust sensor, 就专心测量 30 秒:
写成函数如下:
/// 先把你那个 if 改为如下调用 concentAns( ) 函数比较容易看懂 !
if (sensor_id == DUST_SENSORID)
{
return (int)concentAns( ); // 因为你的函数是 int
}
////// 把使用到以下函数写到整个程序最后面, 不要混入其他函数喔 !
////// 函数如下:
float concentAns( ) { // 计算 concentration; 注意会花掉 30 秒
lowpulseoccupancy = 0; // dustpin 是 LOW 的时间
starttime = millis();
while(38==38) { // loop forever, 用里面的 if 判断是否做完 30 秒了
duration = pulseIn(dustpin, LOW);
lowpulseoccupancy = lowpulseoccupancy+duration;
if ((millis()-starttime) > sampletime_ms) break; // 离开 while Loop
} // while(38==38
// 已经量测 30 秒 (sampletime_ms), 检查 dustpin 在 LOW 的时间总共占的比率 ratio
ratio = lowpulseoccupancy/(sampletime_ms*10.0); // Integer percentage 0=>100
concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve
Serial.print("Dust Density (pcs/cf): ");
Serial.println(concentration);
return concentration; // 你的 concentration 是 float, 所以我写成 float 函数
} // float concentAns(
|