Skip to content

Instantly share code, notes, and snippets.

@abachman
Last active November 5, 2022 10:49
Show Gist options
  • Save abachman/e96b197d4f8488ba54436fa760c0c9c9 to your computer and use it in GitHub Desktop.
Save abachman/e96b197d4f8488ba54436fa760c0c9c9 to your computer and use it in GitHub Desktop.
FONA 808 + Hologram + Adafruit.io MQTT

What it does

This demo script publishes a value to my Adafruit IO account once every minute or so from an Adafruit FONA 808 cellular board controlled by an Adafruit Metro and sending data over the Hologram network.

Resources

Patching Adafruit_FONA

There are two changes required to the Adafruit FONA library to support usage with Hologram. If you're using Arduino, you should be able to find the required files in {Arduino Sketchbook}/libraries/Adafruit_FONA_Library.

I got the patches from the "FONA + Hologram" guide published by James Lewis at https://www.baldengineer.com/hologram-io-connects-fona-mqtt.html.

Hardware Setup

the FONA + Metro

Output

output.log includes the Arduino serial monitor output up through publishing to the Adafruit.io feed once.

--- Adafruit_FONA.cpp 2018-05-14 16:15:07.000000000 -0400
+++ Adafruit_FONA_Library/Adafruit_FONA.cpp 2018-05-14 14:43:20.000000000 -0400
@@ -2090,3 +2090,32 @@
return true;
}
+
+boolean Adafruit_FONA::hologramStart() {
+ getReply(F("AT+COPS?"));
+ getReply(F("AT+CSQ"));
+
+ sendCheckReply(F("AT+CIPSHUT"), F("SHUT OK"), 20000);
+
+ //attach to GPRS
+ if (! sendCheckReply(F("AT+CGATT=1"), ok_reply, 10000))
+ return false;
+
+ // single connection at a time
+ if (! sendCheckReply(F("AT+CIPMUX=0"), F("OK"), 10000)) return false;
+
+
+ // manually read data
+ if (! sendCheckReply(F("AT+CIPRXGET=1"), F("OK"), 10000)) return false;
+
+ //AT+CSTT command to set APN
+ sendCheckReply(F("AT+CSTT=\"hologram\",\"\",\"\""), F("OK"), 10000);
+
+ //bring up wireless connection (GPRS)
+ if (! sendCheckReply(F("AT+CIICR"), F("OK"), 10000)) return false;
+
+ //return assigned ip address. This is necessary, otherwise "operation not allowed" error
+ getReply(F("AT+CIFSR"));
+
+ return true;
+}
--- Adafruit_FONA.h 2018-05-14 16:15:07.000000000 -0400
+++ Adafruit_FONA_Library/Adafruit_FONA.h 2018-05-14 14:01:44.000000000 -0400
@@ -193,6 +193,8 @@
boolean sendCheckReply(FONAFlashStringPtr send, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
boolean sendCheckReply(char* send, FONAFlashStringPtr reply, uint16_t timeout = FONA_DEFAULT_TIMEOUT_MS);
+ // Hologram.io helper function
+ boolean hologramStart();
protected:
int8_t _rstpin;
#include <Adafruit_SleepyDog.h>
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_FONA.h"
#define FONA_APN "hologram"
#define FONA_USERNAME ""
#define FONA_PASSWORD ""
// We default to using software serial. If you want to use hardware serial
// (because softserial isnt supported) comment out the following three lines
// and uncomment the HardwareSerial line
#define FONA_RX 2
#define FONA_TX 3
#define FONA_RST 4
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
// Use this for FONA 800 and 808s
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 1883
// shhhhhh, these are secrets
#define AIO_USERNAME "xxx"
#define AIO_KEY "xxx"
/************ Global State (you don't need to change this!) ******************/
// Setup the FONA MQTT class by passing in the FONA class and MQTT server and login details.
Adafruit_MQTT_FONA mqtt(&fona, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// You don't need to change anything below this line!
#define halt(s) { Serial.println(F( s )); while(1); }
// FONAconnect is a helper function that sets up the FONA and connects to
// the GPRS network. fonahelper.cpp must be included in the Arduino project.
boolean FONAconnect(const __FlashStringHelper *apn, const __FlashStringHelper *username, const __FlashStringHelper *password);
/********************/
// Setup a feed called 'photocell' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/photocell");
// How many transmission failures in a row we're willing to be ok with before reset
uint8_t txfailures = 0;
#define MAXTXFAILURES 3
void setup() {
while (!Serial);
// Watchdog is optional!
Watchdog.enable(12000);
Serial.begin(115200);
Serial.println(F("Adafruit FONA MQTT demo"));
Watchdog.reset();
delay(5000); // wait a few seconds to stabilize connection
Watchdog.reset();
// Initialise the FONA module
while (! FONAconnect(F(FONA_APN), F(FONA_USERNAME), F(FONA_PASSWORD))) {
Serial.println("Retrying FONA");
}
Serial.println(F("Connected to Cellular!"));
Watchdog.reset();
delay(5000); // wait a few seconds to stabilize connection
Watchdog.reset();
}
uint32_t x=0;
unsigned long last_pub = 0;
unsigned long pub_wait = 60000;
void loop() {
// Make sure to reset watchdog every loop iteration!
Watchdog.reset();
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
Watchdog.reset();
if (millis() > last_pub + pub_wait) {
// Now we can publish stuff!
Serial.print(F("\nSending photocell val "));
Serial.print(x);
Serial.print("...");
if (! photocell.publish(x++)) {
Serial.println(F("Failed"));
txfailures++;
} else {
Serial.println(F("OK!"));
txfailures = 0;
last_pub = millis();
}
}
delay(5000);
// ping the server to keep the mqtt connection alive, only needed if we're not publishing
//if(! mqtt.ping()) {
// Serial.println(F("MQTT Ping failed."));
//}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println("MQTT Connected!");
}
#include <Adafruit_SleepyDog.h>
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
#define halt(s) { Serial.println(F( s )); while(1); }
extern Adafruit_FONA fona;
extern SoftwareSerial fonaSS;
boolean FONAconnect(const __FlashStringHelper *apn, const __FlashStringHelper *username, const __FlashStringHelper *password) {
Watchdog.reset();
Serial.println(F("Initializing FONA....(May take 3 seconds)"));
fonaSS.begin(4800);
if (! fona.begin(fonaSS)) {
Serial.println(F("Couldn't find FONA"));
return false;
}
fonaSS.println("AT+CMEE=2");
Serial.println(F("FONA is OK"));
Watchdog.reset();
Serial.println(F("Checking for network..."));
uint8_t n;
boolean success=false;
do {
n = fona.getNetworkStatus();
Serial.print(F("Network status "));
Serial.print(n);
Serial.print(F(": "));
if (n == 0) Serial.println(F("Not registered"));
if (n == 1) Serial.println(F("Registered (home)"));
if (n == 2) Serial.println(F("Not registered (searching)"));
if (n == 3) Serial.println(F("Denied"));
if (n == 4) Serial.println(F("Unknown"));
if (n == 5) Serial.println(F("Registered roaming"));
delay(500);
if ((n == 1) || (n==5))
success = true;
} while(success == false);
Watchdog.reset();
delay(5000); // wait a few seconds to stabilize connection
Watchdog.reset();
fona.setGPRSNetworkSettings(apn, username, password);
Serial.println(F("Disabling GPRS"));
fona.enableGPRS(false);
Watchdog.reset();
delay(5000); // wait a few seconds to stabilize connection
Watchdog.reset();
Serial.println(F("Enabling GPRS"));
fona.hologramStart();
Watchdog.reset();
return true;
}
Adafruit FONA MQTT demo
Initializing FONA....(May take 3 seconds)
Attempting to open comm with ATs
---> AT
<--- +CME ERROR: unknown
---> AT
<--- OK
---> AT
<--- OK
---> ATE0
<--- OK
---> ATE0
<--- OK
---> AT+CVHU=0
<--- OK
---> ATI
<--- SIM808 R13.08
OK
---> AT+CPMS="SM","SM","SM"
<--- +CPMS: 0,10,0,10,0,10
FONA is OK
Checking for network...
---> AT+CREG?
<--- +CREG: 0,5
Network status 5: Registered roaming
Disabling GPRS
---> AT+CIPSHUT
<--- SHUT OK
---> AT+SAPBR=0,1
<--- +CME ERROR: operation not allowed
Enabling GPRS
---> AT+COPS?
<--- +COPS: 0,0,"T-Mobile USA"
---> AT+CSQ
<--- +CSQ: 19,0
---> AT+CIPSHUT
<--- SHUT OK
---> AT+CGATT=1
<--- OK
---> AT+CIPMUX=0
<--- OK
---> AT+CIPRXGET=1
<--- OK
---> AT+CSTT="hologram","",""
<--- OK
---> AT+CIICR
<--- OK
---> AT+CIFSR
<--- 10.170.199.152
Connected to Cellular!
---> AT+CIPSTATUS
<--- OK
<--- STATE: IP STATUS
Connecting to MQTT... [MQTT] connectServer
---> AT+CIPSHUT
<--- SHUT OK
---> AT+CIPMUX=0
<--- OK
---> AT+CIPRXGET=1
<--- OK
AT+CIPSTART="TCP","io.adafruit.com","1883"
<--- OK
<--- CONNECT OK
[MQTT] connect packet send
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
AT+CIPSEND=58
0x10 ...
<--- >
<--- SEND OK
[MQTT] connect packet response read
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPRXGET=4
<--- +CIPRXGET: 4,4
4 bytes available
1 bytes read
0x20
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPRXGET=4
<--- +CIPRXGET: 4,3
3 bytes available
1 bytes read
0x2
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPRXGET=4
<--- +CIPRXGET: 4,2
2 bytes available
2 bytes read
0x0 0x0
[MQTT] setup subscriptions
MQTT Connected!
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
Sending photocell val 0... ---> AT+CIPSTATUS
<--- OK
<--- STATE: CONNECT OK
AT+CIPSEND=29
0x30 ...
<--- >
<--- SEND OK
OK!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment