433mhz Arduino RF transmitter for HFY608A

So I have a set of small RF remotes that came with some led lights. This is how one of them looks like:

HFY608A

I own a Homey and was wondering if and how it was possible to access the led lights by using the Homey and not these remotes. At this moment it took me too long to find out how the 433Mhz capabilities of Homey really work and I surely did not plan to build an application so I had to come with something else.

In the past I used to tinker a bit with Arduino so why not do it again and so I did. This is what I came up with.

Step 1: Signal investigation

As I am no 433Mhz expert I did not what to do. Now (when having finished my project) I do, kind of… So with an Arduino I created a test rig and so required a signal receiver and transmitter. I had to “read” the signal from the remotes and “resend” it to the led lights and see what happens.

So I created two configurations for the single Arduino I am using. This is the Arduino:

Slide1

It is an Arduino Mega 2560 with ethernet shield. Why: I am going to run a simple webserver on the Arduino and will be using some big arrays as RF commands so I needed some memory. Hence the Mega. Besides that I ordered them cheap, so why bother.

To receive or “read” RF signals I needed a RF receiver for my Arduino and ordered a set of RF-5V (receiver) and XKFST (transmitter). You can google these. They are cheap and easy to use. If you like to rebuild this project you can also get a combined one (both receiver and transmitter in one) but I needed the receiver only for investigation and was not going to use it further on. More info on 433Mhz and Arduino, please read this.

To “read” RF signal I used this configuration:

Slide3

Using 3.3v on the vcc pin, GND on GND and A0 on data.

I also needed some code to make the Arduino “read”. The mentioned link did help a lot and so I came up with this:

#define rfReceivePin A0 //RF Receiver data pin = Analog pin 0
#define rfTransmitPin 4 //RF Transmitter pin = digital pin 4

const int dataSize = 500; //Arduino memory is limited (max=1700)
byte storedData[dataSize]; //Create an array to store the data
byte dataOnOff[50] = {9, 2, 9, 2, 3, 8, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 9, 2, 2, 9, 9, 2, 2, 9, 2, 9, 9, 2, 2, 9, 9, 2, 9, 2, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 2, 100};
byte dataUp[50] = {9, 2, 9, 2, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 8, 3, 8, 2, 3, 8, 9, 2, 2, 9, 2, 9, 9, 2, 2, 9, 9, 2, 8, 3, 2, 9, 2, 9, 2, 9, 2, 9, 8, 3, 2, 9, 1, 9, 2, 100};
byte dataDownFirst[52] = {4, 98, 10, 1, 10, 1, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 9, 2, 9, 2, 3, 8, 9, 2, 3, 8, 3, 8, 9, 2, 3, 8, 9, 2, 9, 2, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 2, 9, 2, 99};
byte dataDownRest[50] = {9, 2, 9, 2, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 9, 2, 9, 2, 3, 8, 9, 2, 3, 8, 3, 8, 9, 2, 3, 8, 9, 2, 9, 2, 3, 8, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 2, 9, 2, 100};
byte dataUpFirst[52] = {5, 96, 10, 0, 4, 7, 3, 8, 9, 1, 10, 1, 3, 7, 4, 7, 10, 1, 3, 7, 4, 7, 9, 2, 3, 7, 10, 1, 9, 1, 10, 1, 3, 8, 9, 1, 3, 8, 3, 8, 3, 7, 3, 8, 9, 2, 2, 8, 3, 8, 3, 96};
byte dataUpRest[50] = {9, 2, 3, 8, 2, 8, 9, 2, 9, 1, 3, 8, 3, 8, 9, 1, 3, 8, 3, 8, 9, 1, 3, 8, 9, 2, 8, 2, 9, 2, 2, 8, 9, 2, 3, 8, 2, 8, 3, 8, 3, 8, 9, 1, 3, 8, 3, 8, 2, 97};

const unsigned int threshold = 100; //signal threshold value
int maxSignalLength = 255; //Set the maximum length of the signal
int dataCounter = 0; //Variable to measure the length of the signal
int receivedState = 0; //Variable to store received sinal status
int timeDelay = 107; //Used to slow down the signal transmission (can be from 75 - 135)

void setup() {
  Serial.begin(9600);
  pinMode(rfTransmitPin, OUTPUT);
  Serial.println("Hello world");
}

void loop() {
  initVariables();
  Serial.println("Init");
  listenForSignal();
  Serial.println("Listen");
  if (receivedState == 1) {
    logSignal();
  }
  sendSignaldataOnOff();
  sendSignaldataUp();
  sendSignaldataDown();
  delay(1000);
}

void initVariables() {
  for (int i = 0; i < dataSize; i++) {
    storedData[i] = 0;
  }
  receivedState = 0;
}

void listenForSignal() {
  Serial.println("****IN****");
  while (analogRead(rfReceivePin) < threshold) {
    //Wait here until an RF signal is received
    receivedState = 1;
  }
  //Read and store the rest of the signal into the storedData array
  for (int i = 0; i < dataSize; i = i + 2) {     //Identify the length of the HIGH signal---------------HIGH     dataCounter = 0; //reset the counter     while (analogRead(rfReceivePin) > threshold && dataCounter < maxSignalLength) {
      dataCounter++;
    }
    storedData[i] = dataCounter; //Store the length of the HIGH signal
    //Identify the length of the LOW signal---------------LOW
    dataCounter = 0; //reset the counter
    while (analogRead(rfReceivePin) < threshold && dataCounter < maxSignalLength) {       dataCounter++;     }     storedData[i + 1] = dataCounter; //Store the length of the LOW signal   }   storedData[0]++; //Account for the first AnalogRead>threshold = lost while listening for signal
  Serial.print("----IN");
  Serial.print(receivedState);
  Serial.println("----");
}

void logSignal() {
  Serial.println("HIGH,LOW");
  for (int i = 0; i < dataSize; i = i + 2) {
    Serial.print(storedData[i]);
    Serial.print(",");
    Serial.println(storedData[i + 1]);
  }
}

void sendSignaldataOnOff() {
  Serial.println("**OnOff***");
  for (int j = 0; j < 10; j = j + 1) {
    for (int i = 0; i < 50; i = i + 2) {
      //Send HIGH signal
      digitalWrite(rfTransmitPin, HIGH);
      delayMicroseconds(dataOnOff[i]*timeDelay);
      //Send LOW signal
      digitalWrite(rfTransmitPin, LOW);
      delayMicroseconds(dataOnOff[i + 1]*timeDelay);
    }
  }
  Serial.println("--OnOff---");
}

void sendSignaldataDown() {
  Serial.println("***Down***");
  for (int k = 0; k < 4; k = k + 1) {
    for (int i = 0; i < 52; i = i + 2) {
      //Send HIGH signal
      digitalWrite(rfTransmitPin, HIGH);
      delayMicroseconds(dataDownFirst[i]*timeDelay);
      //Send LOW signal
      digitalWrite(rfTransmitPin, LOW);
      delayMicroseconds(dataDownFirst[i + 1]*timeDelay);
    }
    for (int j = 0; j < 10; j = j + 1) {
      for (int i = 0; i < 50; i = i + 2) {
        //Send HIGH signal
        digitalWrite(rfTransmitPin, HIGH);
        delayMicroseconds(dataDownRest[i]*timeDelay);
        //Send LOW signal
        digitalWrite(rfTransmitPin, LOW);
        delayMicroseconds(dataDownRest[i + 1]*timeDelay);
      }
    }
  }
  Serial.println("---Down---");
}

void sendSignaldataUp() {
  Serial.println("****Up****");
  for (int k = 0; k < 4; k = k + 1) {
    for (int i = 0; i < 52; i = i + 2) {
      //Send HIGH signal
      digitalWrite(rfTransmitPin, HIGH);
      delayMicroseconds(dataUpFirst[i]*timeDelay);
      //Send LOW signal
      digitalWrite(rfTransmitPin, LOW);
      delayMicroseconds(dataUpFirst[i + 1]*timeDelay);
    }
    for (int j = 0; j < 10; j = j + 1) {
      for (int i = 0; i < 50; i = i + 2) {
        //Send HIGH signal
        digitalWrite(rfTransmitPin, HIGH);
        delayMicroseconds(dataUpRest[i]*timeDelay);
        //Send LOW signal
        digitalWrite(rfTransmitPin, LOW);
        delayMicroseconds(dataUpRest[i + 1]*timeDelay);
      }
    }
  }
  Serial.println("----Up----");
}

So what is happening? I am using the serial monitor to read out the received signal. The RF receiver is hooked up to pin A0 of the Arduino and as soon as it picks up a signal, it will fill up a byte array of 500 bytes. It was kind of guessing what the size should be. I changed the loop() part for either sending or receiving.
receiving

Each time the byte array is emptied, the listening process is kicked off and when a signal is received, the byte array is displayed.

It took a while but the best approach was to receive a few signals (aka a few button clicks on the remote) and have the serial monitor fill up with codes. The codes are tuples of HIGH and LOW signal parts. Both values of the tuples are in the range of 0-255. Unfortunately the remote was not the only device on 433 Mhz so you need to have a few readings before getting to a correct signal definition. The signal definitions I found are not generic (I am guessing here) as the remotes have unique id’s.

Copy the content from the serial monitor into your text editor of liking. Now the hard part comes: You will have to find out what the pattern of the signal is. Some signal string are messy as some other device “talked” through your signal. Some times you overrun the 500 bytes when pressing too long on the button. In that case pieces of the signal are stored in the next array. Have fun!

As my remote has 3 buttons, I started with the on/off button. For this specific button I found that an array of 50 bytes did the trick. I also found out that the full signal consisted of a sequence of these 50 bytes (in my case a sequence of 10 works to turn the leds on or off).

The other two (up and down) were a bit more tricky. It somehow seems that both of them use a start array of 52 bytes and a sequence of process arrays. I decided for the same setup as with the on/off button but start with the start array. I also used a sequence of 10. It kind of worked but took a very long time. So for both I run the start array and sequence of 10 process arrays 4 times.

For testing the signals with the leds, I used this configuration:

Slide2

Using 5v on the vcc pin, GND on GND and 4 on data.

In the code I had to change the loop() part:sending

Each of the functions represents a button on the remote.

Step 2: The transmitter

For the transmitter the receiver configuration is not required so that part is not used. Besides the transmitter part, the Arduino will also be hosting a webserver. This way you can use the HTTP GET method or the very simple HTML page hosted by the Arduino to use the leds:

Slide4

The code looks like this:

#include

#define rfTransmitPin 4 //RF Transmitter pin = digital pin 4

byte mac[] = { your mac here };
EthernetServer server(your port here);
int delayer;

byte dataOnOff[50] = {9, 2, 9, 2, 3, 8, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 9, 2, 2, 9, 9, 2, 2, 9, 2, 9, 9, 2, 2, 9, 9, 2, 9, 2, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 2, 100};
byte dataUp[50] = {9, 2, 9, 2, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 8, 3, 8, 2, 3, 8, 9, 2, 2, 9, 2, 9, 9, 2, 2, 9, 9, 2, 8, 3, 2, 9, 2, 9, 2, 9, 2, 9, 8, 3, 2, 9, 1, 9, 2, 100};
byte dataDownFirst[52] = {4, 98, 10, 1, 10, 1, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 9, 2, 9, 2, 3, 8, 9, 2, 3, 8, 3, 8, 9, 2, 3, 8, 9, 2, 9, 2, 2, 9, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 2, 9, 2, 99};
byte dataDownRest[50] = {9, 2, 9, 2, 3, 8, 3, 8, 3, 8, 3, 8, 3, 8, 9, 2, 9, 2, 3, 8, 9, 2, 3, 8, 3, 8, 9, 2, 3, 8, 9, 2, 9, 2, 3, 8, 2, 9, 2, 9, 2, 9, 2, 9, 9, 2, 2, 9, 2, 100};
byte dataUpFirst[52] = {5, 96, 10, 0, 4, 7, 3, 8, 9, 1, 10, 1, 3, 7, 4, 7, 10, 1, 3, 7, 4, 7, 9, 2, 3, 7, 10, 1, 9, 1, 10, 1, 3, 8, 9, 1, 3, 8, 3, 8, 3, 7, 3, 8, 9, 2, 2, 8, 3, 8, 3, 96};
byte dataUpRest[50] = {9, 2, 3, 8, 2, 8, 9, 2, 9, 1, 3, 8, 3, 8, 9, 1, 3, 8, 3, 8, 9, 1, 3, 8, 9, 2, 8, 2, 9, 2, 2, 8, 9, 2, 3, 8, 2, 8, 3, 8, 3, 8, 9, 1, 3, 8, 3, 8, 2, 97};

const unsigned int threshold = 100; //signal threshold value
int maxSignalLength = 255; //Set the maximum length of the signal
int dataCounter = 0; //Variable to measure the length of the signal
int receivedState = 0; //Variable to store received sinal status
int timeDelay = 107; //Used to slow down the signal transmission (can be from 75 - 135)

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Ethernet.begin(mac);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  pinMode(rfTransmitPin, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  EthernetClient client = server.available(); // listen for incoming clients
  if (client) { // if you get a client,
    Serial.println("new client"); // print a message out the serial port
    String currentLine = ""; // make a String to hold incoming data from the client
    while (client.connected()) { // loop while the client's connected
      if (client.available()) { // if there's bytes to read from the client,
        char c = client.read(); // read a byte, then
        Serial.write(c); // print it out the serial monitor
        if (c == '\n') { // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();
            // version text
            client.print("============================================================");
            client.print("Version: 1.0.0");
            client.print("Identity: Buiten Leds");
            // the content of the HTTP response follows the header:
            client.print("============================================================");
            client.print("Klik hier Aan of Uit");
            client.print("Klik hier Harder");
            client.print("Klik hier Zachter");
            // The HTTP response ends with another blank line:
            client.println();
            // break out of the while loop:
            break;
          }
          else { // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        }
        else if (c != '\r') { // if you got anything else but a carriage return character,
          currentLine += c; // add it to the end of the currentLine
        }
        if (currentLine.endsWith("GET /OnOff")) {
          sendSignaldataOnOff();
          Serial.println("***OnOff***");
        }
        if (currentLine.endsWith("GET /Up")) {
          sendSignaldataUp();
          Serial.println("***Up***");
        }
        if (currentLine.endsWith("GET /Down")) {
          sendSignaldataDown();
          Serial.println("***Down***");
        }
      }  
    }
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
  delay(delayer);
}

void sendSignaldataOnOff() {
  Serial.println("**OnOff***");
  for (int j = 0; j < 10; j = j + 1) {
    for (int i = 0; i < 50; i = i + 2) {
      //Send HIGH signal
      digitalWrite(rfTransmitPin, HIGH);
      delayMicroseconds(dataOnOff[i]*timeDelay);
      //Send LOW signal
      digitalWrite(rfTransmitPin, LOW);
      delayMicroseconds(dataOnOff[i + 1]*timeDelay);
    }
  }
  Serial.println("--OnOff---");
}

void sendSignaldataDown() {
  Serial.println("***Down***");
  for (int k = 0; k < 4; k = k + 1) {
    for (int i = 0; i < 52; i = i + 2) {
      //Send HIGH signal
      digitalWrite(rfTransmitPin, HIGH);
      delayMicroseconds(dataDownFirst[i]*timeDelay);
      //Send LOW signal
      digitalWrite(rfTransmitPin, LOW);
      delayMicroseconds(dataDownFirst[i + 1]*timeDelay);
    }
    for (int j = 0; j < 10; j = j + 1) {
      for (int i = 0; i < 50; i = i + 2) {
        //Send HIGH signal
        digitalWrite(rfTransmitPin, HIGH);
        delayMicroseconds(dataDownRest[i]*timeDelay);
        //Send LOW signal
        digitalWrite(rfTransmitPin, LOW);
        delayMicroseconds(dataDownRest[i + 1]*timeDelay);
      }
    }
  }
  Serial.println("---Down---");
}

void sendSignaldataUp() {
  Serial.println("****Up****");
  for (int k = 0; k < 4; k = k + 1) {
    for (int i = 0; i < 52; i = i + 2) {
      //Send HIGH signal
      digitalWrite(rfTransmitPin, HIGH);
      delayMicroseconds(dataUpFirst[i]*timeDelay);
      //Send LOW signal
      digitalWrite(rfTransmitPin, LOW);
      delayMicroseconds(dataUpFirst[i + 1]*timeDelay);
    }
    for (int j = 0; j < 10; j = j + 1) {
      for (int i = 0; i < 50; i = i + 2) {
        //Send HIGH signal
        digitalWrite(rfTransmitPin, HIGH);
        delayMicroseconds(dataUpRest[i]*timeDelay);
        //Send LOW signal
        digitalWrite(rfTransmitPin, LOW);
        delayMicroseconds(dataUpRest[i + 1]*timeDelay);
      }
    }
  }
  Serial.println("----Up----");
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s