Capture RF Codes to transmit later. RCSwitch / VirtualWire do not work!!

I have several ceiling fans with lights controlled by hunter remote controls. I’ve been trying to automate them with and arduino and a PC. They run on 350mhz.

Big thanks to Retroplayer for his advice in another thread in the project guidance forum. It was getting out of disorganized and this is more of a programming issue so I thought I’d create a new thread.

One of my remotes has a “button board” (the board with the pushbuttons) and a “transmitter” (the transmitter). I desoldered the transmitter from the button board.

Power and ground for the button board and the transmitter come from the arduino.

If I directly connect sig out on the button board to sig in on the transmitter - control works.

If I forward the signal though the arduino with this bit of code - control works

int inpin = 2; // makes the input pin pin 2
int outpin = 3; // makes the output pin pin 3

void setup() {
  Serial.begin(9600);  // initialize serial communication at 9600 bits per second:
  pinMode(inpin, INPUT);  // makes inpin the input pin
  pinMode(outpin, OUTPUT);  // makes outpin the output pin
}

void loop() {
  int inpinState = digitalRead(inpin); //reads the state of the input pin
  digitalWrite(outpin, inpinState);  //writes the state of the input pin on the output
  //Serial.print(inpinState); //swap comments out with digitalwrite to see output on screen.  they dont work together!! 

}

If I connect the output of the button board to RX pin 0 and run this bit of code to look at whats happening - I receive data printed on the screen. (I can even do the same thing with //digitalWrite(outpin, inpinState); in the previous example

int incomingByte = 0;   // for incoming serial data

void setup() {
        Serial.begin(9600);     // opens serial port, sets data rate to 9600 bps
}

void loop() {

        // send data only when you receive data:
        if (Serial.available() > 0) {
                // read the incoming byte:
                incomingByte = Serial.read();

                // say what you got:
               Serial.print(incomingByte, BIN);;
        }
}

Here is the interesting part. If I use a library like RCSwitch, or VirtualWire and load their example receive examples, I get NOTHING. No errors, no invalid data, no unknown coding, no result period. Why? I dont understand. Serial.read and digitalread at least give me something.

I even hooked a pushbutton up so that when I pressed the button it would start to write binary data to the screen. If I didn’t press the lighttoggle button, it would write 0s. If I pushed the lighttoggle button, it would write some codes.

Without RCSwitch or VirtualWire is the project dead?

I’ve been trying to make a way to capture some of the data or replay it. I’ve tried
digitalwrite bit
digitalwrite bit
digitalwrite bit
etc… (it never worked)
until I discovered arrays and started playing with those.

int inpin = 2; //sets the recieve pin from button board
int outpin = 3;  //sets the tx pin to transmitter
int logpin = 13;  //ground on this pin start code
int Array[]={};  //array.  I've tried it with precought values too.
int countin = 0;  //keeps track of array values read
int countout = 0;  //keeps track of array values sent
int ArraySize = sizeof(Array);  //generates array size for max array values

void setup()
        {
        Serial.begin(9600);
        pinMode(inpin, INPUT);
        pinMode(outpin, OUTPUT);
        pinMode(logpin, INPUT);
        digitalWrite(logpin, HIGH);
        if (digitalRead(logpin) == 0) //if I press the code-in button then the light toggle it will read code
            {
            Array[countin] = digitalRead(logpin);
            countin++;
            }
        }

void loop()
        {
        if(countout <= ArraySize)
            {
            digitalWrite(outpin, Array[countout]);
            countout++;
            }
        }

Hard coded Array

int outpin = 3;  //sets the tx pin to transmitter
int Array[155]={0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,1,0,0,0,0,0,0,0,0};  //array.  I've tried it with precought values too.
int countout = 0;  //keeps track of array values read
int ArraySize = 155;  //generates array size for max array values

void setup()
        {
        Serial.begin(9600);
        pinMode(outpin, OUTPUT);
        }

void loop()
        {
        if(countout <= ArraySize)
            {
            digitalWrite(outpin, Array[countout]);
            countout++;
            }
        }

Whats the deal here?

Have you tried adapting Ken Shirriff’s IR library?

int Array[155]={0,0

Using over 300 bytes to store 20 bytes-worth of information is not good use of a precious resource.

Great Idea. I just tried it. I tried his simple IRRecivDemo.

/*
 * IRremote: IRrecvDemo - demonstrates receiving IR codes with IRrecv
 * An IR detector/demodulator must be connected to the input RECV_PIN.
 * Version 0.1 July, 2009
 * Copyright 2009 Ken Shirriff
 * http://arcfn.com
 */

#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

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

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

I have no idea why nothing comes up in Serial Montitor when I use a library, but I can read some long binary when I use digitalRead or Serial.read().

Code:
int Array[155]={0,0
Using over 300 bytes to store 20 bytes-worth of information is not good use of a precious resource.

That is another thing I don’t understand. Why am I getting binary with 50-100 digits. With just the remote by itself, 1/4 of a second of a button press is all it takes to turn on the light. If I press it longer it will eventually dim the light. It takes the arduino 2 seconds just to count to 155, much less output anything from an array.

The “button board” has 4 dip switches that select which receiver I’m talking to, and 5 buttons (Fan High, Fan Med, Fan Low, Fan Off, Light Toggle)

Theoretically it should be something like (0000) Receiver Nibble if all dips are off + (some other nibble based on button pressed). Maybe over and over and over again 5 times? I dont know.

You are getting so many hits becuse you are sampling the pin at free-running speed in your loop. Just doing digitalRead will report the pin state as fast as the Arduino can run. If you set up the pin to interrupt (when it is rising, for example) the output would be much less. It still won't be "accurate" because it will trigger for every rising edge which is not what you want. The data is bi-phase mark encoded. You should have 1 rising edge per period, but getting the actual data means sampling the pin at the middle of the period. If it is high, it is Zero. If it is low, it is one.

For a sanity check, you could do that and should get 10 interrupts per code. However, the code will repeat as long as you press the button, so it is possible that it will count more. The ICs used in these just ignore the repeat transmissions (since "ON" is "ON", afterall) but the Arduino wouldn't without code handling that. On some devices, this repeat code is used for stuff like increasing and decreasing brightness, etc..

Ohh. Ok. I understand most of that. I need to go read what in interrupt is.

You would think that if my little “patchthough” worked. The heart of it was

int inpinState = digitalRead(inpin); //reads the state of the input pin
  digitalWrite(outpin, inpinState);  //writes the state of the input pin on the output pin

This should work? It doesn’t.

int outpin = 3;  //sets the tx pin to transmitter
int inpin = 2; //sets the rx pin from button board
int Array[500]; 
int countin = 0;
int countout = 0;  //keeps track of array values read
int ArraySize = 500;  //generates array size for max array values
int ledpin = 13;

void setup()
        {
        Serial.begin(9600);
        pinMode(outpin, OUTPUT);
        pinMode(inpin, INPUT);
        pinMode(logpin, OUTPUT);
        digitalWrite(ledpin, HIGH);  //turns on L Led while creating array
        if(countin <= ArraySize)
            {
            int inpinState = digitalRead(inpin); //reads the state of the input pin to inpinState
            Array[countin] = inpinState;
            countin++;
            }
        digitalWrite(ledpin, LOW);  //turns off L leg when done
        delay(1000);
        }

void loop()
        {
        if(countout <= ArraySize)
            {
            digitalWrite(outpin, Array[countout]);
            countout++;
            }
        delay(1000);
        }

if(countin <= ArraySize) Doesn’t work?
I wonder why not.

       if(countin <= ArraySize)
            {
            int inpinState = digitalRead(inpin); //reads the state of the input pin to inpinState
            Array[countin] = inpinState;
            countin++;
            }

What’s this doing, in your own words?

 if(countin <= ArraySize)  //if countin is less than or equal to ArraySize, and it should be if 0, do this.
            {
            int inpinState = digitalRead(inpin); //reads the value of inpin to veriable inpinState.
            Array[countin] = inpinState;          //adds inpinState to Array (an array called array) at position 0.
            countin++;                                 //add one to the count
            }

Well, that’s what it is supposed to do anyway. I want an array, string, whatever with the values received on inpin. So I can then output the those values later.

If I go directly from one pin to another

 int inpinState = digitalRead(inpin); //reads the state of the input pin
  digitalWrite(outpin, inpinState);  //writes the state of the input pin on the output

That works. I want to read the codes into memory. Store them for awhile. Transmit them later when I want.

Oh shoot! The array values in code isn't even being ran!. I need to use while instead of if. OK. I'm going to go play and see what happens!

OK I fixed it. I verified that the pushbutton, countin and count out work as prescribed with serial mointor.

I added a pushbutton that I can press at the same time as the light toggle so It can get the code.

It still didn’t work. Maybe I just cant use arrays to do what I want? Maybe I need an array with a variable size of how ever much it receives?

int outpin = 3; //connect the transmitter to pin 3
int inpin = 2; //connect the button board to pin 2
int Array[500]; //create an array
int countin = 0; //create a value to keep track of additions to the array
int countout = 0; //create a value to keep track of read position in the array
int ArraySize = 500; //total size of the array
int readpin = 7; //connect to a switch, connect the other side of the switch to ground

void setup()
{
//setup section
Serial.begin(9600);
pinMode(outpin, OUTPUT);
pinMode(inpin, INPUT);
pinMode(readpin, INPUT);
digitalWrite(readpin, HIGH);
Serial.println(“Ready to Recieve”);

//press the button to continute
while (digitalRead(readpin) == HIGH);
{

//read in bits received to the array
while(countin <= ArraySize)
{
int inpinState = digitalRead(inpin);
Array[countin] = inpinState;
//Serial.println(ArraySize);
//Serial.println(countin);
countin++;
}
}
Serial.println(“Ready to Transmit”);
delay(5000);
}

void loop()
{
//read out the array
while(countout <= ArraySize)
{
digitalWrite(outpin, Array[countout]);
//Serial.println(ArraySize);
//Serial.println(countout);
countout++;
}
delay(1000000);
}

See reply #3, you haven't addressed that.

Ahh.. That makes scene. I'm not sure what to do with it. I did play around with adding delay() and delayMicroseconds() at various values to see how the output changes. It never worked though.

I even made the buffer as big as it could be and still run (about 800 byes) and it still never worked.

Lets say the button board outputs 11110001 for light on. The Arudino is running really fast, what it sees is 111111,111111,111111,111111,000000,000000,000000,111111. I separated the bits by commas for clarity. Well, if the arduino outputs that, the transmitter still sees and transmits 11110001, right? Come to think of it, that would mean that I should see all of my binary in groups of 1 or 0 X number of times, and I do see things like 1101001 so that theory just got trashed. A quick read of wikipedias encoding articles makes me think that it is an issue I cant deal with,

Why does this work? "int inpinState = digitalRead(inpin); //reads the state of the input pin digitalWrite(outpin, inpinState); //writes the state of the input pin on the output pin" I can "forward" the signal though the arduino just fine. Woudn't I encounter the same encoding problem?

A more reasonable approach would be to detect transitions, and the time between them.

eg.

ON ... 10 mS ... OFF ... 30 mS ... ON ... 5 mS ... OFF

and so on.

Then you just have to store a sequence of numbers, one per transition.

Well, that's what it is supposed to do anyway.

What you are doing, right there, is writing to a location which is beyond the end of the array. C and C++ arrays start from zero.

Keep in mind that the array you have is using 1/2 of the SRAM that you have. Since you are storing the result of a digitalRead() in the array, and that result will only ever be 0 or 1, int is not the appropriate type for Array.