Voting resources, early voting, and poll worker information - VOTE. ... Adafruit is open and shipping.
0

Guidance on using Feather FONA with HardwareSerial
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Guidance on using Feather FONA with HardwareSerial

by biod101 on Sat Feb 08, 2020 1:26 pm

Hello,

I am currently using the Feather FONA for cellular telemetry of environmental data from remote locations. I've had great success with this board, and am now exploring its use with a tipping bucket rain gage. The tipping bucket gage uses a reed switch that passes in front of a magnet to trigger an interrupt service routine to increment a counter for rain totals. I am aware of issues with reed switch bounce, so I'm using an RC/schmitt trigger circuit as outlined in Jeremy Blum's book to filter out the associated noise, details of which I've posted here as demonstrated with use of a ProTrinket: https://youtu.be/KHrTqdmYoAk?t=1919

The tipping bucket counter circuit with the ISR works fine on its own, but I run into trouble when I couple this filter with my telemetry code running on a Feather FONA. Specifically, I sometimes lose counts during the course of testing (it sometimes works, and sometimes misses batches of counts). I think I've finally tracked down the issue to the use of SoftwareSerial for communication with the FONA, which based on various postings about Arduino, apparently can disable interrupts for long periods of time (I've been using code copied from Adafruit's FONAtest that defaults to use of SoftwareSerial). So, when the interrupts / ISR is blocked, I lose counts.

I'd like to learn how to use HardwareSerial to get around the issue of missed tips associated with blocked interrupt pins. Along those lines, there is a section in the FONAtest sketch that reads as follows, and which I've modified accordingly:

Code: Select all | TOGGLE FULL SIZE
// 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
// #include <SoftwareSerial.h>
// SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
// SoftwareSerial *fonaSerial = &fonaSS;

// Hardware serial is also possible!
HardwareSerial *fonaSerial = &Serial1;


I've also eliminated the definition of RX/TX pins since my understanding is HardwareSerial will default to the hardware RX/TX pins on the board:

Code: Select all | TOGGLE FULL SIZE
// #define FONA_RX  9
// #define FONA_TX  8
#define FONA_RST 4
#define FONA_RI  7
#define FONA_KEY 10


I've also eliminated all the Serial prints from my code since I don't think I don't want to be sending serial output to my FONA via the hardware RX/TX pins (at least that's my understanding).

Unfortunately, the farthest my code gets is turning my FONA on (by pulsing the KEY pin), but nothing else. I can see from my Serial terminal that AT commands are being sent, but nothing is being returned.

AT.png
AT.png (169.42 KiB) Viewed 190 times


(I've also tried running the code without a Serial Terminal window open in the event that was causing problems.) This suggests to me that the FONA libraries are not communicating via RX/TX with the cellular modem via HardwareSerial.

I've been trying to resolve this issue for the past couple of weeks, but I can't find much more guidance online on how to use HardwareSerial, or what I might be doing wrong- can I please get some help on how to use HardwareSerial to communicate with my FONA?

Here is the full sketch:

Code: Select all | TOGGLE FULL SIZE
// LCD code commented out
// OLED code replaced with // Serial.println
// Cleaned up unnecessary lines

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// Adafruit_SSD1306 display = Adafruit_SSD1306();

// Other
#include "Adafruit_FONA.h"

String myUrl;     // for posting myChannel and Sensor Values to ThingSpeak
String myChannel; // URL channel for posting to thingspeak
String myBat;     // string for adding voltage field to myUrl
String myTemp;    // string for adding stage field to myUrl
String myHumid;   // string for adding voltage field to myUrl
String myBaro;    // string for adding stage field to myUrl
String myRain;    // string for adding my rainfall total to my Url

// #define FONA_RX  9
// #define FONA_TX  8
#define FONA_RST 4
#define FONA_RI  7
#define FONA_KEY 10
#define SEALEVELPRESSURE_HPA (1013.25)

// Rain variables
#define RAIN_PIN 1    // replace with your microcontrollers interrupt pin number tied to your rain gauge
#define DEBOUNCE_TIME 15    // referenced in ISR; multiply by 1000 in ISR if using a reed switch and no RC/Schmitt trigger

volatile float rainTotal = 0;
volatile unsigned long last_micros_rg;

#define CALC_INTERVAL 180000 // increment for posting

Adafruit_BME280 bme; // I2C

// this is a large buffer for replies- future functionality
// char replybuffer[255];

// We default to using software serial. If you want to use hardware serial
// (because softserial isnt supported) co\mment out the following three lines
// and uncomment the HardwareSerial line

// #include <SoftwareSerial.h>
// SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
// SoftwareSerial *fonaSerial = &fonaSS;

// Hardware serial is also possible!
HardwareSerial *fonaSerial = &Serial1;

// Use this for FONA 800 and 808s
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
// Use this one for FONA 3G
// Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);

uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
uint8_t type;    // placeholder to return type of FONA

uint8_t gStatus; // FONA GPRS status
uint8_t nStatus; // FONA network status
uint8_t sStatus; // FONA power status
uint8_t dStatus; // FONA search status

// RSSI variables
uint8_t n; // RSSI status
int8_t r;  // signal mapped to dBm

// FONA battery
uint16_t vbat;   

void setup() {

  // Serial.begin(115200);
  attachInterrupt(digitalPinToInterrupt(RAIN_PIN), countingRain, RISING);
  pinMode(RAIN_PIN, INPUT);

// Test BME Sensor

//    while(!Serial);    // time to get serial running
    // // Serial.println(F("BME280 test"));
    unsigned status;
   
    // default settings
    status = bme.begin(); 
    // You can also pass in a Wire library object like &Wire2
    // status = bme.begin(0x76, &Wire2)
    if (!status) {
    // // Serial.println("Could not find a valid BME280 sensor");
     while (1) delay(10);
    }
    else
   
  // Serial.println("Past BME test.");

 // Pin for powering Fona on/off
 pinMode(FONA_KEY, OUTPUT);
 digitalWrite(FONA_KEY, HIGH);

 // Build the string

  // myChannel and myURL reset at top of loop
  myChannel = "http://184.106.153.149/update?key=XXXXXXXXXXX"; // includes channel key - handle gently. 
  myUrl = "";

  gStatus; // GPRS status
  nStatus; // Network status
  sStatus; // FONA status

}

void loop() {

// re-initialize my variables

 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(); //sets sStatus to 1 if fona is turned on successfully

 if(sStatus == 1) {
 
  // FONA is on
 
//  // Serial.println("Delay 15 sec. ");
// 
  delay(15000); // Give FONA time to register
 

  // Check registration
  fonaReg();

  if(nStatus == 1) {
   // FONA registered on network :)


   // Turn GPRS on
//   // Serial.println("GPRS on 3s ");
//   
//   delay(3000); 
   
   GPRS_on(); // function will set gStatus to 1 if GPRS turns on okay.

   if(gStatus) {
    // GPRS turned on okay
    // read parameters
    myBatVolt();
   
    myBat = String(vbat);
    myTemp = String(bme.readTemperature());
    myHumid = String(bme.readHumidity());
    myBaro = String(bme.readPressure() / 100.0F);
    myRain = String(rainTotal);

    // build post string
    myUrl = myChannel + "&field1=" + myBat +"&field2=" + myTemp + "&field3=" + myHumid + "&field4=" + myBaro + "&field5=" + myRain;
    // Serial.println(myUrl);

    // post the string to ThingSpeak and turn off   
    GPRS_post();
    GPRS_off();
   }
   else {
    // If I'm here, something went wrong with GPRS;   
    // since sometimes I'll get here with GPRS on,
    // make sure it shuts down before proceeding
    // since it sometimes hangs in this mode (i.e. fast
    // blinking light with no power down).
    GPRS_off();
   }
  }
 
  else {
   // FONA not registered on network
   //
   // Serial.println("FONA not reg.");
   // Serial.println("End routine");
   // 
   // delay(2000); 
  }
  // FONA off
// 
// Serial.println("FONA off 3s");
// 
//  delay(3000);
  fonaOff();
 }
 
 else {
 // FONA not detected

 // Serial.println("FONA not detected;");
 // Serial.println("End routine"); 
 }

// Pause for power savings

// Serial.print("Pause for ");
// Serial.print(CALC_INTERVAL);
// Serial.println(" ms");
delay(CALC_INTERVAL);
}

// Functions to make loop more readable

void keyToggle() {
 
 // Serial.println("Toggling ");
 //
 digitalWrite(FONA_KEY, LOW);
 delay(2000);
 digitalWrite(FONA_KEY, HIGH);
}

void fonaOn() {
 // Serial.println("Checking FONA");
 //
 fonaSerial->begin(4800);
 
 if(! fona.begin(*fonaSerial)) {
  // FONA is off at start of loop
  // Serial.println("No FONA ");
  //
  delay(2000);
  keyToggle(); // turns FONA on
   
  // next block added per Adafruit Rick's recommendation
  // to call/check fona.begin after FONA on key toggle
 
  if (! fona.begin(*fonaSerial)) {
   // Serial.println("Still no FONA");
   sStatus = 0;
  }
  else {     
   sStatus = 1;
  }
 }

 // all is good   
 else { // FONA is on at start of loop
   // Serial.println("FONA Found and on");
   //
   delay(2000);
   sStatus = 1;
 }
}

void fonaOff() {
 // following line added per Adafruit recommendation
 fonaSerial->end();
 
 
 // Serial.println("Turn FONA Off ");
 //
 delay(2000);

 // use key toggle
 keyToggle();
 sStatus =0;
}

void GPRS_on() {
 
 // Serial.println("Entering GPRS ");
 // turn GPRS on
 if (!fona.enableGPRS(true)) {
  // Serial.println("Failed to turn on");
  gStatus = 0;
 }
 else {
  gStatus = 1;
 }
 //
 delay(CALC_INTERVAL);
}

void GPRS_post() {

 // Get website URL and ping it
 uint16_t statuscode;
 int16_t length;
 char url[256];
     
 // Need to read a string into an array,
 // since fona.HTTP_GET_start() is expecting an array for url.
 // First, define myUrl from channel and sensor value   
 // Get myUrl into the array url
 
 myUrl.toCharArray(url,256);

  // Serial.println(myUrl);
 //
 // Serial.println("URL String Formed");
 //
 // delay(2000);

 // Make the post
 if (!fona.HTTP_GET_start(url, &statuscode, (uint16_t *)&length)) {
  //
  // post failed
  // Serial.println("Post bad. ");
 }     
 else {
  // Post success
  //       
  // Serial.println("Post good. ");
 }
  //
  delay(1000);

 fona.HTTP_GET_end();
 /// Code to POST ends ///
}

void GPRS_off() {

 if (!fona.enableGPRS(false))  {
  // Serial.println("GPRS off bad. "); //must be getting stuck here
 }
 else {
  // Serial.println("GPRS off ok. ");
 }
  //
  // delay(1000);
}

void myBatVolt() {

//
 if (!fona.getBattVoltage(&vbat)) {
  // Serial.println("Bat. read fail");
 } else {
  // Serial.print("VBat = "); // Serial.print(vbat); // Serial.println(" mV");
 }
 //
 delay(2000);
 //   
}

void callStat() {
 //
 int8_t callstat = fona.getCallStatus();
 delay(2000);
}

void netStat() {

/*
 
 // read the network/cellular status
 nStatus = fona.getNetworkStatus();

 // Serial.print("Network status ");
 // Serial.print(nStatus);
 // Serial.println(": ");
 if (nStatus == 0) // Serial.println("Not reg");
 if (nStatus == 1) // Serial.println("Reg (home)");
 if (nStatus == 2) // Serial.print("Searching");
 if (nStatus == 3) // Serial.println("Denied");
 if (nStatus == 4) // Serial.println("Unknown");
 if (nStatus == 5) // Serial.println("Reg roam");
*/

}

void fonaRSSI() {
 // read the RSSI
 n = fona.getRSSI();
 r;
 // Serial.print("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);
 }
}

void fonaReg() {
 while(1) {
  netStat();
  delay(2000);
  if(nStatus == 1) {
   //
   // Serial.println("Registered");
   break;
  } 
  else {       
   //
   fonaRSSI();
   // Serial.print("Searching @ ");
   // Serial.print(r); // Serial.println(" dBm");
   // 
   delay(3000);
   dStatus += 1;
   if(dStatus > 5) {
   // Serial.println("Time Out");
   // delay(3000); 
    break;
   }
  }   
 }
}

void countingRain() {
 if((long)(micros() - last_micros_rg) >= DEBOUNCE_TIME) {
  rainTotal += 0.011;
  last_micros_rg = micros();
  // Serial.print("rainTotal now at: ");
  // Serial.println(rainTotal);
 } 
}


As always, thanks for the stellar customer support.

biod101
 
Posts: 135
Joined: Sun Apr 19, 2015 4:21 pm

Re: Guidance on using Feather FONA with HardwareSerial

by adafruit_support_mike on Sun Feb 09, 2020 2:11 am

The Pro Trinket doesn't have a Serial1 interface. The TX/RX pins are just called Serial, like on an Arduino Uno.

The Pro Trinket doesn't have a built-in USB-to-Serial converter, so it can't talk to the Arduino IDE's Serial Monitor when the main code is running.

adafruit_support_mike
 
Posts: 61422
Joined: Thu Feb 11, 2010 2:51 pm

Re: Guidance on using Feather FONA with HardwareSerial

by biod101 on Sun Feb 09, 2020 11:22 am

Thanks Mike!

The pro trinket setup I shared was only to demonstrate the hardware filter for working with the interrupt. I'm actually using a Feather FONA for the telemetry. The problem is that the (interrupt-registered) tips get lost only when the cellular modem on the Feather FONA is communicating via SoftwareSerial, which apparently disables interrupt pins. That causes me to lose count of tips when the modem is talking to the microcontroller. When the modem is asleep and I tip the bucket, everything registers/works perfectly, I assume because SoftwareSerial is not sending AT commands to the modem (and blocking interrupts).

In this context, I'd like to use HardwareSerial. As per the comments in the FONAtest code, this is possible, but it doesn't seem to work for me as per my original post (?). One work around is to make my telemetry interval really long so as to minimize loss of data, but this doesn't fix the problem since any tips registered during telemetry (engaged by SoftwareSerial) will not be registered. By increasing the interval, all I'm doing is minimizing the probability that my data will be corrupted. There has to be a way to use HardwareSerial to get around this, but my code will not communicate via HardwareSerial.

For further context, please see what I found in this link:https://miscsolutions.wordpress.com/2011/10/16/five-things-i-never-use-in-arduino-projects/

The problem is that in the absence of hardware support, SoftwareSerial has to time the transmitted and received data bits accurately using timing loops. In order to do this, it has to disable interrupts, because an interrupt could cause the timing to go wrong. This in turn is liable to mess up any time-sensitive tasks I have.

biod101
 
Posts: 135
Joined: Sun Apr 19, 2015 4:21 pm

Re: Guidance on using Feather FONA with HardwareSerial

by adafruit_support_mike on Tue Feb 11, 2020 2:30 am

biod101 wrote:tips get lost only when the cellular modem on the Feather FONA is communicating via SoftwareSerial, which apparently disables interrupt pins.

Yep.. if you read the SoftwareSerial library code, it uses pin-change intererrupts to detect incoming data on the RX pin. The ATmega328 can only handle on interrupt at a time, so it automatically disables any other interrupts before executing an ISR.

biod101 wrote:There has to be a way to use HardwareSerial to get around this, but my code will not communicate via HardwareSerial.

We know the FONA will talk to an ATmega328 through the hardware Serial interface, you just have to use Serial.begin(&Serial) IIRC.

As a sanity check, are you sure the hardware connections are correct. TX connects to RX both directions, and it's easy to swap those.

adafruit_support_mike
 
Posts: 61422
Joined: Thu Feb 11, 2010 2:51 pm

Re: Guidance on using Feather FONA with HardwareSerial

by biod101 on Thu Feb 13, 2020 6:33 pm

Thanks for your patience Mike,

Okay - I think I understand what you are suggesting. First, I should eliminate the pin definitions for RX and TX in my code since I will hardwire the RX and TX pins to pins 0 and 1. Since I'm not using SoftwareSerial, I commented those pin definitions out accordingly in my code:

Code: Select all | TOGGLE FULL SIZE
// #define FONA_RX  9
// #define FONA_TX  8


as well as the SoftwareSerial definitions:
Code: Select all | TOGGLE FULL SIZE
// #include <SoftwareSerial.h>
// SoftwareSerial fonaSS = SoftwareSerial(FONA_TX, FONA_RX);
// SoftwareSerial *fonaSerial = &fonaSS;


Next, I need to uncomment the code for hardware serial as noted in the original FONAtest sketch:

Code: Select all | TOGGLE FULL SIZE
// Hardware serial is also possible!
HardwareSerial *fonaSerial = &Serial1;


Next, I actually need to begin the serial communication for that hardware connection. I do this in my setup block:

Code: Select all | TOGGLE FULL SIZE
  // Serial.begin(9600);
  Serial.begin(&Serial1);


Next, since I am using HardwareSerial to talk to the modem, I eliminated all the Serial.println communications since I don't want to be sending debugging statements to the modem, rather I should just rely on the FONA library functions communicate via HardwareSerial. I've done so by commenting all those Serial.println functions out of my code.

This all makes sense, but here is where I get lost-- as per this comment:
As a sanity check, are you sure the hardware connections are correct. TX connects to RX both directions, and it's easy to swap those.


... I need to actually make the respective hardware connections between the RX and TX connections (pins 9 and 8) to pins 0 and 1. I assume I would do this just by jumping the pins per the pinout diagram on the Feather FONA attached below. However, only pin 9 is broken out on the board - there is no pin 8 to tie into the other hardware serial pin (?). Sorry if I'm totally off base on this; I'm hacking my way through this stuff as a non-programmer, so the obvious can sometimes elude me without a little help. I'm so stuck that I'm actually considering attaching a second Arduino to talk over I2C for communicating the tips. Even as a non-programmer/engineer, I know this is bad design. Thanks Mike.
Attachments
connections.jpg
connections.jpg (132.6 KiB) Viewed 150 times

biod101
 
Posts: 135
Joined: Sun Apr 19, 2015 4:21 pm

Re: Guidance on using Feather FONA with HardwareSerial

by adafruit_support_mike on Fri Feb 14, 2020 2:10 am

Sorry, I got confused about the boards.

On the Feather FONA, the connections between the microcontroller and the SIM800 module are pre-wired, and you can't change them. My comment about checking the TX/RX connections was only relevant to the connections between a Pro Trinket and an external FONA module.

With a Feather FONA, you don't really have the option to use a hardware Serial connection. The SIM800's TX/RX pins are wired to GPIO pins 8 and 9 on the PCB.

I suppose in theory you could set pins 8 and 9 as inputs, then use jumpers to connect the Feather's hardware TX/RX pins to pins 9 (FONA_RX) and 8 (FONA_TX). It would probably work, but I don't see a compelling reason to do it.

The instructions for getting the example sketch to work on a Feather FONA live here in the tutorial:

https://learn.adafruit.com/adafruit-fea ... d-demo-7-8

That's the known-working configuration for the board.

adafruit_support_mike
 
Posts: 61422
Joined: Thu Feb 11, 2010 2:51 pm

Re: Guidance on using Feather FONA with HardwareSerial

by biod101 on Fri Feb 14, 2020 7:27 pm

Thanks Mike,

I appreciate the reference on getting it up and running. Actually, I have been using this hardware successfully and lauding it's capabilities online for some time now ;) The interrupts, however, are throwing a new wrinkle into the works. It sounds like the best option for this particular board (when using interrupts) is in having a second Arduino (or ProTrinket) configured as slave; having it record the tips via interrupts; and then communicating the data when requested by the Feather FONA via I2C. At least now I don't feel bad about using a second board.

Thanks again for all your help- I'll post an update to this thread once I get it working.

biod101
 
Posts: 135
Joined: Sun Apr 19, 2015 4:21 pm

Re: Guidance on using Feather FONA with HardwareSerial

by adafruit_support_mike on Sat Feb 15, 2020 1:11 am

Yeah, if you want to use multiple interrupt sources on a single microcontroller, you pretty much have to write all the ISR code yourself. That's the only way to make the competing interests cooperate.

Exporting interrupt-driven jobs to another small microcontroller, or a dedicated device, usually makes life easier.

adafruit_support_mike
 
Posts: 61422
Joined: Thu Feb 11, 2010 2:51 pm

Re: Guidance on using Feather FONA with HardwareSerial

by biod101 on Sat Feb 15, 2020 4:12 pm

This video explains I2C communication between two Arduino Unos very clearly:
https://youtu.be/PnG4fO5_vU4

Using his code, I did manage to get two ProTrinkets to talk to one another, so I will see if I can incorporate an interrupt for communication between a ProTrinket and Feather FONA in support of needed telemetry. This is a critical project for my agency, so I’ll post results to my channel - stay tuned.

https://www.youtube.com/playlist?list=PLqJ5k4cakypy-Dn6dGV_dvC4Hwxp8Z3wN

biod101
 
Posts: 135
Joined: Sun Apr 19, 2015 4:21 pm

Re: Guidance on using Feather FONA with HardwareSerial

by adafruit_support_mike on Sun Feb 16, 2020 3:23 am

Ah, I2C communication is also possible, but can be more of a nuisance to set up than a Serial connection. Glad to hear you found something that works for you!

adafruit_support_mike
 
Posts: 61422
Joined: Thu Feb 11, 2010 2:51 pm

Re: Guidance on using Feather FONA with HardwareSerial

by biod101 on Sun Feb 23, 2020 10:11 pm

The I2C approach did in fact work with the Feather FONA. I'll copy the code here shortly, but most if it including an explanation is summarized here: https://youtu.be/dn78n-dE8zI . Again, Adafruit makes much of this possible for non electrical engineers like me, so thanks once again for the clearly documented hardware and great customer service.

biod101
 
Posts: 135
Joined: Sun Apr 19, 2015 4:21 pm

Re: Guidance on using Feather FONA with HardwareSerial

by adafruit_support_mike on Tue Feb 25, 2020 2:12 am

Glad to hear you found an option that worked for you, and thanks for posting the follow-up!

adafruit_support_mike
 
Posts: 61422
Joined: Thu Feb 11, 2010 2:51 pm

Please be positive and constructive with your questions and comments.