So I am trying to set up a controller for my car that will eventually start the car, lock/unlock doors temperature control, battery control and much more using XBee (for active RFID) and Text messages through a SM5100b
I am starting by creating an active RFID key FOB that will unlock and lock the doors when I am approaching/leaving the car.
the current hardware:
keyfob:
Arduino Fio (blue one not V3) with XBee series 1 (AT Mode) and adxl345(stays off when motionless)
Base Station (in the car)
Arduino Mega with xbee shield
I am setting everything up as state machines so as the code gets more complex everything will run without blocking and states may be accessed by other functions if needed.(some already are)
The main question I have is that I need the delay(1); in the loop function or all my read serial data is garbage, I am assuming it is reading too fast, but can't understand why. (i have searched and my code seems to follow non blocking examples i have seen)
my guess would also be that if i had other tasks running in the loop, which eventually there will be, this would take the time of the delay and everything would work, but i somehow feel like this is cheating as the code should work as a stand alone.
I have come up with two possible solutions
-
change if(Serial.available()) to if(Serial.available()>2), and simply add a character to the end of strings that are sent and code it to ignore that character when it gets pushed through by the next command. Seems simple, but maybe sloppy I don't know.
-
increase the baud, maybe this will help the data keep up with the processor (I seriously doubt this will work, but not sure)
Tell me if there is anything about my coding that looks amateur as I am an armature and would really like to take this further.
FYI I am using atmel studio 6 with visual micro plugin (Any suggestions/opinions on ditching arduino environment for atmel now before i get too deep with arduino?)
The code on the fio:
Listens for "hello1"
responds "hello2"
listens for "hello3"
responds "hello4"
after this the FOB and Base Station are considered associated.
my code is:
/* variables for SendXBeeSerial*/
byte SendXBeeSerialCase = 0; // state machine uses to send serial data while multitasking
byte XBeeCommandLength = 0;
String XBeeCommand = "";
const int XBeeSerialReady = 0;
const int XBeeCommandReceived = 1;
/*Variables for ReadXBeeSerial*/
byte ReadXBeeSerialCase = 0;
char XBeeInChar;
String XBeeInString = "";
const int XBeeWaitingCommand = 0;
const int XBeeReadingCommand = 1;
const int XBeeCommandReady = 2;
/* Variables for KeyFOB*/
byte FOBCase = 0;
const int CallingFOB = 0;
const int WaitFOBResponse = 1;
const int VerifyFOBResponse = 2;
const int CallingFOB2 = 3;
const int WaitFOBResponse2 = 4;
const int VerifyFOBResponse2 = 5;
const int FOBAssociated = 6;
unsigned long FOBTimer;
int XBeeSleepTime = 2500; // Should match sleep of xbee module
int XBeeSleepCorrect = 50; // used to correct to eliminate buffer containing multiple commands
unsigned long FOBAssociateTimOut = XBeeSleepTime + XBeeSleepCorrect;
void setup(){
pinMode (13,OUTPUT);
Serial.begin(9600);
Serial3.begin(9600);
FOBTimer = millis();
}
void loop(){
SendXBeeSerial(); // send commands to xbee (if available)
ReadXBeeSerial(); // read commands (from xbee if available)
KeyFOB();
delay(1);
//// reading inputs and setting outputs should be done here /////
}
void SendXBeeSerial(){
switch (SendXBeeSerialCase) {
case XBeeSerialReady :
break ;
case XBeeCommandReceived :
XBeeCommandLength = XBeeCommand.length();
SendXBeeSerialCase ++;
break;
case 12 : // case # defines the maximum string length of XBeeCommand - 2
Serial3.print('\n');
SendXBeeSerialCase = 0;
XBeeCommand = "";
Serial.print("xbee received string that is too long");/////////////////////////////////////////////////////////////////////////////////
break;
default:
if (SendXBeeSerialCase <= XBeeCommandLength + 1 ){
Serial3.print(XBeeCommand.charAt(SendXBeeSerialCase - 2));
SendXBeeSerialCase ++;
}
else{
Serial3.print('\n');
SendXBeeSerialCase = 0;
XBeeCommand = "";
}
break;
}
}
void ReadXBeeSerial (){
switch (ReadXBeeSerialCase){
case XBeeWaitingCommand :
if (Serial3.available()){
ReadXBeeSerialCase ++;
}
break;
case XBeeReadingCommand :
XBeeInChar = Serial3.read();
switch (XBeeInChar){
case '\r':
ReadXBeeSerialCase ++;
break;
case '\n':
ReadXBeeSerialCase ++;
break;
default:
XBeeInString += XBeeInChar;
break;
}
break;
case XBeeCommandReady :
break;
}
}
void KeyFOB(){
switch (FOBCase){
case CallingFOB :
if (SendXBeeSerialCase == XBeeSerialReady){
XBeeCommand = "hello1";
SendXBeeSerialCase = 1;
FOBCase ++;
FOBTimer = millis();
}
break;
case WaitFOBResponse :
if (millis() - FOBTimer <= FOBAssociateTimOut ){
if (ReadXBeeSerialCase == XBeeCommandReady){
FOBCase = VerifyFOBResponse;
Serial.println("command found");
}
}
else {
Serial.println("fob response timout");
FOBCase = CallingFOB;
}
break;
case VerifyFOBResponse :
if (XBeeInString == "hello2"){
FOBCase ++;
}
else {
FOBCase = CallingFOB;
}
XBeeInString = "";
ReadXBeeSerialCase = XBeeWaitingCommand;
break;
case CallingFOB2 :
if (SendXBeeSerialCase == XBeeSerialReady){
XBeeCommand = "hello3";
SendXBeeSerialCase = 1;
FOBCase ++;
FOBTimer = millis();
Serial.println("hello3 sent");
}
break;
case WaitFOBResponse2 :
if (millis() - FOBTimer <= FOBAssociateTimOut ){
if (ReadXBeeSerialCase == XBeeCommandReady){
FOBCase = VerifyFOBResponse2;
Serial.println("command found");
}
}
else {
Serial.println("fob response timout");
FOBCase = CallingFOB;
}
break;
case VerifyFOBResponse2 :
if (XBeeInString == "hello4"){
FOBCase ++;
FOBTimer = millis();
}
else {
FOBCase = CallingFOB;
}
XBeeInString = "";
ReadXBeeSerialCase = XBeeWaitingCommand;
break;
case FOBAssociated :
if (millis() - FOBTimer <= FOBAssociateTimOut ){
Serial.println("fob associated");
}
else {
FOBCase = 0;
}
break;
default:
FOBCase = 0;
break;
}
}