Skip to content

Instantly share code, notes, and snippets.

@dgomes
Last active August 29, 2015 14:07
Show Gist options
  • Select an option

  • Save dgomes/7fedf94026761bfa973b to your computer and use it in GitHub Desktop.

Select an option

Save dgomes/7fedf94026761bfa973b to your computer and use it in GitHub Desktop.
Greenhouse Source Code
// Greenhouse Interface to read and actuate
#include <Narcoleptic.h>
#include <DHT.h>
#include <SPI.h>
#include <OneWire.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "GreenHouseProtocol.h"
#define DEBUG
#ifdef DEBUG
#define PRINT(X) Serial.print(X)
#define PRINTLN(X) Serial.println(X)
#else
#define PRINT(X)
#define PRINTLN(X)
#endif
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#define PHOTOCELL A5 // the cell and 10K pulldown are connected to a0
#define HUMIDITY0 A0
#define HUMIDITY1 A1
#define HUMIDITY2 A2
#define HUMIDITY3 A3
#define HUMPOWER 4 // what pin controls the external BC548 that powers the humidity sensors
#define DHTPIN 3 // what pin DHT connected to
#define RELAY 5 // what pin RELAY connected to
#define DB18B20 8 // what pin the DB18B20 temperature sensor is connected to
DHT dht;
// Set up nRF24L01 radio on SPI bus plus pins 9 & 10
RF24 radio(9,10);
// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
void powerOnSensors() {
pinMode(HUMPOWER, OUTPUT);
digitalWrite(HUMPOWER, HIGH); //turn ON humidity sensors
#ifdef DEBUG
Serial.begin(115200);
#endif
radio.powerUp();
dht.setup(DHTPIN, DHT::DHT22);
delay(dht.getMinimumSamplingPeriod());
pinMode(RELAY, OUTPUT);
pinMode(PHOTOCELL, INPUT);
pinMode(HUMIDITY0, INPUT);
pinMode(HUMIDITY1, INPUT);
pinMode(HUMIDITY2, INPUT);
pinMode(HUMIDITY3, INPUT);
}
void powerOffSensors() {
radio.powerDown();
//save power on pins by turing them into input
pinMode(HUMPOWER, INPUT);
pinMode(RELAY, INPUT);
}
void setup() {
#ifdef DEBUG
Serial.begin(115200);
printf_begin();
Serial.println("Greenhouse v4");
#endif
analogReference(DEFAULT);
pinMode(HUMPOWER, OUTPUT);
pinMode(RELAY, OUTPUT);
pinMode(PHOTOCELL, INPUT);
pinMode(HUMIDITY0, INPUT);
pinMode(HUMIDITY1, INPUT);
pinMode(HUMIDITY2, INPUT);
pinMode(HUMIDITY3, INPUT);
pinMode(DB18B20, INPUT);
dht.setup(DHTPIN);
//
// Setup and configure rf radio
//
radio.begin();
// enable dynamic payloads
radio.enableDynamicPayloads();
// optionally, increase the delay between retries & # of retries
radio.setRetries(15,15);
radio.setAutoAck(false);
radio.setDataRate(RF24_250KBPS);
//radio.setPALevel(RF24_PA_MIN);
radio.openWritingPipe(pipes[1]);
radio.openReadingPipe(1,pipes[0]);
// Start listening
radio.startListening();
// Dump the configuration of the rf unit for debugging
#ifdef DEBUG
radio.printDetails();
Serial.println("done setup()");
#endif
}
int readLight() {
pinMode(PHOTOCELL, OUTPUT);
digitalWrite(PHOTOCELL, LOW);
delay(20);
pinMode(PHOTOCELL, INPUT);
delay(20);
analogRead(PHOTOCELL);
delay(10); //give it sometime http://forums.adafruit.com/viewtopic.php?f=25&t=11597
int photocellReading = analogRead(PHOTOCELL);
return photocellReading;
}
int readHumidityProbe(int num) {
pinMode(num, OUTPUT);
digitalWrite(num, LOW);
delay(20);
pinMode(num, INPUT);
delay(20);
analogRead(num);
delay(10); //give it sometime http://forums.adafruit.com/viewtopic.php?f=25&t=11597
//Serial.println(analogRead(num));
int humidityReading = 100 - 100*(analogRead(num)/1023.0);
return humidityReading;
}
boolean switchRelay(boolean val) {
if(val) {
digitalWrite(RELAY, HIGH);
} else {
digitalWrite(RELAY, LOW);
}
PRINT("WATER CMD: ");
PRINTLN(val);
return val;
}
float readDHTHumidity() {
float humidity = dht.getHumidity();
switch(dht.getStatus()) {
case DHT::ERROR_NONE:
return humidity;
case DHT::ERROR_TIMEOUT:
case DHT::ERROR_CHECKSUM:
return dht.getStatus();
}
}
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}
float readDHTTemperature() {
float temp = dht.getTemperature();
switch(dht.getStatus()) {
case DHT::ERROR_NONE:
return temp;
case DHT::ERROR_TIMEOUT:
case DHT::ERROR_CHECKSUM:
return dht.getStatus();
}
}
float readInternalTemperature() {
// DS18B20 Temperature chip i/o
// adapted from http://playground.arduino.cc/Learning/OneWire
// tested with http://dx.com/p/ds18b20-digital-temperature-sensor-module-for-arduino-55-125-c-135047
OneWire ds(DB18B20);
byte i;
byte present = 0;
byte data[12];
byte addr[8];
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;
if ( !ds.search(addr)) {
PRINT("No more addresses.\n");
ds.reset_search();
return -255.0;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
PRINT("CRC is not valid!\n");
return -255.1;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
Whole = Tc_100 / 100; // separate off the whole and fractional portions
Fract = Tc_100 % 100;
if (SignBit) // If its negative
{
return -1*(float(Whole*100+Fract)/100);
}
return (float(Whole*100+Fract)/100);
}
void sendValues() {
// First, stop listening so we can talk
radio.stopListening();
int hprobe[4] = { readHumidityProbe(HUMIDITY0), readHumidityProbe(HUMIDITY1), readHumidityProbe(HUMIDITY2), readHumidityProbe(HUMIDITY3)};
digitalWrite(HUMPOWER, LOW); //turn OFF humidity sensors
struct GHDataPacket p = report(readVcc(), readDHTHumidity(), readDHTTemperature(), readInternalTemperature(), readLight(), hprobe, digitalRead(RELAY));
boolean r = radio.write( &p, sizeof(struct GHDataPacket));
#ifdef DEBUG
Serial.println(r ? "\nSent VALUES" : "\nFailed to send VALUES");
printDebug(p);
#endif
// Now, resume listening so we catch the next packets.
radio.startListening();
}
void loop() {
sendValues();
delay(250); //give sometime to reply back with command
if ( radio.available() ) {
uint8_t len;
struct GHCommandPacket c;
bool done = false;
while (!done) {
// Fetch the payload, and see if this was the last one.
len = radio.getDynamicPayloadSize();
if(len == (sizeof(struct GHCommandPacket))) {
done = radio.read(&c, len );
} else {
PRINTLN("Error receiving GHCommandPacket");
}
}
switch(c.cmd) {
case GH_GETDATA:
break;
case GH_ONSWITCH:
switchRelay(true);
break;
case GH_OFFSWITCH:
switchRelay(false);
break;
}
sendValues();
}
powerOffSensors();
Narcoleptic.delay(30000); // During this time power consumption is minimised
powerOnSensors();
}
#ifndef GREENHOUSEPROTOCOL_H
#define GREENHOUSEPROTOCOL_H
#include <Arduino.h>
typedef enum { GH_GETDATA = 0, GH_ONSWITCH = 1, GH_OFFSWITCH = 2 } gh_command;
struct GHCommandPacket {
gh_command cmd;
};
struct GHDataPacket {
long vcc;
float humidity;
float temperature;
float internaltemperature;
int luminosity;
int humidityProbe[4];
byte water;
};
struct GHCommandPacket getData() {
struct GHCommandPacket p;
p.cmd = GH_GETDATA;
return p;
}
struct GHCommandPacket turnOnSwitch() {
struct GHCommandPacket p;
p.cmd = GH_ONSWITCH;
return p;
}
struct GHCommandPacket turnOffSwitch() {
struct GHCommandPacket p;
p.cmd = GH_OFFSWITCH;
return p;
}
struct GHDataPacket report(long vcc, float h, float t, float it, int l, int hp[4], byte w) {
struct GHDataPacket p;
p.vcc = vcc;
p.humidity = h;
p.temperature = t;
p.internaltemperature = it;
p.luminosity = l;
for(int i=0; i<4; i++)
p.humidityProbe[i] = hp[i];
p.water = w;
return p;
}
void printDebug(struct GHDataPacket p) {
Serial.print("VCC: ");
Serial.print(p.vcc);
Serial.println(" v");
Serial.print("Humidity: ");
Serial.print(p.humidity);
Serial.println(" %");
Serial.print("Temperature: ");
Serial.print(p.temperature);
Serial.println(" *C");
Serial.print("Internal Temperature: ");
Serial.print(p.internaltemperature);
Serial.println(" *C");
Serial.print("Luminosity: ");
Serial.println(p.luminosity);
int probes = sizeof(p.humidityProbe)/2; /* int = 2 bytes */
Serial.print("Humidity Probes: [");
for(int i=0; i<probes-1; i++) {
Serial.print(p.humidityProbe[i]);
Serial.print(", ");
}
Serial.print(p.humidityProbe[probes-1]);
Serial.println("]");
Serial.print("Water: ");
Serial.println(p.water);
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment