Skip to content

Instantly share code, notes, and snippets.

@dwblair
Created July 31, 2015 10:06
Show Gist options
  • Save dwblair/e9cc8776d8d5a53c2fc7 to your computer and use it in GitHub Desktop.
Save dwblair/e9cc8776d8d5a53c2fc7 to your computer and use it in GitHub Desktop.
/***************************************************
This is an example for our Adafruit FONA Cellular Module
Designed specifically to work with the Adafruit FONA
----> http://www.adafruit.com/products/1946
----> http://www.adafruit.com/products/1963
----> http://www.adafruit.com/products/2468
----> http://www.adafruit.com/products/2542
These cellular modules use TTL Serial to communicate, 2 pins are
required to interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#include "Adafruit_FONA.h"
#include <JeeLib.h>
#include <Wire.h>
#include <SPI.h>
#include <RTClib.h>
#include <RTC_DS3231.h>
#include<stdlib.h>
//sleeping stuff
ISR(WDT_vect) { Sleepy::watchdogEvent(); }
//RTC stuff
RTC_DS3231 RTC;
//led
#define led 9
//battery stuff
#define batteryAnalogMeasurePin A3
#define batteryReadCircuitSwitch 4
//FONA stuff ------------------------
//#define sendto "16512524765"
#define sendto "+15075818876"
//#define sendto "+16512524765"
#define FONA_RX 2
#define FONA_TX 5
#define FONA_RST A1
#define fonaKey A2
#define fonaPowerStatus 10
#define failCountMax 10
// which analog pin to connect
#define THERMISTORPIN A0
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3950
// the value of the 'other' resistor
#define SERIESRESISTOR 9550
// This is to handle the absence of software serial on platforms
// like the Arduino Due. Modify this code if you are using different
// hardware serial port, or if you are using a non-avr platform
// that supports software serial.
#ifdef __AVR__
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
#else
HardwareSerial *fonaSerial = &Serial1;
#endif
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
//end FONA stuff ------------------------
// debugging -- only do Serial output if debuggin
#define debug 1 // 0: don't print anything out; 1: print out debugging statements
// how long to sleep between measurements
#define sleepSeconds 30
int samples[NUMSAMPLES];
int interruptPin = 1; //corresponds to D2
// conductivity variables
long pulseCount = 0; //a pulse counter variable
unsigned long pulseTime,lastTime, duration, totalDuration;
int samplingPeriod=3; // the number of seconds to measure 555 oscillations
int sensorBoard = 8; // the pin that powers the 555 subcircuit
void setup() {
if (debug) Serial.begin(115200);
// begin I2C protocol (necessary for RTC, and any other I2C on board
Wire.begin();
// RTC -------------------------
initialize_RTC(); // NOTE: need to initialize I2C first -- but also for any other I2C library
// set mode for battery circuit control pin, and turn the circuit off
pinMode(batteryReadCircuitSwitch,OUTPUT);
pinMode(sensorBoard,OUTPUT);
digitalWrite(batteryReadCircuitSwitch, HIGH);
// FONA stuff ----------------------------------------------------
// set mode for FONA power status measurement pin
pinMode(fonaPowerStatus,INPUT);
//set mode for FONA power cycling key
pinMode(fonaKey, OUTPUT);
// make sure the FONA power cycling key is initially pulled 'high' -- i.e. not triggered
digitalWrite(fonaKey, HIGH); //go back to non-trigger
// end FONA stuff ---------------------------------------------------
// LED -----------------------------------------
//set the led pin mode to output
pinMode(led, OUTPUT);
pinMode(sensorBoard,OUTPUT); //turns on the 555 timer and thermistor subcircuit
digitalWrite(sensorBoard,LOW); //turns on the 555 timer and thermistor subcircuit
}
void loop ()
{
uint8_t i;
//measure the battery
digitalWrite(batteryReadCircuitSwitch, LOW); //turn on battery measurement circuit
int batteryLevel = analogRead(batteryAnalogMeasurePin);
digitalWrite(batteryReadCircuitSwitch, HIGH);
//turn on the sensorBoard system
//measure temp
//take temp samples
// take N samples in a row, with a slight delay
for (i=0; i< NUMSAMPLES; i++) {
samples[i] = analogRead(THERMISTORPIN);
//Serial.println(analogRead(THERMISTORPIN));
delay(10);
}
//measure conductivity
// conductivity --------------------------------------
pulseCount=0; //reset the pulse counter
totalDuration=0; //reset the totalDuration of all pulses measured
attachInterrupt(interruptPin,onPulse,RISING); //attach an interrupt counter to interrupt pin 1 (digital pin #3) -- the only other possible pin on the 328p is interrupt pin #0 (digital pin #2)
pulseTime=micros(); // start the stopwatch
delay(samplingPeriod*1000); //give ourselves samplingPeriod seconds to make this measurement, during which the "onPulse" function will count up all the pulses, and sum the total time they took as 'totalDuration'
detachInterrupt(interruptPin); //we've finished sampling, so detach the interrupt function -- don't count any more pulses
//turn off the remote board
//digitalWrite(sensorBoard,HIGH); //turns on the 555 timer and thermistor subcircuit
//analyze temp
float average;
average = 0;
for (i=0; i< NUMSAMPLES; i++) {
average += samples[i];
}
average /= NUMSAMPLES;
// convert the value to resistance
average = 1023 / average - 1;
average = SERIESRESISTOR / average;
//Serial.print("Thermistor resistance ");
//Serial.println(average);
float steinhart;
steinhart = average / THERMISTORNOMINAL; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro)
steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // convert to C
//Serial.print(steinhart);
//Serial.println(" *C");
//do the conductivity calculations
float freqHertz;
if (pulseCount>0) { //use this logic in case something went wrong
double durationS=(totalDuration/double(pulseCount))/1000000.; //the total duration, in seconds, per pulse (note that totalDuration was in microseconds)
freqHertz=1./durationS;
}
else {
freqHertz=0.;
}
// Onboard temp from the RTC
float rtcTemp = RTC.getTempAsFloat();
//get the time
DateTime now = RTC.now();
long unixNow = now.unixtime();
// FONA sending stuff ----------------------
char message[141];
//sprintf(message, "%ld, %d, %d",unixNow,batteryLevel, rtcTempInt);
int sensorID=1;
int conduct=333;
int temp=2333;
sprintf(message,"%d, %d, %d, %d",sensorID,batteryLevel,int(steinhart*100),int(freqHertz));
if(debug) Serial.println(freqHertz);
if(debug) Serial.println(steinhart);
// turn on the FONA
power_up_fona();
// initialize the FONA
int fonaStatus=initialize_fona();
if (!fonaStatus) {
if (debug) Serial.println("FONA not found");
}
int networkStatus=fona_find_network();
if ((networkStatus!=1)&&(networkStatus!=5)) {
if (debug) Serial.println("Couldn't find network in failCountMax tries. Aborting.");
}
if (((networkStatus==1)||(networkStatus==5))&&fonaStatus) { //then we're good to send a message!
if (debug) {
Serial.print(F("Send to #"));
Serial.println(sendto);
Serial.print(F("Type out one-line message (140 char): "));
Serial.println(message);
}
// send an SMS!
if (!fona.sendSMS(sendto, message)) {
if(debug) Serial.println(F("Failed"));
} else {
if (debug) Serial.println(F("Sent!"));
}
}
//turn off the module (should be on to begin with, but if all has failed, we should turn it off.
power_down_fona();
if(debug) {
Serial.println("Sleeping ...");
delay(1000); //seems to be necessary not to mess with serial output when sleeping
}
// PUT ATMEL 328p to SLEEP
go_to_sleep_seconds(sleepSeconds); //
}
// Sleep function
void go_to_sleep_seconds(int seconds) {
int LOG_INTERVAL_BASE = 1000; // 1 sec
for (int k=0;k<seconds;k++) {
Sleepy::loseSomeTime(LOG_INTERVAL_BASE); //-- will interfere with serial, so don't use when debugging
}
}
// RTC functions
int initialize_RTC() {
RTC.begin();
// check on the RTC
if (! RTC.isrunning()) {
if (debug) Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
RTC.adjust(DateTime(__DATE__, __TIME__));
}
DateTime now = RTC.now();
DateTime compiled = DateTime(__DATE__, __TIME__);
if (now.unixtime() < compiled.unixtime()) {
if(debug) Serial.println("RTC is older than compile time! Updating");
RTC.adjust(DateTime(__DATE__, __TIME__));
}
}
// Functions for FONA
void power_up_fona() {
int fonaPower=digitalRead(fonaPowerStatus);
if (!fonaPower) { // off, so power up
digitalWrite(fonaKey, HIGH); //go back to non-trigger
digitalWrite(fonaKey, LOW); //turn on the SMS subcircuit
delay(2000); //so now it's on
digitalWrite(fonaKey, HIGH); //go back to non-trigger
}
else {
// error! was already on for some reason -- do nothing
}
}
void power_down_fona() {
int fonaPower=digitalRead(fonaPowerStatus);
if (fonaPower) { // on, so power down
digitalWrite(fonaKey, HIGH); //go back to non-trigger
digitalWrite(fonaKey, LOW); //turn on the SMS subcircuit
delay(2000); //so now it's on
digitalWrite(fonaKey, HIGH); //go back to non-trigger
}
else {
// error! was already off for some reason -- do nothing
}
}
int initialize_fona() {
int fonaStatus;
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
// things are bad -- couldn't find FONA
fonaStatus=0;
}
else {
//things are good -- FONA OK
fonaStatus=1;
}
return fonaStatus;
}
int fona_find_network() {
uint8_t n = fona.getNetworkStatus();
int avail = fona.available();
int registerCountDelaySeconds=5;
int registerWaitTotalSeconds=0;
int failCount=0;
while ((n!=1)&&(n!=5)&&(failCount<failCountMax)) {
digitalWrite(led, HIGH); //turn on the LED
delay(20);
digitalWrite(led, LOW); //turn on the LED
delay(20);
if(debug) {
Serial.print(F("Network status "));
Serial.println(n);
}
n = fona.getNetworkStatus();
//avail = fona.available();
registerWaitTotalSeconds+=registerCountDelaySeconds;
delay(registerCountDelaySeconds*1000);
failCount=failCount+1;
}
if (debug) {
Serial.print("Network registration time=");
Serial.println(registerWaitTotalSeconds);
}
return n;
}
String padInt(int x, int pad) {
String strInt = String(x);
String str = "";
if (strInt.length() >= pad) {
return strInt;
}
for (int i=0; i < (pad-strInt.length()); i++) {
str += "0";
}
str += strInt;
return str;
}
String int2string(int x) {
// formats an integer as a string assuming x is in 1/100ths
String str = String(x);
int strLen = str.length();
if (strLen <= 2) {
str = "0." + str;
} else if (strLen <= 3) {
str = str.substring(0, 1) + "." + str.substring(1);
} else if (strLen <= 4) {
str = str.substring(0, 2) + "." + str.substring(2);
} else {
str = "-9999";
}
return str;
}
void onPulse()
{
pulseCount++;
//Serial.print("pulsecount=");
//Serial.println(pulseCount);
lastTime = pulseTime;
pulseTime = micros();
duration=pulseTime-lastTime;
totalDuration+=duration;
//Serial.println(totalDuration);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment