Skip to content

Instantly share code, notes, and snippets.

@wgbartley
Created April 26, 2014 05:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wgbartley/11312233 to your computer and use it in GitHub Desktop.
Save wgbartley/11312233 to your computer and use it in GitHub Desktop.
Spark Sensor Madness with Classes
#include "DHT.h"
DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) {
_pin = pin;
_type = type;
_count = count;
firstreading = true;
}
void DHT::begin(void) {
// set up the pins!
pinMode(_pin, INPUT);
digitalWrite(_pin, HIGH);
_lastreadtime = 0;
}
//boolean S == Scale. True == Farenheit; False == Celcius
float DHT::readTemperature(bool S) {
float _f;
if (read()) {
switch (_type) {
case DHT11:
_f = data[2];
if(S)
_f = convertCtoF(_f);
return _f;
case DHT22:
case DHT21:
_f = data[2] & 0x7F;
_f *= 256;
_f += data[3];
_f /= 10;
if (data[2] & 0x80)
_f *= -1;
if(S)
_f = convertCtoF(_f);
return _f;
}
}
return NAN;
}
float DHT::convertCtoF(float c) {
return c * 9 / 5 + 32;
}
float DHT::readHumidity(void) {
float _f;
if (read()) {
switch (_type) {
case DHT11:
_f = data[0];
return _f;
case DHT22:
case DHT21:
_f = data[0];
_f *= 256;
_f += data[1];
_f /= 10;
return _f;
}
}
return NAN;
}
bool DHT::read(void) {
uint8_t laststate = HIGH;
uint8_t counter = 0;
uint8_t j = 0, i;
unsigned long currenttime;
// pull the pin high and wait 250 milliseconds
digitalWrite(_pin, HIGH);
delay(250);
currenttime = millis();
if (currenttime < _lastreadtime) {
// ie there was a rollover
_lastreadtime = 0;
}
if (!firstreading && ((currenttime - _lastreadtime) < 2000)) {
//delay(2000 - (currenttime - _lastreadtime));
return true; // return last correct measurement
}
firstreading = false;
_lastreadtime = millis();
data[0] = data[1] = data[2] = data[3] = data[4] = 0;
// now pull it low for ~20 milliseconds
pinMode(_pin, OUTPUT);
digitalWrite(_pin, LOW);
delay(20);
cli();
digitalWrite(_pin, HIGH);
delayMicroseconds(40);
pinMode(_pin, INPUT);
// read in timings
for ( i=0; i< MAXTIMINGS; i++) {
counter = 0;
while (digitalRead(_pin) == laststate) {
counter++;
delayMicroseconds(1);
if (counter == 255)
break;
}
laststate = digitalRead(_pin);
if (counter == 255)
break;
// ignore first 3 transitions
if ((i >= 4) && (i%2 == 0)) {
// shove each bit into the storage bytes
data[j/8] <<= 1;
if (counter > _count)
data[j/8] |= 1;
j++;
}
}
sei();
// check we read 40 bits and that the checksum matches
if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)))
return true;
return false;
}
#include <math.h>
#define MAXTIMINGS 85
#define cli noInterrupts
#define sei interrupts
#define DHT11 11
#define DHT22 22
#define DHT21 21
#define AM2301 21
class DHT {
private:
uint8_t data[6];
uint8_t _pin, _type, _count;
bool read(void);
unsigned long _lastreadtime;
bool firstreading;
public:
DHT(uint8_t pin, uint8_t type, uint8_t count=6);
void begin(void);
float readTemperature(bool S=false);
float convertCtoF(float);
float readHumidity(void);
};
#include "OneWire.h"
OneWire::OneWire(uint16_t pin) {
pinMode(pin, INPUT);
_pin = pin;
}
void OneWire::DIRECT_WRITE_LOW(void) {
PIN_MAP[_pin].gpio_peripheral->BRR = PIN_MAP[_pin].gpio_pin;
}
void OneWire::DIRECT_MODE_OUTPUT(void) {
GPIO_TypeDef *gpio_port = PIN_MAP[_pin].gpio_peripheral;
uint16_t gpio_pin = PIN_MAP[_pin].gpio_pin;
GPIO_InitTypeDef GPIO_InitStructure;
if (gpio_port == GPIOA )
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
else if (gpio_port == GPIOB )
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = gpio_pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
PIN_MAP[_pin].pin_mode = OUTPUT;
GPIO_Init(gpio_port, &GPIO_InitStructure);
}
void OneWire::DIRECT_WRITE_HIGH(void) {
PIN_MAP[_pin].gpio_peripheral->BSRR = PIN_MAP[_pin].gpio_pin;
}
void OneWire::DIRECT_MODE_INPUT(void) {
GPIO_TypeDef *gpio_port = PIN_MAP[_pin].gpio_peripheral;
uint16_t gpio_pin = PIN_MAP[_pin].gpio_pin;
GPIO_InitTypeDef GPIO_InitStructure;
if (gpio_port == GPIOA )
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
else if (gpio_port == GPIOB )
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = gpio_pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
PIN_MAP[_pin].pin_mode = INPUT;
GPIO_Init(gpio_port, &GPIO_InitStructure);
}
uint8_t OneWire::DIRECT_READ(void) {
return GPIO_ReadInputDataBit(PIN_MAP[_pin].gpio_peripheral, PIN_MAP[_pin].gpio_pin);
}
uint8_t OneWire::reset(void) {
uint8_t r;
uint8_t retries = 125;
noInterrupts();
DIRECT_MODE_INPUT();
interrupts();
do {
if (--retries == 0)
return 0;
delayMicroseconds(2);
} while ( !DIRECT_READ());
noInterrupts();
DIRECT_WRITE_LOW();
DIRECT_MODE_OUTPUT(); // drive output low
interrupts();
delayMicroseconds(480);
noInterrupts();
DIRECT_MODE_INPUT(); // allow it to float
delayMicroseconds(70);
r = !DIRECT_READ();
interrupts();
delayMicroseconds(410);
return r;
}
void OneWire::write_bit(uint8_t v) {
if (v & 1) {
noInterrupts();
DIRECT_WRITE_LOW();
DIRECT_MODE_OUTPUT(); // drive output low
delayMicroseconds(10);
DIRECT_WRITE_HIGH(); // drive output high
interrupts();
delayMicroseconds(55);
} else {
noInterrupts();
DIRECT_WRITE_LOW();
DIRECT_MODE_OUTPUT(); // drive output low
delayMicroseconds(65);
DIRECT_WRITE_HIGH(); // drive output high
interrupts();
delayMicroseconds(5);
}
}
uint8_t OneWire::read_bit(void) {
uint8_t r;
noInterrupts();
DIRECT_MODE_OUTPUT();
DIRECT_WRITE_LOW();
delayMicroseconds(3);
DIRECT_MODE_INPUT(); // let pin float, pull up will raise
delayMicroseconds(10);
r = DIRECT_READ();
interrupts();
delayMicroseconds(53);
return r;
}
void OneWire::write(uint8_t v, uint8_t power /* = 0 */) {
uint8_t bitMask;
for (bitMask = 0x01; bitMask; bitMask <<= 1)
OneWire::write_bit( (bitMask & v)?1:0);
if ( !power) {
noInterrupts();
DIRECT_MODE_INPUT();
DIRECT_WRITE_LOW();
interrupts();
}
}
void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) {
for (uint16_t i = 0 ; i < count ; i++)
write(buf[i]);
if (!power) {
noInterrupts();
DIRECT_MODE_INPUT();
DIRECT_WRITE_LOW();
interrupts();
}
}
uint8_t OneWire::read() {
uint8_t bitMask;
uint8_t r = 0;
for (bitMask = 0x01; bitMask; bitMask <<= 1)
if ( OneWire::read_bit())
r |= bitMask;
return r;
}
void OneWire::read_bytes(uint8_t *buf, uint16_t count) {
for (uint16_t i = 0 ; i < count ; i++)
buf[i] = read();
}
void OneWire::select(const uint8_t rom[8]) {
uint8_t i;
write(0x55); // Choose ROM
for (i = 0; i < 8; i++)
write(rom[i]);
}
void OneWire::skip() {
write(0xCC); // Skip ROM
}
void OneWire::depower() {
noInterrupts();
DIRECT_MODE_INPUT();
interrupts();
}
void OneWire::reset_search() {
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
for(int i = 7; ; i--) {
ROM_NO[i] = 0;
if ( i == 0)
break;
}
}
void OneWire::target_search(uint8_t family_code) {
ROM_NO[0] = family_code;
for (uint8_t i = 1; i < 8; i++)
ROM_NO[i] = 0;
LastDiscrepancy = 64;
LastFamilyDiscrepancy = 0;
LastDeviceFlag = FALSE;
}
uint8_t OneWire::search(uint8_t *newAddr) {
uint8_t id_bit_number;
uint8_t last_zero, rom_byte_number, search_result;
uint8_t id_bit, cmp_id_bit;
unsigned char rom_byte_mask, search_direction;
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = 0;
// if the last call was not the last one
if (!LastDeviceFlag)
{
// 1-Wire reset
if (!reset())
{
// reset the search
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
return FALSE;
}
// issue the search command
write(0xF0);
// loop to do the search
do
{
// read a bit and its complement
id_bit = read_bit();
cmp_id_bit = read_bit();
// check for no devices on 1-wire
if ((id_bit == 1) && (cmp_id_bit == 1))
break;
else
{
// all devices coupled have 0 or 1
if (id_bit != cmp_id_bit)
search_direction = id_bit; // bit write value for search
else
{
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < LastDiscrepancy)
search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
else
// if equal to last pick 1, if not then pick 0
search_direction = (id_bit_number == LastDiscrepancy);
// if 0 was picked then record its position in LastZero
if (search_direction == 0)
{
last_zero = id_bit_number;
// check for Last discrepancy in family
if (last_zero < 9)
LastFamilyDiscrepancy = last_zero;
}
}
// set or clear the bit in the ROM byte rom_byte_number
// with mask rom_byte_mask
if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask;
else
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
// serial number search direction write bit
write_bit(search_direction);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
if (rom_byte_mask == 0)
{
rom_byte_number++;
rom_byte_mask = 1;
}
}
}
while(rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!(id_bit_number < 65))
{
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
LastDiscrepancy = last_zero;
// check for last device
if (LastDiscrepancy == 0)
LastDeviceFlag = TRUE;
search_result = TRUE;
}
}
// if no device found then reset counters so next 'search' will be like a first
if (!search_result || !ROM_NO[0])
{
LastDiscrepancy = 0;
LastDeviceFlag = FALSE;
LastFamilyDiscrepancy = 0;
search_result = FALSE;
}
for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i];
return search_result;
}
uint8_t OneWire::crc8( uint8_t *addr, uint8_t len) {
uint8_t crc = 0;
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix)
crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc) {
crc = ~crc16(input, len, crc);
return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1];
}
uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc) {
static const uint8_t oddparity[16] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
for (uint16_t i = 0 ; i < len ; i++) {
uint16_t cdata = input[i];
cdata = (cdata ^ crc) & 0xff;
crc >>= 8;
if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4])
crc ^= 0xC001;
cdata <<= 6;
crc ^= cdata;
cdata <<= 1;
crc ^= cdata;
}
return crc;
}
#define OneWire_h
#include <inttypes.h>
#define ONEWIRE_SEARCH 1
#define ONEWIRE_CRC 1
#define ONEWIRE_CRC16 1
#define FALSE 0
#define TRUE 1
class OneWire {
private:
uint16_t _pin;
void DIRECT_WRITE_LOW(void);
void DIRECT_MODE_OUTPUT(void);
void DIRECT_WRITE_HIGH(void);
void DIRECT_MODE_INPUT(void);
uint8_t DIRECT_READ(void);
unsigned char ROM_NO[8];
uint8_t LastDiscrepancy;
uint8_t LastFamilyDiscrepancy;
uint8_t LastDeviceFlag;
public:
OneWire( uint16_t pin);
uint8_t reset(void);
void select(const uint8_t rom[8]);
void skip(void);
void write(uint8_t v, uint8_t power = 0);
void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0);
uint8_t read(void);
void read_bytes(uint8_t *buf, uint16_t count);
void write_bit(uint8_t v);
uint8_t read_bit(void);
void depower(void);
void reset_search();
void target_search(uint8_t family_code);
uint8_t search(uint8_t *newAddr);
static uint8_t crc8(uint8_t *addr, uint8_t len);
static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0);
static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0);
};
#include "Photocell.h"
Photocell::Photocell(int pin) {
_pin = pin;
}
void Photocell::begin(void) {
pinMode(_pin, INPUT);
}
int Photocell::getLightRaw(bool smooth=false) {
delay(1);
if(smooth==true) {
int total = 0;
for(int i=0; i<100; i++) {
total += analogRead(_pin);
delay(1);
}
_light_raw = total/100;
} else
_light_raw = analogRead(_pin);
return _light_raw;
}
float Photocell::getLightPercent(bool smooth=false) {
_light_raw = getLightRaw(smooth);
return (float)_light_raw/4096.0*100;
}
float Photocell::getLight(bool smooth=false) {
return getLightPercent(smooth);
}
class Photocell {
private:
int _pin;
int _light_raw;
float _light_percent;
public:
Photocell(int pin);
void begin(void);
float getLight(bool smooth);
int getLightRaw(bool smooth);
float getLightPercent(bool smooth);
};
// Includes
#include "DHT.h"
#include "OneWire.h"
#include "Thermistor.h"
#include "Photocell.h"
// DHT22 SETUP
#define DHTPIN D0
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// THERMISTOR SETUP
#define THERMPIN A0 // Spark Core analog input pin
#define THERMRES 10000 // Value of voltage divider resistor
Thermistor Thermistor(THERMPIN, THERMRES);
// DS18B20 SETUP
OneWire one = OneWire(D1);
// PHOTOCELL SETUP
#define LDRPIN A1
Photocell Photocell(LDRPIN);
// LED COLORS
uint8_t colorRed[3] = { 255, 0, 0 };
uint8_t colorOrange[3] = { 255, 165, 0 };
uint8_t colorYellow[3] = { 255, 255, 0 };
uint8_t colorGreen[3] = { 0, 255, 0 };
uint8_t colorBlue[3] = { 0, 0, 255 };
uint8_t colorPurple[3] = { 128, 0, 128 };
uint8_t colorWhite[3] = { 255, 255, 255 };
uint8_t colorPink[3] = { 255, 192, 203 };
char lastCommand[64] = "NONE";
void setup() {
dht.begin();
Thermistor.begin();
Photocell.begin();
// Cloud functions
Spark.function("fnrouter", fnRouter);
// Cloud variables
Spark.variable("lastCommand", &lastCommand, STRING);
// Delay for DHT22
while(millis()%2000!=0);
// Get initial reading to flush out bad stuff
dht.readHumidity();
dht.readTemperature();
}
void loop() {
// Do nothing
}
float oneTemp() {
uint8_t rom[8];
uint8_t resp[9];
// Get the ROM address
one.reset();
one.write(0x33);
one.read_bytes(rom, 8);
// Get the temp
one.reset();
one.write(0x55);
one.write_bytes(rom,8);
one.write(0x44);
delay(10);
one.reset();
one.write(0x55);
one.write_bytes(rom, 8);
one.write(0xBE);
one.read_bytes(resp, 9);
byte MSB = resp[1];
byte LSB = resp[0];
float tempRead = ((MSB << 8) | LSB); //using two's compliment
float TemperatureSum = tempRead / 16;
return TemperatureSum;
}
int fnRouter(String command) {
command.trim();
command.toUpperCase();
command.toCharArray(lastCommand, 64);
blinkLedRapid(colorOrange);
if(command.equals("DHTHUMIDITY"))
return dht.readHumidity()*100;
else if(command.equals("DHTTEMP") || command.equals("DHTTEMPF"))
return dht.readTemperature(true)*100;
else if(command.equals("DHTTEMPC"))
return dht.readTemperature(false)*100;
else if(command.equals("THERMTEMPK"))
return (Thermistor.getTempK(false)*100);
else if(command.equals("THERMTEMPC"))
return (Thermistor.getTempC(false)*100);
else if(command.equals("THERMTEMP") || command.equals("THERMTEMPF"))
return (Thermistor.getTempF(true)-5)*100;
else if(command.equals("ONETEMPC"))
return oneTemp()*100;
else if(command.equals("ONETEMP") || command.equals("ONETEMPF"))
return ((oneTemp() * 9.0) / 5.0 + 32.0)*100;
else if(command.equals("PHOTOCELL"))
return (Photocell.getLight(true)*100);
else if(command.equals("PHOTOCELLRAW"))
return (Photocell.getLightRaw(true));
else if(command.equals("SECONDS"))
return millis()/1000;
else if(command.equals("MILLIS"))
return millis();
else if(command.equals("LEDRED"))
return blinkLed(colorRed);
else if(command.equals("LEDBLUE"))
return blinkLed(colorBlue);
else if(command.equals("LEDGREEN"))
return blinkLed(colorGreen);
else if(command.equals("LEDWHITE"))
return blinkLed(colorWhite);
else if(command.equals("LEDYELLOW"))
return blinkLed(colorYellow);
else if(command.equals("LEDORANGE"))
return blinkLed(colorOrange);
else if(command.equals("LEDPURPLE"))
return blinkLed(colorPurple);
else if(command.equals("LEDPINK"))
return blinkLed(colorPink);
else if(command.equals("D7BLINK"))
return blinkD7();
else {
blinkLedRapid(colorRed);
return -1000;
}
}
int blinkLed(uint8_t color[3]) {
RGB.control(true);
for(int i=0; i<3; i++) {
RGB.color(color[0], color[1], color[2]);
delay(250);
RGB.color(0, 0, 0);
delay(250);
}
RGB.control(false);
return 1;
}
int blinkLedRapid(uint8_t color[3]) {
RGB.control(true);
for(int i=0; i<10; i++) {
RGB.color(color[0], color[1], color[2]);
delay(25);
RGB.color(0, 0, 0);
delay(25);
}
RGB.control(false);
return 1;
}
int blinkD7() {
pinMode(D7, OUTPUT);
for(int i=0; i<3; i++) {
digitalWrite(D7, HIGH);
delay(250);
digitalWrite(D7, LOW);
delay(250);
}
return 1;
}
#include "Thermistor.h"
Thermistor::Thermistor(int pin, int resistor) {
_pin = pin;
_resistor = resistor;
}
void Thermistor::begin(void) {
pinMode(_pin, INPUT);
}
int Thermistor::getTempRaw(bool smooth=false) {
delay(1);
if(smooth==true) {
int total = 0;
for(int i=0; i<100; i++) {
total += analogRead(_pin);
delay(1);
}
_temp_raw = total/100;
} else
_temp_raw = analogRead(_pin);
return _temp_raw;
}
float Thermistor::getTempK(bool smooth=false) {
_temp_raw = getTempRaw(smooth);
_temp_k = log(((40960000/_temp_raw) - _resistor));
_temp_k = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * _temp_k * _temp_k ))* _temp_k);
return _temp_k;
}
float Thermistor::getTempC(bool smooth=false) {
_temp_k = getTempK(smooth);
_temp_c = _temp_k - 273.15;
return _temp_c;
}
float Thermistor::getTempF(bool smooth=false) {
_temp_c = getTempC(smooth);
_temp_f = (_temp_c * 9.0)/ 5.0 + 32.0;
return _temp_f;
}
float Thermistor::getTemp(bool smooth=false) {
return getTempC(smooth);
}
#include <math.h>
class Thermistor {
private:
int _pin;
int _resistor;
int _temp_raw;
float _temp_k;
float _temp_c;
float _temp_f;
public:
Thermistor(int pin, int resistor);
void begin(void);
float getTemp(bool smooth);
float getTempF(bool smooth);
float getTempC(bool smooth);
float getTempK(bool smooth);
int getTempRaw(bool smooth);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment