// This sketch used the FONA Feather to posts battery voltage to ThingSpeak channel. // This is a barebones sketch which may be ammended with sensor functions // Primary hardware used for this demonstration: // https://www.adafruit.com/product/3027 // https://www.adafruit.com/product/1991 // https://www.adafruit.com/product/772 // https://www.adafruit.com/product/759 // https://www.adafruit.com/product/354 (lower capacity is fine) // https://www.adafruit.com/product/239 // This sketch uses libraries and methods developed by Lady Ada. This project // would not be possible without the support of Adafruit's online tutorials // and its amazing cucstomer service. Thank You! // Necessary libraries downloadable here: // FONA: https://github.com/adafruit/Adafruit_FONA_Library/archive/master.zip // LCD: https://github.com/adafruit/Adafruit-RGB-LCD-Shield-Library/archive/master.zip #include "Adafruit_FONA.h" #include // only needed if LCD shield is attached for debugging Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield(); String myChannel; // Channel for posting to thingspeak String myUrl; // Final URL String for posting myChannel and Battery/Sensor Values to ThingSpeak String myBat; // variable for adding voltage value to myUrl #define FONA_RX 9 #define FONA_TX 8 #define FONA_RST 4 #define FONA_RI 7 #define FONA_KEY 10 // This is a large buffer for replies- comment out for now // char replybuffer[255]; #include SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX); SoftwareSerial *fonaSerial = &fonaSS; // Use this for FONA 800 and 808s Adafruit_FONA fona = Adafruit_FONA(FONA_RST); uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0); uint8_t type; // placeholder to return type of FONA // Variable for checking network and connection status uint8_t gStatus; // FONA GPRS status uint8_t nStatus; // FONA network status uint8_t sStatus; // FONA power status uint8_t dStatus; // FONA search status uint8_t n; // RSSI status int8_t r; // RSSI signal mapped to dBm // FONA battery variable uint16_t vbat; void setup() { // Fire up the LCD lcd.begin(16,2); screenClear(); lcd.print(F("Hello, world!")); delay(3000); // Pin for powering Fona on/off pinMode(FONA_KEY, OUTPUT); digitalWrite(FONA_KEY, HIGH); // will ground this to toggle on/off // Channel write API Key for channel - Barebones_LCD : 06KBO4NLYY83H9S1 // Public channel view: https://thingspeak.com/channels/447574 // Tested okay: http://184.106.153.149/update?key=06KBO4NLYY83H9S1&field1=4000 myChannel = "http://184.106.153.149/update?key=06KBO4NLYY83H9S1"; // includes channel key // HANDLE GENTLY myUrl = ""; } void loop() { // Notify user I am in the loop screenClear(); lcd.print(F("Start loop.")); delay(2000); // New post, so reset my variables at top of loop gStatus = 0; // GPRS status nStatus = 0; // Network status sStatus = 0; // FONA state status dStatus = 0; // FONA search status vbat = 0; // milivolts n = 0; // RSSI status r = 0; // signal mapped to dBm // Turn FONA on fonaOn(); //This will set sStatus to 1 if fona is turned on successfully // Get battery voltage myBatVolt(); if(sStatus == 1) { // FONA is on - procede! screenClear(); lcd.print(F("Delay 15 sec. ")); delay(15000); // Give FONA a few seconds to register on network screenClear(); // Check registration fonaReg(); if(nStatus == 1) { // FONA registered on network okay! // Let's take some sensor readings // ---- START: Call your sensor fuctions here ---- // // ---- END: Sensor readings recorded ---- // // Turn GPRS on screenClear(); lcd.print(F("GPRS on 3s ")); delay(3000); screenClear(); GPRS_on(); // Function will set gStatus to 1 if GPRS turns on okay. // NOTE: GPRS requires a good signal. If GPRS fails in turning // on or transmitting, check signal strength (need ~85 dBm or better) if(gStatus) { // GPRS turned on okay! // Ready to post; // Read parameters: myBat = String(vbat); // Add other sensor variable as appropriate here myUrl = myChannel + "&field1=" + myBat; // Add other sensor variables to myUrl as appropriate screenClear(); lcd.print(F("GPRS post 3s")); delay(3000); // Post the string to ThingSpeak GPRS_post(); screenClear(); lcd.print(F("GPRS off 3s")); delay(3000); // GPRS off GPRS_off(); } } else { // FONA not registered on network screenClear(); lcd.print(F("FONA not reg.")); lcd.setCursor(0,1); lcd.print(F("End routine")); delay(2000); } // FONA off screenClear(); lcd.print(F("FONA off 3s")); delay(3000); fonaOff(); } else { // FONA not detected screenClear(); lcd.print(F("FONA problem")); lcd.setCursor(0,1); lcd.print(F("End routine")); delay(2000); } // Pause for power savings screenClear(); lcd.print(F("Pause 2m")); delay(120000); } // FUNCTIONS // --- Sensor Functions --- // // Add later based on system needs // --- Sensor Functions End --- // // Simple function for clearing LCD screen void screenClear() { lcd.clear(); lcd.setCursor(0,0); } // Function for toggling FONA key pin for tunring FONA on/off void keyToggle() { screenClear(); lcd.print(F("Toggling ")); digitalWrite(FONA_KEY, LOW); delay(2000); digitalWrite(FONA_KEY, HIGH); screenClear(); lcd.print(F("Done ")); delay(2000); } // Function for turning FONA on void fonaOn() { screenClear(); lcd.print(F("Checking FONA")); fonaSerial->begin(4800); if(! fona.begin(*fonaSerial)) { // FONA is off at start of loop lcd.setCursor(0,1); lcd.print(F("No FONA ")); delay(2000); keyToggle(); // turns FONA on // next block added per Rick's recommendation // to call/check fona.begin after FONA on key toggle if (! fona.begin(*fonaSerial)) { screenClear(); lcd.print(F("Still no FONA")); delay(2000); sStatus = 0; } else { screenClear(); lcd.print(F("FONA now on")); delay(2000); sStatus = 1; } } // all is good else { // FONA is on at start of loop lcd.setCursor(0,1); lcd.print(F("FONA Found")); delay(2000); sStatus = 1; } } // Function for turning FONA off void fonaOff() { // Following line added per Adafruit recommendation; // this gets harware in proper state for next run fonaSerial->end(); screenClear(); lcd.print(F("Turn FONA Off ")); delay(2000); // use key toggle keyToggle(); sStatus =0; } void GPRS_on() { // Turn GPRS on // screenClear(); lcd.print(F("Entering GPRS ")); delay(2000); lcd.setCursor(0,1); /// --> set gStatus = 0 if GPRS mode fails /// --> set gStatus = 1 if GPRS mode succeeds /// --> gStatus will enable other functions in main loop // turn GPRS on if (!fona.enableGPRS(true)) { lcd.print(F("Failed to turn on")); gStatus = 0; } else { lcd.print(F("GPRS on")); gStatus = 1; } } void GPRS_post() { screenClear(); lcd.print(F("GPRS on; delay 5s")); delay(5000); // Get website URL and ping it uint16_t statuscode; int16_t length; char url[256]; // Since fona.HTTP_GET_start() is expecting an array for url, // I need to read a string into an array. First, define // myUrl from channel and battery/sensor values. screenClear(); lcd.print(F("Posting. ")); delay(2000); // Get myUrl into the array url myUrl.toCharArray(url,256); screenClear(); lcd.println(myUrl); delay(2000); // Make the post if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) { screenClear(); // post failed lcd.print(F("Post bad. ")); delay(1000); } else { // Post success screenClear(); lcd.print(F("Post good. ")); delay(1000); } fona.HTTP_GET_end(); /// Code to POST ends /// } void GPRS_off() { /// Turn GPRS off /// screenClear(); if (!fona.enableGPRS(false)) { lcd.print(F("GPRS off bad. ")); // sometimes, GPRS does not shut down properly; // I'm not sure why- perhaps weak signal strength? // Confirm the same via LCD. } else { lcd.print(F("GPRS off ok. ")); delay(1000); } } void myBatVolt() { screenClear(); // read the battery voltage and percentage if (! fona.getBattVoltage(&vbat)) { lcd.print(F("Bat. read fail")); } else { lcd.print(F("VBat = ")); lcd.print(vbat); lcd.print(F(" mV")); } delay(2000); screenClear(); } void callStat() { // screenClear(); int8_t callstat = fona.getCallStatus(); delay(2000); } void netStat() { screenClear(); // read the network/cellular status nStatus = fona.getNetworkStatus(); lcd.print(F("Network status ")); lcd.print(nStatus); lcd.print(F(": ")); lcd.setCursor(0,1); if (nStatus == 0) lcd.print(F("Not reg")); if (nStatus == 1) lcd.print(F("Reg (home)")); if (nStatus == 2) lcd.print(F("Searching")); if (nStatus == 3) lcd.print(F("Denied")); if (nStatus == 4) lcd.print(F("Unknown")); if (nStatus == 5) lcd.print(F("Reg roam")); } void fonaRSSI() { // read the RSSI n = fona.getRSSI(); r; // Serial.print(F("RSSI = ")); Serial.print(n); Serial.print(": "); if (n == 0) r = -115; if (n == 1) r = -111; if (n == 31) r = -52; if ((n >= 2) && (n <= 30)) { r = map(n, 2, 30, -110, -54); } // Serial.print(r); Serial.println(F(" dBm")); } void fonaReg() { while(1) { netStat(); delay(2000); if(nStatus == 1) { screenClear(); lcd.print(F("Registered")); break; } else { screenClear(); fonaRSSI(); lcd.print(F("Searching @ ")); lcd.print(r); delay(3000); dStatus += 1; if(dStatus > 5) { screenClear(); lcd.print(F("Time Out")); delay(3000); break; } } } }