I am using a Pololu A-Star 328PB running 8MHz at 3.3V.
I have a RN4871 BLE module connected to the Serial1 ports.
I include the "avr/sleep.h" to enable me to run in Low Power by putting the 328PB to sleep (set_sleep_mode(SLEEP_MODE_PWR_DOWN);).
My sketch "sleeps" for three cycles of 8 seconds each.
On third sleep cycle, I call, amongst other functions, "scanBLE();" which starts the BLE scanning.
However, although "scanBLE()" function is called, I do not receive any data on the Serial1.
I suspect that either the "sleep" function or something else is preventing this.
I cannot, after a few days, fathom why this is happening.
I have written a "test" sketch which does not have any sleep functions and it runs fine when "scanBLE()" is called from setup().
My "Test" sketch:
int beaconcount;
String beaconMAC;
String beaconName;
boolean scanning = false;
#define INTERVAL_SCAN 5000
unsigned long scantime = 0;
void setup() {
Serial.begin(9600);
Serial1.begin(9600); // Enable Serial1 (BLE)
delay(500);
scanBLE();
}
void loop() {
if (Serial1.available()) {
String s = Serial1.readStringUntil('\n');
// Serial.println(s);
if (scanning == true) {
int posCMD = s.indexOf("D>");
if (posCMD > 0) {
Serial1.println("F");
Serial1.print('\r');
}
}
scantime = millis();
int posName = s.indexOf("45434F");
if (posName > 0) {
beaconcount = beaconcount + 1;
int posMAC = s.indexOf(",");
beaconMAC = s.substring(posMAC - 12, posMAC);
beaconName = s.substring(posName + 6, posName);
}
}
if ((millis() - scantime) >= INTERVAL_SCAN)
{
scantime = millis();
scanning = false;
if (beaconcount >= 1) {
Serial.print("Beacon MAC: ");
Serial.println(beaconMAC);
}
if (beaconcount <= 0) {
Serial.println("NO Beacon Found");
}
Serial1.print("R,1");// RESET BLE Module
Serial1.print('\r');
}
}
void scanBLE() {
scanning = true;
Serial1.print("$$");
Serial.println("Scanning.......");
}
Serial Monitor output:
Scanning.......
Beacon MAC: B752B81093D7
My "Full" Sketch with "Sleep":
#include <SoftwareSerial.h>
#include <avr/wdt.h> // library for default watchdog functions
#include <avr/interrupt.h> // library for interrupts handling
#include <avr/sleep.h> // library for sleep
#include <avr/POWER.h> // library for POWER_3V control
#include <Vcc.h> // library to read battery voltage
const float VccMin = 0.0; // Minimum expected Vcc level, in Volts.
const float VccMax = 3.6; // Maximum expected Vcc level, in Volts.
const float VccCorrection = 1.0 / 1.0; // Measured Vcc by multimeter divided by reported Vcc
Vcc vcc(VccCorrection);
int myVolts;
const byte pinGPS_Power = 5;
const byte pinSIG_Sleep = 6;
const byte pinBLE_Sleep = 7;
int beaconcount = 0;
String beaconMAC;
String beaconName;
boolean scanning = false;
#define INTERVAL_SCAN 5000
unsigned long scantime = 0;
double lastLAT;
double lastLON;
// how many times remain to sleep before wake up
int nbr_remaining;
// how long to sleep for - n x 8 seconds
int sleep_time;
// count sleep_periods
int sleep_periods_count = 0;
// count sleep periods for check sensors
int check_sensor_count = 0;
// count sleep periods for transmit
int check_transmit_count = 0;
// interrupt raised by the watchdog firing
// when the watchdog fires during sleep, this function will be executed
// remember that interrupts are disabled in ISR functions
ISR(WDT_vect)
{
// not hanging, just waiting
// reset the watchdog
wdt_reset();
}
// function to configure the watchdog: let it sleep 8 seconds before firing
// when firing, configure it for resuming program execution
void configure_wdt(void)
{
cli(); // disable interrupts for changing the registers
MCUSR = 0; // reset status register flags
// Put timer in interrupt-only mode:
WDTCSR |= 0b00011000; // Set WDCE (5th from left) and WDE (4th from left) to enter config mode,
// using bitwise OR assignment (leaves other bits unchanged).
WDTCSR = 0b01000000 | 0b100001; // set WDIE: interrupt enabled
// clr WDE: reset disabled
// and set delay interval (right side of bar) to 8 seconds
sei(); // re-enable interrupts
// reminder of the definitions for the time before firing
// delay interval patterns:
// 16 ms: 0b000000
// 500 ms: 0b000101
// 1 second: 0b000110
// 2 seconds: 0b000111
// 4 seconds: 0b100000
// 8 seconds: 0b100001
}
// Put the Arduino to deep sleep. Only an interrupt can wake it up.
void sleep(int ncycles)
{
nbr_remaining = ncycles; // defines how many cycles should sleep
// Set sleep to full POWER down. Only external interrupts or
// the watchdog timer can wake the CPU!
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// // Turn off the ADC while asleep.
// POWER_adc_disable();
while (nbr_remaining > 0) { // while some cycles left, sleep!
// Enable sleep and enter sleep mode.
sleep_mode();
// CPU is now asleep and program execution completely halts!
// Once awake, execution will resume at this point if the
// watchdog is configured for resume rather than restart
// When awake, disable sleep mode
sleep_disable();
// we have slept one time more
nbr_remaining = nbr_remaining - 1;
}
// // put everything on again
// POWER_3V_all_enable();
}
SoftwareSerial sigSerial(8, 9); // RX, TX
void setup() {
Serial.begin(9600);
Serial1.begin(9600); // Enable Serial1 (BLE)
sigSerial.begin(9600); // Enable SoftwareSerial sigSerial
// configure the watchdog
configure_wdt();
pinMode (pinGPS_Power, OUTPUT);
digitalWrite (pinGPS_Power, HIGH); // MAKE SURE GPS IS OFF
}
void loop() {
// sleep_time = 225;// 30 minutes
// sleep_time = 112.5;// 15 minutes
// sleep_time = 30;// 5 minutes THIS IS DEFAULT
// sleep_time = 5;// 40 seconds
// sleep_time = 2.5;// 20 seconds
sleep_time = 1;// 8 seconds
// BLE:**********************************************************************
if (Serial1.available()) {
String s = Serial1.readStringUntil('\n');
Serial.print("BLE Sent: ");
Serial.println(s);
if (scanning == true) {
int posCMD = s.indexOf("D>");
if (posCMD > 0) {
Serial1.print("F");
Serial1.print('\r');
}
}
scantime = millis();
int posName = s.indexOf("45434F");
if (posName > 0) {
beaconcount = beaconcount + 1;
int posMAC = s.indexOf(",");
beaconMAC = s.substring(posMAC - 12, posMAC);
beaconName = s.substring(posName + 6, posName);
}
}
if ((millis() - scantime) >= INTERVAL_SCAN)
{
scantime = millis();
scanning = false;
if (beaconcount >= 1) {
Serial.print("Beacon MAC: ");
Serial.println(beaconMAC);
}
if (beaconcount <= 0) {
Serial.println("NO Beacon Found");
}
Serial1.println("R,1");// RESET BLE Module
Serial1.print('\r');
}
//END BLE**********************************************************************
//CHECK SENSORS AFTER COUNT == N
check_sensor_count++;
Serial.print("Sleep Count: ");
Serial.println(check_sensor_count);
if (check_sensor_count >= 3)// time to check sensors
{
Serial.print("Time to do BLE Stuff: ");
Serial.println(check_sensor_count);
scanBLE(); // Start BLE scan
readBattery();
Serial.print("My Voltage: ");
Serial.println(myVolts);
delay(50);
check_sensor_count = 0;
}
//TRANSMIT AFTER COUNT == N
check_transmit_count++;
Serial.print("Transmit counts: ");
Serial.println(check_transmit_count);
delay(50);
Serial.println("-----------------------------------------");
delay(50);
if (check_transmit_count >= 10)// time to transmit
{
Serial.println("Time to Transmit");
delay(50);
check_transmit_count = 0;
}
sleep(sleep_time);
}
void scanBLE() {
scanning = true;
Serial1.print("$$");
Serial.println("Scanning.......");
}
void readBattery()
{
float v = vcc.Read_Volts();
myVolts = v * 10;
}
Serial Monitor output:
Sleep Count: 1
Transmit counts: 1
-----------------------------------------
Sleep Count: 2
Transmit counts: 2
-----------------------------------------
Sleep Count: 3
Time to do BLE Stuff: 3
Scanning.......
My Voltage: 32
Transmit counts: 3
-----------------------------------------