Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: libmDot mbed-rtos mbed
main.cpp
- Committer:
- SebastianOZ
- Date:
- 2017-06-13
- Revision:
- 1:86a5ef2c60f2
- Parent:
- 0:37bb545b7e21
File content as of revision 1:86a5ef2c60f2:
/** mDot with AirQuality sensors (SDS018,CMM5042)
*
* This program reads CO(CMM5042) and particle(SDS018) sensor data
* in specified time intervals. After defined wait time, prints read-out in USB
* serial port to PC, connects to LoRa gateway and sends data (CO_avg, PM2.5, PM10):
*
* "AQ, %d, %1.2f, %1.2f, %3.2f,\r\n",
* "AQ, seconds,PM2_5_avg, PM10_avg, CO_avg",
*
* IT DOES NOT USE mDOT SLEEP MODE YET, JUST WAITS SOME TIME
*
* SDS018 (PM particle sensor) 5V
* It reads out the digital serial PA_2 and PA_2 ((D1, D0) in UDK2 board)) and
* calculates the respective PM2.5 and PM10 values.
*
* CMM 5042 (CO sensor) 2.5 - 5.3 V
* Reads analog input connected to pin PB_1 (UDK2 pin A0). Since it is analog input
* there is an averaging time (avg_time) and sampling time (time_wait) between
* read-outs. It then estimates the corresponding concentration (ppm).
* Warm-up time for this sensor is 30 s so it is better to read after PM sensor.
*
* The only additional hardware is jumper wires from sensor to
* board.
*
* Sebastian Ortega, 06/2016
*/
#include "mbed.h"
#include "mDot.h"
// Define objects (I/O, mDot)
mDot* dot;
Serial sensor1(PA_2, PA_3); // sensor1 - particle sensor [(D1, D0) in UDK2 board]
AnalogIn sensor2(PB_1); // sensor2 - CO sensor [A0 in UDK2 board]
Timer t;
//Serial pc(USBTX, USBRX); // tx, rx
// Gateway configuration variables
static std::string config_network_name = "SIGMA_LoRa";
static std::string config_network_pass = "sigma2013";
static uint8_t config_frequency_sub_band = 1;
//Function prototypes for network connections
//void batteryvoltageMonitorTock();
void printError(mDot* dot, int32_t returnCode);
void printVersion();
bool setFrequencySubBand(uint8_t subBand);
bool setNetworkName(const std::string name);
bool setNetworkPassphrase(const std::string passphrase);
bool setPower(uint8_t power);
bool setAck(uint8_t retries);
bool joinNetwork();
bool send(const std::string text);
void sleep(uint32_t);
float CO_sensor();
float particle_sensor();
// Global variables
float PM2_5_avg = 0, PM10_avg = 0, CO_avg = 0;
float V_ref = 3.02f; //3.013f
uint32_t time_sleep = 30; // Time in s to wait between reads
uint16_t time_avg_CO = 5000; // Time in ms for average of CO sensor
uint8_t samples_CO = 10; // Samples for average of particle sensor (0.1s per sample)
uint8_t samples_par = 5; // Samples for average of particle sensor (1s per sample)
//static volatile bool timeToReadBatteryVoltage = true;
//static volatile bool dataChanged = true;
// MAIN PROGRAM-----------------------------------------------------------------------------
int main()
{
printf("\r\n\r\n");
printf("=====================================\r\n");
printf("Air Quality with LoRa mDot\r\n");
printf("=====================================\r\n");
printVersion();
set_time(1465391100); // Wed, 08 Jun 2016 13:05:00 GMT
time_t seconds = time(NULL);
printf("Unix Epoch time = %d\r\n", seconds);
// NETWORK INITIALIZATION
// get the mDot handle
dot = mDot::getInstance();
// reset to default config so we know what state we're in
dot->resetNetworkSession();
dot->resetConfig();
if (dot->getPublicNetwork() == false) {
dot->setPublicNetwork(true);
printf("Public network = FALSE \r\n");
}
// set up the mDot with our network information
setNetworkName(config_network_name);
setNetworkPassphrase(config_network_pass);
setFrequencySubBand(config_frequency_sub_band);
setPower(14); // Reduce latency for 868 units
setAck(0); // Disable ack for less latency
while (!joinNetwork()) {
wait(2);
dot->resetNetworkSession();
}
// SENSOR READOUT
while (true)
{
t.start(); // start of sensor readout
char latestData[100];
int time_start = t.read_ms();
// Read particle sensor data
printf("\nPARTICLE\n\r");
particle_sensor();
int time_PART = t.read_ms();
// Read CO sensor data
printf("\nC0 SENSOR\n\r");
CO_sensor();
int time_CO = t.read_ms();
// Print out average readouts
time_t seconds = time(NULL);
printf("\nCSV OUT:\n\r");
printf("Time(s), time_particle(ms), time_CO(ms), time_ALL(ms), PM2.5 (ug/m3), PM10 (ug/m3), CO(ppm),\r\n");
//printf("%f,\t%d,\t%d,\t%d,\t%1.2f,\t%1.2f,\t%3.2f,\r\n", t.read(),time_PART-time_start,time_CO-time_PART,time_CO-time_start, PM2_5_avg, PM10_avg, CO_avg);
printf("%d,\t%d,\t%d,\t%d,\t%1.2f,\t%1.2f,\t%3.2f,\r\n", seconds,time_PART-time_start,time_CO-time_PART,time_CO-time_start, PM2_5_avg, PM10_avg, CO_avg);
// Prepare data to send to gateway
//sprintf(latestData,"AQ: %f,\t%1.2f,\t%1.2f,\t%3.2f,\r\n", t.read(),PM2_5_avg, PM10_avg, CO_avg);
sprintf(latestData,"AQ, %d, %1.2f, %1.2f, %3.2f,\r\n", seconds,PM2_5_avg, PM10_avg, CO_avg);
send(latestData);
sleep(time_sleep);
} // while (true)
}
// SENSOR FUNCTIONS----------------------------------------------------------------
float particle_sensor()
{
int aux=0, t_init =0;
float PM2_5_A = 0, PM10_A = 0, PM2_5_sum = 0, PM10_sum = 0;
uint8_t oneByte = 0, mCheck = 0, PM2_5 = 0, PM10 = 0, myData[10];
int i = 0;
printf("PM2.5,\tPM10,\n\r");
while (aux < samples_par) //while(t.read_ms()-t_init < time_avg)
{
if (aux==0)
t_init = t.read_ms();
while (sensor1.readable()) { // whenever sensor transmits packet (every 1 s)
// packet format: AA C0 PM25_Low PM25_High PM10_A_Low PM10_A_High ID1 ID2 CRC AB
oneByte = sensor1.getc();
if(oneByte == 0xAA) { // head1 (AB) ok
myData[0] = oneByte;
//wait_ms(2);
oneByte = sensor1.getc();
if(oneByte == 0xc0) { // head2 (C0) ok
//printf("\n Packet: ");
myData[1] = oneByte;
mCheck = 0;
for(i=0; i < 6; i++) { // DATA 1-6 received and crc calc
myData[i+2] = sensor1.getc();
//wait_ms(2);
mCheck += myData[i+2];
}
myData[8] = sensor1.getc(); // crc
//wait_ms(1);
myData[9] = sensor1.getc(); // tail (AB)
// Print the received packet HEX bytes
/*
for (i=0; i<=9 ; i++) {
printf("%X ",myData[i]);
}
*/
if(mCheck == myData[8]) { // if checksum OK
PM2_5 = ((uint16_t)myData[2] | (uint16_t)(myData[3]<<8));
PM10 = ((uint16_t)myData[4] | (uint16_t)(myData[5]<<8));
PM2_5_A = (float) PM2_5/10;
PM10_A = (float) PM10/10;
if(PM2_5_A*10 > 9999)
PM2_5_A = 999.9;
if(PM10_A*10 > 9999)
PM10_A = 999.9;
aux++;
// Print the PM received data
//printf("PM2.5_A:\t%1.2f \tPM10_A:\t%1.2f,\n\r", PM2_5_A, PM10_A);
PM2_5_sum+=PM2_5_A; // sum samples for future averaging
PM10_sum+=PM10_A; // sum samples for future averaging
printf("%1.2f,\t%1.2f,\n\r", PM2_5_A, PM10_A); // CSV print: PM2.5, PM10
}
} // head2
} // head1
} // while readable()
//break;
} // while aux<10
PM2_5_avg = PM2_5_sum/aux; // AVERAGE
PM10_avg = PM10_sum/aux; // AVERAGE
printf("AVERAGE PARTICLE (Samples = %d):\r\n%1.2f,\t%1.2f,\n\r", aux,PM2_5_avg, PM10_avg); // CSV print: PM2.5, PM10
return PM2_5_avg;
}
float CO_sensor()
{
int count = 0, t_init = 0, tim1;
float v_sum=0, CO_ppm;
uint16_t time_wait = 100; // Time in ms to wait between ADC reads
//uint16_t time_avg = 10000; // Time in ms for average
printf("Time,\tV_in_ADC,\tV_in(V),\tCO(ppm),\n\r");
while(count < samples_CO)//while(t.read_ms()-t_init <= time_avg_CO)
{
if (count == 0){
t_init = t.read_ms();
}
tim1 = t.read_ms();
float v_in_norm = sensor2.read(); // read analog input and returns value between [0.0,1.0]
//printf("\n\rsensor read:\t %f\t", v_in_norm);
float v_in = v_in_norm * V_ref;
//printf("analog voltage:\t %1.3fV \r\n", v_in);
CO_ppm = (v_in-2)*(-400);
if (v_in >= 2) {
CO_ppm = 0;
}
else {
CO_ppm = (v_in-2)*(-400);
}
count++;
v_sum+=v_in_norm; // sum samples for future averaging
printf("%d,\t%f,\t%1.3f,\t\t%3.2f,\r\n", tim1, v_in_norm,v_in,CO_ppm);
uint16_t print_delay = t.read_ms()-tim1; // to measure delay of printf call
wait_ms(time_wait-print_delay);
}
float v_norm_avg = v_sum/count; // AVERAGE
float v_avg = v_norm_avg * V_ref;
//float CO_avg = (v_avg-2)*(-400);
if (v_avg >= 2) {
CO_avg = 0;
}
else {
CO_avg = (v_avg-2)*(-400);
}
printf("AVERAGE CO (Samples = %d):\r\n%d,\t%f,\t%1.3f,\t\t%3.2f,\r\n", count, tim1, v_norm_avg,v_avg,CO_avg);
return CO_avg;
}
// NETWORK FUNCTIONS----------------------------------------------------------------
void printVersion()
{
printf("%s\r\n\r\n", dot->getId().c_str());
}
bool setFrequencySubBand(uint8_t subBand)
{
int32_t returnCode;
printf("Setting frequency sub band to '%d'...\r\n", subBand);
if ((returnCode = dot->setFrequencySubBand(subBand)) != mDot::MDOT_OK) {
printError(dot, returnCode);
return false;
}
return true;
}
bool setNetworkName(const std::string name)
{
int32_t returnCode;
//printf("Setting network name to '%s'...\r\n", name.c_str());
printf("Setting network name ...\r\n");
if ((returnCode = dot->setNetworkName(name)) != mDot::MDOT_OK)
{
printError(dot, returnCode);
return false;
}
return true;
}
bool setNetworkPassphrase(const std::string passphrase)
{
int32_t returnCode;
//printf("Setting passphrase to '%s'...\r\n", passphrase.c_str());
printf("Setting passphrase...\r\n");
if ((returnCode = dot->setNetworkPassphrase(passphrase)) != mDot::MDOT_OK)
{
printError(dot, returnCode);
return false;
}
return true;
}
bool setPower(uint8_t power)
{
int32_t returnCode;
printf("Setting tx power to '%d'...\r\n", power);
if ((returnCode = dot->setTxPower(power)) != mDot::MDOT_OK) {
printError(dot, returnCode);
return false;
}
return true;
}
bool joinNetwork()
{
int32_t returnCode;
printf("\r\nJoining network...\r\n");
if ((returnCode = dot->joinNetworkOnce()) != mDot::MDOT_OK) {
printError(dot, returnCode);
return false;
}
printf("Network Joined!\r\n");
return true;
}
bool setAck(uint8_t retries)
{
int32_t returnCode;
printf("Setting ack to '%d'...\r\n", retries);
if ((returnCode = dot->setAck(retries)) != mDot::MDOT_OK)
{
printError(dot, returnCode);
return false;
}
return true;
}
bool send(const std::string text)
{
int32_t returnCode;
uint32_t timeTillSend = dot->getNextTxMs();
if (timeTillSend != 0) {
printf("waiting %lu ms to send\r\n", timeTillSend);
return false;
}
printf("Sending data... ");
std::vector<uint8_t> data(text.begin(), text.end());
if ((returnCode = dot->send(data, 1)) != mDot::MDOT_OK)
{
printError(dot, returnCode);
return false;
}
printf("Data sent!\r\n");
return true;
}
void printError(mDot* dot, int32_t returnCode)
{
std::string error = mDot::getReturnCodeString(returnCode) + " - " + dot->getLastError();
printf("%s\r\n", error.c_str());
}
void sleep(uint32_t time_sleep)
{
// TO DO: add mDot sleep sequence here
printf("Going to sleep...\n\r\n\r");
wait(time_sleep);
}