Skip to content
Snippets Groups Projects
ESP8266_Transmitter.ino 5.24 KiB
Newer Older
#include <SPI.h>
#include <LoRa.h>
#include <SoftwareSerial.h>

// Lora Config Pins
#define ss 5
#define rst 0
#define dio0 4

static const int RXPin = 4, TXPin = 3;
static const int pollingFrequency = 2500; // ms

// Particle Sensor Serial
SoftwareSerial pmsSerial(2, 3);

// LoRa Message Tracking
byte localAddress = 0xBB;
byte destination = 0xFF;
byte msgCount = 0;

// Sensor Values - Temp / Humidity
byte temperature;
byte 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 = 60; //number of seconds to wait - also the divisor for avg

bool setupLoRa() {
  LoRa.setPins(ss, rst, dio0);  
  if (!LoRa.begin(915E6)) {
    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() {
  Serial.begin(9600); // Console Debug
  Serial.println("[+] Transmitter Node");

  pmsSerial.begin(9600); // Partical Sensor

  // Setup LoRa
  //if (!setupLoRa()) { while(1); } // Die on error
}

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);
    
    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;

      // 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);
//      String outgoing = "Hello World!";
      
//      LoRa.beginPacket();
      //LoRa.write(destination);
      //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;
      
      eventCount = 0;
      Serial.println("---------------+++++-------------------");
    }
  }

  msgCount++;
  //delay(pollingFrequency);
}