SDS011 fan making noise after couple of weeks

Hello all,

I have a SenseBox, and in that using an SDS011.
As with the default config it runs 24/7, so the fan runs 24/7. (still looking to get something like 5 or 10 readings per hour, but that is a different subject all together)
The issue is that the first sensor I got with the box started „rattling“ or making „worn baring“ noises after 3 months or so.
Now I got myself a new SDS011 and that starts the rattling noises already after 3 weeks.

Readings seem unaffected, however, just not nice to have that sensor make this noise.

So, the questions:

  • Is this „normal“ (hopefully not)
  • Could it be a quality issue and does someone have a location/brand that has better fan quality
  • Did someone successfully use „periodic reading“ on the SDS011? (and/or can someone put me to a post that is successful)

I am perfectly ok with reading/understanding German, just the writing part is too awkward. :wink:

Thanks,

Wim,

Hi Wim,
I have use my SDS011 now for almost 2 years. The fan is getting louder yet but still ok.
I measure the dust every 15 minutes and I wakeup the sensor one minute before I do the measurement.
Please find a C-code snippet below.
For access to the SDS011 I use the SDS011-select-serial library:

CU
Wolfgang

static SDS011 SDS(SDS_UART_PORT);
#define SDS011_MEASURE_CYCLE 15

static void SDS011_init(void)
{
    SDS_UART_PORT.begin(9600);
}

static void SDS011_measure(void)
{
    // Activate dust sensor in first loop and measure values in next loop.
    // This ensures that dust sensor fan is on for one minute before measurement is performed.
    static bool sdsIsOn = false;
    // Process dust sensor only every SDS011_MEASURE_CYCLE minutes.
    if (sdsIsOn) {
      uint8_t attempt = 0;
      float pm10, pm25;
      while (attempt < 5) {
        bool error = SDS.read(&pm25, &pm10);
        if (!error) {
          addMeasurement(PM10SENSOR_ID, pm10);
          addMeasurement(PM25SENSOR_ID, pm25);
          break;
        }
        attempt++;
      }
      DEBUG("SLEEP SDS011 dust particle sensor...");
      SDS.sleep(); 
      sdsIsOn = false;
    } else {
      if (0 == loopCount % SDS011_MEASURE_CYCLE) {
        DEBUG("WAKEUP SDS011 dust particle sensor...");
        SDS.wakeup();
        sdsIsOn = true;
      }
    }
}

Hello Wolfgang,

Thanks for the feedback, and thanks for the example to get „per 15 min“ measurements.
But I am kind of „fresh“ to Arduino. Therefor I am using the „standard SenseBox.ino“ that kind of „works out of the box“ and is generated from the OpenSenseMap
The only thing missing seems to be the „periodic measurement“ for the SDS011.

So, should this routine work also with the SDS library provided? (SDS011-select-serial.h) or should I use the SDS011 library you pointed to?

Another ask, does „loopCount“ need to be defined somewhere?
because now I get "error: ‚loopCount‘ was not declared in this scope…

Danke,

Wim,

@wschoch, made some progress.

I have figured out to create a loop counter. Changed the approach so would not need to alter the default .ino that OpenSenseMap provides too much.
since a full measurement (with delay) by default lasts a minute, I just do the SDS measurement every 15th run.
So, basically set a loopCount, do one measurement, SDS011 to sleep, count 14 measurements and then „enable“ the SDS011 again for one measurement.
HOWEVER!
This is fully compliant with one of the laws applicable in IT. „law of conservation of disaster“…
The library for the SDS011 delivered with the OpenSensemap Arduino package has a „known issue“ where SDS.sleep() works absolutely fine, but SDS.wakeup() does not because the data-format seems to have changed for the newer SDS011’s (loads of debate and solutions for some libraries, just not this one so far).

Anyway… getting closer (I guess, but yet so far away…)

SOLVED!!
Well, not the noise, because still need to replace the sensor. BUT now changed the .INO file so only every 10 loops the SDS011 is switched on for about 30 seconds.

How?

  • add following just before the „void loop()“ section:
// ---- SDS011 changes ----
static bool sdsIsOn = true;
uint8_t loopCount = 0;
uint8_t maxloopCount = 9;
// ---- SDS011 changes ----
  • Add following just after the line „void loop()“
// SDS011 measurement loop.
// Only enable every 10th measurement
if (loopCount < maxloopCount) {    
    // Increase loopCount by one    
     loopCount++;
     DEBUG(loopCount);
   }
  else {
    // Reset loopCount and take measurement
     loopCount = 0;
     sdsIsOn = true;
     DEBUG("Reset SDS loopCount and wakeup");
     SDS.wakeup();
     DEBUG("delay start");
     delay(20000);
     DEBUG("delay done");
  }
// End of SDS011 measurement loop.
  • then alter the „//------PM-----//“ section to look like this:
  //-----PM-----//
  #ifdef SDS011_CONNECTED

  if (sdsIsOn)
    {
      DEBUG("Now in SDS011 Main measure loop");
      uint8_t attempt = 0;
      float pm10, pm25;
      while (attempt < 5) 
      {
        bool error = SDS.read(&pm25, &pm10);
        if (!error) 
        {
          addMeasurement(PM10SENSOR_ID, pm10);
          addMeasurement(PM25SENSOR_ID, pm25);
          break;
        }
        attempt++;
      }
      DEBUG("sleep SDS011 for a number of loops defined in maxloopCount");
      SDS.sleep(); //put SDS011 into sleep mode, stopping fan as well
      sdsIsOn = false; //define the status so next time no measurement is taken
    }
  • Then the applicable SDS011-select-serial.cpp file needs to be changed to make sure SDS.wakeup() actually works.
  • This needs to be added:
static const byte WAKECMD[19] = {
	0xAA,	// head
	0xB4,	// command id
	0x06,	// data byte 1
	0x01,	// data byte 2 (set mode)
	0x01,	// data byte 3 (wake up)
	0x00,	// data byte 4
	0x00,	// data byte 5
	0x00,	// data byte 6
	0x00,	// data byte 7
	0x00,	// data byte 8
	0x00,	// data byte 9
	0x00,	// data byte 10
	0x00,	// data byte 11
	0x00,	// data byte 12
	0x00,	// data byte 13
	0xFF,	// data byte 14 (device id byte 1)
	0xFF,	// data byte 15 (device id byte 2)
	0x06,	// checksum
	0xAB	// tail
};
  • And this needs to replace the wakeup section that is there:
// --------------------------------------------------------
// SDS011:wakeup
// --------------------------------------------------------
void SDS011::wakeup() {
	for (uint8_t i = 0; i < 19; i++) {
		sds_data.write(WAKECMD[i]);
	}
	sds_data.flush();
	while (sds_data.available() > 0) {
		sds_data.read();
	}
}

Thanks @wschoch for giving the valuable hints into the right direction.

I also created an „issue“ in the Gidhub repository for OpenSenseMap repository (#426)

Hi Wim @wlaarhov ,
sorry that I was not replying earlier.
But with re-enginering you drilled the hole through the SDS sensor. ;-). Really good!

The wakeup function in „my“ SDS011 lib is very short. At least for my old sensor this works.
I have to try your changes with my sensor.
But first I have to figure out why my Sensebox can no longer connect to the OSM server…

void SDS011::wakeup() {
	sds_data.write(0x01);
	sds_data.flush();
}

CU
Wolfgang