Yes, absolutely.
Here is my sketch - still work in progress and I know there is a lot that needs to be cleaned up.
I am running a barebones ATMEGA328PB.
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <Vcc.h> // library to read battery voltage
#include "SIM800L.h"
//int myVolts;
Vcc vcc;
float v;
#define MAXIMUM_GPS_DURATION_SEC 1200//
#define MAXIMUM_REG_DURATION_SEC 240
char gpsValid[2];
float myLatGeo;
float myLonGeo;
char gpsLat[11];
char latNS[2];
char gpsLon[12];
char lonEW[2];
char latHex[9];
char lonHex[10];
int myKMPH;
int mySignal;
char txSignal[3];
char txSpeed[4];
String msgTX1;
String msgTX2;
String msgTX;
char txVolts[3];
int myVolts;
volatile int watchdog_counter;
int wakeCount;
String msgID;
String myDeviceID = "IS003";
#define SIM800_RST_PIN 7
#define SIM800_DTR_PIN 13
SIM800L* sim800l;
int BUZZER = 2;
int GPS_PWR = 5;
boolean AT_cmd_result = false;
#define DEBUG true
//String response = "";
boolean status;
bool ModuleState = false;
// watchdog interrupt
ISR (WDT_vect)
{
watchdog_counter++;
// wdt_disable(); // disable watchdog
} // end of WDT_vect
void sleepNOW() {
// disable ADC
ADCSRA = 0;
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = bit (WDCE) | bit (WDE);
// set interrupt mode and an interval
WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay
wdt_reset(); // pat the dog
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
noInterrupts (); // timed sequence follows
sleep_enable();
// // turn off brown-out enable in software
// MCUCR = bit (BODS) | bit (BODSE);
// MCUCR = bit (BODS);
interrupts (); // guarantees next instruction executed
sleep_cpu ();
}
void setup()
{
Serial.begin(9600);
Serial.println("BOOT");
// Initialize the hardware Serial1
Serial1.begin(9600);
delay(1000);
Serial1.println("AT+IPR=9600");
delay(100);
Serial1.println("AT&W");
delay(100);
Serial.print("CutOut-L80-800L-");
Serial.println(myDeviceID);
pinMode(GPS_PWR, OUTPUT);// GPS Pin
digitalWrite(GPS_PWR, HIGH);// GPS OFF
pinMode(BUZZER, OUTPUT);
// BUZZER - BOOT
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
intSIM800L();
getPowerMode();
setPowerNormal();
delay(1000);
getSignal();
delay(1000);
getRegistered();
// BUZZER - READY
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
delay(100);
digitalWrite(BUZZER, HIGH);
delay(100);
digitalWrite(BUZZER, LOW);
sleep800L();
getGPSrmc();
msgID = "90";
sendHTTP();
/*
wakeCount 5 == ~1 minute
wakeCount 10 == ~2 minute
wakeCount 25 == ~5 minute
wakeCount 50 == ~10 minute
wakeCount 75 == ~13 minute
wakeCount 86 == ~15 minute
wakeCount 172 == ~30 minute
*/
wakeCount = 50;
}
void intSIM800L() {
// Equivalent line with the debug enabled on the Serial
sim800l = new SIM800L((Stream *)&Serial1, SIM800_RST_PIN, 200, 512, (Stream *)&Serial);
Serial.println("Start of test protocol");
// Wait until the module is ready to accept AT commands
while (!sim800l->isReady()) {
Serial.println(F("Problem to initialize AT command, retry in 1 sec"));
delay(1000);
}
// Active echo mode (for some module, it is required)
sim800l->enableEchoMode();
Serial.println("Module ready");
}
void getPowerMode() {
// Check Power Mode
Serial.print("Power Mode ");
Serial.println(sim800l->getPowerMode());
delay(500);
/* POWER MODES
"AT+CFUN?" // Check the current power mode
"AT+CFUN=0" // Switch minimum power mode
"AT+CFUN=1" // Switch normal power mode
"AT+CFUN=4" // Switch sleep power mode
*/
}
void setPowerNormal() {
// Set Power Mode NORMAL
Serial.println(sim800l->setPowerMode(NORMAL));
}
void getSignal() {
// Wait for the GSM signal
uint8_t signal = sim800l->getSignal();
while (signal <= 0) {
delay(1000);
signal = sim800l->getSignal();
mySignal = signal;
}
sprintf(txSignal, "%02d", mySignal);
Serial.print("txSignal: ");
Serial.println(txSignal);
}
void getRegistered() {
NetworkRegistration network = sim800l->getRegistrationStatus();
while (network != REGISTERED_HOME && network != REGISTERED_ROAMING) {
delay(1000);
network = sim800l->getRegistrationStatus();
}
if (network == 5) {
Serial.print("Network: ");
Serial.println(network);
}
/*
case '0' : return NOT_REGISTERED;
case '1' : return REGISTERED_HOME;
case '2' : return SEARCHING;
case '3' : return DENIED;
case '5' : return REGISTERED_ROAMING;
default : return NET_UNKNOWN;
*/
}
void loop() {
sleepNOW(); //Go to sleep!
Serial.print("Wake Count Set: ");
Serial.println(wakeCount);
delay(50);
Serial.print("Sleep Count: ");
Serial.println(watchdog_counter);
delay(50);
if (watchdog_counter >= wakeCount)
{
Serial.println("800L Awake");
delay(50);
awake800L();
getGPSrmc();
msgID = "91";
sendHTTP();
watchdog_counter = 0;
}
}
void sleep800L() {
// Set Power Mode SLEEP
Serial.println(sim800l->setPowerMode(SLEEP));
Serial1.println("AT+CSCLK=2");
Serial.println(F("800L Going to SLEEP "));
delay(100);
}
void awake800L() {
// digitalWrite(SIM800_DTR_PIN, LOW);
Serial.println(sim800l->setPowerMode(NORMAL));
Serial1.println("AT");
delay(500);
Serial1.println("AT");
delay(500);
Serial1.println("AT+CSCLK=0");
Serial.println(F("Going to AWAKE "));
sendATcmd("AT+CFUN=1", 10, "OK");
}
void sendHTTP() {
myVolts = Vcc::measure(1000, 1100);
myVolts = (myVolts / 100);
awake800L();
delay(1000);
Serial1.println("AT");
delay(500);
Serial.println(F("--------------------GET Message----------------------"));
msgTX += String(latHex);
msgTX += "#";
msgTX += String(latNS);
msgTX += "#";
msgTX += lonHex;
msgTX += "#";
msgTX += String(lonEW);
msgTX += "#";
msgTX += String(myVolts);
msgTX += "#";
msgTX += msgID;
msgTX += "#";
msgTX += myDeviceID;
msgTX += "#";
msgTX += String(mySignal);
msgTX += "#";
msgTX += String(txSpeed);
Serial.println(msgTX);
int lenTX = msgTX.length();
Serial.print("msgTX.length: ");
Serial.println(lenTX);
msgTX = "";
// Still working on the below code - this not working
// const char URL[] = "https//:www.xxxxxxxxxxxxxxxx.dedicated.xxx/5000";
// const char CONTENT_TYPE[] = "text";
// const char PAYLOAD[] = "0185777E#S#01ACC033#E#36#91#IS003#31#001";
const char APN[] = "flickswitch";
// Setup APN for GPRS configuration
bool success = sim800l->setupGPRS(APN);
while (!success) {
success = sim800l->setupGPRS(APN);
delay(5000);
}
Serial.println(F("GPRS config OK"));
// Establish GPRS connectivity (5 trials)
bool connected = false;
for (uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
connected = sim800l->connectGPRS();
}
Serial.println(F("Start HTTP POST..."));
// Do HTTP POST communication with 10s for the timeout (read and write)
uint16_t rc = sim800l->doPost(URL, CONTENT_TYPE, PAYLOAD, 10000, 10000);
if (rc == 200) {
// Success, output the data received on the serial
Serial.print(F("HTTP POST successful ("));
Serial.print(sim800l->getDataSizeReceived());
Serial.println(F(" bytes)"));
Serial.print(F("Received : "));
Serial.println(sim800l->getDataReceived());
} else {
// Failed...
Serial.print(F("HTTP POST error "));
Serial.println(rc);
}
// Close GPRS connectivity (5 trials)
bool disconnected = sim800l->disconnectGPRS();
for (uint8_t i = 0; i < 5 && !connected; i++) {
delay(1000);
disconnected = sim800l->disconnectGPRS();
}
if (disconnected) {
Serial.println(F("GPRS disconnected !"));
} else {
Serial.println(F("GPRS still connected !"));
}
delay(5000);
sleep800L();
}
String sendData(String command, const int timeout, boolean debug)
{
String response = "";
Serial1.println(command);
delay(20);
long int time = millis();
while ((time + timeout) > millis())
{
while (Serial1.available())
{
char c = Serial1.read();
response += c;
}
}
if (DEBUG)
{
Serial.print(response);
delay(100);
}
return response;
}
bool sendATcmd(String AT_cmd, int AT_cmd_maxTime, char readReply[])
{
int trycnt = 0;
bool status = false;
Serial.print(F("AT command:"));
Serial.println(AT_cmd);
delay(50);
while (trycnt < AT_cmd_maxTime) {
Serial1.println(AT_cmd);
if (Serial1.find(readReply)) {
AT_cmd_result = true;
break;
}
++trycnt;
}
Serial.print(F("Result:"));
if (true == AT_cmd_result) {
Serial.print(AT_cmd);
Serial.println(F(" DONE"));
status = true;
} else {
Serial.println(F("FAILED"));
}
AT_cmd_result = false;
return status;
}
bool moduleStateCheck()
{
int i = 0;
bool moduleState = false;
for (i = 0; i < 5; i++)
{
String msg = String("");
Serial1.println("AT");
if (msg.indexOf("OK") >= 0)
{
Serial.println("A9G was ON.");
moduleState = true;
return moduleState;
}
delay(1000);
}
return moduleState;
}
void getGPSrmc() {
// Wake Up GPS
digitalWrite (GPS_PWR, LOW); // turn POWER_GPS ON
delay(1000);
Serial.println("Got to getGPS");
// RMC Only
Serial.println("$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
delay(2000);
char gpsResponse[82] = {0}; // 80 chars + null terminator
// while (Serial.available()) Serial.read(); // Clear all ACK logs
const unsigned char MAX_gpsCOUNT = 4;
unsigned char gpsCount = 0;
bool gpsSuccess = false;
do {
for (int s = 0; s < MAXIMUM_GPS_DURATION_SEC; s++) {
do {
while (Serial.available()) gpsResponse[0] = Serial.read();
}
while (gpsResponse[0] != '$'); // Wait for response message
for (unsigned char c = 0; c < sizeof(gpsResponse) - 1; c++) {
while (!Serial.available());
gpsResponse[c] = Serial.read(); // Capture response character
if (gpsResponse[c] == '\r') gpsResponse[c] = 0x00; // Ignore CR
if (gpsResponse[c] == '\n') break; // LF means the end of one line of response
}
Serial.println(gpsResponse);
delay(50);
//GNRMC,070932.860,A,2551.3716,S,02810.7482,E,0.84,290.21,081122,,,A*7C
const char* foundGPS = "GPRMC";
char* p;
p = strstr (gpsResponse, foundGPS);
if (p) {
// Check that GPS has a Valid message (A==Valid / V==Not Valid)
strncpy(gpsValid, gpsResponse + 17, 1);
gpsValid[1] = '\0';
if (gpsValid[0] == 65) {// A==Dec 65
// Get Latitude
char gpsLat[10];
strncpy(gpsLat, gpsResponse + 19, 4);
strncpy(&gpsLat[4], gpsResponse + 24, 4);
gpsLat[8] = '\0';
float myLatGeo0 = atof(gpsLat);
float myLatGeo1 = myLatGeo0 / 1000000;
float latNmea = myLatGeo1 * 100;
uint16_t wholeDegrees = 0.01 * latNmea;
myLatGeo = wholeDegrees + (latNmea - 100.0 * wholeDegrees) / 60.0;
Serial.print("Lat DD.dddd: ");
Serial.println(myLatGeo, 6);
delay(50);
Serial.print("Lat DEC: ");
Serial.println(gpsLat);
delay(50);
sprintf(latHex, "%08lX", atol(gpsLat));
Serial.print("Lat HEX: ");
Serial.println(latHex);
delay(50);
// Get NS
strncpy(latNS, gpsResponse + 29, 1);
latNS[1] = '\0';
Serial.print("NS: ");
Serial.println(latNS);
// Get Longitude
char gpsLon[10];
strncpy(gpsLon, gpsResponse + 31, 5);
strncpy(&gpsLon[5], gpsResponse + 37, 4);
gpsLon[9] = '\0';
float myLonGeo0 = atof(gpsLon);
float myLonGeo1 = myLonGeo0 / 1000000;
float lonNmea = myLonGeo1 * 100;
uint16_t wholeDegreesLon = 0.01 * lonNmea;
myLonGeo = wholeDegreesLon + (lonNmea - 100.0 * wholeDegreesLon) / 60.0;
Serial.print("Lon DD.dddd: ");
Serial.println(myLonGeo, 6);
delay(50);
Serial.print("Lon DEC: ");
Serial.println(gpsLon);
delay(50);
sprintf(lonHex, "%08lX", atol(gpsLon));
Serial.print("Lon HEX: ");
Serial.println(lonHex);
delay(50);
// Get EW
strncpy(lonEW, gpsResponse + 42, 1);
lonEW[1] = '\0';
Serial.print("EW: ");
Serial.println(lonEW);
delay(50);
int i = 0;
char *start_pch, *end_pch;
char extracted_str[16];
start_pch = gpsResponse - 1;
end_pch = strstr (gpsResponse, ",");
while ( end_pch != NULL ) {
memset (extracted_str, 0, 16);
strncpy (extracted_str, start_pch + 1, end_pch - start_pch - 1); //<----
Serial.print(++i);
Serial.print(": ");
Serial.println(extracted_str);
start_pch = end_pch;
end_pch = strstr (end_pch + 1, ",");
if (i == 8) {
myKMPH = atoi(extracted_str);
// int KMPH = (atoi(extracted_str)) * 1.852);
myKMPH = myKMPH * 1.852;
sprintf(txSpeed, "%03d", myKMPH);
Serial.print("txSpeed: ");
Serial.println(txSpeed);
//to print out the last value
memset (extracted_str, 0, 16);
strncpy (extracted_str, start_pch + 8, strlen(start_pch));
// Serial.print(++i);
// Serial.print(": ");
// Serial.println(extracted_str);
}
}
gpsSuccess = true;
break; // Not continue if found A (65)
}// END if (gpsValid[0] == 65)
} else {
gpsSuccess = false;
}
}// END for (int s = 0; s < MAXIMUM_GPS_DURATION_SEC; s++)
Serial.print("gpsCount: ");
Serial.println(gpsCount);
delay(50);
// } while (++gpsCount < MAX_gpsCOUNT && !gpsSuccess);
} while (++gpsCount < MAX_gpsCOUNT && gpsSuccess);
Serial.println("GPS Timeout");
// Switch GPS OFF
Serial.println("GPS OFF");
delay(50);
digitalWrite (GPS_PWR, HIGH); // turn POWER_GPS OFF
}
void readBattery()
{
myVolts = Vcc::measure(1000, 1100);
sprintf(txVolts, "%02d", myVolts);
}