Related
I have an ESP8266 connected to PMS5003 particulate matter sensor through (hardware) UART.
I'm getting many checksum errors while reading from PMS5003.
Here's the library that I'm using to communicate with PMS5003:
PMS5003.cpp
#include "PMS5003.h"
void PMS5003::processDataOn(HardwareSerial &serial) {
unsigned long timeout = millis();
int count = 0;
byte incomeByte[NUM_INCOME_BYTE];
boolean startcount = false;
byte data;
int timeoutHops = 0;
while (1){
if (((millis() - timeout) > 1000) && (timeoutHops == 0)) {
timeoutHops = 1;
yield();
ESP.wdtFeed();
}
if (((millis() - timeout) > 2000) && (timeoutHops == 1)) {
timeoutHops = 2;
yield();
ESP.wdtFeed();
}
if ((millis() - timeout) > 3000){
Serial.println("SENSOR-ERROR-TIMEOUT");
break;
}
if (serial.available()){
data = serial.read();
if (data == CHAR_PRELIM && !startcount) {
startcount = true;
count++;
incomeByte[0] = data;
} else if (startcount) {
count++;
incomeByte[count - 1] = data;
if (count >= NUM_INCOME_BYTE){
break;
}
}
}
}
unsigned int calcsum = 0;
unsigned int exptsum;
for (int i = 0; i < NUM_DATA_BYTE; i++) {
calcsum += (unsigned int)incomeByte[i];
}
exptsum = ((unsigned int)incomeByte[CHECK_BYTE] << 8) + (unsigned int)incomeByte[CHECK_BYTE + 1];
if (calcsum == exptsum) {
pm1 = ((unsigned int)incomeByte[PM1_BYTE] << 8) + (unsigned int)incomeByte[PM1_BYTE + 1];
pm25 = ((unsigned int)incomeByte[PM25_BYTE] << 8) + (unsigned int)incomeByte[PM25_BYTE + 1];
pm10 = ((unsigned int)incomeByte[PM10_BYTE] << 8) + (unsigned int)incomeByte[PM10_BYTE + 1];
} else {
Serial.println("#[exception] PM2.5 Sensor CHECKSUM ERROR!");
pm1 = -1;
pm25 = -1;
pm10 = -1;
}
return;
}
int PMS5003::getPM1() {
return pm1;
}
int PMS5003::getPM25() {
return pm25;
}
int PMS5003::getPM10() {
return pm10;
}
PMS5003.h
#ifndef _PMS_5003_H
#define _PMS_5003_H
#include <Wire.h>
#include <Arduino.h>
#define VERSION 0.2
#define Sense_PM 6
#define NUM_INCOME_BYTE 32
#define CHAR_PRELIM 0x42
#define NUM_DATA_BYTE 29
#define CHECK_BYTE 30
#define PM1_BYTE 10
#define PM25_BYTE 12
#define PM10_BYTE 14
class PMS5003 {
public:
//void processData(int *PM1, int *PM25, int *PM10);
void processDataOn(HardwareSerial &serial);
int getPM1();
int getPM25();
int getPM10();
private:
int pm1;
int pm25;
int pm10;
};
#endif
Here's how I'm using it:
struct ParticulateMatterMeasurements {
private:
bool _areValid = false;
int PM01Value = 0;
int PM25Value = 0;
int PM10Value = 0;
public:
void setAreValid(bool _areValid) {
ParticulateMatterMeasurements::_areValid = _areValid;
}
bool getAreValid() const {
return _areValid;
}
int getPM01Value() const {
return PM01Value;
}
void setPM01Value(int PM01Value) {
ParticulateMatterMeasurements::PM01Value = PM01Value;
}
int getPM25Value() const {
return PM25Value;
}
void setPM25Value(int PM25Value) {
ParticulateMatterMeasurements::PM25Value = PM25Value;
}
int getPM10Value() const {
return PM10Value;
}
void setPM10Value(int PM10Value) {
ParticulateMatterMeasurements::PM10Value = PM10Value;
}
};
ParticulateMatterMeasurements getMeasurements() {
ParticulateMatterMeasurements measurements;
measurements.setAreValid(false);
pms5003.processDataOn(Serial);
measurements.setPM01Value(pms5003.getPM1());
measurements.setPM25Value(pms5003.getPM25());
measurements.setPM10Value(pms5003.getPM10());
if (measurements.getPM01Value() != -1 && measurements.getPM25Value() != -1 && measurements.getPM10Value() != -1) {
measurements.setAreValid(true);
}
return measurements;
}
The problem is that I get many checksum errors. During 60 measurements I get about 100 of: #[exception] PM2.5 Sensor CHECKSUM ERROR!.
What could be the problem here?
#edit
I ran a test where I print what PMS5003 sends to my ESP8266. It looks like the checksum which is the last byte is sometimes not sent. Instead, I get 66 usually but I can see sometimes 66 77 instead of the last 2 bytes as well.
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 201 2 216 0 86 0 8 0 3 0 1 145 0 3 172
16
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 201 2 216 0 86 0 8 0 3 0 1 145 0 3 172
16
66 77 0 28 0 14 0 18 0 22 0 14 0 18 0 22 10 32 2 239 0 93 0 9 0 3 0 1 145 0 3 45
18
66 77 0 28 0 14 0 18 0 22 0 14 0 18 0 22 10 32 2 239 0 93 0 9 0 3 0 1 145 0 3 66
18
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 17 0 20 0 13 0 17 0 20 10 50 2 231 0 88 0 9 0 3 0 1 145 0 3 42
17
66 77 0 28 0 12 0 16 0 20 0 12 0 16 0 20 9 225 2 208 0 90 0 8 0 3 0 1 145 0 3 190
16
66 77 0 28 0 13 0 17 0 21 0 13 0 17 0 21 9 225 2 208 0 90 0 8 0 3 0 1 145 0 3 196
17
66 77 0 28 0 12 0 15 0 17 0 12 0 15 0 17 9 249 2 211 0 76 0 5 0 0 0 0 145 0 3 188
15
66 77 0 28 0 12 0 15 0 17 0 12 0 15 0 17 9 249 2 211 0 76 0 5 0 0 0 0 145 0 3 188
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 210 2 188 0 70 0 5 0 0 0 0 145 0 3 118
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 210 2 188 0 70 0 5 0 0 0 0 145 0 3 118
15
66 77 0 28 0 13 0 16 0 17 0 13 0 16 0 17 9 198 2 183 0 78 0 5 0 0 0 0 145 0 3 115
16
66 77 0 28 0 13 0 16 0 17 0 13 0 16 0 17 9 198 2 183 0 78 0 5 0 0 0 0 145 0 3 66
16
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 12 0 16 0 18 0 12 0 16 0 18 9 234 2 195 0 87 0 8 0 1 0 0 145 0 3 176
16
66 77 0 28 0 12 0 16 0 18 0 12 0 16 0 18 9 234 2 195 0 87 0 8 0 1 0 0 145 0 3 176
16
66 77 0 28 0 12 0 15 0 17 0 12 0 15 0 17 9 186 2 184 0 77 0 6 0 1 0 0 145 0 3 101
15
66 77 0 28 0 13 0 16 0 18 0 13 0 16 0 18 9 186 2 184 0 77 0 6 0 1 0 0 145 0 3 107
16
66 77 0 28 0 13 0 16 0 18 0 13 0 16 0 18 9 186 2 184 0 77 0 6 0 1 0 0 145 0 3 107
16
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 165 2 180 0 76 0 6 0 1 0 0 145 0 3 83
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 165 2 180 0 76 0 6 0 1 0 0 145 0 3 83
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 156 2 186 0 76 0 6 0 1 0 0 145 0 3 80
17
66 77 0 28 0 12 0 16 0 17 0 12 0 16 0 17 9 156 2 186 0 76 0 6 0 1 0 0 145 0 3 66
16
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 12 0 16 0 17 0 12 0 16 0 17 9 249 2 200 0 67 0 6 0 1 0 0 145 0 3 172
16
66 77 0 28 0 12 0 16 0 17 0 12 0 16 0 17 9 249 2 200 0 67 0 6 0 1 0 0 145 0 3 172
16
66 77 0 28 0 12 0 16 0 17 0 12 0 16 0 17 9 231 2 197 0 73 0 7 0 1 0 0 145 0 3 158
16
66 77 0 28 0 12 0 16 0 17 0 12 0 16 0 17 9 231 2 197 0 73 0 7 0 1 0 0 145 0 3 158
16
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 243 2 194 0 73 0 7 0 1 0 0 145 0 3 173
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 243 2 194 0 73 0 7 0 1 0 0 145 0 3 173
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 231 2 190 0 70 0 8 0 1 0 0 145 0 3 155
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 231 2 190 0 70 0 8 0 1 0 0 145 0 3 155
17
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 10 65 2 219 0 68 0 7 0 1 0 0 145 0 3 66
17
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 10 65 2 219 0 68 0 7 0 1 0 0 145 0 3 18
17
66 77 0 28 0 13 0 18 0 20 0 13 0 18 0 20 10 86 2 218 0 79 0 11 0 2 0 0 145 0 3 58
18
66 77 0 28 0 13 0 18 0 20 0 13 0 18 0 20 10 86 2 218 0 79 0 11 0 2 0 0 145 0 3 58
18
66 77 0 28 0 13 0 18 0 19 0 13 0 18 0 19 10 86 2 216 0 76 0 8 0 1 0 0 145 0 3 47
18
66 77 0 28 0 13 0 18 0 19 0 13 0 18 0 19 10 86 2 216 0 76 0 8 0 1 0 0 145 0 3 47
18
66 77 0 28 0 14 0 18 0 20 0 14 0 18 0 20 10 212 2 250 0 75 0 8 0 1 0 0 145 0 3 210
18
66 77 0 28 0 14 0 18 0 20 0 14 0 18 0 20 10 212 2 250 0 75 0 8 0 1 0 0 145 0 3 210
18
66 77 0 28 0 12 0 17 0 20 0 12 0 17 0 20 10 137 2 234 0 86 0 10 0 1 0 0 145 0 3 126
17
66 77 0 28 0 12 0 17 0 20 0 12 0 17 0 20 10 137 2 234 0 86 0 10 0 1 0 0 145 0 3 126
17
66 77 0 28 0 12 0 17 0 20 0 12 0 17 0 20 10 137 2 234 0 86 0 10 0 1 0 0 145 0 3 66
17
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 164 2 240 0 95 0 10 0 1 0 0 145 0 3 178
19
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 164 2 240 0 95 0 10 0 1 0 0 145 0 3 178
19
66 77 0 28 0 13 0 19 0 21 0 13 0 19 0 21 10 110 2 223 0 95 0 10 0 1 0 0 145 0 3 105
19
66 77 0 28 0 13 0 19 0 21 0 13 0 19 0 21 10 110 2 223 0 95 0 10 0 1 0 0 145 0 3 105
19
66 77 0 28 0 13 0 19 0 21 0 13 0 19 0 21 10 128 2 227 0 101 0 10 0 1 0 0 145 0 3 133
19
66 77 0 28 0 13 0 19 0 21 0 13 0 19 0 21 10 128 2 227 0 101 0 10 0 1 0 0 145 0 3 133
19
66 77 0 28 0 14 0 20 0 24 0 14 0 20 0 24 10 158 2 254 0 106 0 13 0 4 0 0 145 0 3 211
20
66 77 0 28 0 13 0 19 0 23 0 13 0 19 0 23 10 158 2 254 0 106 0 13 0 4 0 0 145 0 3 205
19
66 77 0 28 0 13 0 19 0 23 0 13 0 19 0 23 10 212 3 10 0 107 0 12 0 4 0 0 145 0 3 66
19
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 14 0 20 0 24 0 14 0 20 0 24 10 212 3 10 0 107 0 12 0 4 0 0 145 0 3 22
20
66 77 0 28 0 14 0 20 0 24 0 14 0 20 0 24 10 236 3 11 0 109 0 13 0 4 0 0 145 0 3 50
20
66 77 0 28 0 14 0 20 0 24 0 14 0 20 0 24 10 236 3 11 0 109 0 13 0 4 0 0 145 0 3 50
20
66 77 0 28 0 15 0 20 0 23 0 15 0 20 0 23 10 254 3 29 0 105 0 9 0 3 0 0 145 0 3 77
20
66 77 0 28 0 15 0 20 0 23 0 15 0 20 0 23 10 254 3 29 0 105 0 9 0 3 0 0 145 0 3 77
20
66 77 0 28 0 14 0 19 0 22 0 14 0 19 0 22 11 22 3 40 0 99 0 9 0 3 0 0 145 0 2 101
19
66 77 0 28 0 14 0 19 0 22 0 14 0 19 0 22 11 22 3 40 0 99 0 9 0 3 0 0 145 0 2 101
19
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 149 3 6 0 93 0 8 0 3 0 0 145 0 2 184
19
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 149 3 6 0 93 0 8 0 3 0 0 145 0 2 66
19
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 14 0 18 0 20 0 14 0 18 0 20 10 140 3 2 0 77 0 5 0 3 0 0 145 0 2 148
18
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 10 140 3 2 0 77 0 5 0 3 0 0 145 0 2 142
17
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 10 104 2 251 0 77 0 5 0 3 0 0 145 0 3 98
17
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 10 104 2 251 0 77 0 5 0 3 0 0 145 0 3 98
17
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 10 104 2 251 0 77 0 5 0 3 0 0 145 0 3 98
17
66 77 0 28 0 13 0 18 0 20 0 13 0 18 0 20 10 116 3 11 0 77 0 8 0 3 0 0 145 0 2 134
18
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 116 3 11 0 77 0 8 0 3 0 0 145 0 2 140
19
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 137 3 18 0 76 0 7 0 3 0 0 145 0 2 166
19
[update] This is the newest version.
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 10 137 3 18 0 76 0 7 0 3 0 0 145 0 2 166
19
66 77 0 28 0 12 0 17 0 18 0 12 0 17 0 18 10 77 2 241 0 77 0 5 0 0 0 0 145 0 3 66
17
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 12 0 17 0 18 0 12 0 17 0 18 10 77 2 241 0 77 0 5 0 0 0 0 145 0 3 54
17
66 77 0 28 0 13 0 18 0 19 0 13 0 18 0 19 10 32 2 224 0 80 0 6 0 0 0 0 145 0 3 2
18
66 77 0 28 0 13 0 18 0 19 0 13 0 18 0 19 10 32 2 224 0 80 0 6 0 0 0 0 145 0 3 2
18
66 77 0 28 0 13 0 19 0 19 0 13 0 19 0 19 10 47 2 240 0 81 0 5 0 0 0 0 145 0 3 35
19
66 77 0 28 0 12 0 18 0 18 0 12 0 18 0 18 10 47 2 240 0 81 0 5 0 0 0 0 145 0 3 29
18
66 77 0 28 0 14 0 20 0 20 0 14 0 20 0 20 10 173 3 6 0 90 0 6 0 1 0 1 145 0 2 202
20
66 77 0 28 0 14 0 20 0 20 0 14 0 20 0 20 10 173 3 6 0 90 0 6 0 1 0 1 145 0 2 202
20
66 77 0 28 0 14 0 21 0 21 0 14 0 21 0 21 10 233 3 24 0 90 0 9 0 1 0 1 145 0 3 31
21
66 77 0 28 0 13 0 19 0 22 0 13 0 19 0 22 10 242 3 25 0 84 0 12 0 4 0 2 145 0 3 38
19
66 77 0 28 0 13 0 19 0 22 0 13 0 19 0 22 10 242 3 25 0 84 0 12 0 4 0 2 145 0 3 38
19
66 77 0 28 0 13 0 19 0 22 0 13 0 19 0 22 10 242 3 25 0 84 0 12 0 4 0 2 145 0 3 66
19
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 15 0 20 0 23 0 15 0 20 0 23 11 79 3 40 0 88 0 9 0 4 0 2 145 0 2 156
20
66 77 0 28 0 15 0 20 0 23 0 15 0 20 0 23 11 79 3 40 0 88 0 9 0 4 0 2 145 0 2 156
20
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 11 67 3 38 0 83 0 9 0 4 0 2 145 0 2 129
19
66 77 0 28 0 14 0 19 0 21 0 14 0 19 0 21 11 67 3 38 0 83 0 9 0 4 0 2 145 0 2 129
19
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 11 58 3 43 0 82 0 8 0 4 0 2 145 0 2 121
18
66 77 0 28 0 15 0 19 0 22 0 15 0 19 0 22 11 58 3 43 0 82 0 8 0 4 0 2 145 0 2 127
19
66 77 0 28 0 15 0 19 0 21 0 15 0 19 0 21 11 31 3 37 0 79 0 7 0 4 0 2 145 0 2 88
19
66 77 0 28 0 15 0 19 0 21 0 15 0 19 0 21 11 31 3 37 0 79 0 7 0 4 0 2 145 0 2 88
19
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 10 203 3 11 0 84 0 8 0 4 0 2 145 0 2 66
18
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 10 203 3 11 0 84 0 8 0 4 0 2 145 0 2 235
18
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 10 197 3 5 0 84 0 9 0 4 0 2 145 0 2 224
18
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 10 197 3 5 0 84 0 9 0 4 0 2 145 0 2 224
18
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 10 179 3 8 0 81 0 8 0 3 0 1 145 0 2 203
18
66 77 0 28 0 14 0 18 0 21 0 14 0 18 0 21 10 179 3 8 0 81 0 8 0 3 0 1 145 0 2 203
18
66 77 0 28 0 14 0 17 0 20 0 14 0 17 0 20 10 98 2 243 0 75 0 8 0 3 0 1 145 0 3 90
17
66 77 0 28 0 14 0 17 0 20 0 14 0 17 0 20 10 98 2 243 0 75 0 8 0 3 0 1 145 0 3 90
17
66 77 0 28 0 14 0 17 0 19 0 14 0 17 0 19 10 116 2 246 0 77 0 5 0 3 0 1 145 0 3 108
17
66 77 0 28 0 14 0 17 0 19 0 14 0 17 0 19 10 116 2 246 0 77 0 5 0 3 0 1 145 0 3 66
17
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 14 0 17 0 19 0 14 0 17 0 19 10 74 2 232 0 80 0 3 0 1 0 1 145 0 3 51
17
66 77 0 28 0 14 0 17 0 19 0 14 0 17 0 19 10 74 2 232 0 80 0 3 0 1 0 1 145 0 3 51
17
66 77 0 28 0 14 0 17 0 19 0 14 0 17 0 19 10 74 2 232 0 80 0 3 0 1 0 1 145 0 3 51
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 246 2 220 0 79 0 3 0 1 0 1 145 0 3 205
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 246 2 220 0 79 0 3 0 1 0 1 145 0 3 205
17
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 9 255 2 222 0 82 0 6 0 1 0 1 145 0 3 224
17
66 77 0 28 0 13 0 17 0 19 0 13 0 17 0 19 9 255 2 222 0 82 0 6 0 1 0 1 145 0 3 224
17
66 77 0 28 0 14 0 18 0 20 0 14 0 18 0 20 10 89 2 242 0 85 0 6 0 1 0 1 145 0 3 88
18
66 77 0 28 0 14 0 18 0 20 0 14 0 18 0 20 10 89 2 242 0 85 0 6 0 1 0 1 145 0 3 66
18
#[exception] PM2.5 Sensor CHECKSUM ERROR!
After some time I get more errors:
66 77 0 28 0 13 0 17 0 66 77 0 28 0 13 0 17 0 17 0 13 0 17 0 17 9 129 2 177 0 65 0
7168
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 17 0 17 0 66 77 0 28 0 13 0 17 0 17 0 13 0 17 0 17 9 129 2 177 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 17 0 17 0 66 77 0 28 0 12 0 16 0 16 0 12 0 16 0 16 9 186 2 186 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 12 0 16 0 16 0 12 0 16 0 16 9 186 2 186 0 67 0 6 0 0 0 0 145 0 3 92
16
66 77 0 28 0 12 0 16 0 16 0 12 0 16 0 16 9 174 2 193 0 62 0 5 0 0 0 0 145 0 3 81
16
66 77 0 28 0 13 0 17 0 17 0 13 0 17 0 17 9 174 2 193 0 62 0 5 0 0 0 0 145 0 3 87
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 180 2 197 0 62 0 6 0 1 0 1 145 0 3 102
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 180 2 197 0 62 0 6 0 1 0 1 145 0 3 102
17
66 77 0 28 0 13 0 17 0 18 0 13 0 17 0 18 9 165 2 190 0 62 0 6 0 1 0 1 145 0 3 80
17
66 77 0 28 0 13 0 17 0 66 77 0 28 0 13 0 16 0 18 0 13 0 16 0 18 9 135 2 182 0 65 0
7168
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 16 0 18 0 66 77 0 28 0 13 0 16 0 18 0 13 0 16 0 18 9 135 2 182 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 16 0 18 0 13 0 16 0 18 9 117 2 180 0 64 0 3 0 2 0 1 145 0 3 20
16
66 77 0 28 0 13 0 16 0 18 0 66 77 0 28 0 13 0 16 0 18 0 13 0 16 0 18 9 117 2 180 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 12 0 15 0 17 0 12 0 15 0 17 9 153 2 196 0 64 0 3 0 2 0 1 145 0 3 66
15
66 77 0 28 0 12 0 15 0 17 0 12 0 15 0 17 9 153 2 196 0 64 0 3 0 2 0 1 145 0 3 66
15
[update] This is the newest version.
66 77 0 28 0 12 0 16 0 19 0 12 0 16 0 19 9 162 2 206 0 71 0 6 0 5 0 2 145 0 3 105
16
66 77 0 28 0 13 0 17 0 20 0 13 0 17 0 20 9 162 2 206 0 71 0 6 0 5 0 2 145 0 3 111
17
66 77 0 28 0 13 0 16 0 19 0 13 0 16 0 19 9 123 2 189 0 74 0 6 0 5 0 2 145 0 3 54
16
66 77 0 28 0 13 0 16 0 66 77 0 28 0 12 0 16 0 20 0 12 0 16 0 20 9 54 2 166 0 76 0
7168
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 12 0 16 0 20 0 12 0 16 0 20 9 54 2 166 0 76 0 7 0 6 0 2 145 0 2 222
16
66 77 0 28 0 11 0 15 0 19 0 66 77 0 28 0 11 0 15 0 19 0 11 0 15 0 19 9 21 2 166 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 11 0 15 0 19 0 66 77 0 28 0 12 0 16 0 20 0 12 0 16 0 20 9 21 2 166 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 120 2 189 0 83 0 9 0 6 0 1 145 0 3 65
16
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 120 2 189 0 83 0 9 0 6 0 1 145 0 3 65
16
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 186 2 198 0 74 0 9 0 5 0 1 145 0 3 130
16
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 186 2 198 0 74 0 9 0 5 0 1 145 0 3 130
16
66 77 0 28 0 13 0 15 0 19 0 13 0 15 0 19 9 171 2 184 0 74 0 9 0 5 0 1 145 0 3 97
15
66 77 0 28 0 13 0 15 0 66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 198 2 190 0 77 0
7168
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 16 0 20 0 13 0 16 0 20 9 198 2 190 0 77 0 8 0 5 0 1 145 0 3 136
16
66 77 0 28 0 13 0 16 0 19 0 66 77 0 28 0 13 0 16 0 19 0 13 0 16 0 19 9 225 2 190 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
66 77 0 28 0 13 0 17 0 20 0 13 0 17 0 20 10 23 2 214 0 81 0 9 0 3 0 0 145 0 2 246
17
66 77 0 28 0 13 0 17 0 20 0 13 0 17 0 20 10 23 2 214 0 81 0 9 0 3 0 0 145 0 2 246
17
66 77 0 28 0 13 0 17 0 20 0 13 0 17 0 20 10 23 2 214 0 81 0 9 0 3 0 0 145 0 2 246
17
66 77 0 28 0 13 0 17 0 20 0 66 77 0 28 0 13 0 17 0 20 0 13 0 17 0 20 10 98 2 234 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
The lonely number in the new line after 32 bytes is the value of PM2.5 which shouldn't get high. However, it gets sometimes high and sometimes not when the checksum is incorrect.
I wonder why the situation changes over time... Maybe I could keep resetting the UART somehow?
For each of the packets that fail the checksum test, you find a CHAR_PRELIM (66) either in the middle or at the end. This means the sensor is occasionally dropping packets and causing misalignment.
One solution is to restart packet reading each time a 66 is read. This code should do it:
UPDATE: as per #sawdust's comment, the presence of both 66 and 77 should be used as a start condition because it may be possible for 66 to appear by itself in the data. The other consideration is to use the packet length provided by the 3rd and 4th bytes instead of assuming the length to be 32. Hopefully these improvements make the code more durable.
size_t length;
incomingByte[0] = 66; // the first two bytes are always known
incomingByte[1] = 77;
...
if (serial.available()) {
if (serial.read() == 66 && serial.read() == 77)
incomingByte[2] = serial.read(); // length high byte
incomingByte[3] = serial.read(); // length low byte
int length = (incomingByte[2] << 8) + incomingByte[3];
// starting at index 4, read `length` bytes
serial.readBytes(incomingByte + 4, length);
break;
}
}
// when the code breaks out of the while(1) loop, you still need to evaluate the checksum.
According to the protocol defined by this source, the packet length is fixed at 32 bytes, so the encoded frame length (bytes 3 and 4) should always equal 0 28 (32 bytes - 2 start bytes - 2 frame length bytes = 28).
However, this code should work even for variable length packets (thanks #sawdust).
Fair warning: I do not have one of these sensors, so obviously I didn't test this, but the concept remains.
I recognize that this code won't solve the issue of characters being dropped, since it just ignores incomplete packets and you still rely on the validity of the checksum.
Finally, I find it interesting that the reason that the checksum is failing is because the checksum bytes are not even being received in those cases!
Hope this helps!
UPDATE #2: This is more or less a revised answer in it of itself.
Using this code to read packets, the following criteria (which are defined by the protocol) are guaranteed:
The packets begins with [66 77]
The packet contains 32 bytes
The start condition [66 77] will never occur in the body of the packet.
Here's the code. I manage to reduce it down to a few if statements
void PMS5003::processDataOn(HardwareSerial &serial) {
bool possibleStart = false;
incomeByte[0] = 66;
incomeByte[1] = 77;
uint8_t count = 0;
...
while (1) {
...
if (serial.available()) {
uint8_t c = serial.read();
if (possibleStart) {
possibleStart = false;
if (c == 77) count = 2;
}
if (c == 66) possibleStart = true;
if (count >= 2) incomeByte[count++] = c;
if (count == NUM_DATA_BYTE) break;
}
}
// at this point, incomeByte must:\
// > begin with [66 77]
// > contain 32 bytes
// > not contain [66 77] anywhere after the first two bytes
// > therefore, it is guaranteed to contain a checksum
// now is the right time to evaluate the checksum.
// I expect all of the checksums to match, but you might as well check
}
At the time of posting, the OP has already coded a solution which fulfills the requirements. I am posting this because I believe this code improves upon the OP's by being more concise, more readable/declarative, and hopefully more easily manageable.
This code can also serve as a general solution for any case in which two characters define a start condition, provided the packet length is known or can be determined.
While the question why the data comes corrupted still remains, here is a workaround I managed to achieve:
I'm checking the checksum, if it's incorrect, then:
I'm looking for 66 77 in the whole data. When I find it:
I'm checking if in the next 16 bytes there's another 66 77. If it's not found:
I'm presuming the values that are distanced by 10-15 bytes from 66 77 are the ones I'm looking for (PM1, PM2.5, PM10).
Here's the code:
void PMS5003::processDataOn(HardwareSerial &serial) {
unsigned long timeout = millis();
int count = 0;
byte incomeByte[NUM_INCOME_BYTE];
boolean startcount = false;
byte data;
int timeoutHops = 0;
while (1){
if (((millis() - timeout) > 1000) && (timeoutHops == 0)) {
timeoutHops = 1;
yield();
ESP.wdtFeed();
}
if (((millis() - timeout) > 2000) && (timeoutHops == 1)) {
timeoutHops = 2;
yield();
ESP.wdtFeed();
}
if ((millis() - timeout) > 3000) {
yield();
ESP.wdtFeed();
Serial.println("SENSOR-ERROR-TIMEOUT");
break;
}
if (serial.available()) {
data = serial.read();
if (data == CHAR_PRELIM && !startcount) {
startcount = true;
count++;
incomeByte[0] = data;
} else if (startcount) {
count++;
incomeByte[count - 1] = data;
if (count >= NUM_INCOME_BYTE){
break;
}
}
}
}
unsigned int calcsum = 0;
unsigned int exptsum;
for (int a = 0; a < NUM_INCOME_BYTE; a++) {
Serial.print((unsigned int)incomeByte[a]);
Serial.print(" ");
}
Serial.println();
Serial.println(((unsigned int)incomeByte[PM25_BYTE] << 8) + (unsigned int)incomeByte[PM25_BYTE + 1]);
for (int i = 0; i < NUM_DATA_BYTE; i++) {
calcsum += (unsigned int)incomeByte[i];
}
exptsum = ((unsigned int)incomeByte[CHECK_BYTE] << 8) + (unsigned int)incomeByte[CHECK_BYTE + 1];
if (calcsum == exptsum) {
pm1 = ((unsigned int)incomeByte[PM1_BYTE] << 8) + (unsigned int)incomeByte[PM1_BYTE + 1];
pm25 = ((unsigned int)incomeByte[PM25_BYTE] << 8) + (unsigned int)incomeByte[PM25_BYTE + 1];
pm10 = ((unsigned int)incomeByte[PM10_BYTE] << 8) + (unsigned int)incomeByte[PM10_BYTE + 1];
} else {
Serial.println("#[exception] PM2.5 Sensor CHECKSUM ERROR!");
pm1 = -1;
pm25 = -1;
pm10 = -1;
for (int a = 0; a < NUM_INCOME_BYTE; a++) {
bool valid = true;
if (((unsigned int)incomeByte[a] == 66) && ((unsigned int)incomeByte[a+1] == 77)) {
if (a+16 < NUM_INCOME_BYTE) {
for (int b = a+1; b < a+15; b++) {
if (((unsigned int)incomeByte[b] == 66) && ((unsigned int)incomeByte[b+1] == 77)) {
valid = false;
break;
}
}
if (valid) {
pm1 = ((unsigned int)incomeByte[a+10] << 8) + (unsigned int)incomeByte[a+11];
pm25 = ((unsigned int)incomeByte[a+12] << 8) + (unsigned int)incomeByte[a+13];
pm10 = ((unsigned int)incomeByte[a+14] << 8) + (unsigned int)incomeByte[a+15];
Serial.println("valid: ");
Serial.print(pm1);
Serial.print(" ");
Serial.print(pm25);
Serial.print(" ");
Serial.print(pm10);
Serial.println();
break;
}
}
}
}
}
return;
}
Theoretically, it may produce false positives or negatives but in practice, it just works.
66 77 0 28 0 12 0 15 0 17 0 12 0 15 0 17 9 102 2 176 66 77 0 28 0 12 0 15 0 16 0 12
15
#[exception] PM2.5 Sensor CHECKSUM ERROR!
valid:
12 15 17
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 114 2 175 0 73 0 4 0 1 0 0 145 0 3 12
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 114 2 175 0 73 0 4 0 1 0 0 145 0 3 12
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 141 2 190 0 72 0 3 0 1 0 0 145 0 3 52
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 141 2 190 0 72 0 3 0 1 0 0 145 0 3 52
15
66 77 0 28 0 12 0 16 0 16 0 12 0 16 0 16 9 198 2 202 0 75 0 3 0 0 0 0 145 0 3 125
16
66 77 0 28 0 12 0 16 0 16 0 66 77 0 28 0 12 0 16 0 16 0 12 0 16 0 16 9 198 2 202 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
valid:
12 16 16
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 174 2 199 0 71 0 3 0 0 0 0 145 0 3 92
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 174 2 199 0 71 0 3 0 0 0 0 145 0 3 92
15
66 77 0 28 0 12 0 15 0 16 0 12 0 15 0 16 9 174 2 199 66 77 0 28 0 13 0 16 0 16 0 13
15
#[exception] PM2.5 Sensor CHECKSUM ERROR!
valid:
12 15 16
66 77 0 28 0 13 0 16 0 16 0 13 0 16 0 16 9 213 2 205 0 72 0 3 0 0 0 0 145 0 3 142
16
66 77 0 28 0 13 0 16 0 16 0 13 0 16 0 16 9 213 2 205 0 72 0 3 0 0 0 0 145 0 3 142
16
66 77 0 28 0 13 0 16 0 17 0 13 0 16 0 17 9 207 2 208 0 83 0 6 0 1 0 0 145 0 3 156
16
66 77 0 28 0 13 0 16 0 17 0 13 0 16 0 17 9 207 2 208 0 83 0 6 0 1 0 0 145 0 3 156
16
66 77 0 28 0 13 0 17 0 17 0 13 0 17 0 17 9 159 2 202 0 87 0 5 0 1 0 0 145 0 3 107
17
66 77 0 28 0 13 0 17 0 17 0 66 77 0 28 0 13 0 17 0 17 0 13 0 17 0 17 9 159 2 202 0
19712
#[exception] PM2.5 Sensor CHECKSUM ERROR!
valid:
13 17 17
I am trying to replace values in a dataframe by 0. the first column I need to replace the 1st 3 values, the next column the 1st 6 values so on so forth increasing by 3 every time
a=np.array([133,124,156,189,132,176,189,192,100,120,130,140,150,50,70,133,124,156,189,132])
b = pd.DataFrame(a.reshape(10,2), columns= ['s','t'])
for columns in b:
yy = 3
for i in xrange(yy):
b[columns][i] = 0
yy += 3
print b
the outcome is the following
s t
0 0 0
1 0 0
2 0 0
3 189 189
4 132 132
5 176 176
6 189 189
7 192 192
8 100 100
9 120 120
I am clearly missing something really simple, to make the loop replace 6 values instead of only 3 in column t, any ideas?
i would do it this way:
i = 1
for c in b.columns:
b.ix[0 : 3*i-1, c] = 0
i += 1
Demo:
In [86]: b = pd.DataFrame(np.random.randint(0, 100, size=(20, 4)), columns=list('abcd'))
In [87]: %paste
i = 1
for c in b.columns:
b.ix[0 : 3*i-1, c] = 0
i += 1
## -- End pasted text --
In [88]: b
Out[88]:
a b c d
0 0 0 0 0
1 0 0 0 0
2 0 0 0 0
3 10 0 0 0
4 8 0 0 0
5 49 0 0 0
6 55 48 0 0
7 99 43 0 0
8 63 29 0 0
9 61 65 74 0
10 15 29 41 0
11 79 88 3 0
12 91 74 11 4
13 56 71 6 79
14 15 65 46 81
15 81 42 60 24
16 71 57 95 18
17 53 4 80 15
18 42 55 84 11
19 26 80 67 59
You need inicialize yy=3 before loop:
yy = 3
for columns in b:
for i in xrange(yy):
b[columns][i] = 0
yy += 3
print b
Python 3 solution:
yy = 3
for columns in b:
for i in range(yy):
b[columns][i] = 0
yy += 3
print (b)
s t
0 0 0
1 0 0
2 0 0
3 189 0
4 100 0
5 130 0
6 150 50
7 70 133
8 124 156
9 189 132
Another solution:
yy= 3
for i, col in enumerate(b.columns):
b.ix[:i*yy+yy-1, col] = 0
print (b)
s t
0 0 0
1 0 0
2 0 0
3 189 0
4 100 0
5 130 0
6 150 50
7 70 133
8 124 156
9 189 132
I'm new to R. This is my data (using dplyr):
> withCommas
Source: local data frame [326 x 1]
NA
1 16,244,600
2 8,227,103
3 5,959,718
4 3,428,131
5 2,612,878
6 2,471,784
7 2,252,664
8 2,014,775
9 2,014,670
10 1,841,710
.. ...
Classes ‘tbl_df’ and 'data.frame': 326 obs. of 1 variable:
$ : Factor w/ 207 levels ""," 1,008 "," 1,129 ",..: 40 178 143 100 66 63 61 58 57 16 ...
I'm trying to get rid of the commas (so the first row should be 16244600). So I tried the following:
#1st try
noCommas <- gsub("([0-9]+)\\,([0-9])", "\\1\\2", withCommas)
#2nd try
noCommas <- gsub(",", "", withCommas)
In all cases, I got this output:
[1] "c(40 178 143 100 66 63 61 58 57 16 14 11 9 6 4 182 176 174 170 161 148 147 139 137 136 134 118 117 116 114 113 109 107 105 95 93 92 90 89 88 87 84 83 78 75 74 73 72 71 70 56 55 49 47 43 42 39 28 25 24 23 190 188 181 172 165 163 162 160 153 152 151 150 149 146 145 144 138 132 131 130 129 128 127 126 125 124 115 112 111 110 106 98 97 96 94 86 85 82 81 80 77 76 69 68 54 52 51 50 46 45 44 41 \n38 37 36 35 34 33 32 31 30 29 27 26 22 21 20 19 18 17 187 186 185 184 183 179 177 169 168 167 166 159 158 157 156 155 142 141 140 122 121 120 119 104 103 102 101 99 67 65 64 62 60 59 15 13 12 10 8 7 5 3 2 189 180 175 173 173 171 164 154 135 133 108 91 79 53 48 123 1 191 191 191 191 191 1 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 191 1 206 1 205 200 202 198 201 196 \n195 204 194 199 193 203 197 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)"
This seems very strange to me as I don't understand where the numbers are coming from. Any help appreciated.
Edit:
Only the first 225 rows of the variable withCommas have values. After that, the values of the column are empty.
Source: http://data.worldbank.org/data-catalog/GDP-ranking-table
CSV: https://d396qusza40orc.cloudfront.net/getdata%2Fdata%2FGDP.csv
What about this solution? I think that main problems arise because a data frame is a list and gsub is expecting a character string and so passing it to that function cause to apply the function to the lists and not the elements that are part of the lists themselves. That's the reason for an apply function. Or of course, if the columns is one, passing just that column as a vector with ddf$column_with_commas as the solution provided by other users.
as.data.frame(apply(ddf, 2, function(x) as.numeric(gsub(",", "", x))))
NA.
1 16244600
2 8227103
3 5959718
4 3428131
5 2612878
6 2471784
7 2252664
8 2014775
9 2014670
10 1841710
Data
ddf <- structure(list(NA. = structure(c(2L, 10L, 9L, 8L, 7L, 6L, 5L,
4L, 3L, 1L), .Label = c("1,841,710", "16,244,600", "2,014,670",
"2,014,775", "2,252,664", "2,471,784", "2,612,878", "3,428,131",
"5,959,718", "8,227,103"), class = "factor")), .Names = "NA.", class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10"))
data <- read.table(header=F, text="1 16,244,600
2 8,227,103
3 5,959,718
4 3,428,131
5 2,612,878
6 2,471,784
7 2,252,664
8 2,014,775
9 2,014,670
10 1,841,710 ")
colnames(data) <- c("a","b")
data$b <- as.numeric(gsub(",", "", data$b))
Output:
a b
1 1 16244600
2 2 8227103
3 3 5959718
4 4 3428131
5 5 2612878
6 6 2471784
7 7 2252664
8 8 2014775
9 9 2014670
10 10 1841710
Three threads are created that instantiate the same class.
Each thread has a different delay.
But after some time only 1 thread executes. ???
GenNum1 = new CGenerateNumbers();
GenNum1->m_threadNumber = 1;
GenNum1->m_usec = 10000;
connect(GenNum1, SIGNAL(OnIndexReady()), this, SLOT(hGenNumOnIndexReady1()));
QThread *tGenNum1 = new QThread;
GenNum1->moveToThread(tGenNum1);
GenNum1->connect(tGenNum1, SIGNAL(started()), GenNum1, SLOT(Started()), Qt::DirectConnection);
tGenNum1->start();
GenNum2 = new CGenerateNumbers();
GenNum2->m_threadNumber = 2;
GenNum2->m_usec = 15000;
connect(GenNum2, SIGNAL(OnIndexReady()), this, SLOT(hGenNumOnIndexReady2()));
QThread *tGenNum2 = new QThread;
GenNum2->moveToThread(tGenNum2);
GenNum2->connect(tGenNum2, SIGNAL(started()), GenNum2, SLOT(Started()), Qt::DirectConnection);
tGenNum2->start();
GenNum3 = new CGenerateNumbers();
GenNum3->m_threadNumber = 3;
GenNum3->m_usec = 20000;
connect(GenNum3, SIGNAL(OnIndexReady()), this, SLOT(hGenNumOnIndexReady3()));
QThread *tGenNum3 = new QThread;
GenNum3->moveToThread(tGenNum3);
GenNum3->connect(tGenNum3, SIGNAL(started()), GenNum3, SLOT(Started()), Qt::DirectConnection);
tGenNum3->start();
//this is what each thread calls to:
void CGenerateNumbers::Started()
{
int i = 0;
int c = 0;
char v;
while(1){
usleep(m_usec);
v = (i % 26) + 65;
for(int j = 0; j < 11; j++){
mem->m_cmMessageWrite.cMessage[j] = v;
}
mem->m_cmMessageWrite.cMessage[0] = m_threadNumber + 48;
mem->m_cmMessageWrite.cMessage[1] = 32;
mem->Write();
m_i = i;
emit OnIndexReady();
i++;
}
}
index index thread message
0 0 1 AAAAAAAAA
1 1 2 AAAAAAAAA
2 2 3 AAAAAAAAA
3 3 1 BBBBBBBBB
4 4 1 CCCCCCCCC
5 5 2 BBBBBBBBB
6 6 3 BBBBBBBBB
7 7 1 DDDDDDDDD
8 8 2 CCCCCCCCC
9 9 1 EEEEEEEEE
10 10 3 CCCCCCCCC
11 11 1 FFFFFFFFF
12 12 2 DDDDDDDDD
13 13 1 GGGGGGGGG
14 14 2 EEEEEEEEE
15 15 3 DDDDDDDDD
16 16 1 HHHHHHHHH
17 17 1 IIIIIIIII
18 18 2 FFFFFFFFF
19 19 3 EEEEEEEEE
20 20 1 JJJJJJJJJ
21 21 2 GGGGGGGGG
22 22 1 KKKKKKKKK
23 23 3 FFFFFFFFF
24 24 2 HHHHHHHHH
25 25 1 LLLLLLLLL
26 26 2 IIIIIIIII
27 27 3 GGGGGGGGG
28 28 1 MMMMMMMMM
29 29 1 NNNNNNNNN
30 30 2 JJJJJJJJJ
31 31 3 HHHHHHHHH
32 32 1 OOOOOOOOO
33 33 2 KKKKKKKKK
34 34 1 PPPPPPPPP
35 35 3 IIIIIIIII
36 36 1 QQQQQQQQQ
37 37 2 LLLLLLLLL
38 38 1 RRRRRRRRR
39 39 2 MMMMMMMMM
40 40 1 SSSSSSSSS
41 41 2 NNNNNNNNN
42 42 1 TTTTTTTTT
43 43 1 UUUUUUUUU
44 44 1 VVVVVVVVV
45 45 1 WWWWWWWWW
46 46 2 OOOOOOOOO
47 47 1 XXXXXXXXX
48 48 2 PPPPPPPPP
49 49 1 YYYYYYYYY
50 50 2 QQQQQQQQQ
51 51 1 ZZZZZZZZZ
52 52 1 AAAAAAAAA
53 53 2 RRRRRRRRR
54 54 1 BBBBBBBBB
55 55 2 SSSSSSSSS
56 56 1 CCCCCCCCC
57 57 1 DDDDDDDDD
58 58 2 TTTTTTTTT
59 59 1 EEEEEEEEE
60 60 2 UUUUUUUUU
61 61 1 FFFFFFFFF
62 62 1 GGGGGGGGG
63 63 2 VVVVVVVVV
64 64 1 HHHHHHHHH
65 65 2 WWWWWWWWW
66 66 1 IIIIIIIII
67 67 1 JJJJJJJJJ
68 68 2 XXXXXXXXX
69 69 1 KKKKKKKKK
70 70 2 YYYYYYYYY
71 71 1 LLLLLLLLL
72 72 1 MMMMMMMMM
73 73 2 ZZZZZZZZZ
74 74 1 NNNNNNNNN
75 75 2 AAAAAAAAA
76 76 1 OOOOOOOOO
77 77 1 PPPPPPPPP
78 78 2 BBBBBBBBB
79 79 1 QQQQQQQQQ
80 80 2 CCCCCCCCC
81 81 1 RRRRRRRRR
82 82 1 SSSSSSSSS
83 83 2 DDDDDDDDD
84 84 1 TTTTTTTTT
85 85 2 EEEEEEEEE
86 86 1 UUUUUUUUU
87 87 1 VVVVVVVVV
88 88 2 FFFFFFFFF
89 89 1 WWWWWWWWW
90 90 2 GGGGGGGGG
91 91 1 XXXXXXXXX
92 92 1 YYYYYYYYY
93 93 2 HHHHHHHHH
94 94 1 ZZZZZZZZZ
95 95 2 IIIIIIIII
96 96 1 AAAAAAAAA
97 97 1 BBBBBBBBB
98 98 2 JJJJJJJJJ
99 99 1 CCCCCCCCC
100 100 2 KKKKKKKKK
101 101 1 DDDDDDDDD
102 102 2 LLLLLLLLL
103 103 1 EEEEEEEEE
104 104 2 MMMMMMMMM
105 105 1 FFFFFFFFF
106 106 1 GGGGGGGGG
107 107 2 NNNNNNNNN
108 108 1 HHHHHHHHH
109 109 2 OOOOOOOOO
110 110 1 IIIIIIIII
111 111 1 JJJJJJJJJ
112 112 2 PPPPPPPPP
113 113 1 KKKKKKKKK
114 114 2 QQQQQQQQQ
115 115 1 LLLLLLLLL
116 116 1 MMMMMMMMM
117 117 2 RRRRRRRRR
118 118 1 NNNNNNNNN
119 119 2 SSSSSSSSS
120 120 1 OOOOOOOOO
121 121 1 PPPPPPPPP
122 122 2 TTTTTTTTT
123 123 1 QQQQQQQQQ
124 124 2 UUUUUUUUU
125 125 1 RRRRRRRRR
126 126 2 VVVVVVVVV
127 127 1 SSSSSSSSS
128 128 1 TTTTTTTTT
129 129 2 WWWWWWWWW
130 130 1 UUUUUUUUU
131 131 2 XXXXXXXXX
132 132 1 VVVVVVVVV
133 133 2 YYYYYYYYY
134 134 1 WWWWWWWWW
135 135 1 XXXXXXXXX
136 136 2 ZZZZZZZZZ
137 137 1 YYYYYYYYY
138 138 2 AAAAAAAAA
139 139 1 ZZZZZZZZZ
140 140 1 AAAAAAAAA
141 141 2 BBBBBBBBB
142 142 1 BBBBBBBBB
143 143 2 CCCCCCCCC
144 144 1 CCCCCCCCC
145 145 1 DDDDDDDDD
146 146 2 DDDDDDDDD
147 147 1 EEEEEEEEE
148 148 2 EEEEEEEEE
149 149 1 FFFFFFFFF
150 150 1 GGGGGGGGG
151 151 2 FFFFFFFFF
152 152 1 HHHHHHHHH
153 153 2 GGGGGGGGG
154 154 1 IIIIIIIII
155 155 2 HHHHHHHHH
156 156 1 JJJJJJJJJ
157 157 1 KKKKKKKKK
158 158 2 IIIIIIIII
159 159 1 LLLLLLLLL
160 160 2 JJJJJJJJJ
161 161 1 MMMMMMMMM
162 162 1 NNNNNNNNN
163 163 2 KKKKKKKKK
164 164 1 OOOOOOOOO
165 165 2 LLLLLLLLL
166 166 1 PPPPPPPPP
167 167 1 QQQQQQQQQ
168 168 2 MMMMMMMMM
169 169 1 RRRRRRRRR
170 170 2 NNNNNNNNN
171 171 1 SSSSSSSSS
172 172 1 TTTTTTTTT
173 173 2 OOOOOOOOO
174 174 1 UUUUUUUUU
175 175 2 PPPPPPPPP
176 176 1 VVVVVVVVV
177 177 2 QQQQQQQQQ
178 178 1 WWWWWWWWW
179 179 1 XXXXXXXXX
180 180 2 RRRRRRRRR
181 181 1 YYYYYYYYY
182 182 2 SSSSSSSSS
183 183 1 ZZZZZZZZZ
184 184 1 AAAAAAAAA
185 185 2 TTTTTTTTT
186 186 1 BBBBBBBBB
187 187 2 UUUUUUUUU
188 188 1 CCCCCCCCC
189 189 1 DDDDDDDDD
190 190 2 VVVVVVVVV
191 191 2 WWWWWWWWW
192 192 1 EEEEEEEEE
193 193 1 FFFFFFFFF
194 194 2 XXXXXXXXX
195 195 1 GGGGGGGGG
196 196 2 YYYYYYYYY
197 197 1 HHHHHHHHH
198 198 2 ZZZZZZZZZ
199 199 1 IIIIIIIII
200 200 1 JJJJJJJJJ
201 201 2 AAAAAAAAA
202 202 1 KKKKKKKKK
203 203 2 BBBBBBBBB
204 204 1 LLLLLLLLL
205 205 1 MMMMMMMMM
206 206 2 CCCCCCCCC
207 207 1 NNNNNNNNN
208 208 2 DDDDDDDDD
209 209 1 OOOOOOOOO
210 210 2 EEEEEEEEE
211 211 2 FFFFFFFFF
212 212 1 PPPPPPPPP
213 213 1 QQQQQQQQQ
214 214 1 RRRRRRRRR
215 215 1 SSSSSSSSS
216 216 1 TTTTTTTTT
217 217 1 UUUUUUUUU
218 218 1 VVVVVVVVV
219 219 1 WWWWWWWWW
220 220 1 XXXXXXXXX
221 221 1 YYYYYYYYY
222 222 1 ZZZZZZZZZ
223 223 1 AAAAAAAAA
224 224 1 BBBBBBBBB
225 225 1 CCCCCCCCC
226 226 1 DDDDDDDDD
227 227 1 EEEEEEEEE
228 228 1 FFFFFFFFF
229 229 1 GGGGGGGGG
230 230 1 HHHHHHHHH
231 231 1 IIIIIIIII
232 232 1 JJJJJJJJJ
233 233 1 KKKKKKKKK
234 234 1 LLLLLLLLL
235 235 1 MMMMMMMMM
236 236 1 NNNNNNNNN
237 237 1 OOOOOOOOO
238 238 1 PPPPPPPPP
239 239 1 QQQQQQQQQ
240 240 1 RRRRRRRRR
241 241 1 SSSSSSSSS
242 242 1 TTTTTTTTT
243 243 1 UUUUUUUUU
There are two issues:
You do not want to tell connect to use a direct connection, just leave that off, the default will be properly chosen for you. In this case, the two QObjects that you connect between live in different threads. The QThread object lives in the current thread - it's not a thread, it's a controller. The CGenerateNumbers instance lives in the new thread. So you do not want a direct connection, it must be a queued connection!
In my applications I'm using a custom build of Qt and I've done a global search-replace of QThread with QThreadController. The latter is a more descriptive and less misleading name. There is no Qt class that is really equivalent to a thread per se.
The mem->Write(); call may be blocking. It would not cause a thread to "die", but merely to block. If it's a deadlock, as I presume it might well be, the thread is stopped forever (deadlocked). It's not dead, only appears to be.
The code below demonstrates a SSCCE that works fine on both Qt 5 and Qt 4. You'd need to reduce your code to a similarly simple example, my bet is that your problem is with code that is NOT shown. Perhaps in the process of reduction you'll figure it out.
# threads-18369174.pro
QT += core
QT -= gui
TARGET = threads-18369174
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
.
// main.cpp
#include <QCoreApplication>
#include <QObjectList>
#include <QList>
#include <QThread>
#include <iostream>
const int cycleCount = 500; //!< number of cycles to run at, set to 0 to run forever
const int threadCount = 5; //!< number of threads to create
class Object : public QObject
{
Q_OBJECT
int m_threadNumber;
int m_delayUs;
volatile bool m_active;
public:
explicit Object(int delayUs, int no) : m_threadNumber(no), m_delayUs(delayUs) {}
Q_SIGNAL void indexReady(int);
Q_SLOT void stop() { m_active = false; }
Q_SLOT void start()
{
m_active = true;
while (m_active) {
usleep(m_delayUs);
emit indexReady(m_threadNumber);
}
}
};
class Consumer : public QObject
{
Q_OBJECT
QList<Object*> m_objects;
QList<QThread*> m_threads;
int m_threadCount; //!< number of active threads in m_threads
int m_count;
public:
Consumer() : m_count(0) {}
void addObject(Object * o) { m_objects << o; }
void addThread(QThread * t) {
m_threads << t;
m_threadCount ++;
connect(t, SIGNAL(finished()), SLOT(done()));
connect(t, SIGNAL(terminated()), SLOT(done()));
}
Q_SLOT void ready(int n) {
std::cout << "<" << m_count++ << ":" << n << ">" << std::endl;
if (m_count == cycleCount) {
foreach (Object * o, m_objects) o->stop();
foreach (QThread * t, m_threads) t->wait();
}
}
Q_SLOT void done() {
QThread * t = qobject_cast<QThread*>(sender());
int i = m_threads.indexOf(t);
if (t) t->deleteLater();
if (i>=0) {
std::cout << "\nThread " << i << " is done." << std::endl;
m_threadCount --;
}
if (! m_threadCount) qApp->quit();
}
};
int main(int argc, char *argv[])
{
Consumer c;
QObjectList l;
QCoreApplication a(argc, argv);
std::cout << "Running under Qt version " << qVersion() << std::endl;
for (int i = 0; i < threadCount; ++i) {
Object * o = new Object(10000 + 5000*i, i+1);
QThread * t = new QThread;
c.addObject(o);
c.addThread(t);
o->moveToThread(t);
o->connect(t, SIGNAL(started()), SLOT(start()));
c.connect(o, SIGNAL(indexReady(int)), SLOT(ready(int)));
t->start();
t->exit();
l << o;
}
return a.exec();
}
#include "main.moc"
For a given time period, thread 1 produces the most messages as it has the smallest sleep.
If your message receiver reads messages at a slower rate than the sending rate, then above output is expected as there were most messages from thread 1 and least messages from thread 3 in the message queue.
I am trying to put together a little script which would track back the history of an object, by analyzing the R history. I am stuck at efficiently parsing R commands and splitting them. Consider the following R command:
for( i in 1:10 ) { a[i] <- myfunc() ; print( sprintf( "done step %d; proceeding", i ) ) }
Splitting at semicolons or curly brackets is not a problem, but what about the semicolons (or other special things) which are in quotes? I end up going char by char and keeping track of whether I am in a quote of not (and also of the backslashes...). This is footwork, and I'm sure there is something simpler, probably invented around the time Unix was born. A clever regex, maybe?
Use parse. It returns an expression which can be subsetted into the various components of the parse tree:
x <- parse(text='for( i in 1:10 ) { a[i] <- myfunc() ; print( sprintf( "done step %d; proceeding", i ) ) }',n=1)
x[[1]]
for (i in 1:10) {
a[i] <- myfunc()
print(sprintf("done step %d; proceeding", i))
}
x[[1]][[1]]
`for`
x[[1]][[4]]
{
a[i] <- myfunc()
print(sprintf("done step %d; proceeding", i))
}
x[[1]][[4]][[2]]
a[i] <- myfunc()
It depends on how much details you need, but beside the base parse function you might also check out the awesome parser package that is really fast to do its job and also returns much more details compared to parse. Quick demo:
> library(parser)
> parser(text='for( i in 1:10 ) { a[i] <- myfunc() ; print( sprintf( "done step %d; proceeding", i ) ) }')
expression(for (i in 1:10) {
a[i] <- myfunc()
print(sprintf("done step %d; proceeding", i))
})
attr(,"data")
line1 col1 byte1 line2 col2 byte2 token id parent top_level token.desc terminal text
1 1 0 0 1 3 3 270 1 77 0 FOR TRUE for
2 1 3 3 1 4 4 40 2 77 0 '(' TRUE (
3 1 5 5 1 6 6 263 4 77 0 SYMBOL TRUE i
4 1 7 7 1 9 9 271 6 77 0 IN TRUE in
5 1 10 10 1 11 11 261 8 9 0 NUM_CONST TRUE 1
6 1 10 10 1 11 11 78 9 15 0 expr FALSE
7 1 11 11 1 12 12 58 10 15 0 ':' TRUE :
8 1 12 12 1 14 14 261 11 12 0 NUM_CONST TRUE 10
9 1 12 12 1 14 14 78 12 15 0 expr FALSE
10 1 15 15 1 16 16 41 14 77 0 ')' TRUE )
11 1 10 10 1 14 14 78 15 77 0 expr FALSE
12 1 17 17 1 18 18 123 18 74 0 '{' TRUE {
13 1 19 19 1 20 20 263 20 22 0 SYMBOL TRUE a
14 1 20 20 1 21 21 91 21 28 0 '[' TRUE [
15 1 19 19 1 20 20 78 22 28 0 expr FALSE
16 1 21 21 1 22 22 263 23 25 0 SYMBOL TRUE i
17 1 22 22 1 23 23 93 24 28 0 ']' TRUE ]
18 1 21 21 1 22 22 78 25 28 0 expr FALSE
19 1 19 19 1 23 23 78 28 40 0 expr FALSE
20 1 24 24 1 26 26 265 30 40 0 LEFT_ASSIGN TRUE <-
21 1 27 27 1 33 33 297 32 34 0 SYMBOL_FUNCTION_CALL TRUE myfunc
22 1 33 33 1 34 34 40 33 37 0 '(' TRUE (
23 1 27 27 1 33 33 78 34 37 0 expr FALSE
24 1 34 34 1 35 35 41 35 37 0 ')' TRUE )
25 1 27 27 1 35 35 78 37 40 0 expr FALSE
26 1 36 36 1 37 37 59 39 74 0 ';' TRUE ;
27 1 19 19 1 35 35 78 40 74 0 expr FALSE
28 1 38 38 1 43 43 297 44 46 0 SYMBOL_FUNCTION_CALL TRUE print
29 1 43 43 1 44 44 40 45 69 0 '(' TRUE (
30 1 38 38 1 43 43 78 46 69 0 expr FALSE
31 1 45 45 1 52 52 297 48 50 0 SYMBOL_FUNCTION_CALL TRUE sprintf
32 1 52 52 1 53 53 40 49 64 0 '(' TRUE (
33 1 45 45 1 52 52 78 50 64 0 expr FALSE
34 1 54 54 1 80 80 260 52 54 0 STR_CONST TRUE "done step %d; proceeding"
35 1 80 80 1 81 81 44 53 64 0 ',' TRUE ,
36 1 54 54 1 80 80 78 54 64 0 expr FALSE
37 1 82 82 1 83 83 263 58 61 0 SYMBOL TRUE i
38 1 84 84 1 85 85 41 60 64 0 ')' TRUE )
39 1 82 82 1 83 83 78 61 64 0 expr FALSE
40 1 45 45 1 85 85 78 64 69 0 expr FALSE
41 1 86 86 1 87 87 41 66 69 0 ')' TRUE )
42 1 38 38 1 87 87 78 69 74 0 expr FALSE
43 1 89 89 1 90 90 125 71 74 0 '}' TRUE }
44 1 17 17 1 90 90 78 74 77 0 expr FALSE
45 1 0 0 1 90 90 78 77 0 0 expr FALSE