Simple posting of Sensor Data to Thingspeak (simple GET)
Posted: Thu Dec 24, 2015 11:07 am
This sketch also Tweets some sensor readings every 15 minutes, dependant on the timing of the Thingspeak Post (60 posts @ 15 seconds per 1 tweet).
This is using a BMP180 and MPU6050 on Pins 4+5 with the HC5883 on XCL + XDA of MPU6050, on an ESP8266-12
If the interrupt from the MPU or Compass is to be used, use pin15.....
The twitter.h file has been modified for the ESP included here also......
The Sketch...
The modified Twitter.h.....
The twitter feed.....
https://twitter.com/mcuautomation
The Thingspeak page......
https://thingspeak.com/channels/73449
The Device.....
This is using a BMP180 and MPU6050 on Pins 4+5 with the HC5883 on XCL + XDA of MPU6050, on an ESP8266-12
If the interrupt from the MPU or Compass is to be used, use pin15.....
The twitter.h file has been modified for the ESP included here also......
The Sketch...
Code: Select all
/* Modified for easy ESP8266 use December 19 2015
♀♪♂
<iframe width="450" height="260" style="border: 1px solid #cccccc;" src="http://api.thingspeak.com/channels/XXXXX/charts/Y?width=450&height=260&results=ZZ&dynamic=true" ></iframe>
Embed this in any html to see the output Replacing the XXXXX with Your Channel Number, Y with the Chart "&fieldY=" to display and ZZ with the number of readings to retrieve.
*/
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <Twitter.h>
#include <Wire.h>
#include <HMC5883L.h>
#include <MPU6050.h>
#include <SFE_BMP180.h>
double baseline; // baseline pressure
SFE_BMP180 pressure;
#define ALTITUDE 30.0 // Meters above Sea level
double T,a,P,p0;
HMC5883L compass;
MPU6050 mpu;
// Timers
unsigned long timer = 0;
float timeStep = 0.01;
// Pitch, Roll and Yaw values
float pitch = 0;
float roll = 0;
float yaw = 0;
int previousDegree;
// Set time compare to select post rather than delay.......
unsigned long ulMeasDelta_ms; // Distance to Tweet Time Timer
unsigned long ulNextMeas_ms; // Holder for the next Tweet Time Value
int loop_timer = 15; // Set the delay in Seconds for Thingspeak
int tweet_timer = 60; // The number of 15 second periods to wait before Tweeting
int tweet_count = 0; // Loop to cout thing posts
int i=1; // How many Tweets
// Remember the transaction takes time to negotiate ....
// So for faster updates than 1 Second use a Stream and separate Twitter......
char buf[120]; // The Tweet
WiFiServer server(80);
WiFiClient client;
Twitter twitter("Your-Twitter API_KEY"); // Twitter API Key
const char* thingspeak_key = "Your-API_KEY"; // Thingspeak API Write Key Channel 1
const char* thingspeak_key1 = "Your-API_KEY"; // Thingspeak API Write Key Channel 2
const char* ssid = "Your SSID";
const char* password = "Your Password";
const char* hostts = "api.thingspeak.com";
// http://thingspeak.com for Channel setup
// http://freeboard.io for simple dashboard from data posted
// http://arduino-tweet.appspot.com/oauth/twitter/login Get Your Twitter API Key here
void tweet(char msg[]){
// Do something with the response......ignored here......cast and leave it to ripple...
if (twitter.post(msg)) {
int status = twitter.wait();
if (status == 200) {
} else {
}
} else {
}
}
void setup() {
Serial.begin(115200);
Serial.println("I2C init");
Wire.begin();
Serial.println("I2C init done");
// Initialize MPU6050
while(!mpu.begin(MPU6050_SCALE_2000DPS, MPU6050_RANGE_2G))
{
Serial.println("Could not find a valid MPU6050 sensor, check wiring!");
delay(500);
}
Serial.println("Found a valid MPU6050 sensor");
// Enable bypass mode
mpu.setI2CMasterModeEnabled(false);
mpu.setI2CBypassEnabled(true);
mpu.setSleepEnabled(false);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
// Print the IP address
Serial.println(WiFi.localIP());
// Start the server
server.begin();
ulMeasDelta_ms = ( (unsigned long) loop_timer * 1000); // Sample Interval X in Seconds placed above in the declarations....
ulNextMeas_ms = millis()+ulMeasDelta_ms;
Serial.println("Server started");
if (pressure.begin())
{
Serial.println("Initialized BMP180");
}
else
{
// Oops, something went wrong, this is usually a connection problem,
// see the comments at the top of this sketch for the proper connections.
Serial.println("BMP180 init fail (disconnected?)\n\n");
while(1); // Pause forever.
}
baseline = getPressure();
// Initialize HMC5883L
Serial.println("Initialize HMC5883L");
while (!compass.begin())
{
Serial.println("Could not find a valid HMC5883L sensor, check wiring!");
delay(500);
}
// Set measurement range
// +/- 0.88 Ga: HMC5883L_RANGE_0_88GA
// +/- 1.30 Ga: HMC5883L_RANGE_1_3GA (default)
// +/- 1.90 Ga: HMC5883L_RANGE_1_9GA
// +/- 2.50 Ga: HMC5883L_RANGE_2_5GA
// +/- 4.00 Ga: HMC5883L_RANGE_4GA
// +/- 4.70 Ga: HMC5883L_RANGE_4_7GA
// +/- 5.60 Ga: HMC5883L_RANGE_5_6GA
// +/- 8.10 Ga: HMC5883L_RANGE_8_1GA
compass.setRange(HMC5883L_RANGE_1_3GA);
// Set measurement mode
// Idle mode: HMC5883L_IDLE
// Single-Measurement: HMC5883L_SINGLE
// Continuous-Measurement: HMC5883L_CONTINOUS (default)
compass.setMeasurementMode(HMC5883L_CONTINOUS);
// Set data rate
// 0.75Hz: HMC5883L_DATARATE_0_75HZ
// 1.50Hz: HMC5883L_DATARATE_1_5HZ
// 3.00Hz: HMC5883L_DATARATE_3HZ
// 7.50Hz: HMC5883L_DATARATE_7_50HZ
// 15.00Hz: HMC5883L_DATARATE_15HZ (default)
// 30.00Hz: HMC5883L_DATARATE_30HZ
// 75.00Hz: HMC5883L_DATARATE_75HZ
compass.setDataRate(HMC5883L_DATARATE_3HZ);
// Set number of samples averaged
// 1 sample: HMC5883L_SAMPLES_1 (default)
// 2 samples: HMC5883L_SAMPLES_2
// 4 samples: HMC5883L_SAMPLES_4
// 8 samples: HMC5883L_SAMPLES_8
compass.setSamples(HMC5883L_SAMPLES_8);
// Set calibration offset. See HMC5883L_calibration.ino
compass.setOffset(-56, -156);
}
double getPressure()
{
char status;
double T,P,p0,a;
// You must first get a temperature measurement to perform a pressure reading.
// Start a temperature measurement:
// If request is successful, the number of ms to wait is returned.
// If request is unsuccessful, 0 is returned.
status = pressure.startTemperature();
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
// Retrieve the completed temperature measurement:
// Note that the measurement is stored in the variable T.
// Use '&T' to provide the address of T to the function.
// Function returns 1 if successful, 0 if failure.
status = pressure.getTemperature(T);
if (status != 0)
{
// Start a pressure measurement:
// The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
// If request is successful, the number of ms to wait is returned.
// If request is unsuccessful, 0 is returned.
status = pressure.startPressure(3);
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
// Retrieve the completed pressure measurement:
// Note that the measurement is stored in the variable P.
// Use '&P' to provide the address of P.
// Note also that the function requires the previous temperature measurement (T).
// (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
// Function returns 1 if successful, 0 if failure.
status = pressure.getPressure(P,T);
if (status != 0)
{
return(P);
}
else Serial.println("error retrieving pressure measurement\n");
}
else Serial.println("error starting pressure measurement\n");
}
else Serial.println("error retrieving temperature measurement\n");
}
else Serial.println("error starting temperature measurement\n");
}
void loop() {
// Only post when timer match occurs................
if (millis()>=ulNextMeas_ms)
{
ulNextMeas_ms = millis()+ulMeasDelta_ms;
long x = micros();
Vector norm = compass.readNormalize();
// Calculate heading
float heading = atan2(norm.YAxis, norm.XAxis);
// Set declination angle on your location and fix heading
// You can find your declination on: http://magnetic-declination.com/
// (+) Positive or (-) for negative
// For Glasgow / Scotland declination angle is -2'59W (negative)
// Formula: (deg + (min / 60.0)) / (180 / M_PI);
float declinationAngle = (-2.0 + (59.0 / 60.0)) / (180 / M_PI);
heading += declinationAngle;
// Correct for heading < 0deg and heading > 360deg
if (heading < 0)
{
heading += 2 * PI;
}
if (heading > 2 * PI)
{
heading -= 2 * PI;
}
// Convert to degrees
float headingDegrees = heading * 180/M_PI;
// Fix HMC5883L issue with angles
float fixedHeadingDegrees;
if (headingDegrees >= 1 && headingDegrees < 240)
{
fixedHeadingDegrees = map(headingDegrees, 0, 239, 0, 179);
} else
if (headingDegrees >= 240)
{
fixedHeadingDegrees = map(headingDegrees, 240, 360, 180, 360);
}
// Smooth angles rotation for +/- 3deg
int smoothHeadingDegrees = round(fixedHeadingDegrees);
if (smoothHeadingDegrees < (previousDegree + 3) && smoothHeadingDegrees > (previousDegree - 3))
{
smoothHeadingDegrees = previousDegree;
}
previousDegree = smoothHeadingDegrees;
// Use WiFiClient class to create Thingspeak Post
WiFiClient client;
if (!client.connect(hostts, 80)) {
return;
}
//Construct the post...
String url = "/update?key=";
url += thingspeak_key;
url += "&field1=";
url += fixedHeadingDegrees;
url += "&field2=";
url += headingDegrees;
url += "&field3=";
url += smoothHeadingDegrees;
url += "&field4=";
url += norm.XAxis;
url += "&field5=";
url += norm.YAxis;
url += "&field6=";
url += norm.ZAxis;
delay(3000);
// This will send the Thingspeak Post request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + hostts + "\r\n" +
"Connection: close\r\n\r\n");
delay(50);
client.stop();
char status;
P = getPressure();
a = pressure.altitude(P,baseline);
p0 = pressure.sealevel(P,ALTITUDE);
pressure.getTemperature(T);
status = pressure.startTemperature();
if (status != 0)
{
// Wait for the measurement to complete:
delay(status);
// Retrieve the completed temperature measurement:
// Note that the measurement is stored in the variable T.
// Function returns 1 if successful, 0 if failure.
}
status = pressure.getTemperature(T);
// Use WiFiClient class to create Thingspeak Post to Second Channel.....
if (!client.connect(hostts, 80)) {
return;
}
//Construct the post...
url = "/update?key=";
url += thingspeak_key1;
url += "&field1=";
url += T;
url += "&field2=";
url += P,2;
url += "&field3=";
url += P*0.0295333727,2;
url += "&field4=";
url += a,0;
url += "&field5=";
url += a*3.28084,0;
// This will send the Thingspeak Post request to the server
client.print(String("GET ") + url + " HTTP/1.1\r\n" +
"Host: " + hostts + "\r\n" +
"Connection: close\r\n\r\n");
delay(50);
client.stop();
tweet_count++;
if (tweet_count==tweet_timer){
int TEint = T+0.5;
int MpressU = p0+0.5;
sprintf(buf, "Current room Temp: %dC Air Pressure(MSLP): %dmbar, TweetNo: %d via an #ESP8266", TEint, MpressU, i );
tweet (buf);
i++;
tweet_count=0;
}
}
}
The modified Twitter.h.....
Code: Select all
/*
Twitter.cpp - Arduino library to Post messages to Twitter using OAuth.
Copyright (c) NeoCat 2010-2011. All right reserved.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
// ver1.2 - Use <Udp.h> to support IDE 0019 or later
// ver1.3 - Support IDE 1.0
#ifndef TWITTER_H
#define TWITTER_H
#include <inttypes.h>
#include <pgmspace.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <WiFiUdp.h>
class Twitter
{
private:
uint8_t parseStatus;
int statusCode;
const char *token;
WiFiClient client;;
public:
Twitter(const char *user_and_passwd);
bool post(const char *msg);
bool checkStatus(Print *debug = NULL);
int wait(Print *debug = NULL);
int status(void) { return statusCode; }
};
#endif //TWITTER_H
The twitter feed.....
https://twitter.com/mcuautomation
The Thingspeak page......
https://thingspeak.com/channels/73449
The Device.....