Program not looping

So i've been trying to make it so that my code is printing the data from sensors even without a gps-signal (this has been a problem before). The code i had before printed only "NoGPS", in a loop, but this loop seems to have vanished. Can someone help me find the error, i can't see it?

#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#include <DHT.h>
#include <SDS011.h>

#define DHTPIN 9
DHT dht22(DHTPIN, DHT22);

#define PM_TX 2
#define PM_RX 3
SDS011 sds;

#define LED_RED A1
#define LED_GREEN A0

#define GPS_RX 7
#define GPS_TX 6

SoftwareSerial gpsCom(GPS_RX, GPS_TX);
TinyGPSPlus gps;

void setup() {
  // Activate control over LEDs
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);

  // Initialize serial communication
  Serial.begin(9600); // to Computer (USB)
  gpsCom.begin(9600); // to GPS antenna
  sds.begin(PM_TX, PM_RX);
}

void loop() {
  float temperature = 0;
  float humidity = 0;
  temperature = dht22.readTemperature();
  humidity = dht22.readHumidity();

  float pm25, pm10;
  int error;
  do{
  error = sds.read(&pm25, &pm10);
  } while (error != 0);
  
  gpsCom.listen();
  bool gpsEncodeComplete = false;
  do {
    if (!gpsCom.available()) {
      // No new data available.
      // Immediately jump to next iteration
      continue;
    }
    gpsEncodeComplete = gps.encode(gpsCom.read());
    if (!gpsEncodeComplete) {
      // Data is incomplete, 
      // Jump to next iteration and try again
      continue;
    }
  } while (!gpsEncodeComplete);  // Loop until gps data was successfully read and encoded from GPS module

  bool gpsValid = gps.location.isValid();
  bool gpsUpdated = gps.location.isUpdated();
  bool isUseful = gpsValid && gpsUpdated;
  if (!isUseful) {
    // No valid position.
    // I.e. no GPS fix.
    Serial.print("NoGPS");
    Serial.print(", ");
    Serial.print(temperature);
    Serial.print(", ");
    Serial.print(humidity);
    Serial.print("%");
    Serial.print(", ");

    Serial.print(pm25);
    Serial.print(", ");
    Serial.println(pm10);
    digitalWrite(LED_RED, HIGH);
    delay(500);
    digitalWrite(LED_RED, LOW);
    return;
  }

  digitalWrite(LED_GREEN, HIGH);
  delay(500);
  digitalWrite(LED_GREEN, LOW);

  Serial.print(gps.date.day());
  Serial.print(".");
  Serial.print(gps.date.month());
  Serial.print(".");
  Serial.print(gps.date.year());
  Serial.print(" ");
  Serial.print(gps.time.hour());
  Serial.print(":");
  Serial.print(gps.time.minute());
  Serial.print(":");
  Serial.print(gps.time.second());
  Serial.print(", ");

  Serial.print(temperature);
  Serial.print(", ");
  Serial.print(humidity);
  Serial.print("%");
  Serial.print(", ");

  Serial.print(pm25);
  Serial.print(", ");
  Serial.println(pm10);
  
}

You are stuck in this loop until you get GPS data. That is why you cannot display anything else.

Yes, i know.

But the loop isn't "looping". It prints once, then just stops. I can't find where in the code this is happening.

If you are stuck in the do-while loop then you will never exit the loop() function and therefore never enter the loop() function again.

Ok, and how would you fix that?

Sorry, but i am not very good at these things.

You could also be stuck here forever if you have an continuous sds error:

You really don't need those do-while loops. Just let loop() do the looping. Like this:

#include <SoftwareSerial.h>
#include <TinyGPS++.h>
#include <DHT.h>
#include <SDS011.h>

#define DHTPIN 9
DHT dht22(DHTPIN, DHT22);

#define PM_TX 2
#define PM_RX 3
SDS011 sds;

#define LED_RED A1
#define LED_GREEN A0

#define GPS_RX 7
#define GPS_TX 6

SoftwareSerial gpsCom(GPS_RX, GPS_TX);
TinyGPSPlus gps;

void setup() 
{
  // Activate control over LEDs
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);

  // Initialize serial communication
  Serial.begin(9600); // to Computer (USB)
  gpsCom.begin(9600); // to GPS antenna
  sds.begin(PM_TX, PM_RX);
}

void loop() 
{
  float temperature;
  float humidity;
  float pm25, pm10;
  bool isUseful = false;

  digitalWrite(LED_GREEN, HIGH);
  delay(500);
  digitalWrite(LED_GREEN, LOW);

  gpsCom.listen();
  if (gpsCom.available() && gps.encode(gpsCom.read()) && gps.location.isValid() && gps.location.isUpdated())
  {
    Serial.print(gps.date.day());
    Serial.print(".");
    Serial.print(gps.date.month());
    Serial.print(".");
    Serial.print(gps.date.year());
    Serial.print(" ");
    Serial.print(gps.time.hour());
    Serial.print(":");
    Serial.print(gps.time.minute());
    Serial.print(":");
    Serial.print(gps.time.second());
    Serial.print(", ");
  }
  else
  {
    Serial.println("No valid GPS data to report");
  }

  temperature = dht22.readTemperature();
  humidity = dht22.readHumidity();

  Serial.print(temperature);
  Serial.print(", ");
  Serial.print(humidity);
  Serial.print("%");
  Serial.print(", ");

  if (sds.read(&pm25, &pm10) == 0)
  {
    Serial.print(pm25);
    Serial.print(", ");
    Serial.println(pm10);
  }
  else
  {
    Serial.println("Could not read sds");
  }
}

I tested your suggestion, and it didn't seem to print correctly for the sds sensor. I also had to switch the "== 0" with "!= 0". Idk why, but here is the code without any gps:

#include <DHT.h>
#include <SoftwareSerial.h>
#include <SDS011.h>


// Klargjør for temperatur og fuktighet
#define DHTPIN 9
DHT dht22(DHTPIN, DHT22);

// Klargjør led-lysene rød og grønn
#define LED_RED A1
#define LED_GREEN A0

// Klargjør PM modul
#define PM_TX 2
#define PM_RX 3
SDS011 sds;

void setup() {
  // put your setup code here, to run once:
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);

Serial.begin(9600);

sds.begin(PM_TX, PM_RX);

}

void loop() {
  // put your main code here, to run repeatedly:

 
// nullstill temperatur og fuktighet
float temperature = 0;
float humidity = 0;
temperature = dht22.readTemperature();
humidity = dht22.readHumidity();


float pm25, pm10;
int error;
do{
error = sds.read(&pm25, &pm10);
} while (error != 0);
 

Serial.print(temperature);
Serial.print(", ");
Serial.print(humidity);
Serial.print("%");
Serial.print(", ");

Serial.print(pm25);
Serial.print(", ");

Serial.println(pm10);




delay(2500);



}

You could still get stuck here:

But i dont in the one without gps. Could it be placed wrongly in the gps code?

This is not a question of where you place this do while-loop in the code.
Whenever this loop is entered and you get no valid sds-reading you stay stucked in this loop until you switch power off!

do {
the things inside the loop
} while you get no valid reading

if a wire to the sensor is broken
if the sensor is damaged

you don't get a valid reading and then you are stuck forever

That doesn't explain why the readings are valid in other sketches though. :frowning:

I looked at the data sheet for that sensor. The SDS sensor has a baud rate of 9600 and only updates once per second. If an update is not completed you get a return of 1 from the sds.read() call. You can either print the SDS data when you have an update (about once per second) or save the last reading in global variables, print them out every time loop() executes, and update them when you have a valid reading from sds.read().

If you do it like you are with a do-while loop then you will stay in that do-while loop until SDS updates! Which is about 1 second! The way I am suggesting you can do other things while waiting for SDS to update.

@StefanL38 is also right. If there is a problem communicating with the SDS sensor you will be stuck in that loop forever. But like I said, even if the sensor is working you will be in that loop for at least 1 second.

Yeah, that is fine. But the sds readings are still wrong. Your suggestion gives much lower data than expected.

If SDS readings are wrong then there is a problem other than the code.

I have no idea what you mean by that. I actually looked at the SDS library you are using. That is the way the library operates. Use this in loop():

  if (sds.read(&pm25, &pm10) == 0)
  {
    Serial.print(pm25);
    Serial.print(", ");
    Serial.println(pm10);
  }

If you are communicating properly with the SDS sensor then the readings should print about once per second. If the readings do not print once per second then you have an issue communicating with the sensor. It is just that simple.

Look at the read() method of the SDS011.cpp file in the library and you will see what I mean: SDS011.cpp

Look at the "UART communication protocol" section of the SDS data sheet and you will see it states a Data Packet frequency of 1Hz: SDS011-DATASHEET

Ok, so the sds sensor is a dust sensor which measures the dust in micrograms/m^3. My previous code for sensors only gave a reading of about 0.6 and 4, while yours give 0 and 0.2 or cant even read. Theoretically mine makes sense. I don't know what is wrong.

My point was the protocol and frequency. You should not see updates more than once per second.

You can call read() more than once per second but it WILL NOT update the pm25 and pm10 variables more than once per second. It will only update those variables when it returns a 0 which will only be once per second. The read() method is pretty simple if you go look at it.

Me neither. I don't have the hardware or the necessary equipment to validate the data. If the sensor is transmitting valid data packets and the numbers are verifiably wrong then you have a bad sensor. The packet protocol is simple.

The thing is, im using a 2.5 second delay in addition. So i dont think the updating is the problem.

Post your latest code

This is for sensors only:

#include <DHT.h>
#include <SoftwareSerial.h>
#include <SDS011.h>


// Klargjør for temperatur og fuktighet
#define DHTPIN 9
DHT dht22(DHTPIN, DHT22);

// Klargjør led-lysene rød og grønn
#define LED_RED A1
#define LED_GREEN A0

// Klargjør PM modul
#define PM_TX 2
#define PM_RX 3
SDS011 sds;

void setup() {
  // put your setup code here, to run once:
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);

Serial.begin(9600);

sds.begin(PM_TX, PM_RX);

}

void loop() {
  // put your main code here, to run repeatedly:

 
// nullstill temperatur og fuktighet
float temperature = 0;
float humidity = 0;
temperature = dht22.readTemperature();
humidity = dht22.readHumidity();


float pm25, pm10;
int error;
do{
error = sds.read(&pm25, &pm10);
} while (error != 0);
 

Serial.print(temperature);
Serial.print(", ");
Serial.print(humidity);
Serial.print("%");
Serial.print(", ");

Serial.print(pm25);
Serial.print(", ");

Serial.println(pm10);




delay(2500);



}