Samuel Cadavid PalaciosJuan Javier LunaAlejandra AmayaLaura Velasquez
Published

Atmospheric data collection and Real-time transmission

Linkit one project to get atmospheric data on board a high altitude balloon, including air quality sensors, pressure, temperature, and GPS

BeginnerWork in progress1,210
Atmospheric data collection and Real-time transmission

Things used in this project

Hardware components

Hydrogen Gas Sensor - MQ-8
×1
Temperature Sensor
×1

Software apps and online services

Ubidots
Ubidots

Story

Read more

Schematics

schematic

Code

Linkit one atmospherics

C/C++
/* Based on the Chip McClelland - Cellular Data Logger BSD license, Please keep my name in any redistribution
Requirements:
  - Account on Ubidots.  http://www.ubidots.com
  - Seedstudio LinkIt ONE - http://www.seeedstudio.com/wiki/LinkIt_ONE
This code will be part of a larger project to build a connected Air Quality Sensor -
  - Project documentation here: http://triembed.org/blog/?page_id=736
  - GitHub repo here: https://github.com/chipmc/AirQualitySensorProject
***********************************************************************************/
#include <LGPS.h>            // LinkIt GPS Library
#include <LBattery.h>  // Want to be able to read the battery charge level
#include <LGPRS.h>      //include the base GPRS library
#include <LGPRSClient.h>  //include the ability to Post and Get information using HTTP
#include <LFlash.h>
#include <LSD.h>
#include <LStorage.h>

//uncomment the storage you want to use
//#define Drv LFlash          // use Internal 10M Flash
#define Drv LSD           // use SD card

// These are the variables you will want to change based on your IOT data streaming account / provider
char action[] = "POST ";  // Edit to build your command - "GET ", "POST ", "HEAD ", "OPTIONS " - note trailing space
char server[] = "things.ubidots.com";
char path[] = "/api/v1.6/variables/XXXXXX/values";  // Edit Path to include you source key
char token[] = "XXXXXXXXXXX";  // Edit to insert you API Token
int port = 80; // HTTP

// Here are the program variables
int num;                            // part of the length calculation
int temp;
int hyd;
String le;                         // length of the payload in characters
String var;                        // This is the payload or JSON request
unsigned long ReportingInterval = 20000;  // How often do you want to update the IOT site in milliseconds
unsigned long LastReport = 0;      // When was the last time you reported
const int ledPin = 13;                 // Light to blink when program terminates
String Location = "";          // Will build the Location string here
const int AOUTpin0=0;
const int AOUTpin1=1;
float temperature;
float hydrogen;

// Create instantiations of the GPRS and GPS functions
LGPRSClient globalClient;  // See this support topic from Mediatek - http://labs.mediatek.com/forums/posts/list/75.page
gpsSentenceInfoStruct info;  // instantiate

void setup()
{
  Serial.begin(19200);             // setup Serial port
  Serial.print("Initializing memory...");
  pinMode(10, OUTPUT); //needed for SD card
  if(!Drv.begin())
  {
    Serial.println("Error initalizing memory.");  
    while(true);
  }
  LGPS.powerOn();                  // Start the GPS first as it takes time to get a fix
  Serial.println("GPS Powered on, and waiting ...");
  Serial.println("Attach to GPRS network");   // Attach to GPRS network - need to add timeout
  while (!LGPRS.attachGPRS("web.vmc.net.co","Virgin Mobile","")) { //attachGPRS(const char *apn, const char *username, const char *password);
    delay(500);
  }
  LGPRSClient client;    //Client has to be initiated after GPRS is established with the correct APN settings - see above link
  globalClient = client;  // Again this is a temporary solution described in support forums
}

void loop(){
  
  temp= analogRead(AOUTpin0);
  hyd= analogRead(AOUTpin1);
  temperature = (temp-500)/10;
  hydrogen = (9900/1023)*hyd+100;

  if (globalClient.available()) {// if there are incoming bytes available from the server
    char c = globalClient.read();   // read them and print them:
    Serial.print(c);
  }
  if (millis() >= LastReport + ReportingInterval) {  // Section to report - will convert to a function on next rev
    String value = String(LBattery.level());
    LGPS.getData(&info);                     // Get a GPS fix
    if (ParseLocation((const char*)info.GPGGA)) {  // This is where we break out needed location information
      Serial.print("Location is: ");
      Serial.println(Location);                 // This is the format needed by Ubidots
    }
    if (Location.length()==0) {
      var="{\"value\":"+ value + "}"; //Build the JSON packet without GPS info
    }
    else {
      var="{\"value\":"+ value + ", \"context\":"+ Location + "}";  // with GPS info
    }
    num=var.length();               // How long is the payload
    le=String(num);                 //this is to calcule the length of var
    Serial.print("Connect to ");    // For the console - show you are connecting
    Serial.println(server);
    if (globalClient.connect(server, port)){  // if you get a connection, report back via serial:
      Serial.println("connected");  // Console monitoring
      Serial.print(action);                   // These commands build a JSON request for Ubidots but fairly standard
      Serial.print(path);                     // specs for this command here: http://ubidots.com/docs/api/index.html
      Serial.println(" HTTP/1.1");
      Serial.println(F("Content-Type: application/json"));
      Serial.print(F("Content-Length: "));
      Serial.println(le);
      Serial.print(F("X-Auth-Token: "));
      Serial.println(token);
      Serial.print(F("Host: "));
      Serial.println(server);
      Serial.println();
      Serial.println(var);  // The payload defined above
      Serial.println();
      Serial.println((char)26); //This terminates the JSON SEND with a carriage return
      globalClient.print(action);                   // These commands build a JSON request for Ubidots but fairly standard
      globalClient.print(path);                     // specs for this command here: http://ubidots.com/docs/api/index.html
      globalClient.println(" HTTP/1.1");
      globalClient.println(F("Content-Type: application/json"));
      globalClient.print(F("Content-Length: "));
      globalClient.println(le);
      globalClient.print(F("X-Auth-Token: "));
      globalClient.println(token);
      globalClient.print(F("Host: "));
      globalClient.println(server);
      globalClient.println();
      globalClient.println(var);  // The payload defined above
      globalClient.println();
      globalClient.println(temperature);  // The payload defined above
      globalClient.println();
      globalClient.println(hydrogen);  // The payload defined above
      globalClient.println();
      globalClient.println((char)26); //This terminates the JSON SEND with a carriage return
      LastReport = millis();
    }
  }
  String file_name = date_format;
    file_name += ".txt";
    file_name.toCharArray(file, 14);
    Serial.println(file);
    LFile dataFile = Drv.open(file, FILE_WRITE);
    if (dataFile)
    {
      dataFile.println(str);
      dataFile.close();
      Serial.println("File written.");
    }
    else Serial.println("Error opening file.");*/
}

boolean ParseLocation(const char* GPGGAstr)
// Refer to http://www.gpsinformation.org/dale/nmea.htm#GGA
// Sample data: $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
{
  char latarray[6];
  char longarray[6];
  int index = 0;
  Serial.println(GPGGAstr);
  Serial.print("Fix Quality: ");
  Serial.println(GPGGAstr[43]);
  if (GPGGAstr[43]=='0') {        //  This is the place in the sentence that shows Fix Quality 0 means no fix
    Serial.println("No GPS Fix");
    Location = "";           // No fix then no Location string
    return 0;
  }
  String GPSstring = String(GPGGAstr);
  for (int i=20; i<=26; i++) {         // We have to jump through some hoops here
    latarray[index] = GPGGAstr[i];     // we need to pick out the minutes from the char array
    index++;
  }
  float latdms = atof(latarray);        // and convert them to a float
  float lattitude = latdms/60;          // and convert that to decimal degrees
  String lattstring = String(lattitude);// Then put back into a string
  Location = "{\"lat\":";
  if(GPGGAstr[28] == 'S') Location = Location + "-";
  Location += GPSstring.substring(18,20) + "." + lattstring.substring(2,4);
  index = 0;
  for (int i=33; i<=38; i++) {         // And do the same thing for longitude
    longarray[index] = GPGGAstr[i];     // the good news is that the GPS data is fixed column
    index++;
  }
  float longdms = atof(longarray);        // and convert them to a float
  float longitude = longdms/60;          // and convert that to decimal degrees
  String longstring = String(longitude);// Then put back into a string
  Location += " ,\"lng\":";
  if(GPGGAstr[41] == 'W') Location = Location + "-";
  if(GPGGAstr[30] == '0') {
    Location = Location + GPSstring.substring(31,33) + "." + longstring.substring(2,4) + "}";
  }
  else {
    Location = Location + GPSstring.substring(30,33) + "." + longstring.substring(2,4) + "}";
  }
  return 1;
}

Credits

Samuel Cadavid Palacios

Samuel Cadavid Palacios

1 project • 2 followers
Juan Javier Luna

Juan Javier Luna

1 project • 1 follower
Aeronautical Engineering student
Alejandra Amaya

Alejandra Amaya

1 project • 0 followers
Laura Velasquez

Laura Velasquez

1 project • 0 followers

Comments