PPD42NJ and photon

Hi,

I am trying to get this air quality sensor to work with a photon. These are my connections. It compiles and flashes, but the readings are just 0. Has anyone used one before and can help. It it for university and I can’t get any help because my university is closed and I am working from home. thanks

Particle Photon ==> PPD42NJ sensor (placed in vertical direction)

GND ==> Pin1 (GND)
D6  ==> Pin2 (Output)
Vin ==> Pin3 (5V)
GND ==> Pin5 (Input)
int SensorPin = D6;  //  reads data from the sensor
int REDled = D1; // RED
int GREENled = D2; //GREEN
int BLUEled = D3; //BLUE

unsigned long starttime;
unsigned long sampletime_ms = 30000;  //Length of sampling time before it reports. 30,000=30 sec.  You can change this
unsigned long triggerOnP2;
unsigned long triggerOffP2;
unsigned long pulseLengthP2;
unsigned long durationP2;
boolean valP2 = HIGH;
boolean triggerP2 = false;
double ratioP2 = 0;  // start the code with the ratio set to 0.  This clears any previous data
double PM25 = 0; // start the code with the PM25 set to 0.  This clears any previous data

String colour; // tells the color
String category;  // tells the category of air


//used to control the wifi if being used in an area where there is no wifi
const uint32_t msRetryTime  =   30000; // stop trying to connect to the internet after 30sec of boot up
SYSTEM_MODE(SEMI_AUTOMATIC)
SYSTEM_THREAD(ENABLED)
// end of Wifi checking

TCPClient client;

#define THINGNAME "AirQualDev" // Name you give to your device on dweet.io  Don't use spaces.


void setup()
{
  
  
  pinMode(REDled, OUTPUT);
  pinMode(GREENled, OUTPUT);
  pinMode(BLUEled, OUTPUT);
  pinMode(SensorPin,INPUT);
  starttime = millis();//millis() is the on chip timer that starts running when the program starts running.
  //Tells you how many milliseconds since the program started

   Particle.connect();  //if it can't connect to the internet in 30 seconds of booting up it will turn the Wifi off and keep running
     if (!waitFor(Particle.connected, msRetryTime))
    WiFi.off(); // if the wifi comes back it will not turn the wifi on the photon.  You must reset it to get it back on wifi.

    delay(120000); //this delays the sensor for 2 minutes while it warms up

}

void loop(){ 

      valP2 = digitalRead(SensorPin);

     if(valP2 == LOW && triggerP2 == false){
    triggerP2 = true;
    triggerOnP2 = micros();
  }

    if (valP2 == HIGH && triggerP2 == true){
      triggerOffP2 = micros();
      pulseLengthP2 = triggerOffP2 - triggerOnP2;
      durationP2 = durationP2 + pulseLengthP2;
      triggerP2 = false;
  }
    if ((millis() - starttime) > sampletime_ms) {  //if the difference between what time it is right now and when this sample started is greater than our sample time
    //than end this sample and report the data.

    ratioP2 = durationP2/(sampletime_ms*10.0);  //  percentage 0=>100   Percent of time this pin was triggered during sampling.
    //a higher ratio tells dirtier air. 

    PM25= ratioP2 * ratioP2 * .1809 + 3.8987 * ratioP2;  //This is the calibration between the ratio and PM25 in ug/m3

    //this section controls what color the LED is at on different PM25 levels.

    if (PM25 < 10)   
    {
        digitalWrite(REDled, LOW); 
        digitalWrite(GREENled, HIGH); 
        digitalWrite(BLUEled, LOW); 
        colour = "Green";
        category = "Good";
    }
    if (PM25 < 20 && PM25 > 10) 
 {
        digitalWrite(REDled, LOW); 
        digitalWrite(GREENled, HIGH); 
        digitalWrite(BLUEled, HIGH); 
        colour = "Cyan";
        category = "Satisfactory";

    }
     if (PM25 < 30 && PM25 > 20) 
 {
        digitalWrite(REDled, LOW); 
        digitalWrite(GREENled, LOW); 
        digitalWrite(BLUEled, HIGH); 
        colour = "Blue";
        category = "Moderately satisfactory";
        
    }
     if (PM25 < 40 && PM25 > 30) 
 {
        digitalWrite(REDled, HIGH);
        digitalWrite(GREENled, LOW);
        digitalWrite(BLUEled, HIGH);
        colour = "Magenta";
        category = "Poor";

    }
     if (PM25 < 100 && PM25 > 40)
 {
        digitalWrite(REDled, HIGH); 
        digitalWrite(GREENled, LOW);
        digitalWrite(BLUEled, LOW);
        colour = "Red";
        category = "Very poor";

    }
       if (PM25 > 100)  
 {
        digitalWrite(REDled, HIGH);
        digitalWrite(GREENled, HIGH);
        digitalWrite(BLUEled, HIGH);
        colour = "Black";
        category = "Severe";
        
    }

 
    //ends the LED control section
    
  


    
    Particle.publish("colour", String(colour));
    delay(2000);
    Particle.publish("PM25", String(PM25));
    delay(2000);
    Particle.publish("ratioP2", String(ratioP2));
    delay(2000);
    Particle.publish("category", String(category));
    delay(2000);
    // Starts the section that will publish the results to DWEET
   
    if (client.connect("dweet.io", 80))
    // Go to  http://dweet.io/follow/thingname  to see the results in your browser. change "thingname" to your thingname in the web address.
    {
      client.print("GET /dweet/for/");
      client.print(THINGNAME);
      client.print("?ratioP2=");  // Don't use spaces for data names
      client.print(ratioP2);
      client.print("&PM25=");  // Don't use spaces for data names
      client.print(PM25);
      client.println(" HTTP/1.1");
      client.println("Host: dweet.io");
      client.println("Connection: close");
      client.println();
           }
           // ends publishing to DWEET
    
  
  

   durationP2 = 0;  //resets the lowpulseoccupancy back to zero to start the next sample
      starttime = millis(); // set the start time to what time it is now.
      // go back to the top of the loop and start sampling again

}

}

You may want to use pulseIn() instead of this

BTW, it would be easier to follow the code if the indentation was consistent :wink:

Then it would also be better style to unify your four publishes into one single event (e.g. by use of snprintf()) and the spaghetti categorisation of the PM25 reading could be done via a loop (or even mathematically) and an array that holds the boundaries, messages and RGB values.

As is, your check neglects the cases where PM25 equals one of 10.0, 20.0, 30.0, 40.0 and 100.0

3 Likes