NewSoftSerial Library: An AFSoftSerial update

Hi Mikal

my code is for a wireless RFID reader. I would like to check battery levels and look for tags in my main loop. As has been reported in other threads - http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1201703850/9#9 - SoftwareSerial's read function blocks until there is a tag available to read, making it 'impossible' to perform both checks. The available function in NewSoftSerial would hopefully resolve this.

Much thanks for the support.
Roger :slight_smile:

#include <NewSoftSerial.h>
#include <avr/sleep.h>
#include <string.h>

#define BATTERY_CHECK_INTERVAL 60000
#define SIX_HOUR 952
#define FIVE_HOUR 945
#define FOUR_HOUR 936
#define THREE_HOUR 926
#define TWO_HOUR 910
#define ONE_HOUR 881
#define ZERO_HOUR 836


// RFID reader for Arduino
// Wiring version by BARRAGAN <http://people.interaction-ivrea.it/h.barragan>
// Modified for Arudino by djmatic
// Modified to use SoftwareSerial by Erik Sjodin <http://www.eriksjodin.net>
// Modified for use in TagMat by Roger Meintjes <http://www.doc.gold.ac.uk/~ma701rm/>
 
/*
 * RFID_Scratch03 (Arduino)
 * 
 * Tests communication between RFID, ArduinoXbee, Processing & Scratch.
 * Reads in RFID tag code from reader and writes it out through Xbee.
 * Code is written out as the String start_byte<10 char code>stop_byte.
 *
 * Battery is checked once every minute.
 * Battery charge written out as String start_byte<10 char charge in hours>stop_byte.
 *
 * Connect:
 * Arduino pin 3 to RFID SOUT
 * Arduino GND to RFID GND
 * Arduino Digital pin 2 to RFID /ENABLE
 * Arduino 5v to RFID VCC
 */

 
char code[13] = "";  
char charge[13] = "";
char baseString[11] = {72, 82, 95, 67, 72, 65, 82, 71, 69, 13, 0};   

unsigned long timeNow = 0;
int batteryLevel = 0;
int val = 0;
int bytesRead = 0;

int rx = 3;
int tx = 4;
int batteryPin = 5;
int rfidEnable = 2;

//set up software serial port
NewSoftSerial softSerial = NewSoftSerial(rx, tx);

void setup()
{
  timeNow = millis();
  pinMode(rx, INPUT);
  pinMode(tx, OUTPUT);
  pinMode(batteryPin, INPUT);
  pinMode(rfidEnable, OUTPUT); 
  
  softSerial.begin(2400);     //set software serial port to reader baud rate
  Serial.begin(9600);         //set hardware serial port to xbee baud rate
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);   //set sleep_mode to most power saving   
  
  //initialize reader with reset cycle
  digitalWrite(rfidEnable, LOW);       
  delay(100);
  digitalWrite(rfidEnable, HIGH);
  delay(100);
  digitalWrite(rfidEnable, LOW);
  delay(100);
}

void loop() {
  if((millis() - timeNow) > BATTERY_CHECK_INTERVAL) {
    checkBattery();
    timeNow = millis();
  }
  else {
    checkReader();
  }
}

void checkReader() {
  digitalWrite(rfidEnable, LOW);
  if(softSerial.available() > 0) {
    //check for start byte
    if((val = softSerial.read()) == 10) {
      bytesRead = 0;
      code[bytesRead] = val;
      bytesRead++;
      //do nothing until all twelve bytes have arrived
      while(softSerial.available() < 12);
      //read in code and stop byte
      while(bytesRead < 12) {
        val = softSerial.read();
        code[bytesRead] = val;
        bytesRead++;
      }
      digitalWrite(rfidEnable, HIGH);
      //check for the stop byte
      if(val == 13) {
        Serial.print(code);
      }
      delay(250);      
    }
  }
}

void checkBattery() {
  batteryLevel = analogRead(batteryPin);
  charge[0] = 10;  //start byte
  charge[2] = 0;   //termination byte
  if(batteryLevel > SIX_HOUR) {
    charge[1] = 54;   //ASCII 6
  }
  else if(batteryLevel > FIVE_HOUR) {
    charge[1] = 53;   //ASCII 5
  }
  else if(batteryLevel > FOUR_HOUR) {
    charge[1] = 52;   //ASCII 4
  }
  else if(batteryLevel > THREE_HOUR) {
    charge[1] = 51;   //ASCII 3
  }
  else if(batteryLevel > TWO_HOUR) {
    charge[1] = 50;   //ASCII 2
  }
  else if(batteryLevel > ONE_HOUR) {
    charge[1] = 49;   //ASCII 1
  }
  else if(batteryLevel > ZERO_HOUR) {
    charge[1] = 48;   //ASCII 0
  }
  else {
    sleep_mode();
  }
  Serial.print(strcat(charge, baseString));  //create and write charge string
}