Prototype V1 IMP Code
Posted by Taylor Bernard on January 3, 2014
here's an existing guys temp sensor code with xively web IDE so its new
// AGENT:
/*
Copyright (C) 2013 electric imp, inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* TempBug Example Agent Code
* Tom Byrne
* tom@electricimp.com
* 12/5/2013
*/
/* GLOBALS and CONSTANTS -----------------------------------------------------*/
const XIVELY_API_KEY = "ADD YOUR API KEY HERE";
const XIVELY_FEED_ID = "ADD YOUR FEED ID HERE";
Xively <- {}; // this makes a 'namespace'
/* CLASS AND GLOBAL FUNCTION DEFINITIONS -------------------------------------*/
// Xively "library". See https://github.com/electricimp/reference/tree/master/webservices/xively
class Xively.Client {
ApiKey = null;
triggers = [];
constructor(apiKey) {
this.ApiKey = apiKey;
}
/*****************************************
* method: PUT
* IN:
* feed: a XivelyFeed we are pushing to
* ApiKey: Your Xively API Key
* OUT:
* HttpResponse object from Xively
* 200 and no body is success
*****************************************/
function Put(feed){
local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
local request = http.put(url, headers, feed.ToJson());
return request.sendsync();
}
/*****************************************
* method: GET
* IN:
* feed: a XivelyFeed we fulling from
* ApiKey: Your Xively API Key
* OUT:
* An updated XivelyFeed object on success
* null on failure
*****************************************/
function Get(feed){
local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
local headers = { "X-ApiKey" : ApiKey, "User-Agent" : "xively-Imp-Lib/1.0" };
local request = http.get(url, headers);
local response = request.sendsync();
if(response.statuscode != 200) {
server.log("error sending message: " + response.body);
return null;
}
local channel = http.jsondecode(response.body);
for (local i = 0; i < channel.datastreams.len(); i++)
{
for (local j = 0; j < feed.Channels.len(); j++)
{
if (channel.datastreams[i].id == feed.Channels[j].id)
{
feed.Channels[j].current_value = channel.datastreams[i].current_value;
break;
}
}
}
return feed;
}
}
class Xively.Feed{
FeedID = null;
Channels = null;
constructor(feedID, channels)
{
this.FeedID = feedID;
this.Channels = channels;
}
function GetFeedID() { return FeedID; }
function ToJson()
{
local json = "{ \"datastreams\": [";
for (local i = 0; i < this.Channels.len(); i++)
{
json += this.Channels[i].ToJson();
if (i < this.Channels.len() - 1) json += ",";
}
json += "] }";
return json;
}
}
class Xively.Channel {
id = null;
current_value = null;
constructor(_id)
{
this.id = _id;
}
function Set(value) {
this.current_value = value;
}
function Get() {
return this.current_value;
}
function ToJson() {
return http.jsonencode({id = this.id, current_value = this.current_value });
}
}
/* REGISTER DEVICE CALLBACKS ------------------------------------------------*/
device.on("temp", function(datapoint) {
server.log("Got new temp data: "+datapoint+" degrees");
xivelyChannel.Set(datapoint);
xivelyFeed <- Xively.Feed(XIVELY_FEED_ID, [xivelyChannel]);
xivelyClient.Put(xivelyFeed);
});
/* REGISTER HTTP HANDLER -----------------------------------------------------*/
// This agent does not need an HTTP handler
/* RUNTIME BEGINS HERE -------------------------------------------------------*/
server.log("TempBug Agent Running");
// instantiate our Xively client
xivelyClient <- Xively.Client(XIVELY_API_KEY);
xivelyChannel <- Xively.Channel("temperature");
// AGENT:
/*
Copyright (C) 2013 electric imp, inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* TempBug Example Agent Code
* Tom Byrne
* tom@electricimp.com
* 12/5/2013
*/
/* GLOBALS and CONSTANTS -----------------------------------------------------*/
const XIVELY_API_KEY = "ADD YOUR API KEY HERE";
const XIVELY_FEED_ID = "ADD YOUR FEED ID HERE";
Xively <- {}; // this makes a 'namespace'
/* CLASS AND GLOBAL FUNCTION DEFINITIONS -------------------------------------*/
// Xively "library". See https://github.com/electricimp/reference/tree/master/webservices/xively
class Xively.Client {
ApiKey = null;
triggers = [];
constructor(apiKey) {
this.ApiKey = apiKey;
}
/*****************************************
* method: PUT
* IN:
* feed: a XivelyFeed we are pushing to
* ApiKey: Your Xively API Key
* OUT:
* HttpResponse object from Xively
* 200 and no body is success
*****************************************/
function Put(feed){
local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
local headers = { "X-ApiKey" : ApiKey, "Content-Type":"application/json", "User-Agent" : "Xively-Imp-Lib/1.0" };
local request = http.put(url, headers, feed.ToJson());
return request.sendsync();
}
/*****************************************
* method: GET
* IN:
* feed: a XivelyFeed we fulling from
* ApiKey: Your Xively API Key
* OUT:
* An updated XivelyFeed object on success
* null on failure
*****************************************/
function Get(feed){
local url = "https://api.xively.com/v2/feeds/" + feed.FeedID + ".json";
local headers = { "X-ApiKey" : ApiKey, "User-Agent" : "xively-Imp-Lib/1.0" };
local request = http.get(url, headers);
local response = request.sendsync();
if(response.statuscode != 200) {
server.log("error sending message: " + response.body);
return null;
}
local channel = http.jsondecode(response.body);
for (local i = 0; i < channel.datastreams.len(); i++)
{
for (local j = 0; j < feed.Channels.len(); j++)
{
if (channel.datastreams[i].id == feed.Channels[j].id)
{
feed.Channels[j].current_value = channel.datastreams[i].current_value;
break;
}
}
}
return feed;
}
}
class Xively.Feed{
FeedID = null;
Channels = null;
constructor(feedID, channels)
{
this.FeedID = feedID;
this.Channels = channels;
}
function GetFeedID() { return FeedID; }
function ToJson()
{
local json = "{ \"datastreams\": [";
for (local i = 0; i < this.Channels.len(); i++)
{
json += this.Channels[i].ToJson();
if (i < this.Channels.len() - 1) json += ",";
}
json += "] }";
return json;
}
}
class Xively.Channel {
id = null;
current_value = null;
constructor(_id)
{
this.id = _id;
}
function Set(value) {
this.current_value = value;
}
function Get() {
return this.current_value;
}
function ToJson() {
return http.jsonencode({id = this.id, current_value = this.current_value });
}
}
/* REGISTER DEVICE CALLBACKS ------------------------------------------------*/
device.on("temp", function(datapoint) {
server.log("Got new temp data: "+datapoint+" degrees");
xivelyChannel.Set(datapoint);
xivelyFeed <- Xively.Feed(XIVELY_FEED_ID, [xivelyChannel]);
xivelyClient.Put(xivelyFeed);
});
/* REGISTER HTTP HANDLER -----------------------------------------------------*/
// This agent does not need an HTTP handler
/* RUNTIME BEGINS HERE -------------------------------------------------------*/
server.log("TempBug Agent Running");
// instantiate our Xively client
xivelyClient <- Xively.Client(XIVELY_API_KEY);
xivelyChannel <- Xively.Channel("temperature");
Comments
Taylor Bernard on January 3, 2014:
/*
Copyright (C) 2013 electric imp, inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* TempBug Example Device Code
* Tom Byrne
* tom@electricimp.com
* 12/5/2013
*/
/* GLOBALS and CONSTANTS -----------------------------------------------------*/
// all calculations are done in Kelvin
// these are constants for this particular thermistor; if using a different one,
// check your datasheet
const b_therm = 3988;
const t0_therm = 298.15;
const r_therm = 10000;
const WAKEINTERVAL_MIN = 15; // interval between wake-and-reads in minutes
/* CLASS AND GLOBAL FUNCTION DEFINITIONS -------------------------------------*/
/*
* simple NTC thermistor
*
* Assumes thermistor is the high side of a resistive divider unless otherwise specified in constructor.
* Low-side resistor is of the same nominal resistance as the thermistor
*/
class thermistor {
// thermistor constants are shown on your thermistor datasheet
// beta value (for the temp range your device will operate in)
b_therm = null;
t0_therm = null;
// nominal resistance of the thermistor at room temperature
r0_therm = null;
// analog input pin
p_therm = null;
points_per_read = null;
high_side_therm = null;
constructor(pin, b, t0, r, points = 10, _high_side_therm = true) {
this.p_therm = pin;
this.p_therm.configure(ANALOG_IN);
// force all of these values to floats in case they come in as integers
this.b_therm = b * 1.0;
this.t0_therm = t0 * 1.0;
this.r0_therm = r * 1.0;
this.points_per_read = points * 1.0;
this.high_side_therm = _high_side_therm;
}
// read thermistor in Kelvin
function read() {
local vdda_raw = 0;
local vtherm_raw = 0;
for (local i = 0; i < points_per_read; i++) {
vdda_raw += hardware.voltage();
vtherm_raw += p_therm.read();
}
local vdda = (vdda_raw / points_per_read);
local v_therm = (vtherm_raw / points_per_read) * (vdda / 65535.0);
local r_therm = 0;
if (high_side_therm) {
r_therm = (vdda - v_therm) * (r0_therm / v_therm);
} else {
r_therm = r0_therm / ((vdda / v_therm) - 1);
}
local ln_therm = math.log(r0_therm / r_therm);
local t_therm = (t0_therm * b_therm) / (b_therm - t0_therm * ln_therm);
return t_therm;
}
// read thermistor in Celsius
function read_c() {
return this.read() - 273.15;
}
// read thermistor in Fahrenheit
function read_f() {
local temp = this.read() - 273.15;
return (temp * 9.0 / 5.0 + 32.0);
}
}
/* REGISTER AGENT CALLBACKS --------------------------------------------------*/
/* RUNTIME BEGINS HERE -------------------------------------------------------*/
// Register with imp server
imp.configure("TempBug",[],[]);
// Configure Pins
// pin 8 is driven high to turn off temp monitor (saves power) or low to read
therm_en_l <- hardware.pin8;
therm_en_l.configure(DIGITAL_OUT);
therm_en_l.write(1);
// pin 9 is the middle of the voltage divider formed by the NTC - read the analog voltage to determine temperature
temp_sns <- hardware.pin9;
// instantiate our thermistor class
myThermistor <- thermistor(temp_sns, b_therm, t0_therm, r_therm, 10, false);
// enable the temperature sensor
therm_en_l.write(0);
// wait 5 ms to let things settle
imp.sleep(0.005);
// read the temperature and send it to the agent
agent.send("temp",format("%.2f",myThermistor.read_c()));
// Prefer Fahrenheit? Use the line below instead of the one above.
//agent.send("temp",format("%.2f",myThermistor.read_f()));
// disable the temperature sensor again to save power
therm_en_l.write(1);
//Sleep for 15 minutes and 1 second, minus the time past the 0:15
//so we wake up near each 15 minute mark (prevents drifting on slow DHCP)
imp.onidle( function() {
server.sleepfor(1 + WAKEINTERVAL_MIN*60 - (time() % (WAKEINTERVAL_MIN*60)));
});
// full firmware is reloaded and run from the top on each wake cycle, so no need to construct a loop
Taylor Bernard on January 3, 2014:
http://www.instructables.com/id/TempBug-internet-connected-thermometer/?ALLSTEPS
Justin Bernard on January 5, 2014:
may have to start up a new project or something to get that feed ID. API key is most likely generated whenever a new account is established. lemme know if you have problems finding either of those...
Justin Bernard on January 5, 2014:
Taylor Bernard on January 6, 2014:
2069217821
API:
4Nig4ELdAFXz974hq8JJRTbPljJfMggJgIoFe7l6FbFvOhVo
in his documentation i think he said that it creates a new channel (data feed stream for a certain variable) thru his code. i dont think we want this, as i have already setup a channel for us
Taylor Bernard on January 6, 2014:
now just need to figure out Xively side.
Taylor Bernard on January 6, 2014:
http://learn.adafruit.com/connecting-the-max31855-thermocouple-amplifier-breakout-to-an-electric-imp/configure-the-agent-for-xively
but look at their agent code....WTF....
https://github.com/joel-wehr/Tutorial_Electric_Imp_MAX31855/blob/master/agent.nut
Taylor Bernard on January 6, 2014:
Taylor Bernard on January 6, 2014:
//-------------------------------
Justin Bernard on January 6, 2014:
working on your temp equation at the moment, need anything else?
Taylor Bernard on January 6, 2014:
Justin Bernard on January 6, 2014:
for now just see if you can get the device to cloud communication down maybe
Taylor Bernard on January 6, 2014:
//-----------------
//From the bildr article http://bildr.org/2012/11/flexiforce-arduino/
int flexiForcePin = A0; //analog pin 0
void setup(){
Serial.begin(9600);
}
void loop(){
int flexiForceReading = analogRead(flexiForcePin);
Serial.println(flexiForceReading);
delay(250); //just here to slow down the output for easier reading
}
Justin Bernard on January 6, 2014:
Justin Bernard on January 6, 2014:
Taylor Bernard on January 16, 2014:
WORKING CODE:
Justin Bernard on January 17, 2014:
Taylor Bernard on January 22, 2014:
//=============================
#include <stdio.h> #include <homelab/adc.h> #include <homelab/delay.h> #include <homelab/pin.h> #include <homelab/module/lcd_gfx.h> // Map a value from one range to another. long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } // Main program int main(void) { signed short value; // The analog reading. char text[16]; int voltage; // The analog reading converted to voltage. unsigned long resistance; // The voltage converted to resistance. unsigned long conductance; long force; // The resistance converted to force. long weight; // The force converted to weight. // Set the external sensors pins. pin ex_sensors = PIN(G, 0); pin_setup_output(ex_sensors); pin_set(ex_sensors); // LCD initialization. lcd_gfx_init(); // Display clearing. lcd_gfx_clear(); // Move the cursor to the right of the screen. lcd_gfx_goto_char_xy(1,1); // Print the name of the program. lcd_gfx_write_string("Force sensor"); // Set the ADC. adc_init(ADC_REF_AVCC, ADC_PRESCALE_8); // An endless loop. while (true) { // Converting and averaging channel 0 value. value = adc_get_average_value(0, 4); // Analog voltage reading ranges from about 0 to 1023 // which maps to 0V to 5V (= 5000mV) voltage = map(value, 0, 1023, 0, 5000); // The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V // so FSR = ( (Vcc - V) * R) / V // fsrVoltage is in millivolts so 5V = 5000mV resistance = 5000 - voltage; resistance *= 10000; // 10K resistor resistance /= voltage; // FSR resistance in ohms. conductance = 1000000; //We measure in micromhos. conductance /= resistance; //Conductance in microMhos. // Move the cursor to the right of the screen. lcd_gfx_goto_char_xy(1,3); // Calculate the force. force = conductance / 80; sprintf(text, "%lu Newtons ", force); // Printing of the force. lcd_gfx_goto_char_xy(1,3); lcd_gfx_write_string(text); // Printing and calculating of the weight. lcd_gfx_goto_char_xy(1,4); weight = force / 9,8; sprintf(text, "%lu kg ", weight); lcd_gfx_write_string(text); // Delay. sw_delay_ms(500); } }Justin Bernard on January 22, 2014:
Justin Bernard on January 22, 2014: