Skip to content

Instantly share code, notes, and snippets.

@openfirmware
Last active December 21, 2015 21:19
Show Gist options
  • Select an option

  • Save openfirmware/6367246 to your computer and use it in GitHub Desktop.

Select an option

Save openfirmware/6367246 to your computer and use it in GitHub Desktop.
Electric Imp program for April breakout board and NTC Thermistor to measure temperature wirelessly. Modified from original version to return Celsius instead of Fahrenheit.
/*
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.
*/
// April with a 10k, 1% from 3V3 to pin9 and 10k B57861S0103F040 NTC Thermistor from pin9 to pin8
// pin8 TEMP_READ_EN_L - drive low to enable temp reading (great for batteries!)
// pin9 ANALOG NTC value
// benchmarking runtime: first tick with hardware.micros
local tick = hardware.micros();
// turn on WiFi power save to reduce power consumption when awake
imp.setpowersave(true);
// Output structure for sending temperature to server
local resistOut = OutputPort("Resistance (Ohms)", "number");
local tempOut = OutputPort("Temperature (C)", "number");
local tempOutStr = OutputPort("Temperature (C)", "string");
local battOut = OutputPort("Battery Voltage", "number");
// Configure on planner and register with imp server
imp.configure("April NTC Thermometer (C)", [], [resistOut, tempOut, tempOutStr, battOut]);
// Configure Pins
//
// pin 8 is driven high to turn off temp monitor (saves power) or low to read.
hardware.pin8.configure(DIGITAL_OUT);
hardware.pin8.write(1);
// pin 9 is the middle of the voltage divider formed by the NTC - read the
// analog voltage to determine temperature.
hardware.pin9.configure(ANALOG_IN);
// 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 = 4540;
const t0_therm = 298.15;
// Battery Voltage
//
// To read the battery voltage reliably, we take 10 readings and average them.
local v_high = 0;
for(local i = 0; i < 10; i++){
imp.sleep(0.01);
v_high += hardware.voltage();
}
v_high = v_high / 10.0;
// Thermistor Reading
//
// Benchmarking: see how long thermistor is "on"
local ton = hardware.micros();
// Turn on the thermistor network
hardware.pin8.write(0);
// Gather several ADC readings and average them (just takes out some noise).
local val = 0;
for (local i = 0; i < 10; i++) {
imp.sleep(0.01);
val += hardware.pin9.read();
}
val = val / 10;
// Turn the thermistor network back off
hardware.pin8.write(1);
local toff = hardware.micros();
server.log(format("Thermistor Network on for %d microseconds", (toff - ton)));
// Scale the ADC reading to a voltage by dividing by the full-scale value and
// multiplying by the supply voltage
local v_therm = v_high * val / 65535.0;
// Calculate the resistance of the thermistor at the current temperature
local r_therm = 10000.0 / ( (v_high / v_therm) - 1);
resistOut.set(r_therm);
server.log("Current resistance is " + resistOut + " Ohms");
local ln_therm = math.log(10000.0 / r_therm);
local t_therm = (t0_therm * b_therm) / (b_therm - t0_therm * ln_therm) - 273.15;
// Format into a string for the string output port
local c_str = format("%.01f", t_therm);
server.log("Current temp is " + c_str + " C");
// Emit values to our output ports
tempOut.set(c_str);
tempOutStr.set(c_str + " C");
// Update the current battery voltage with a nicely-formatted string of the most
// recently-calculated value
local batt_str = format("%.02f V", v_high);
battOut.set(v_high);
server.log("Battery Voltage is " + batt_str);
// Benchmarking runtime
local tock = hardware.micros();
server.log(format("Read cycle took %d microseconds", (tock - tick)));
// 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 + 15 * 60 - (time() % (15 * 60)));
});
// full firmware is reloaded and run from the top on each wake cycle, so no need
// to construct a loop.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment