Question

I have decoded my IR codes for my remote and have them working when run in a sketch, see IR CODE.

My RFID cat feeder sketch runs fine as well, see RFID Code.

I am however having trouble using the IR remote with any other blocking functions, specifically this RFID reader sketch...each skecth seems to need to wait all the time in order to be ready for the signal. What I want to be able to do is have a RFID reader running normally but be able to put it into manual mode via the IR remote. Any help or pointers would be greatly appreciated. I have code that has tried to integrate the two, but it has never worked right, please let me know if that would help, Thanks!

IR Code

#include <IRremote.h>

int RECV_PIN = 4;
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup(){
  irrecv.enableIRIn(); // Start the receiver
  Serial.begin(2400);
}

// Compare two tick values, returning 0 if newval is shorter,
// 1 if newval is equal, and 2 if newval is longer
// Use a tolerance of 20%
int compare(unsigned int oldval, unsigned int newval) {
  if (newval < oldval * .8) {
    return 0;
  } 
  else if (oldval < newval * .8) {
    return 2;
  } 
  else {
    return 1;
  }
}

// Use FNV hash algorithm: http://isthe.com/chongo/tech/comp/fnv/#FNV-param
#define FNV_PRIME_32 16777619
#define FNV_BASIS_32 2166136261

/* Converts the raw code values into a 32-bit hash code.
 * Hopefully this code is unique for each button.
 */
unsigned long decodeHash(decode_results *results) {
  unsigned long hash = FNV_BASIS_32;
  for (int i = 1; i+2 < results->rawlen; i++) {
    int value =  compare(results->rawbuf[i], results->rawbuf[i+2]);
    // Add value into the hash
    hash = (hash * FNV_PRIME_32) ^ value;
  }
  return hash;
}

void loop() {
  if (irrecv.decode(&results)) {
    unsigned long hash = decodeHash(&results);
    switch (hash) {
      case 0x4AB0F7B6: // any button held down
        Serial.println("Button Repeat");
        break;
      case 0x2D4AFCCE: // Power
        Serial.println("Power");
        break;
      case 0xE8187BAA: // EQ
        Serial.println("EQ");
        break;
      case 0x95D01E65: // CD/Tuner
        Serial.println("CD/Tuner");
        break;
      case 0xE20BA29: // Mute
        Serial.println("Mute");
        break;
      default:
        Serial.print("Unknown ");
        Serial.println(hash, HEX);    
    }
    irrecv.resume(); // Resume decoding (necessary!)
  }
}

RFID Code

/*** Cord Slatton
* date 12-13-2012 **/

#include <IRremote.h>
#define RFID_ENABLE 2   //to RFID ENABLE
#define CODE_LEN 10      //Max length of RFID tag
#define START_BYTE 0x0A 
#define STOP_BYTE 0x0D
#define MOTOR_RUN_LENGTH 1000 //time, in ms, to run door motor

char tag[CODE_LEN];
int pwm_b = 11;  //PWM control for motor outputs 3 and 4 is on digital pin 11
int dir_b = 13;  //direction control for motor outputs 3 and 4 is on digital pin 13
int door_status = 1; // 1 == closed, 0 == open
//PIR sensor
const int sensorPIR = A0;

unsigned long rfidHitTime = 0; //when did we get last rfid hit?
unsigned long pirHitTime = 0; //when did we get last PIR hit?
unsigned int pirClose = 0;
unsigned int rfidClose = 0;

void setup() {
  Serial.begin(2400); //parallax rfid reader seems to only like serial 2400  
  Serial.println("RoboFeeder Online");
  //rfid
  pinMode(RFID_ENABLE,OUTPUT);
  //motor
  pinMode(pwm_b, OUTPUT);
  pinMode(dir_b, OUTPUT);
  //PIR
  pinMode(sensorPIR, INPUT);
  digitalWrite(sensorPIR, LOW);
  Serial.println("Warming up PIR...");
  delay(10000);
  Serial.println("PIR ready");

  Serial.println("RoboFeeder startup test: Door");
  openDoor();
  delay(2500);
  closeDoor();
  Serial.println("RoboFeeder door test complete");
}

void loop() {
  delay(1500);
  enableRFID(); 
  getRFIDTag(); //waiting function, till gets any tag

  disableRFID();
  openDoor();
  sendCode();

  Serial.flush();
  clearCode();
}

/*** Clears out the memory space for the tag to 0s. */
void clearCode() {
  for(int i=0; i<CODE_LEN; i++) {
    tag[i] = 0; 
  }
}

/*** Sends the tag to the computer. */
void sendCode() {
    Serial.print("TAG:");
    for(int i=0; i<CODE_LEN; i++) {
      Serial.print(tag[i]); 
    }
    Serial.println("\r"); 
}

/**************************************************************/
/********************   RFID Functions  ***********************/
/**************************************************************/

void enableRFID() {
   digitalWrite(RFID_ENABLE, LOW);    
}

void disableRFID() {
   digitalWrite(RFID_ENABLE, HIGH);  
}

/*** Blocking function, waits for and gets the RFID tag. */
void getRFIDTag() {
  byte next_byte; 
  while(Serial.available() <= 0) {
    if(door_status == 0){ //open
      pirDetection(); 
      rfidClose = millis() - rfidHitTime;
      pirClose =  millis() - pirHitTime;
      Serial.print("RFID Close: ");
      Serial.print(rfidClose);
      Serial.print(" - PIR Close: ");
      Serial.println(pirClose);
      //if door has been open for more than a certain amount of time with no rfid hit and PIR no hit for certain time
      if( (rfidClose > 30000) && (pirClose > 10000) ){
        closeDoor();     
      }
    }        
  }
  pirHitTime = 0;
  if((next_byte = Serial.read()) == START_BYTE) {      
    byte bytesread = 0; 
    while(bytesread < CODE_LEN) {
      if(Serial.available() > 0) { //wait for the next byte
          if((next_byte = Serial.read()) == STOP_BYTE) break;       
          tag[bytesread++] = next_byte;         
      }
    }
    rfidHitTime = millis(); //keep track of when last rfid hit was    
  }
}

/********************   Motor Functions  ***********************/

void openDoor() {
  if(door_status == 1){      
    motorRun(150);
    digitalWrite(dir_b, HIGH);  //Set motor direction, 1 low, 2 high
    Serial.println("Door opening");
    delay(MOTOR_RUN_LENGTH);
    motorStop();
    door_status = 1 - door_status;
  }
}

void closeDoor() {
  if(door_status == 0){    
    motorRun(150);
    digitalWrite(dir_b, LOW);  //Reverse motor direction, 1 high, 2 low
    Serial.println("Door closing");
    delay(MOTOR_RUN_LENGTH);
    motorStop();
    door_status = 1 - door_status; 
  }     
}

void motorRun(int speed) {
  analogWrite(pwm_b, speed);  //set motor to run at speed variable value
}
void motorStop() {
  analogWrite(pwm_b, 0);  //set motor to run at 0
}

/********************   PIR Functions  ***********************/

boolean pirDetection() {
  //returns true if PIR analog reading has been rising for more than 10 cycles, false if has been falling
  int counter = 0;
  int pirSensorReading[10];
  int avgReading = 0;
  while(counter < 10){
    pirSensorReading[counter] = analogRead(sensorPIR);
    avgReading += pirSensorReading[counter];  
    counter++;
    delay(300);
  }
  avgReading = avgReading/10;
  Serial.print("Avg. PIR: ");
  Serial.print(avgReading);
  Serial.print(" - Last PIR: ");
  Serial.println( pirSensorReading[9] );

  if( (pirSensorReading[9] > avgReading+1) || (analogRead(sensorPIR) > 700) ){
    pirHitTime = millis(); //keep track of when last PIR hit was
    return true;
  }
  else if(pirSensorReading[9] <= avgReading){
    return false;
  }
}
Was it helpful?

Solution

I was able to successfully resolve this problem by using AttachInterrupt().

Specifically I found a library for IR Remotes that is interrupt based instead of polling based as I was previously trying to use.

In case anyone is interested the finished RFID IR remote control cat feeder code is:

/*** Cord Slatton
 * date 12-28-2012 **/

//IR includes
//info: http://www.zbotic.com/index.php/download/
//download: http://www.zbotic.com/index.php/download_file/view/12/118/
#include "PCInterrupt.h"
#include "Device.h"
#include "irController.h"

#define RFID_ENABLE 8 //to RFID ENABLE
#define CODE_LEN 10 //Max length of RFID tag
#define START_BYTE 0x0A
#define STOP_BYTE 0x0D
#define MOTOR_RUN_LENGTH 1000 //time, in ms, to run door motor

char tag[CODE_LEN];
int pwm_b = 11; //PWM control for motor outputs 3 and 4 is on digital pin 11
int dir_b = 13; //direction control for motor outputs 3 and 4 is on digital pin 13
int door_status = 1; // 1 == closed, 0 == open
int manual_mode = 1; // 1 == auto, 0 == manual
//PIR sensor
const int sensorPIR = A0;
//IR init
int manualModePin = 10; //led pin for indication of manual mode
IRController irController;

unsigned long rfidHitTime = 0; //when did we get last rfid hit?
unsigned long pirHitTime = 0; //when did we get last PIR hit?
unsigned long pirClose = 0;
unsigned long rfidClose = 0;

void setup() {
  Serial.begin(2400); //parallax rfid reader seems to only like serial 2400  
  Serial.println("RoboFeeder Online");
  //rfid
  pinMode(RFID_ENABLE,OUTPUT);
  //motor
  pinMode(pwm_b, OUTPUT);
  pinMode(dir_b, OUTPUT);
  //PIR
  pinMode(sensorPIR, INPUT);
  digitalWrite(sensorPIR, LOW);
  Serial.println("Warming up PIR...");
  delay(10000);
  Serial.println("PIR ready");
  //IR remote
  pinMode(manualModePin, OUTPUT);
  digitalWrite(manualModePin, LOW);
  int res = irController.begin(IR_PIN, OTHER_DEVICE);
  if (res != SUCCESS) {
    Serial.println("error=");
    Serial.println(res);
  }
  Serial.println("IR Remote enabled");

  Serial.println("RoboFeeder startup test: Door");
  openDoor();
  delay(2500);
  closeDoor();
  Serial.println("RoboFeeder door test complete");
}

void loop() {
  delay(1500);
  enableRFID(); 
  getRFIDTag(); //waiting function, till gets any tag

  disableRFID();
  openDoor();
  sendCode();

  Serial.flush();
  clearCode();
}

/*** Clears out the memory space for the tag to 0s. */
void clearCode() {
  for(int i=0; i<CODE_LEN; i++) {
    tag[i] = 0; 
  }
}

/*** Sends the tag to the computer. */
void sendCode() {
    Serial.print("TAG:");
    for(int i=0; i<CODE_LEN; i++) {
      Serial.print(tag[i]); 
    }
    Serial.println("\r"); 
}

/**************************************************************/
/********************   RFID Functions  ***********************/
/**************************************************************/

void enableRFID() {
   digitalWrite(RFID_ENABLE, LOW);    
}

void disableRFID() {
   digitalWrite(RFID_ENABLE, HIGH);  
}

/*** Blocking function, waits for and gets the RFID tag. */
void getRFIDTag() {
  byte next_byte; 
  while(Serial.available() <= 0) {
    if(door_status == 0){ //open
      pirDetection(); 
      rfidClose = millis() - rfidHitTime;
      pirClose =  millis() - pirHitTime;
      Serial.print("RFID Close: ");
      Serial.print(rfidClose);
      Serial.print(" - PIR Close: ");
      Serial.println(pirClose);
      //if door has been open for more than a certain amount of time with no rfid hit and PIR no hit for certain time
      if( (rfidClose > 40000) && (pirClose > 15000) ){
        closeDoor();     
      }
    }    
    IRRemote(); 
    if(manual_mode == 0)
      manualMode();   
  }
  //PIR set to current loop time to keep it from freaking out
  pirHitTime = millis();

  if((next_byte = Serial.read()) == START_BYTE) {      
    byte bytesread = 0; 
    while(bytesread < CODE_LEN) {
      if(Serial.available() > 0) { //wait for the next byte
          if((next_byte = Serial.read()) == STOP_BYTE) break;       
          tag[bytesread++] = next_byte;         
      }
    }
    rfidHitTime = millis(); //keep track of when last rfid hit was    
  }
}

/**************************************************************/
/********************   Motor Functions  ***********************/
/**************************************************************/

void openDoor() {
  if(door_status == 1){      
    motorRun(150);
    digitalWrite(dir_b, HIGH);  //Set motor direction, 1 low, 2 high
    Serial.println("Door opening");
    delay(MOTOR_RUN_LENGTH);
    motorStop();
    door_status = 1 - door_status;
  }
}

void closeDoor() {
  if(door_status == 0){    
    motorRun(150);
    digitalWrite(dir_b, LOW);  //Reverse motor direction, 1 high, 2 low
    Serial.println("Door closing");
    delay(MOTOR_RUN_LENGTH);
    motorStop();
    door_status = 1 - door_status; 
  }     
}

void motorRun(int speed) {
  analogWrite(pwm_b, speed);  //set motor to run at speed variable value
}
void motorStop() {
  analogWrite(pwm_b, 0);  //set motor to run at 0
}

/**************************************************************/
/********************   PIR Functions  ***********************/
/**************************************************************/

boolean pirDetection() {
  //returns true if PIR analog reading has been rising for more than 10 cycles, 
  //false if has been falling
  int counter = 0;
  int pirSensorReading[10];
  int avgReading = 0;
  while(counter < 10){
    pirSensorReading[counter] = analogRead(sensorPIR);
    avgReading += pirSensorReading[counter];  
    counter++;
    delay(300);
  }
  avgReading = avgReading/10;
  Serial.print("Avg. PIR: ");
  Serial.print(avgReading);
  Serial.print(" - Last PIR: ");
  Serial.println( pirSensorReading[9] );

  if( (pirSensorReading[9] > avgReading+1) || (analogRead(sensorPIR) > 700) ){
    pirHitTime = millis(); //keep track of when last PIR hit was
    return true;
  }
  else if(pirSensorReading[9] <= avgReading){
    return false;
  }
}

/**************************************************************/
/********************   IR Remote Functions  ***********************/
/**************************************************************/

void IRRemote(){ 
  int val = irController.read(); // Returns negative value if no new command rcvd  
  if (val >=0){
    Serial.print("Key: ");
    Serial.println(val);
    if(val == 100){
      manual_mode = 1 - manual_mode;
    }    
    else if( (val >= 0) && (manual_mode == 0) ){
      if(door_status == 1)
        openDoor();
      else
        closeDoor();
    }
  }
  delay(500); 
}

//blocking function that won't let you leave till you turn off manual mode
void manualMode(){
  disableRFID();
  Serial.println("Manual Mode on");
  digitalWrite(manualModePin, HIGH);
  while(manual_mode == 0){
    IRRemote();
  }
  Serial.println("Manual Mode exiting");
  digitalWrite(manualModePin, LOW);
  //set sensors to count from now, esentially zero them out
  pirHitTime = millis();
  rfidHitTime = millis();
  enableRFID();
}    
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top