Library for HT12E

Hello,

This is my first post in the forum, and I am sort of new to Arduino, too.

I was looking for something related to RF data transmission into my Arduino board, but all I have found were Arduino-to-Arduino data exchange projects.

Since I have got only one Arduino board, I had to look for a legacy IC. That's why I came across HT12E, which is suited for what I need.

Basically, it is a 12-bit encoder. Of those 12 bits, 8 bits are the address code, and the remaining 4 bits are data.

Once you set up the address and the data pins, you can send the 12-bit serial stream by driving low the IC's Transmission Enable pin.

I plugged the IC's output to a Telecontrolli RF Transmitter, and an RF Receiver to Arduino's digital pin #7. According to the manufacturer, these tranceivers have a somewhat narrow bandwidth, so I set up the HT12E clock frequency around 3.0~4.0 kHz, which yields a baud rate around 1200 bps.

I wrote a library for decoding the HT12E serial stream, and it follows below.

HT12E.cpp

/*---
  HT12E.cpp
  HT12E Support for Arduino
  Author: Marcelo Shiniti Uchimura
  Date  : May '08
---*/

#include "WProgram.h"
#include "HT12E.h"

HT12E::HT12E(int pin, unsigned int addrMask)
{
  _pin = pin;
  pinMode(_pin, INPUT);
  _data = 0;
  _mask = addrMask << 4;  // the HT12E basic word is a stream with an 8-bit address
                          // followed by 4-bit data. I left shift the
                          // address mask 4 bits so I can match it to the entire word
}

int HT12E::read()
{
  byte ctr;            // for general error handling
  _tries = 0;
  do
  {
    /* look for HT12E basic word's pilot stream */
    for(ctr = 0; ctr < 13; ++ctr)
    {
      while(digitalRead(_pin) == LOW);                // wait for the signal to go HIGH
      _dur = pulseIn(_pin, LOW);

      if(_dur > 9000 && _dur < 12000) break;          // 36x(clock tick interval)
    }

    /* if error, skip everything */
    if(ctr == 13)
      {
        _tries = 4;
        break;
      }

    /* now wait until sync bit is gone */
    for(ctr = 0; ctr < 6; ++ctr)
      {
        if(digitalRead(_pin) == LOW) break;
        delayMicroseconds(80);
    }

      /* if error, skip everything */
      if(ctr == 6)
      {
        _tries = 5;
        break;
      }

    /* let's get the address+data bits now */
    for(_data = 0, ctr = 0; ctr < 12; ++ctr)
    {
      _dur = pulseIn(_pin, HIGH);
      if(_dur > 250 && _dur < 333)        // if pulse width is between 1/4000 and 1/3000 secs
      {
        _data = (_data << 1) + 1;         // attach a *1* to the rightmost end of the buffer
      }
      else if(_dur > 500 && _dur < 666)   // if pulse width is between 2/4000 and 2/3000 secs
      {
        _data = (_data << 1);             // attach a *0* to the rightmost end of the buffer
      }
      else
      {
        /* force loop termination */
        _data = 0;
            break;
      }
    }

    // check if buffered data matches the address mask
    if((_data & _mask) < _mask)
    {
      /* data error */
      _tries = 6;
    }
    else ++_tries;

  } while(_tries < 3);

  if(_tries > 3)
  {
    switch(_tries)
      {
        case 4: return 0xffff;
        case 5: return 0xfffe;
        case 6: return 0xfffd;
    }
  }
  return (_data ^ _mask);
}

HT12E.h

/*---

  HT12E.h
  HT12E Support for Arduino
  Author: Marcelo Shiniti Uchimura
  Date  : May '08

  Note  : make sure HT12E is operating at 3~4kHz clock range

---*/

#ifndef HT12E_h
#define HT12E_h
#include "WConstants.h"

class HT12E 
{
  public:
                 HT12E(int pin, unsigned int addrMask); // this is the constructor
    int          read();                                // this is the main method
  private:
    byte         _pin;      // this is Arduino input pin
    unsigned int _data;     // this is data
    unsigned int _mask;     // this is the address mask
    byte         _tries;    // this is how many times Arduino could find
                            // valid HT12E words
    unsigned long _dur;     // pulse duration
};

#endif

Usage example

#include <HT12E.h>

HT12E remote(7, B01111111); // pino 7, endereço 0111 1111b

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  unsigned int valor;
  valor = remote.read();
  if(valor > 0xFFF0) Serial.println(valor, HEX);
  else
  {
    Serial.print("DATA ");
    Serial.println(valor, BIN);
  }
  delay(1000);
}

I hope this might be helpful. Cheers! :slight_smile:

Cool! You should consider posting this to the Arduino playground: Arduino Playground - HomePage. Things in the forum tend to get lost as time goes on.

Thanks for the advice, mellis. Now there is a reference to this library at Arduino Playground, too.

Thanks for the advice, mellis. Now there is a reference to this library at Arduino Playground, too.

Could You please show us the schema (circuit) how to connect all together?

Basically, this is how you set up the HT12E IC:

You can also try this (I found it on the datasheet):

The value of R depends on the supply voltage value (and also on the transmission baud rate, but let's assume it is 3kbps, since this is how much bandwidth you can safely use with simple RF transmitters).

If your power supply is 5VDC, R = 1.0 Mohms. If you are using more than that, please check the HT12E datasheet (http://www.people.cornell.edu/pages/cl457/cl457_yft2/datasheets/HT12E.pdf) to find the correct value.

Once you realize that your HT12E is working all right, you can replace direct connection to Arduino with the RF transmitter and receiver. The transmitter goes attached to HT12E, while the receiver goes with Arduino.

I have a question about the application of this chip.

Is it possible to send data without pushing the send button. Could that be linked to an output pin on arduino?

Is it possible to make the whole thing send data automatically from arduino?

Thanks

The chip can be controlled by the Arduino itself, but then it would lose its purpose which is to send data to an Arduino remotely.

Hi, neuron_upheaval

Thanks for posting these info, but how do I connect those data ports AD11,AD10,AD9 and AD8 to Arduino ? Or should I ask do I need to connect those ports to Arduino ?

What I understand from the schema, I need to connect to those 4 data ports in order to send data, right ? In your code, I can't see that you declared how these 4 ports are connected with Arduino.

Hello Chinese Jack!

My diagram was not clear, what I meant is that the data pins are up to you to decide what is going to be sent.

Imagine that your remote control has 4 commands. So each of your HT12E data pins are going to signalize each command. You will connect each pin to each button in your remote control, for instance.

The data pins are not a priori meant to be connected to an Arduino, but to your remote control instead.

Hi neuron_upheaval,

Thanks for your quick response. In your code example, did you sent the word "DATA" out to receiver by using "Serial.print("DATA ");" ?

So what I should do, if I want to send text to receiver from HT12E ? I certainly can't do it by control 4 command buttons, so that's why I think I need to connect HT12E to the Arduino.

What I image is Arduino->HT12E encoder->Transmitter....Receiver->HT12 decoder->Arduino, is that right ?

Hi neuron_upheaval,

I've just tried to complie the Usage example, but it failed and shows the following error msg:

d:/arduino/arduino-0017/arduino-0017/hardware/tools/avr/lib/gcc/../../avr/include/stdlib.h:111: error: expected `)' before 'int'

Is there something wrong with the HT12E.h file ? cause even I deleted everything just left code like this:

#include <HT12E.h>

void setup()
{
}
void loop()
{
}

it still failed and has the same error msg.

Hi Chinese Jack,

I'm afraid you might not want to send characters using the HT12E unless you have a set of 2^4 = 16 characters to be sent. This is not the ideal application for this IC.

As for the library, first you have to make a, say, HT12E folder inside of the hardware/libraries subfolder of the Arduino application folder. Then you copy both the HT12E.h and HT12E.cpp into that folder and relaunch the Arduino IDE.

New reference for the HT12E datasheet: http://www.rfsolutions.co.uk/acatalog/HT12E.pdf

Hi neuron_upheaval,

I did created the folder like what you said:

hardware/libraries/HT12E/HT12E.h
hardware/libraries/HT12E/HT12E.cpp
hardware/libraries/HT12E/examples/HT12ETest
hardware/libraries/HT12E/examples/HT12ETest/HT12ETest.pde

but it still doesn't work and has the same error msg.

Hey Chinese Jack,

It seems that the solution "mikalhart" gave, solves the problem.

in topic "LedControl library fails in Arduino IDE 0012"

"...If you find modifying system headers distasteful, I think adding the following lines AFTER the #include "LedControl.h" should also resolve the problem:

#include "LedControl.h"
#undef int
#undef abs
#undef double
#undef float
#undef round

Mikal"

:slight_smile:

I added the above undef statements below the include <HT12E.h> statement and the errors went away.

hi neuron_upheaval
i have seen you work on ht12e library for arduino and you did a great job.
taking reference from your work i was trying to develop a project where i am using around 50 ht12e in which all are having different addresses and ht12e are sending data to arduino which is running your algorithm
now as you have shown in your example i am able to connect arduino to one address but a am not able to do that with other addresses.
i can only configure arduino for only one address at a time
please help me so that i can configure arduino for all addresses at once
my details of circuit are
ht12e with 9vDC
ROSC=1Mohm