Hello,
Thank you for your advice! I have re-worked my code as suggested by you and @chipmc
#include <Seeed_HM330X.h>
#include <vector>
// #define SERIAL_OUTPUT_ENABLE
// #define TIME_SYNC_ENABLE
// #define SLEEP_ENABLE
#define SLEEP_TIME 30min
#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
#define MAX_SAMPLE 48
unsigned long lastSync = millis();
uint8_t sample_counter = 0;
int DUST_SENSOR = D6;
HM330X sensor;
uint8_t buf[30];
// before setup - enable feature
STARTUP(System.enableFeature(FEATURE_RESET_INFO));
// Enable logging as we ware looking at messages that will be off-line - need to connect to serial terminal
SerialLogHandler logHandler(LOG_LEVEL_INFO);
typedef struct data {
uint16_t day = 0;
uint16_t hour = 0;
uint16_t minute = 0;
uint16_t ae_value [3] = {0,0,0};
} Data;
std::vector<Data> sensor_record;
const char* str[] = {
"PM1.0 concentration(Atmospheric environment,unit:ug/m3): ",
"PM2.5 concentration(Atmospheric environment,unit:ug/m3): ",
"PM10 concentration(Atmospheric environment,unit:ug/m3): ",
};
HM330XErrorCode publish_daily_record() {
while(!sensor_record.empty()){
Data data_to_publish = sensor_record.front();
// Some String manipulation
String to_publish = ((String)data_to_publish.day);
to_publish.concat(",");
to_publish.concat((String)data_to_publish.hour);
to_publish.concat(",");
to_publish.concat((String)data_to_publish.minute);
to_publish.concat(",");
to_publish.concat((String)data_to_publish.ae_value[0]);
to_publish.concat(",");
to_publish.concat((String)data_to_publish.ae_value[1]);
to_publish.concat(",");
to_publish.concat((String)data_to_publish.ae_value[2]);
delay(1000);
// Check for connection
// if YES, transmitted everything in the buffer
// if NO, leave the current data in the buffer, send it next day
if (Particle.connected()){
Particle.publish(to_publish);
sensor_record.erase(sensor_record.begin());
} else {
break;
}
}
return NO_ERR;
}
/*parse buf with 29 uint8_t-data*/
HM330XErrorCode parse_result(uint8_t* data, Data& new_sample) {
uint16_t value = 0;
if (NULL == data) {
return ERROR_PARAM;
}
// my_record.sensor_no = (uint16_t) data[2] << 8 | data[5];
for (int i = 5; i < 8; i++) {
value = (uint16_t) data[i * 2] << 8 | data[i * 2 + 1];
new_sample.ae_value[i - 5] = new_sample.ae_value[i - 5] + value;
}
return NO_ERR;
}
HM330XErrorCode print_result(const char* str, uint16_t value) {
if (NULL == str) {
return ERROR_PARAM;
}
Log.info(str + String(value));
return NO_ERR;
}
void safeDelay(unsigned long delayMillis) { // Ensures Particle functions operate during long delays
unsigned long timeStamp = millis();
while (millis() - timeStamp < delayMillis) {
delay(10);
Particle.process();
}
}
SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);
void setup() {
pinMode(DUST_SENSOR, OUTPUT);
digitalWrite(DUST_SENSOR, HIGH);
safeDelay(10000);
if (System.resetReason() == RESET_REASON_PIN_RESET) {
Log.info("Restarted due to a pin reset");
} else if (System.resetReason() == RESET_REASON_USER) { // Check to see if we are starting from a pin reset or a reset in the sketch
Log.info("Restarted due to a user reset");
} else Log.info("System reset reason %i", System.resetReason());
if (sensor.init()) {
Log.info("Init Failed");
Particle.disconnect();
Cellular.off();
while (1){
Particle.process();
};
} else {
Log.info("Init Success");
Particle.disconnect();
Cellular.off();
}
}
void loop() {
Data new_sample;
// Take 5 samples with 1s interval
for (int i = 0; i < 5; i++){
if (sensor.read_sensor_value(buf, 29)) {
Log.info("Read Result Failed");
}
parse_result(buf, new_sample);
safeDelay(1000);
}
// Average 5 samples
for (int i = 0; i < 3; i++){
new_sample.ae_value[i] = new_sample.ae_value[i] / 5;
}
// Record the time
new_sample.day = Time.day();
new_sample.hour = Time.hour();
new_sample.minute = Time.minute();
// Add it to the sensor record and increment the sampler counter
sensor_record.emplace_back(new_sample);
sample_counter = sample_counter + 1;
// For the second last sample taken, open up the connection with cloud
if (sample_counter == MAX_SAMPLE - 1){
Log.info("attemp to connect");
Particle.connect();
safeDelay(20000);
#ifdef TIME_SYNC_ENABLE
// Code taken from Particle's tutorial
// https://docs.particle.io/cards/firmware/cloud-functions/particle-synctime/
//
if (millis() - lastSync > ONE_DAY_MILLIS) {
// Request time synchronization from the Particle Device Cloud
Particle.syncTime();
lastSync = millis();
}
#endif
}
// Publish the record to the cloud every 48 samples (48 samples * 30 min/sample = 24 hr)
// Reset all the counters
if (sample_counter == MAX_SAMPLE){
Log.info("ready to publish");
publish_daily_record();
sample_counter = 0;
Particle.disconnect();
Cellular.off();
Log.info("Switch off network facility");
}
Log.info("Turning off the sensor");
digitalWrite(DUST_SENSOR, LOW);
#ifdef SLEEP_ENABLE
// Last cycle will have network enabled for potential OTA
if (sample_counter == MAX_SAMPLE - 1){
SystemSleepConfiguration config;
config.mode(SystemSleepMode::STOP)
.network(NETWORK_INTERFACE_CELLULAR)
.duration(SLEEP_TIME);
System.sleep(config);
} else {
SystemSleepConfiguration config;
config.mode(SystemSleepMode::STOP)
.duration(SLEEP_TIME);
System.sleep(config);
}
#else
safeDelay(10000);
#endif
Log.info("Turning on the sensor");
digitalWrite(DUST_SENSOR, HIGH);
Log.info("Waiting for sensor starting up...");
safeDelay(30000);
Log.info("Counter number is " + String(sample_counter));
}
For the Seeed_HM330X.h and subsequent dependencies, please take at look at
I used the sensor’s demo code, and wrote my code based on their demo.
For now, I am still having the problem, it seems right after I set the pin back to high in the loop (the line: digitalWrite(DUST_SENSOR, HIGH);), Boron resets (it ran the setup and the loop again, and resets at the same position).
Thank you for your time looking at my code 
Please let me know if you spot anything that might go wrong.