I'm looking at air quality sensors with the intention of monitoring indoor air quality.
One sensor I'm looking at is the Waveshare Dust Sensor Detector Module with Sharp GP2Y1010AU0F Onboard. See https://www.waveshare.com/wiki/Dust_Sensor for a technical description of the sensor board.
I found this sensor on Amazon and reading over the reviews found one with a fair amount of technical details about how the person is using it.
This review mentions the code used with this sensor and one thing I do not understand is the multiple sampling of the analog signal for 11 times creating a sum of those 11 samples. The reason given for this code is because the line output is routed through a resistor voltage divider that is some 11K ohms (a 10k ohms plus a 1K ohms resistors) on the sensor board before presented to the output connector on the board.
I've also looked at the demo source code from the Waveshare website, a copy of which is posted further below. That code generates an average of 10 samples which is then multiplied by 11.
So it seems that both the Amazon reviewer's code and the demo program are taking the 11 to 1 resister voltage divider into account using two different procedures.
Why are they doing an adjustment rather than just using a reading of the line and taking that value?
Post on Amazon and the code there
This is the review: https://www.amazon.com/gp/customer-reviews/R1F9XM8DD9GPS9/ref=cm_cr_dp_d_rvw_ttl?ie=UTF8&ASIN=B07P94LCFZ
The reviewer wrote:
2./ While the Sharp sensor has output Aout on pin 5 in range 0.4-4V the Waweshare board lowers it with the resistor divider R10 10k + R6 1k (11:1);
3./ I simply compensated the voltage divider by adding 11 counts in the measuring loop. In addition the command 'analogReference(INTERNAL);' changes default reference voltage from 5V to 1.1V further increasing counts from the analog to digital converter.
The source code posted is as follows:
long int systemTime; // replaces delay()
int AoutMin = 360; // equal to Aout min in mV for clean air
int AoutMax = 3600; // equal to Aout max in mV (toothpick in measuring window)
float dustConst; // it will be computed from Aout range and Sharp sensor range 0-500 ug/m3
int dustConc; // dust concentration in ug/m3/mV
unsigned int sum11; // sum of 11 counts to compensate 11:1 Aot voltage divider
int AoutAvg; // direct Sharp Vout in mV computed as average from 11 measurements
int ref1024 = 1100; // reference voltage for 10-bit ADC; 1023 counts = 1100 mV
int dustQualityIndex; // it is quite arbitrary
char *dustQualityChar[] = {"1.Excellent", "2.Very good", "3.Good", "4.Fair", "5.Poor"};
void setup() {
Serial.begin(9600);
pinMode(A0, INPUT); // pin selected for 3.3V, GND, AOUT, and ILED
pinMode(A2, OUTPUT); // in order RED, BLACK, BLUE, and YELLOW as on WaveShare board
analogReference(INTERNAL); // for better resolution use 1100mV instead of default 5000mV
analogRead(A0); // activate IOref pin, 1.1V will be present
dustConst = 500 / float(AoutMax - AoutMin); // in ug/m3 per millivolt
Serial.print("\n ------------------------------------------------------\n");
Serial.print(" The WaveShare board divides the Sharp Sensor Vout 11:1.\n");
Serial.print(" The sum of 11 counts will compensate for lowered output.\n");
Serial.print(" Then the sum is converted to mV, and from it\n");
Serial.print(" is computed dust concentration and air quality.");
Serial.print("\n-------------------------------------------------------\n");
Serial.print("500/(");
Serial.print(AoutMax);
Serial.print("-");
Serial.print(AoutMin);
Serial.print(")=");
Serial.print(dustConst);
Serial.print(" Dust density constant in ug/m3/mV");
Serial.print("\n-------------------------------------------------------\n");
}
void loop() {
sum11 = 0;
for (int i = 0; i < 11; i++) {
//Sharp datasheet: pulse cycle 10ms, pulse width 0.32ms, sampling at 0,28ms
digitalWrite(A2, HIGH);
delayMicroseconds(280);
sum11 += analogRead(A0);
delayMicroseconds(40); // 280+40=320
digitalWrite(A2, LOW);
delayMicroseconds(9680); // 320 + 9680 = 10000
}
if ((millis() - systemTime) > 2000) {
computeAirQuality();
systemTime = millis();
}
}
void computeAirQuality()
{
AoutAvg = float(sum11) * float(ref1024) / 1024; // Sharp sensor direct Aout in mV
int q, i;
q = float(AoutAvg - AoutMin) * dustConst;
if (q < 0) q = 0; // handle non positive values
if (q < 40) i = 0;
else if (q < 80) i = 1;
else if (q < 160) i = 2;
else if (q < 320) i = 3;
else i = 4;
dustConc = q; dustQualityIndex = i;
printAirQuality();
}
void printAirQuality()
{
Serial.print(" Sum_11 ");
Serial.print(sum11);
Serial.print(" \t ");
Serial.print(AoutAvg);
Serial.print(" mV \tdust_C ");
Serial.print(dustConc);
Serial.print(" ug/m3\t\t");
Serial.print(dustQualityChar[dustQualityIndex]);
Serial.print(" air quality\n");
}
Demo code posted on Waveshare site
The demo Arduino program from the Waveshare site is doing a kind of moving average of the last ten values read from the sensor and then multiplying that average by 11.
/*********************************************************************************************************
*
* File : DustSensor
* Hardware Environment:
* Build Environment : Arduino
* Version : V1.0.5-r2
* By : WaveShare
*
* (c) Copyright 2005-2011, WaveShare
* http://www.waveshare.net
* http://www.waveshare.com
* All Rights Reserved
*
*********************************************************************************************************/
#define COV_RATIO 0.2 //ug/mmm / mv
#define NO_DUST_VOLTAGE 400 //mv
#define SYS_VOLTAGE 5000
/*
I/O define
*/
const int iled = 7; //drive the led of sensor
const int vout = 0; //analog input
/*
variable
*/
float density, voltage;
int adcvalue;
/*
private function
*/
int Filter(int m)
{
static int flag_first = 0, _buff[10], sum;
const int _buff_max = 10;
int i;
if(flag_first == 0)
{
flag_first = 1;
for(i = 0, sum = 0; i < _buff_max; i++)
{
_buff[i] = m;
sum += _buff[i];
}
return m;
}
else
{
sum -= _buff[0];
for(i = 0; i < (_buff_max - 1); i++)
{
_buff[i] = _buff[i + 1];
}
_buff[9] = m;
sum += _buff[9];
i = sum / 10.0;
return i;
}
}
void setup(void)
{
pinMode(iled, OUTPUT);
digitalWrite(iled, LOW); //iled default closed
Serial.begin(9600); //send and receive at 9600 baud
Serial.print("*********************************** WaveShare ***********************************\n");
}
void loop(void)
{
/*
get adcvalue
*/
digitalWrite(iled, HIGH);
delayMicroseconds(280);
adcvalue = analogRead(vout);
digitalWrite(iled, LOW);
adcvalue = Filter(adcvalue);
/*
covert voltage (mv)
*/
voltage = (SYS_VOLTAGE / 1024.0) * adcvalue * 11;
/*
voltage to density
*/
if(voltage >= NO_DUST_VOLTAGE)
{
voltage -= NO_DUST_VOLTAGE;
density = voltage * COV_RATIO;
}
else
density = 0;
/*
display the result
*/
Serial.print("The current dust concentration is: ");
Serial.print(density);
Serial.print(" ug/m3\n");
delay(1000);
}