0

PMSA-003i not working with other hardware
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

PMSA-003i not working with other hardware

by mrh335 on Mon Aug 02, 2021 5:33 pm

I am just getting up and running with my Arduino project. I am using a BMP390 (0x77) pressure sensor and a 0.96" OLED (0x3X)and a DHT22 (not I2C) temperature/humidity sensor.

I have connected these to both an Arduino Nano and MKR1010.

I am able to display temperature, pressure, humidity, etc on the OLED and even got a web server running on the MKR where I can view the same information on a webpage.

When I add the PMSA-003i (0x12) air quality sensor to the system, it hangs and I get no updates of temperature, pressure, etc.

If I run the built in example for the PMSA it works well and displays the output from the sensor in my serial window. If I unplug the PMSA and upload my other code for all the other sensors, those work as expected. When I add the PMSA example code to the other working code, the MKR doesn't boot, no sensors update, etc. I can unplug the power from the PMSA and get the system booted and then plug in the PMSA power, but there is then no output from the PMSA.

The I2C addresses are all different as listed above. I thought it was a power issue, so I have added a dedicated power board to supply 5VDC up to 700mA. In all configuration whether USB powered or powered by the power board, the PMSA fan does spin.

I have also noticed when supplying power from the external power supply through the Vin of the MKR1010, I won't be able to connect via USB to the MKR and monitor the serial window. I need to instead connect the USB cable before applying power, establish a connection, and then turn on the power supply. If I do this in any other order, the COM7 power on my computer won't even show as an option in the IDE to connect.

Please let me know of some other troubleshooting steps or ways to get my project working with the above listed sensors.

Code: Select all | TOGGLE FULL SIZE
/* Test sketch for Adafruit PM2.5 sensor with UART or I2C */

#include "Adafruit_PM25AQI.h"
#include "DHT.h"
#include "Adafruit_BMP3XX.h"


#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
#include <SPI.h>
#include <WiFiNINA.h>
#include <NTPClient.h>


// #include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = "CCCCCc";        // your network SSID (name)
char pass[] = "CCCCCC";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;                 // your network key index number (needed only for WEP)

int status = WL_IDLE_STATUS;

WiFiServer server(80);

// If your PM2.5 is UART only, for UNO and others (without hardware serial)
// we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
//#include <SoftwareSerial.h>
//SoftwareSerial pmSerial(2, 3);
#define DHTPIN 2
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
DHT dht(DHTPIN, DHTTYPE);

// define BMP390 pressure sensor
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BMP3XX bmp;

struct dht_out {
  float t;
  float h;
  float f;
  float hic;
  float hif;
};

int i = 0;

Adafruit_PM25AQI aqi = Adafruit_PM25AQI();


// U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// U8G2_SSD1306_128X64_VCOMH0_F_HW_I2C gfx(U8G2_R0); // WORKS and doesn't freeze, so far!
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

void setup() {
  // Wait for serial monitor to open
  Serial.begin(115200);
  // while (!Serial) delay(10);

  Serial.println("Adafruit PMSA003I Air Quality Sensor");

  // Wait one second for sensor to boot up!
  delay(1000);

  // If using serial, initialize it and set baudrate before starting!
  // Uncomment one of the following
  //Serial1.begin(9600);
  //pmSerial.begin(9600);

  // There are 3 options for connectivity!
  // if (! aqi.begin_I2C()) {      // connect to the sensor over I2C
  // //if (! aqi.begin_UART(&Serial1)) { // connect to the sensor over hardware serial
  // //if (! aqi.begin_UART(&pmSerial)) { // connect to the sensor over software serial
  //   Serial.println("Could not find PM 2.5 sensor!");
  //   while (1) delay(10);
  // }
  aqi.begin_I2C();
  Serial.println("PM25 found!");

  Serial.println(F("DHTxx test!"));

  dht.begin();

  while (!Serial);
  Serial.println("Adafruit BMP388 / BMP390 test");

  if (!bmp.begin_I2C()) {   // hardware I2C mode, can pass in address & alt Wire
  //if (! bmp.begin_SPI(BMP_CS)) {  // hardware SPI mode 
  //if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) {  // software SPI mode
    Serial.println("Could not find a valid BMP3 sensor, check wiring!");
    while (1);
  }

  // Set up oversampling and filter initialization
  bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
  bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
  bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
  bmp.setOutputDataRate(BMP3_ODR_50_HZ);


  u8g2.begin();
  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
  server.begin();
  // you're connected now, so print out the status:
  printWifiStatus();
  timeClient.begin();
  timeClient.setTimeOffset(-28800);
}

void loop() {
  read_aqi();
  float p = get_bmp();
  dht_out dht_local_data;
  dht_local_data = read_dht();
  float h = dht_local_data.h;
  float t = dht_local_data.t;
  float f = dht_local_data.f;
  float hic = dht_local_data.hic;
  float hif = dht_local_data.hif;

  // Serial.print(F("Humidity: "));
  // Serial.print(h);
  // Serial.print(F("%  Temperature: "));
  // Serial.print(t);
  // Serial.print(F("C "));
  // Serial.print(f);
  // Serial.print(F("F  Heat index: "));
  // Serial.print(hic);
  // Serial.print(F("C "));
  // Serial.print(hif);
  // Serial.println(F("F"));

  send_display(f, h, hif, p);
  // send_display();
  web_server_post(f, h, hif, p);
  current_timestamp();
  delay(2000);
}

void read_aqi(){
  PM25_AQI_Data data;
  int j = 0;
  if (! aqi.read(&data)) {
    Serial.println("Could not read from AQI");
    aqi.begin_I2C();
    // delay(500);  // try again in a bit!
    // j = j + 1:
    // if (j > 5) {
    //   return;
    // }
    return;
  }
  Serial.println("AQI reading success");

  Serial.println();
  Serial.println(F("---------------------------------------"));
  Serial.println(F("Concentration Units (standard)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_standard);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_standard);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_standard);
  Serial.println(F("Concentration Units (environmental)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_env);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_env);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_env);
  Serial.println(F("---------------------------------------"));
  Serial.print(F("Particles > 0.3um / 0.1L air:")); Serial.println(data.particles_03um);
  Serial.print(F("Particles > 0.5um / 0.1L air:")); Serial.println(data.particles_05um);
  Serial.print(F("Particles > 1.0um / 0.1L air:")); Serial.println(data.particles_10um);
  Serial.print(F("Particles > 2.5um / 0.1L air:")); Serial.println(data.particles_25um);
  Serial.print(F("Particles > 5.0um / 0.1L air:")); Serial.println(data.particles_50um);
  Serial.print(F("Particles > 10 um / 0.1L air:")); Serial.println(data.particles_100um);
  Serial.println(F("---------------------------------------"));

};

struct dht_out read_dht() {
  struct dht_out dht_data;
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  // if (isnan(h) || isnan(t) || isnan(f)) {
  //   Serial.println(F("Failed to read from DHT sensor!"));
  //   return;
  // }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);
  dht_data.t = t;
  dht_data.h = h;
  dht_data.f = f;
  dht_data.hif = hif;
  dht_data.hic = hic;

  // Serial.print(F("Humidity: "));
  // Serial.print(h);
  // Serial.print(F("%  Temperature: "));
  // Serial.print(t);
  // Serial.print(F("C "));
  // Serial.print(f);
  // Serial.print(F("F  Heat index: "));
  // Serial.print(hic);
  // Serial.print(F("C "));
  // Serial.print(hif);
  // Serial.println(F("F"));
  return dht_data;
};

float get_bmp(){
    if (! bmp.performReading()) {
    Serial.println("Failed to perform reading :(");
    // return;
  }
  Serial.print("Temperature = ");
  Serial.print(bmp.temperature);
  Serial.println(" *C");
  float p = bmp.pressure;
  Serial.print("Pressure = ");
  Serial.print(p / 100.0);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.println();
  return p;
}

// void send_display(){
void send_display(float t, float h, float hic, float p){
  timeClient.update();

  // Serial.println(timeClient.getFormattedTime());
  String disp_text = "Temperature: " + String(t) + "   Humidity: " + String(h) + "  Heat Index: " + String(hic) + " Pressure: " + String(p);
  // String disp_text = "Hello World! " + String(i);
  u8g2.clearBuffer();               // clear the internal memory
  u8g2.setFont(u8g2_font_ncenB08_tr);   // choose a suitable font
  u8g2.drawStr(0,10,("Temperature: " + String(t)).c_str());   // write something to the internal memory
  u8g2.drawStr(0,20,("Humidity: " + String(h)).c_str());   // write something to the internal memory
  u8g2.drawStr(0,30,("Heat Index: " + String(hic)).c_str());   // write something to the internal memory
  u8g2.drawStr(0,40,("Pressure: " + String(p)).c_str());   // write something to the internal memory
  // u8g2.drawStr(0,50,("Time: " + String(timeClient.getFormattedTime()).c_str()));   // write something to the internal memory

  u8g2.sendBuffer();               // transfer internal memory to the display
  Serial.println(disp_text);
  i = i + 1;
}

void web_server_post(float f, float h, float hif, float p) {
  // listen for incoming clients
  WiFiClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an HTTP request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the HTTP request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard HTTP response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 2");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
          // output the value of each analog input pin
          client.print("Temperature: ");
          client.print(f);
          client.print(" F");
          client.println("<br />");
          client.print("Humidity: ");
          client.print(h);
          client.print("%");
          client.println("<br />");
          client.print("Heat Index: ");
          client.print(hif);
          client.print(" F");
          client.println("<br />");
          client.print("Pressure: ");
          client.print(p);
          client.print(" Pa");
          client.println("<br />");
          // for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
          //   int sensorReading = analogRead(analogChannel);
          //   client.print("analog input ");
          //   client.print(analogChannel);
          //   client.print(" is ");
          //   client.print(sensorReading);
          //   client.println("<br />");
          // }
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);

    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
}


void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void current_timestamp() {
  timeClient.update();

  Serial.println(timeClient.getFormattedTime());
  // Serial.println(timeClient.getFormattedDate());


}

mrh335
 
Posts: 3
Joined: Wed Jul 21, 2021 2:24 pm

Re: PMSA-003i not working with other hardware

by mrh335 on Tue Aug 03, 2021 12:22 pm

I have spent more time troubleshooting and have found that whenever I add the OLED and the u8g2.begin() code, there is a conflict with the PMSA-003i and the code hangs.

I built the following test crudely from the example files to test this. I started by reading the PMSA and printing to serial. This worked.
I then added the BMP390 sensor and printed to serial. This worked.
I added the "Hello World" U8G2 example and now the code cannot detect the PMSA sensor and stops at that line.

I have tested with two different OLEDs with same result. The address of the OLED is 0x3C which should not conflict with the PMSA.

My next test code is below. Please advise if this is an address collision and if so how that is possible given the addresses of the device.

The following code has the U8G2 begin and display lines commented out as this version of the code works. Uncommenting those lines causes the fail.

Code: Select all | TOGGLE FULL SIZE
/* Test sketch for Adafruit PM2.5 sensor with UART or I2C */

#include "Adafruit_PM25AQI.h"
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BMP3XX.h"

#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

// If your PM2.5 is UART only, for UNO and others (without hardware serial)
// we must use software serial...
// pin #2 is IN from sensor (TX pin on sensor), leave pin #3 disconnected
// comment these two lines if using hardware serial
//#include <SoftwareSerial.h>
//SoftwareSerial pmSerial(2, 3);

Adafruit_PM25AQI aqi = Adafruit_PM25AQI();
#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BMP3XX bmp;

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);


void setup() {
  // Wait for serial monitor to open
  Serial.begin(115200);
  while (!Serial) delay(10);

  Serial.println("Adafruit PMSA003I Air Quality Sensor");

  // Wait one second for sensor to boot up!
  delay(1000);

  // If using serial, initialize it and set baudrate before starting!
  // Uncomment one of the following
  //Serial1.begin(9600);
  //pmSerial.begin(9600);

  // There are 3 options for connectivity!
  if (! aqi.begin_I2C()) {      // connect to the sensor over I2C
  //if (! aqi.begin_UART(&Serial1)) { // connect to the sensor over hardware serial
  //if (! aqi.begin_UART(&pmSerial)) { // connect to the sensor over software serial
    Serial.println("Could not find PM 2.5 sensor!");
    while (1) delay(10);
  }

  Serial.println("PM25 found!");
    Serial.println("Adafruit BMP388 / BMP390 test");

  if (!bmp.begin_I2C()) {   // hardware I2C mode, can pass in address & alt Wire
  //if (! bmp.begin_SPI(BMP_CS)) {  // hardware SPI mode 
  //if (! bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI)) {  // software SPI mode
    Serial.println("Could not find a valid BMP3 sensor, check wiring!");
    while (1);
  }

  // Set up oversampling and filter initialization
  bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
  bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
  bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
  bmp.setOutputDataRate(BMP3_ODR_50_HZ);

    u8g2.begin();

}

void loop() {
  PM25_AQI_Data data;
 
  if (! aqi.read(&data)) {
    Serial.println("Could not read from AQI");
    delay(500);  // try again in a bit!
    return;
  }
  Serial.println("AQI reading success");

  Serial.println();
  Serial.println(F("---------------------------------------"));
  Serial.println(F("Concentration Units (standard)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_standard);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_standard);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_standard);
  Serial.println(F("Concentration Units (environmental)"));
  Serial.println(F("---------------------------------------"));
  Serial.print(F("PM 1.0: ")); Serial.print(data.pm10_env);
  Serial.print(F("\t\tPM 2.5: ")); Serial.print(data.pm25_env);
  Serial.print(F("\t\tPM 10: ")); Serial.println(data.pm100_env);
  Serial.println(F("---------------------------------------"));
  Serial.print(F("Particles > 0.3um / 0.1L air:")); Serial.println(data.particles_03um);
  Serial.print(F("Particles > 0.5um / 0.1L air:")); Serial.println(data.particles_05um);
  Serial.print(F("Particles > 1.0um / 0.1L air:")); Serial.println(data.particles_10um);
  Serial.print(F("Particles > 2.5um / 0.1L air:")); Serial.println(data.particles_25um);
  Serial.print(F("Particles > 5.0um / 0.1L air:")); Serial.println(data.particles_50um);
  Serial.print(F("Particles > 10 um / 0.1L air:")); Serial.println(data.particles_100um);
  Serial.println(F("---------------------------------------"));
 
  if (! bmp.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }
  Serial.print("Temperature = ");
  Serial.print(bmp.temperature);
  Serial.println(" *C");

  Serial.print("Pressure = ");
  Serial.print(bmp.pressure / 100.0);
  Serial.println(" hPa");

  Serial.print("Approx. Altitude = ");
  Serial.print(bmp.readAltitude(SEALEVELPRESSURE_HPA));
  Serial.println(" m");

  Serial.println();



  // u8g2.clearBuffer();               // clear the internal memory
  // u8g2.setFont(u8g2_font_ncenB08_tr);   // choose a suitable font
  // u8g2.drawStr(0,10,"Hello World!");   // write something to the internal memory
  // u8g2.sendBuffer();               // transfer internal memory to the display


  delay(1000);
}

mrh335
 
Posts: 3
Joined: Wed Jul 21, 2021 2:24 pm

Re: PMSA-003i not working with other hardware

by mrh335 on Tue Aug 03, 2021 12:43 pm

I did some other searching to find issues with the U8G2 library and other I2C devices at times.

The solution that now has the above two versions of code working is to set the I2C bus speed for the U8G2 device by using the following command prior to the begin statement in the setup loop. It would be great to understand a bit more as to why this is. The display is now updating its values, but its font appears larger and more distorted.

Code: Select all | TOGGLE FULL SIZE
  u8g2.setBusClock(100000);
  u8g2.begin();

mrh335
 
Posts: 3
Joined: Wed Jul 21, 2021 2:24 pm

Re: PMSA-003i not working with other hardware

by adafruit_support_carter on Tue Aug 03, 2021 5:13 pm

Not sure, but seems like it might have something to do with how ug82 is managing and/or sharing (or not) the I2C bus. Sounds like you found a work around though.

adafruit_support_carter
 
Posts: 21124
Joined: Tue Nov 29, 2016 2:45 pm

Please be positive and constructive with your questions and comments.