GP2Y1010AU0F. Большая погрешность датчика пыли

e3p7j
Offline
Зарегистрирован: 09.01.2015
Здравствуйте.
Приобрел вот такой датчик пыли: https://www.sparkfun.com/datasheets/Sensors/gp2y1010au_e.pdf
 
Подключил как описано здесь: http://arduinodev.woofex.net/2012/12/01/standalone-sharp-dust-sensor/ оттуда-же был взят код для расчета плотности пыли мкг/m3.
 
Кроме это, добавил расчет среднего арифметического и среднего квадратичного отклонения для 30 замеров
 
Сенсор был плотно обернут в пакет, для уменьшения влияния внешних факторов и лежал нетронутым в течении нескольких часов
 
 
В файле ds1.txt можно посмотреть реультаты.
Где (через запятую) :
время между двумя замерами в мс
вольтаж с аналогового выхода 
расчетное значение в (мкг/m3).
 
Ну во первых, при задержке между двумя замерами датчиков в районе 11-17 мс данные явно совсем не те, которые ожидались, вольтаж совсем маленький приходит, хотя, cогласно документации, рекомендуемое время между двумя замерами - 10 мс.
 
При задержке более 500 мс - данные уже больше похожи на правду (в относительных величинах, реальные значения пыли в мкг/m3 в комнате, где происходили замеры мне не известны).
 
Но смущает уж слишком сильный разброс значений, учитывая, что все таки датчик изолирован и влияние окружающей среды миниально - значение сигмы в районе 7 (среднее квадратичное отклонение).
Причем похожие значения сигмы были и для не изолированного датчика (см. ds2.txt).
 
Вот думаю, это такой чувствительный датчик - или я что-то не понимаю?
Кто юзал данный сенсор - поделитесь впечатлениями.
 
 
 
 
 
 
 
 
 
 
Artemiy
Offline
Зарегистрирован: 20.10.2014

А у меня тоже вопрос по такому датчику. Подключил к ардуине. Он при старте начинает со значений ~700 и опускается до 300-320 чего-то там. Видимо мг/м3. При этом не слезает с этих значений что бы я с ним не делал и куда бы не носил.

он правильно работает? Может как-то отверстие надо разместить? У меня датчик просто на столе лежит. Сверху дырка открыта, снизу соотв. поверхность стола.

кто разбирался - подскажите, плиз. 

bizzon
Offline
Зарегистрирован: 29.03.2016

Раз есть дырка, значит в ней соберётся пыль, если он будет лежать дыркой кверху. В даташите,к сожалению, не указано рабочее положение. Но уж точно в пакет не заворачивать и стеклом не накрывать- он же оптический.

nik182
Offline
Зарегистрирован: 04.05.2015

Там ж черным по белому написано, что для проверки дым от MILD SEVEN надо вдувать.

Artemiy
Offline
Зарегистрирован: 20.10.2014

nik182 пишет:

Там ж черным по белому написано, что для проверки дым от MILD SEVEN надо вдувать.

Вот блин, а я звездной пылью на него сыпал. :)

Ну ладно, хоть правильно расположил. Вы меня успокоили, спасибо.

erav
Offline
Зарегистрирован: 28.12.2016

На сколько я понимаю, через датчик пыли, (а так же через датчик влажности, анализатор газов) надо гонять воздух вентилятором. Иначе по ряду причин вокруг датчика образуется застоявшаяся область с тепличными условиями и своими показаниями.

Logik
Offline
Зарегистрирован: 05.08.2014

erav пишет:

На сколько я понимаю, через датчик пыли, (а так же через датчик влажности, анализатор газов) надо гонять воздух вентилятором. Иначе по ряду причин вокруг датчика образуется застоявшаяся область с тепличными условиями и своими показаниями.

Газоаналтзаторы с подогревом, конвекция создает небольшую, но вполне достаточную циркуляцию.

erav
Offline
Зарегистрирован: 28.12.2016

Ну датчик пыли оптический там движуху нечем создавать.

kost82
Offline
Зарегистрирован: 30.11.2015

Кто-нибудь разобрался с этим датчиком?

Интересно все-таки как его правильно применять? Например судя по этой статье http://www.howmuchsnow.com/arduino/airquality/ автор продувал воздух через датчик при помощи маленького вентилятора 40х40. Может есть более экономичный и компактный способ это делать? Например если необходимо сделать мобильное устройство для проверки качества воздуха, которое будет работать от аккумуляторов. Думается мне, что вентилятор довольно быстро их разрядит, насколько бы вентилятор ни был маломощным.

И еще вопрос, по формуле, которую вывел автор статьи и которую все копируют (dustdensity = 0.17*voltage-0.1;) - как я понял он вывел ее опытным путем, сравнивая показания с эталонным датчиком. Или она справедлива для любого такого же датчика? В даташите (https://www.sparkfun.com/datasheets/Sensors/gp2y1010au_e.pdf) приведен похожий график зависимости напряжения от запыленности, но есть оговорка, что он показан как пример и верить ему особо нельзя. Тогда как все-таки откалибровать датчик в бытовых условиях?

Ну и еще вопрос по напряжению питания: кто-то питает его от 3,3В, а кто-то от 5В. Сдается мне, что напряжение питания будет влиять на показания датчика. Как минимум яркость и/к светодиода будет разной. Так как же его все-таки правильно питать? Судя по даташиту - он до 7 Вольт выдержит.

Волшебник
Offline
Зарегистрирован: 22.12.2016

У меня уже с пол года пашет, бесперебойно, с датчиком давление/температура в паре. ТФТ экран графики рисует, цветной типа 0154, 2.4 дюйма - самые доступные на али экраны с тачем.

Вентилятор не ставил, датчик приклеил на двусторонюю липкую ленту вертикально, провода вниз, там кажется спилить пришлось пластик чтобы плотно стал. В корпусе прибора дырок насверлил и всё. Диффузия всё остальное делает, на пыль реакция особенно не требуется.

Калибровку не делал, нет эталонного прибора. Да она и ни к чему, в принципе это показометр, но чувствительный. Если задуть спичку на расстоянии с пол метра - зашкаливает. На кухне жарится чего-нить - показания увеличиваются 3-4 раза хотя визуально дыма нет, есть вытяжка. 

Показометр - потому что сигнал дрейфует от температуры - у меня ж там второй график и сразу видно как они вместе вверх вниз ползут. Не сильно, но заметно. От напряжения тоже меняется, если на 3.3 там резистор пересчитать надо будет.

 

kost82
Offline
Зарегистрирован: 30.11.2015

Я подключил датчик как написано в приведенных статьях, какие-то странные показания он выдает, иногда даже отрицательные. Пробовал питать его как от 3.3В, так и от 5В - разницы почти нет. Самое интересное - если просунуть что-нибудь в отверстие датчика - напряжение на его выводе повышается почти до 4В, вроде бы все хорошо. Но если датчик просто лежит на столе - показания близки к нулю. Как-то не верится, что в квартире пыль совсем отсутствует. Или это нормальное его поведение?

Думается мне, что либо что-то не так со схемой подключения (возможно не контачит), либо со скетчем (неверная формула, например). Поделитесь пожалуйста куском скетча, где происходит считывание напряжения и преобразование его в мкг/м3.

На всякий случай мой код:
 

#define MEASURE_PIN 6
#define LED_POWER 12
#define SAMPLING_TIME 280
#define DELTA_TIME 40

float voMeasured = 0.0;
float calcVoltage = 0.0;
float dustDensity = 0.0;

void setup()
{
  Serial.begin(9600);
pinMode(LED_POWER, OUTPUT);
}

void loop()
{
      digitalWrite(LED_POWER, LOW);
      delayMicroseconds(SAMPLING_TIME);
      voMeasured = analogRead(MEASURE_PIN);
      Serial.println(voMeasured);
      delayMicroseconds(DELTA_TIME);
      digitalWrite(LED_POWER, HIGH);

      calcVoltage = float(voMeasured) * 5.0 / 1024.0;
      Serial.println(calcVoltage);
      dustDensity = 0.17 * calcVoltage - 0.1;
      Serial.println(dustDensity);
      delay(1000);
}

 

Волшебник
Offline
Зарегистрирован: 22.12.2016

У меня нет простой версии, всё допиливал как комбайн с экраном, тут скачать

Проще будет вам взять пустой скетч и добавлять постепенно, главное начать с ADC   и  Dust. 

ISR(TIMER1_COMPB_vect) {
  static   uint16_t counter =  0;
  static   uint32_t accumul =  0;
  volatile uint16_t timerdl =  0;  

  int16_t temp  = ADCL;  
          temp += (ADCH << 8);  
  accumul += temp;

  PORTB  &= ~(pin_Led);    // pin Low             
  timerdl = 315;           // wait 280
  while(timerdl--){ }      // do countdown 1.13 count/ usec
  ADCSRA |= (1<<ADSC);     // start conv.
  timerdl = 45;            // wait 40
  while(timerdl--){ }   
  PORTB  |= pin_Led;       // pin High         
 
  if(++counter >= 122) {   // 1 sec.
//    TIMSK1 &= ~(1<<OCIE1B);    
    counter = 0;
    average = accumul;
    accumul = 0;
    flag    = 1;
    }
}

void adc_init() { 
  DDRB   |=   pin_Led;     // Set OUPUTS pinmode
  PORTB  &= ~(pin_Led);    // Set LOW                

  ADCSRA  =  0x87;         // Turn ON ADC, 125 kHz. 
  ADMUX   =  0x45;         // Pin 5 analog input
  ADCSRA |=  (1<<ADSC);
  DIDR0   =  ( 1<<ADC5D ); // Turn Off Digital Input Buffer.

  /* Set up TIMER 1 - ADC sampler */
  TIMSK1 = 0x00;
  TCCR1A = 0;
  TCCR1B = 0;
  TCCR1C = 0;
  TCNT1  = 0;

  TCCR1A =  (1<<WGM11);    // Mode 6, Fast PWM
  TCCR1B =  (1<<WGM12);
  TCCR1B |=  (1<<CS12);    // clk/256 prescaling.
  OCR1B  = 18;             // 16     x19(18+1) = 304usec.       
  TIFR1  |= (1<<OCF1B); 
  TIMSK1 |= (1<<OCIE1B);
}

void printDust() 
{
  static float old_dust  = 0.0;
   
   val_dust  = average / 122.0;
   val_dust -= 122.76;               // 0.6V Offset-datasheet
   val_dust *= 0.758449123;          // 660 max-value (measured) = 500 mkg/m^3 max-datasheet

   val_dust = old_dust * 0.85 + val_dust * 0.15;
   old_dust = val_dust;

   tft.fillRect(15, 30, 80, 18, BLACK);  
  
   tft.setTextColor(CYAN);
   tft.setTextSize(2);  
   tft.setCursor( 15, 30);

   tft.print(val_dust, 1);
   tft.print(F("mkg"));
}

Первая накапливает данные как сумму за 1 сек, 122 точки, вторая фильтрует, а в основной программе ещё раз усредняется за час, это кому то может и не потребуется. Тогда просто, по флагу вызывать printDust и печатать val_dust посекундно.

void loop()
{
  char    incomingByte;
  int16_t temporar = 0;

  if( flag ) {  
    printDust();

    flag = 0;

   принтЛн( тут и заменить);
    }

 

kost82
Offline
Зарегистрирован: 30.11.2015

Спасибо за код. Как я понял Вы 122 раза измеряли напряжение на выходе, а потом считали среднее значение. Но почему именно 122?

Я тут решил вспомнить курс школьной математики и понять откуда взялась формула расчета (может кому полезно будет).

За основу берется график из даташита (зависимость напряжения от запыленности):
Зависимость напряжения от запыленности

Часть графика до 3.5В очень похожа на прямую. Формула прямой: y = kx+b, в нашем случае y - это напряжение, а x - содержание пыли (мкг/м3). Возьмем две характерные точки A (0; 0,6) и B (0,4; 3) и составим для них систему уравнений:
0,6 = 0k + b
3 = 0,4k + b
Решая ее получим: b=0,6, k=6. Итоговое уравнение кривой: y=6x+0,6
Из этого уравнения: x = (y-0,6)/6 если каждый член в скобке поделить на 6 и получается формула y = 0.17x - 0.1

kost82
Offline
Зарегистрирован: 30.11.2015

Также я попытался "откалибровать" датчик: засунул в отверстие для пыли круглую ручку подходящего диаметра, чтобы имитировать абсолютно загрязненный воздух. По-идее это должна быть горизонтальная часть кривой. На графике она проходит на уровне 3.6-3.7В, у меня же максимальное напряжение получилось 3.2В, поэтому я решил внести изменения в формулу подсчета, занизить график на 0.4В. Таким образом получилось: x = (y-0,2)/6 - думаю такая формула более удобна для корректировок и более точна при вычислениях.

Если верить даташиту - напряжение при отсутствии пыли может быть от 0 до 1,5В, что вроде бы укладывается в мою теорию подсчетов.

Также я решил также измерять напряжение несколько раз, а затем вычислять среднее. Начал с 10 раз, но похоже это не сильно помогло. Значения напряжения пляшут в одних и тех же условиях, возможно нужно на порядок больше измерений. Увеличение длительности импульсов включения ИК-диода тоже практически не влияет на них.

Вывод: без калибровки по эталонному прибору - это всего лишь показометр, который позволяет измерять содержание пыли в довольно условных "попугаях" и показывать лишь приблизительный уровень, а также изменение содержания пыли.

Волшебник
Offline
Зарегистрирован: 22.12.2016

kost82 пишет:

Спасибо за код. Как я понял Вы 122 раза измеряли напряжение на выходе, а потом считали среднее значение. Но почему именно 122?

Таймер крутится на такой частоте, а данные я беру за секунду. Не принципиально, можно и за 10 сек (тогда 1220), но это компромис между точностью и реакцией, на экране потом вывожу значение циферное - посекундно, а точку на графике ставлю - почасовую.