Newer
Older
#include <SPI.h>
#include <LoRa.h>
#include <SoftwareSerial.h>
// Lora Config Pins
#define ss 16 // Physical Pin 16 = D0 (Default is Physical Pin 5)
#define rst 0
#define dio0 15 // Physical Pin 15 = D8 (Default is Physical Pin 4)
static const int RXPin = 4, TXPin = 3;
static const int pollingFrequency = 2500; // ms
// Temp / Humidity Sensor
SHTSensor sht;
// Particle Sensor Serial
SoftwareSerial pmsSerial(2, 3);
// LoRa Message Tracking
byte localAddress = 0xBB;
byte destination = 0xFF;
byte msgCount = 0;
// Sensor Values - Temp / Humidity
double temperature;
double humidity;
double avgTemperature = 0;
double avgHumidity = 0;
// Sensor Values - Co2
byte co2;
double avgCo2 = 0;
// Sensor Values - Particles
uint32_t ppm10;
uint32_t ppm25;
uint32_t ppm100;
uint32_t avgPpm10 = 0;
uint32_t avgPpm25 = 0;
uint32_t avgPpm100 = 0;
// Partial Sensor Data
struct pms5003data {
uint16_t framelen;
uint16_t pm10_standard, pm25_standard, pm100_standard;
uint16_t pm10_env, pm25_env, pm100_env;
uint16_t particles_03um, particles_05um, particles_10um, particles_25um, particles_50um, particles_100um;
uint16_t unused;
uint16_t checksum;
};
struct pms5003data data;
int eventCount = 0; //counts the loop, which iterates every second
int secsToPost = 10; //number of seconds to wait - also the divisor for avg
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/**
* Setup Humidity / Temperature Sensor
*/
bool setupSHT() {
Wire.begin();
if (!sht.init()) {
Serial.println("[-] SHT Init Failed");
return false;
}
sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM);
return true;
}
double getTemperature() {
double t = -1;
if (sht.readSample()) {
t = sht.getTemperature();
temperature += t;
}
return t; // -1 on error TODO Make this better!
}
double getHumidity() {
double h = -1;
if (sht.readSample()) {
h = sht.getHumidity();
humidity += h;
}
return h; // -1 on error
}
bool setupLoRa() {
LoRa.setPins(ss, rst, dio0);
if (!LoRa.begin(433E6)) {
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
Serial.println("[-] Fatal. Starting LoRa failed!");
return false;
}
Serial.println("[+] LoRa Initialized OK!");
return true;
}
/**
* Get data from PMS Partical Sensor
* @param Stream s PMS Serial Connection
* @modifies struct data PMS Sensor Data
* @returns boolean Data Read Success status
*/
boolean readPMSdata(Stream *s) {
if (!s->available()) {
return false;
}
// Read a byte at a time until we get to the special '0x42' start-byte
if (s->peek() != 0x42) {
s->read();
return false;
}
// Now read all 32 bytes
if (s->available() < 32) {
return false;
}
uint8_t buffer[32];
uint16_t sum = 0;
s->readBytes(buffer, 32);
// get checksum ready
for (uint8_t i=0; i<30; i++) {
sum += buffer[i];
}
// The data comes in endian'd, this solves it so it works on all platforms
uint16_t buffer_u16[15];
for (uint8_t i=0; i<15; i++) {
buffer_u16[i] = buffer[2 + i*2 + 1];
buffer_u16[i] += (buffer[2 + i*2] << 8);
}
// Struct it
memcpy((void *)&data, (void *)buffer_u16, 30);
if (sum != data.checksum) {
Serial.println("Checksum failure");
return false;
}
return true;
}
void setup() {
delay(1000);
Serial.begin(115200); // Console Debug
Serial.println("[+] Transmitter Node");
pmsSerial.begin(9600); // Partical Sensor
// Setup Sensors
if (!setupSHT()) { while(1); } // Temp/Humidity - Die on Error
// Setup LoRa
if (!setupLoRa()) { while(1); } // Die on error
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
}
void loop() {
// TODO Gather Sensor Data
if (readPMSdata(&pmsSerial)) {
Serial.println();
Serial.println("---------------------------------------");
Serial.println("Concentration Units (standard)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_standard);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_standard);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_standard);
Serial.println("---------------------------------------");
Serial.println("Concentration Units (environmental)");
Serial.print("PM 1.0: "); Serial.print(data.pm10_env);
Serial.print("\t\tPM 2.5: "); Serial.print(data.pm25_env);
Serial.print("\t\tPM 10: "); Serial.println(data.pm100_env);
Serial.println("---------------------------------------");
Serial.print("Particles > 0.3um / 0.1L air:"); Serial.println(data.particles_03um);
Serial.print("Particles > 0.5um / 0.1L air:"); Serial.println(data.particles_05um);
Serial.print("Particles > 1.0um / 0.1L air:"); Serial.println(data.particles_10um);
Serial.print("Particles > 2.5um / 0.1L air:"); Serial.println(data.particles_25um);
Serial.print("Particles > 5.0um / 0.1L air:"); Serial.println(data.particles_50um);
Serial.print("Particles > 10.0 um / 0.1L air:"); Serial.println(data.particles_100um);
Serial.println("---------------------------------------");
Serial.print("Temperature: "); Serial.println(getTemperature());
Serial.print("Humidity: "); Serial.println(getHumidity());
eventCount++;
Serial.println("-------------------" + String(eventCount) + "--------------------");
// Choose Standard (_standard) or Environmental (_env)
ppm10 = ppm10 + data.pm10_standard;
ppm25 = ppm25 + data.pm25_standard;
ppm100 = ppm100 + data.pm100_standard;
//ppm10 = ppm10 + data.pm10_env;
//ppm25 = ppm25 + data.pm25_env;
//ppm100 = ppm100 + data.pm100_env;
if (eventCount == secsToPost) {
// Average Values over recording period
avgPpm10 = ppm10 / secsToPost;
avgPpm25 = ppm25 / secsToPost;
avgPpm100 = ppm100 / secsToPost;
avgTemperature = temperature / secsToPost;
avgHumidity = humidity / secsToPost;
// TODO Transmit Sensor Data
Serial.print("Avg ppm10: "); Serial.println(avgPpm10);
Serial.print("Avg ppm25: "); Serial.println(avgPpm25);
Serial.print("Avg ppm100: "); Serial.println(avgPpm100);
Serial.print("Avg Temperature: "); Serial.println(avgTemperature);
Serial.print("Avg Humidity: "); Serial.println(avgHumidity);
LoRa.beginPacket();
LoRa.print(avgPpm10); LoRa.print(',');
LoRa.print(avgPpm25); LoRa.print(',');
LoRa.print(avgPpm100); LoRa.print(',');
LoRa.print(avgTemperature); LoRa.print(',');
LoRa.print(avgHumidity);
//LoRa.write(localAddress);
// LoRa.write(msgCount);
//LoRa.write(outgoing.length());
//LoRa.print(outgoing);
LoRa.endPacket();
Serial.println("Packet Sent\n");
// Reset Loop Values
ppm10 = 0;
ppm25 = 0;
ppm100 = 0;
temperature = 0;
humidity = 0;