Amaljith Cf
Created March 3, 2019 © LGPL

Spresense weather and web radio

project uses speech synthesis to announce a web portal for streaming MP3 audio files through a Sony Spresense via I2S and anounces weather

IntermediateShowcase (no instructions)5 days59
Spresense weather and web radio

Things used in this project

Hardware components

Spresense boards (main & extension)
Sony Spresense boards (main & extension)
×1
Adafruit Feather HUZZAH with ESP8266 WiFi
Adafruit Feather HUZZAH with ESP8266 WiFi
×1
Photo resistor
Photo resistor
×1
Resistor 10k ohm
Resistor 10k ohm
×1

Software apps and online services

Arduino IDE
Arduino IDE
ThingSpeak API
ThingSpeak API

Story

Read more

Code

weather arduino file

Arduino
//-----------------------------------------------------------------------------------------
// WeatherPost
// - An Enhancement to ESP8266-01 and ThingSpeak integration with Sony's Arduino Spritzer
// James Penner
// March 11, 2018    Created
// March 25, 2018    Updated  Satellite, Temperature, Preasure, and Light data post to ThinkSpeak
// March 30, 2018    Switch from Adafruit to SparkFun BMP180 library
// May 20, 2018      Ported from Spritzer to SPRESENSE; Corrections and comments added
//                   Corrected reference to analog port from 0 to A0 (SPRESENSE issue #80)
//-----------------------------------------------------------------------------------------
// Wiring Sony's Arduino Spritzer/SPRESENSE
// Spritzer  Color    ESP8266     LDR/Cell  BMP180  Arduino
// --------  -------  ----------  --------  ------  -------
// 3.3vdc    Red      VCC 3.3vdc  3.3vdc    3.3vdc  3.3vdc
// 3.3vdc    Red      CH_CD       -         -       3.3vdc
// GND       Black    GND         GND       GND     GND
// D0(RX)    Green    TX          -         -       D10(RX) Using SoftwareSerial for Arduino
// D1(TX)    Yellow   RX          -         -       D11(TX) Using SoftwareSerial for Arduino
// A0        White    -           Signal    -       A0
// D14/SDA   White    -           -         SDA     A4
// D15/SCL   Blue     -           -         SCL     A5
//-----------------------------------------------------------------------------------------
// The following is a base code used to support a multi sensor read and post to a data store;
// In this case, the data store selected is ThingSpeak. This code is stripped from my
// WeatherStationTS.ino application and its intent is to transpose to standard code to the
// SPRESENSE.
//-----------------------------------------------------------------------------------------
// Changes:
// - Serial connection: Since the SPRESENSE has a seperate UART, the softwareSerial was removed
//   and Serial2 used in its place.
//   The RX/TX connections (D0/D1) are used.
// - Analog Reference: SPRESENSE Analog port 0, must be referenced a A0, and cannot be referenced
//   as 0 in Spritzer and UNO
// General features:
// - SPRESENSE is connected to an ESP2866-01
// - Programming connects to wireless AP (local network), then subsequently connects and
//   posts simulated data to ThingSpeak
// - GNSS satalite locating and posting of geo coordinates to ThingSpeak channel
// - BMP180 added for Temperature and Barometric presure readings; posted to ThingSpeak channel
// - Photocell added for Ambient light readings; posted to ThingSpeak channel
// Enhancement next steps
// - Wire a sensor to take readings and substitute in posting for your own use!
//-----------------------------------------------------------------------------------------
// See WeatherPost document for revisions to the ESP8266-01 sketch to understand changes
//-----------------------------------------------------------------------------------------
//Basic Requirements:
// - Sony Arduino SPRESENSE
// - Preflashed ESP8266-01 module
// - An account set up on ThingSpeak
// - DuPont style, M-F Jumper wires; Red(2), Black(1), Yellow(1), Green(1) 
//-----------------------------------------------------------------------------------------
// ESP8266 Commands:
// AT                                                       OK
// AT+RST                                                   OK
// AT+CIPMUX=0                                              OK
// AT+CWMODE=1                                              OK
// AT+CWJAP="NetID","Password"                              OK
// AT+CIPSTART="TCP","144.212.80.11",80                     CONNECT, OK
// AT+CIPSEND=45                                            OK, >
// GET /update?key=********549JQXB1&field1=50f              OK, +IPD,3:508CLOSED or busy s...
// AT+CWQAP                                                 OK, WIFI DISCONNECT
// Other comands
//  AT+CWLAP                                                C+CWLAP: (...
//  AT+CIPSTA="192.168.0.47"                                OK
//  AT+CIPCLOSE                                             OK
//-----------------------------------------------------------------------------------------
// Key GNSS data elements:
//   pNavData->latitude                                      // Latitude
//   pNavData->longitude                                     // Longitude
//   pNavData->time.year                                     // Year
//   pNavData->time.month                                    // Month
//   pNavData->time.day                                      // Day
//   pNavData->time.hour                                     // Hour
//   pNavData->time.minute                                   // Minutes
//   fsec                                                    // Seconds in floating point notation
//   float fsec = (float)pNavData->time.sec + ((float)pNavData->time.usec / 1000000);
//   pNavData->getSatelliteElevation(1)                      // Elevation of Satellite 1
// ------------------------------------------------------------------------------
#include <SFE_BMP180.h>                    // Include SparkFun library to support BMP180
#include <Wire.h>                          // Include the synchronous Wire library
SFE_BMP180 bmp180;                         // Instantiate the BMP library functions
#define ALTITUDE 213.36                    // Altitude of your location in meters (Default for BMP180)
#include <GNSS.h>                          // Include the Sony Spritzer GPS library
SpGnss gnss;                               // Instanciate the GNSS library functions
#define SSID        "Net_ID"               // Must be changed - WiFi SSID/Hostname
#define PASS        "drowssap"             // Must be changed - Encrypted password
#define APIKEY      "********549JQXB1"     // Must be changed - API Key Sandbox on ThingSpeak Channel
#define IP          "184.106.153.149"      // IP address of thingspeak.com from my location
#define MONITOR     true                   // Debuging messages over the monitor
#define BROADCAST   true                   // Broadcast readings to ThingSpeak
#define POST_PERIOD 120000                 // 2 minutes = 120,000ms = 120sec
#define CELPIN      A0                     // Analog pin for the PhotoCell (Ambient Light)
//---------------------------------------------------------------------
String cmd;                                // Output string to the ESP8266
String passcode;                           // Decrypted Network password
float xTemp = 76.9;                        // Dummy Temerature          76.9  F
float xTempC = 8.3;                        // Dummy Temerature          8.3   C
float xHumi = 23.3;                        // Dummy Humidity            23.3  %
float xPres = 873.6;                       // Dummy Barometric preasure 873.6 mb
float xInHg = 29.3;                        // Dummy Barometric preasure 29.3  inHg
int xLite = 738;                           // Dummy Ambient light       738   ambient
float xWspd = 12.8;                        // Dummy Wind speed          12.8  mph
int xWdir = 270;                           // Dummy Wind Direction      270   compass
float xLong = 0.0;                         // Default Longitude         0.0
float xLati = 0.0;                         // Default Latitude          0.0
unsigned long markTime;                    // Time mark for the delay timer
int cri = 0;                               // Index for connection
SpNavData *pNavData;                       // Pointer for NavData
char caString[36];                         // Character Array for formating String
char buff[12];                             // Character Array buffer to support sprintf conversion
bool BMPfailure = false;                   // Set flag for BMPfailure
char bmpStatus;                            // Used for bmp180 function call status (single byte 0-255)

// === Set up ================================================================================
void setup(){
  if (MONITOR) Serial.begin(9600);
  if (MONITOR){
    Serial.println("Sony Spritzer ESP8266-01 posting to ThingSpeak");
    Serial.println("James Penner / March 20, 2018");
    Serial.println();
  }
  Serial2.begin(115200);
  while(!Serial2){
    ; // wait for ESP8266 port to open/connect; vehicle Monitoring
  }

  Serial.println("ESP8266: Serial connection made");
  if (bmp180.begin()){
    Serial.println("BMP180: Sensor is OK");
    BMPfailure = false;
  }else{
    BMPfailure = true;
  }

  gnss.setDebugMode(PrintInfo);                              // Put GPS readings into a debug mode
  int r;
  r = gnss.begin();                                          // Initialize GNSS handling
  if (r != 0){                                               // Error encountered
    Serial.print("GNSS: Unable to initialize! (");Serial.print(r);Serial.println(")");
  }else{
    r = gnss.start(COLD_START);                              // Start GNSS listening
    if (r != 0){                                             // Error encountered
      Serial.print("GNSS: Unable to start! (");Serial.print(r);Serial.println(")");
    }else{
      Serial.println("GNSS: Is online/listening");           // GSNN is online 
    }
  }  

  passcode = decryptPass(PASS);
}

// --- Satellite check -----------------------------------------------------------------------
boolean getNavData(SpNavData *pNavData){
  boolean ret;
  if (pNavData->posDataExist == 0)  {
    Serial.println("GNSS: Position is not yet fixed");
    ret = false;
  }else{
    ret = true;
  }
  return ret;
}

// === Main loop =============================================================================
void loop(){
  randomSeed(analogRead(0));                                    // Standard Arduino technique using unused Analog pin noise to seed
  double tempT, tempP;                                          // Used for bmp180 function calls
  if (MONITOR){Serial.println("Start reporting cycle....");Serial.println();}
  Led_On(LED0);

  bmpStatus = bmp180.startTemperature();
  if (bmpStatus != 0){
    delay(bmpStatus);                                           // Wait for measurement to complete (bus time)
    bmpStatus = bmp180.getTemperature(tempT);
    if (bmpStatus != 0){
      xTemp = ((tempT*9.0)/5.0)+32.0;                           // Read Celsius convert to Fahrenheit
      bmpStatus = bmp180.startPressure(3);                      // Set oversampling 0-... (10)
      if (bmpStatus != 0){
        delay(bmpStatus);                                       // Wait for measurement to complete (bus time)
        bmpStatus = bmp180.getPressure(tempP,tempT);
//        if (isnan(tempP)){
//          Serial.print("a-NAN p("); Serial.print(tempP); Serial.println(")");
//          Serial.print("a-NAN t("); Serial.print(tempT); Serial.println(")");
//        }
        if (bmpStatus != 0){
          xPres = tempP;                                        // Read mb
          xPres = bmp180.sealevel(tempP,ALTITUDE);              // Compensate for Altitude
        }else{
          xPres = 0.0;
          Serial.println("BMP180: Error retrieving Pressure; 0mb used!");
        }
      }else{
        xPres = 0.0;
        Serial.println("BMP180: Error Starting Pressure readings; 0mb used!");
      }
    }else{
      xTemp = 0.0;
      Serial.println("BMP180: Error retrieving Temperature; 0.0F used!");
    }
  }else{
    xTemp = 0.0;
    Serial.println("BMP180: Error Starting Temperature readings; 0.0F used!");
  }
  
  xLite = analogRead(CELPIN);                                  // Read Ambient Light from Analog pin
  
  xHumi = 23.3+random(15.0);                                   // Simulate Humidity +variation
  xInHg = 29.3+random(1.0);                                    // Simulate variation
  xWspd = 12.8+random(20.0);                                   // Simulate variation
  xWdir = 270+random(45);                                      // Simulate variation
  // --- Get location --------------------------------------------------------------------------
  if (gnss.waitUpdate(-1)){                                    // Have an update?
    SpNavData NavData;
    gnss.getNavData(&NavData);                                 // Receive in Nav data if available
    if (getNavData(&NavData)){                                 // There is data!
      pNavData = &NavData;
      xLong = (float) (pNavData->longitude);                   // recaset to float
      xLati = (float) (pNavData->latitude);                    // recaset to float
      Serial.print("GNSS: Found Satellite! Position is ");
      sprintf(caString, "%3.6f, %3.6f\0", pNavData->longitude, pNavData->latitude);
      Serial.println(caString);
    }else{
      Serial.println("GNSS: No satellite discovered");         // No satellite yet
      xLong = 0.0;                                             // Default if not read longitude
      xLati = 0.0;                                             // Default if not read latitude
    }
  }else{
    Serial.println("GNSS: Data not updated");                  // Catch if data not updated
  }
  // --- Post Readings -----------------------------------------------------------------------
  waitTime(4000);
  connectWifi();
  waitTime(1000);
  if (BROADCAST) postReadings();
  waitTime(4000);
  Led_Off(LED0);
  Led_Off(LED1);
  Led_Off(LED2);
  Led_Off(LED3);
  
  delay(POST_PERIOD);
}

boolean connectWifi(){
  Led_On(LED1); 
  if (MONITOR) Serial.println("\nAT> AT ------------------------------------------------------------");
  Serial2.println("AT");                        // Check:                     OK is returned
  waitTime(500);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());
  waitTime(100);

  if (MONITOR) Serial.println("\nAT> AT+RST --------------------------------------------------------");
  Serial2.println("AT+RST");                        // Check:                     OK is returned
  waitTime(5500);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());
  waitTime(1000);

  if (MONITOR) Serial.println("\nAT> AT+CIPMUX=0 -------------------------------------------------");
  Serial2.println("AT+CIPMUX=0");                   // Single connection mode:    OK is returned
  waitTime(500);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());
  waitTime(100);
  
  if (MONITOR) Serial.println("\nAT> AT+CWMODE=1 ---------------------------------------------------");
  Serial2.println("AT+CWMODE=1");                   // Access Point=0, Station=1: OK is returned
  waitTime(500);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());
  waitTime(100);
  
  if (MONITOR) Serial.println("\nAT> AT+CWLAP ------------------------------------------------------");
  Serial2.println("AT+CWLAP");                   // List Access Points
  waitTime(7000);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());
  waitTime(2000);
  
  Led_On(LED2); 
  cmd="AT+CWJAP=\"";cmd+=SSID;cmd+="\",\"";cmd+=passcode;cmd+="\"";
  if (MONITOR){ Serial.print("\nAT> ");Serial.print(cmd); Serial.println(" ---------------------------------------");}
  for (int cri=0; cri <= 3; cri++){
    Serial2.println(cmd);                   // Join Access Point:  OK is returned after about 3-4 seconds
    Serial2.flush();
    waitTime(6000);
    if (Serial2.find((char *)"OK")){
      if (MONITOR){
        Serial.println(cmd);
        Serial.print("Network Connected! ("); Serial.print(cri); Serial.println(")");
      }
      cri=5;
      break;
    }
  } 
  if (cri==3){
    if (MONITOR){
      while (Serial2.available() > 0) Serial.write(Serial2.read());
      Serial.println("AT+CWJAP failed...");
    }
  }
  if (MONITOR){
    while (Serial2.available() > 0) Serial.write(Serial2.read());
    Serial.write("AT+CWJAP=SSID and Passcode");     // Do not expose decypted password
  }
  waitTime(100);

  if (MONITOR) Serial.println("\nAT> AT+CIFSR ------------------------------------------------------");
  Serial2.println("AT+CIFSR");                     // Check Connection status
  Serial2.flush();
  waitTime(2000);
  if (MONITOR){
    while (Serial2.available() > 0) Serial.write(Serial2.read());
    Serial.println();
  }
}

//--- V2.0 ------------------------------------------------------------
void postReadings(){
  cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += IP;
  cmd += "\",80";
  Led_On(LED3); 
  if (MONITOR) Serial.println("\nAT> AT+CISTART ----------------------------------------------------");
  for (int cri=0; cri <= 3; cri++){
    Serial2.println(cmd);                   // Conenct to ThingSpeak: CONNECT is returned after about 1-2 seconds
    Serial2.flush();
    waitTime(4000);
    if (Serial2.find((char *)"CONNECT")){
      if (MONITOR){
        Serial.println(cmd);
        Serial.print("Thingspeak Connected! ("); Serial.print(cri); Serial.println(")");
      }
      cri=5;
      break;
    }
  } 
  if (cri==3){
    if (MONITOR){
      while (Serial2.available() > 0) Serial.write(Serial2.read());
      Serial.println("Thingspeak Connection failed...");
    }
  }

  cmd = "GET /update?api_key="; cmd += APIKEY;
  cmd += "&field1=";   sprintf(buff,"%.2f",xTemp);     cmd += buff;
  cmd += "&field2=";   sprintf(buff,"%.2f",xHumi);     cmd += buff;
  cmd += "&field3=";   sprintf(buff,"%.2f",xPres);     cmd += buff;
  cmd += "&field4=";                                   cmd += xLite;
  cmd += "&field5=";   sprintf(buff,"%.2f",xWspd);     cmd += buff;
  cmd += "&field6=";                                   cmd += xWdir;
  cmd += "&field7=";   sprintf(buff,"%.6f",xLong);     cmd += buff;
  cmd += "&field8=";   sprintf(buff,"%.6f",xLati);     cmd += buff;
  cmd += "\r\n";

  if (MONITOR){ Serial.print("\nAT> AT+CIPSEND=");Serial.print(cmd.length()); Serial.println(" ------------------------------------------------");}
  Serial2.print("AT+CIPSEND=");
  Serial2.println(cmd.length());                // Send length of IP string:  OK is returned  
  Serial2.flush();
  waitTime(2000);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());

  if (MONITOR) Serial.println("\n> GET -------------------------------------------------------------");
  Serial.print("> "); Serial.println(cmd);
  Serial2.println(cmd);                         // Send Get/Post command:     SEND OK and +IPD,1:5CLOSED are returned
  Serial2.flush();
  waitTime(3000);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());

  if (MONITOR) Serial.println("\nAT> AT+CWQAP ------------------------------------------------------");
  Serial2.println("AT+CWQAP");
  Serial2.flush();
  waitTime(3000);
  if (MONITOR) while (Serial2.available() > 0) Serial.write(Serial2.read());
}
//------------------------------------------------------------------------
// Custom routine to decrypt password; somewhat obfuscates it from code
//------------------------------------------------------------------------
String decryptPass(String inStr){
  String outStr = "";
  char x;
  for (int i = 0; i < inStr.length(); i++){
    x = (byte(inStr[i]) + 8 - i);
    outStr = outStr + x;
  }
  return outStr;
}
//------------------------------------------------------------------------
// Suplement to delay() fucntion as delay() does not pause all actions and is asynchronous. 
//------------------------------------------------------------------------
void waitTime(int milsec){
  markTime = millis();
  while (millis()-markTime < milsec){
  }
}

Audio Through for Spresense

web radio ino

Credits

Amaljith Cf

Amaljith Cf

10 projects • 26 followers
Technology enthusiast

Comments