I am having some interesting behaviour when I only have the battery connected. My code below describes a simple rfid tag system where I have an nfc reader (http://www.electrodragon.com/product/pn532-nfc-rfid-easy-module-r2/) that will grab the ID of the tag, store the number locally through the sparkfun micro sd breakout (https://www.sparkfun.com/products/13743) and then also send the tag up to the cloud while giving feedback locally with a small strip of ws2812s.
I have been testing potential pitfalls when the electron drops connection and I have come across some strange behaviour. If the device is connected via a USB cable, this behaviour does not present itself. When the electron is running off of the battery, and it connects to the cloud, there are no problems. When the device cannot connect (disconnecting the antenna), the indicator light is flashing green and it becomes difficult to read a tag. I have noticed that the code is still responsive as I have a button connected to give feedback about the battery however, I need to leave the tag on top of the reader for about 10 seconds and then it will eventually get picked up. I’m curious if the antenna is sucking up all the power and has a timeout set to roughly 10 seconds before it retries which allows my reader to get enough power for a second and read out a tag? But that’s just a random guess currently.
// This #include statement was automatically added by the Particle IDE.
#include <SdFat.h>
#include "Particle.h"
#include "neopixel.h"
//------------------------------------------------------------------------------
// Setup SPI configuration.
// Primary SPI with DMA
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default)
SdFat sd;
const uint8_t chipSelect = SS;
#define DEBUG_MODE 0
FuelGauge fuel;
SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D2
#define PIXEL_COUNT 8
#define PIXEL_TYPE WS2812B
int counting = 0;
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
const unsigned char wake[24]={
0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xfd, 0xd4, 0x14, 0x01, 0x17, 0x00};//wake up NFC module
const unsigned char firmware[9]={
0x00, 0x00, 0xFF, 0x02, 0xFE, 0xD4, 0x02, 0x2A, 0x00};//
const unsigned char tag[11]={
0x00, 0x00, 0xFF, 0x04, 0xFC, 0xD4, 0x4A, 0x01, 0x00, 0xE1, 0x00};//detecting tag command
const unsigned char std_nfc[25] = {
0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x0C, \
0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x4b, 0x00};
unsigned char old_id[5];
unsigned char receive_nfc[25];//Command receiving buffer
unsigned char tag_id[8];//Command receiving buffer
int local_status = 0;
//button variables
int button_val = 0;
int button_val_last = 0;
bool debounce_state = false;
int debounce_count = 0;
int debounce_threshold = 200;
String tag_str = "";
void setup()
{
pinMode(D0, INPUT_PULLUP);
if (DEBUG_MODE == 1) Serial.begin(9600);
while (!Serial) {
SysCall::yield();
}
// Initialize SdFat or print a detailed error message and halt
// Use half speed like the native library.
// Change to SPI_FULL_SPEED for more performance.
if (!sd.begin(chipSelect, SPI_HALF_SPEED)) {
sd.initErrorHalt();
}
fuel.quickStart();
strip.begin();
strip.show(); // Initialize all pixels to 'off'
strip.setBrightness(10);
flash(100,100,100, 5); //initial white flash to let the user know we are online
//to initially turn on the leds for checking the diffusion on the white acrylic
//setAllPixels(8,0,100,0);
Serial1.begin(115200);
wake_nfc();
delay(100);
read_nfc(15);
delay(100);
display(15);
}
void loop()
{
Particle.connect();
setAllPixels(strip.numPixels(), 0, 0, 0);
int bat_level = random(0, 100);//fuel.getSoC();
int button_val = checkButton();
if (button_val == 0){
checkBatLevel(bat_level);
}
File myFile;
send_tag();
read_nfc(25);
delay(100);
if (!cmp_id()){
if(test_nfc()){
display(25);
if (DEBUG_MODE == 1) Serial.println(fuel.getSoC());
if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) {
sd.errorHalt("opening test.txt for write failed");
}
// if the file opened okay, write to it:
myFile.println(tag_str);
// close the file:
myFile.close();
if (Particle.connected()){
Particle.publish("Button Pressed", String(fuel.getSoC()),1,PRIVATE);
flash(0,100,0,5);
} //publishing nfc data to cloud
else{
flash(100,0,0,5);
}
delay(100);
}
}
copy_id();
}
void wake_nfc(void)
{
unsigned char i;
for(i=0; i<24; i++){
Serial1.write(wake[i]);
Serial1.flush();
}
}
void read_nfc(unsigned int size)
{
unsigned int i, j;
tag_str = "";
for(i=0;i<size;i++){
receive_nfc[i] = Serial1.read();
}
}
void display(unsigned int size)
{
unsigned int i;
tag_str = "";
// for(i=0;i<size;i++){
// Serial.print(receive_nfc[i], HEX);
// Serial.print(" ");
// }
Serial.println();
for(i=19;i<size-2;i++){
tag_str += String(receive_nfc[i],HEX) + ":";
}
if (DEBUG_MODE == 1) Serial.println(tag_str);
}
void send_tag(void)
{
unsigned char i;
for(i=0;i<11;i++){
Serial1.write(tag[i]);
Serial1.flush();
}
}
char cmp_id (void)
{
int ai, oi;
for(oi=0,ai=19; oi<5; oi++,ai++){
if(old_id[oi] != receive_nfc[ai]){
return 0;
}
}
return 1;
}
int test_nfc(void)
{
int i;
for(i=0; i<19; i++){
if(receive_nfc[i] != std_nfc[i]){
return 0;
}
}
return 1;
}
void copy_id(void)
{
int ai, oi;
for (oi=0,ai=19; oi<5; oi++,ai++){
old_id[oi] = receive_nfc[ai];
}
}
void flash(int r, int g, int b, int flashes){
for(int j = 0; j < flashes; j++){
setAllPixels(8,r,g,b);
delay(100);
setAllPixels(8,0,0,0);
delay(100);
}
}
void holdLights(int pixels, int r, int g, int b, int seconds){
setAllPixelsChase(pixels, r, g, b);
delay(seconds);
setAllPixels(pixels, 0, 0, 0);
}
void setAllPixelsChase(int pixels, int r, int g, int b){
for(int i=0; i< pixels; i++) {
strip.setPixelColor(i, r, g, b);
strip.show();
delay(50);
}
}
void setAllPixels(int pixels, int r, int g, int b){
for(int i=0; i< pixels; i++) {
strip.setPixelColor(i, r, g, b);
strip.show();
}
}
void checkBatLevel(int bat_level){
int bat_delay = 1000;
if (bat_level > 0 and bat_level < 20){
holdLights(2, 100,0,0,bat_delay);
}
else if (bat_level > 20 and bat_level < 50){
holdLights(4, 255,165,0, bat_delay);
}
else if (bat_level > 50 and bat_level < 80){
holdLights(6, 100,100,0,bat_delay);
}
else if (bat_level > 80){
holdLights(8, 0,100,0,bat_delay);
}
}
int checkButton(){
button_val = digitalRead(D0);
return button_val;
}