Monday, December 15, 2014

Using Arduino as an IR remote and some other ideas


This post is about a simple project that was the basis of anther project posted on my blog. In this project, we are going to show how to use Arduino as a remote control for a TV. The requirement for the project was: a TV is connected to a security camera, camera is always ON, and we want to turn the TV ON/OFF from a distance/angle that the TV infrared (IR) remote does not support, please see Figure-1 below.

Figure-1 TV, Security camera and the Arduino mounted on the lower left side of the TV



As you know, the IR remote that comes with the TV works at a line of sight distance: this means you have to be facing the TV to be able to use the remote. The TV you see in Figure-1 was placed in the second floor and we want to turn it ON using a device placed at the first floor. Usually, the best thing to turn power ON/OFF is to use a relay, well that is true but note that nowadays TV needs to be turned ON using a remote after turning the main power ON. Nevertheless, the relay had to be controller from anther location, the first floor, this made things a little bit complicated!!

Best engineering practice is to divide the problem into parts, called divide and conquer approach. First, the simple part: using a relay will only help to turn on the power to the TV; but, if we connect the TV and an Arduino to the relay then relay will power the TV and in the same time power the Arduino. Bingo, think of the idea of using the Arduino as a remote: connect an Infrared (IR) LED to it and let it send the ON signal to TV after main power was turned on using the relay. What about the OFF signal? No need for it since the relay will turn the TV OFF anyway. Seems simple project!! It is simple but the relay was placed next to the TV, at the second floor, and controlling the relay was done from the first floor. Hence, the relay had to be controlled via Radio Frequency (RF)

Fortunately, a relay that can be controlled via Radio Frequency (RF) was available at hand. The relay comes with anther unit, a push button connected to a RF unit; push button used to turn the relay ON/OFF. Neither the details of the relay unit nor the details of the RF unit are available at this time; somebody else bought it, many thanks to him.    

Let us talk about the software side then we can talk about physical connection. To use the Arduino as an IR remote you need IR LED and you need to know the protocol and codes your TV use to communicate with its actual IR remote; M. McCracken explains this in details in his post and provides useful links about IR protocols and codes each TV use (you may need to be logged as registered user to hifi-remote.com). One great thing about Arduino, you can find library for anything you need; some people already did a lot of work using Arduino and made their software available to public. One name to mention here is Ken Shirriff’s work to provide an open source multi-protocol IR library for the Arduino; currently, his library is included with Ardunio and Energia distributions.

You can easily figure out the rest of steps regarding using Ardunio as an IR remote: either use the links on McCracken post to lookup the protocol your device uses and the associated ON code for your device or you us an IR detector to decipher the protocol and the codes your IR remote sends based on the Ken Shirriff’s  library. One thing to note when you are programming your Arduino to mimic a remote sending ON signal, it is timing; keep reading the hardware part to know more….

Hardware setup is simple; see Figure-2 and Figure-3 below. The multi-outlet has the relay plugged to the top receptacle and the lower receptacle has the camera AC-DC convertor plugged to it. The relay its self is powering both the TV and the Arduino AC-DC convertor using the white extension cord. Next, let us talk about the Arduino hardware. This project used ArduinoOSEPP UNO hardware; I have to admit that during the testing period, more than a month, the board never stopped responding or malfunction due to repeated restarts. On Figure-3, you can see that the IR LED is connected to a PCB breadboard and an additional resistor is used to limit the current going to IR LED; on the UNO board pin 11 and the ground pin are used to connect the IR LED. Note that the whole setup was mounted to the wall next to the TV such that IR LED is positioned as close as possible to the IR detector found in the TV. A simple AC-DC converter provides the input voltage for OSEPP UNO, 6-12 volts allowed, in this project an AC-DC 12 volts convertor was used with no issues.  One final note, when you program the Arduino, you will need to add some delay just before sending the ON signal using Pulse Width Modulation, this will the allow some time for the TV to initialize and actually turn the IR detector on. Also, it is better to add the code to send ON signal in the setup part of the Arduino code.

Figure-2 Wiring setup showing a picture of the relay on the bottom
 
Figure-3 OSEPP Arduino mounted next to the TV; note IR LED is in front of the IR detector inside TV


Sunday, December 7, 2014

Project: Motion Sensing over wireless link using MSP430 and Anaren Booster Pack

In a previous post, problem of finding suitable programming environment for the Anaren Booster Pack has been discussed; we talked about how easy it was to program MSP430 using the Energia environment. In the newer versions of Energia 0101E0013 (09/05/2014), Anaren has included a library with some cool functions and couple of code examples for sensor-hub communication, control example, and simple wireless communication test example. Stay tuned to read a nice post about a simple modification to Anaren code to include acknowledgment mechanism. But for this post will cover a cool project that I was asked to do.

Requirements were simple: we have a TV connected to a security camera (camera always on). Turn TV ON whenever motion happens in a certain area. To safe power, TV had to be turned OFF when no motion is detected for a specified period.  


Remember in a previous post you have seen how to program a pair of TI MSP430 Microcontroller Units (MCU) to communicate motion detection event coming from Passive Infra Red (PIR) sensor. Well, this is just what we are going to do in this cool project. One end, where motion is to be detected, will have a PIR sensor connected to MSP430 MCU plus Anaren Booster Pack RF module in order to communicate motion detection event to the other end. On the TV/Security camera end we have to turn the TV ON when receiving a signal on the RF module. While first thing comes into your mind is a RELAY to turn TV ON, remember that now days all TV’s need to be turned on using an IR remote even if the power source is on!! To satisfy your curiosity, yes we will have a post about using a relay to turn TV. In that project, my contribution was only the part of turning TV on using Infra Red (IR) signal coming from IR LED connected to the MCU after the relay turns power source on; stay tuned to see how to get MCU acting like a remote!! This post will only deal with the end composed of MSP430 LaunchPad, PIR sensor and the Anaren Booster Pack. 





Figure 1 TI MSP430 LuanchPad, Anaren Booster Pack inside the enclosure

 First thing is to decide program structure, next we can talk about the choosing enclosure, mounting, and power supply. As mentioned above, code examples published by Anaren included a sensor-hub example code; this is exactly what we need. The sensor will send data and hub will receive data; we can choose to have the hub acknowledging sensor’s packets but this project did not go this direction, we will talk more about using an acknowledgment in the end of this post. Since one requirement is to count no motion period, we have to use timers. Since MSP430 is busy with counting (timer), we can not afford to have the MCU waiting on a positive edge from PIR (when it detects motion); interrupts will be the best choice to alarm for a positive edge. Next, we get to choose the pin on MCU to connect to PIR output. Note that some pins do not have interrupt enabled, and some pins are used by the Anaren Booster Pack. This leaves us with very limited choice, either pin 1_3 or pin 2_3. In our code we choose pin 1.3 which is defined as PUSH2 in Energia, it happens to be connected to a push button on TI LaunchPad. Next, lets us choose the timer; note that we need to measure periods in order of minutes when counting no motion period. This means the timer should drive its clock from a low frequency oscillator; MSP430 has many choices for oscillator. MSP430 runs its system clock of 1.1MHz oscillator, but the best thing with MSP430 is you can run multiple oscillators same time.  You can have a 1.1Mhz oscillator as the source of the system clock and anther low frequency oscillator for peripherals.For a low frequency , the VLO oscillator is one choice, it runs somewhere around 12KHz, and the second choice would be to attach an external crystal, the one supplied with TI Launchpad provide 32KHz clock. VLO was the choice for this setup, and this allows a timer as long as 40seconds.  If you allow the timer to overflow certain number of times you can get the time period you like; allowing the timer to overflow 15 times will allow periods of10 minutes. Well, this is it about the program structure. Below is code:

#include <SPI.h>
#include <AIR430BoostFCC.h>
// -----------------------------------------------------------------------------
/**
 *  Defines, enumerations, and structure definitions
 */
#define ADDRESS_LOCAL    0x02
#define ADDRESS_REMOTE   0x01
#define PIR_Settling_Time 20000 //Allow PIR learn its environment up to 40sec (datasheet)
#define CC110L_Settling_Time 5000//Startup time between MSP430 and CC110L
 /**
 *  sPacket - packet format.
 */
struct sPacket
{
  uint8_t from;           // Local node address that message originated from
  uint8_t message[1];    // Local node message
};

// -----------------------------------------------------------------------------
/**
 *  Global data
 */
 struct sPacket txPacket;
volatile boolean Lockhigh=true;
volatile unsigned char counter = 0;
 // -----------------------------------------------------------------------------
// Main example

void setup()
{
     //Allow setup time for PIR and CC110L
     if (PIR_Settling_Time>CC110L_Settling_Time){
      delay(PIR_Settling_Time);}
       else{delay(CC110L_Settling_Time);}
  /**
   * 
   *  Note: Set radio first to ensure that GDO2 line isn't being driven by the
   *  MCU as it is an output from the radio.
   */
    Radio.begin(ADDRESS_LOCAL, CHANNEL_1, POWER_MAX);

  txPacket.from = ADDRESS_LOCAL;
  memset(txPacket.message, 0, sizeof(txPacket.message));

   WDTCTL = WDTPW + WDTHOLD;      // stop WDT
  
   pinMode(PUSH2,INPUT);//P1.3 is PIR input
   attachInterrupt (PUSH2, Port_1, CHANGE);//activate interrupt on pin P1_3
   P1DIR = BIT0; // set P1.0 as output (RED LED on LaunchPad)
   P1OUT =~BIT0;// Turn OFF RED LED
     
   BCSCTL1 = CALBC1_1MHZ;    // Set DCO to calibrated 1 MHz.
   DCOCTL = CALDCO_1MHZ;
   BCSCTL3 =LFXT1S_2;   //Set VLO
   TACCR0 = 60000 - 1;    // A period of 60,000 cycles (~40sec@VLO)
   TACCTL0 = CCIE;        // Enable interrupts for CCR0.
   TACTL = TASSEL_1 + ID_3 + MC_1 + TACLR;  // ACKL, div 8, up mode,clear timer
 
}

void loop()
{
 
}

//// Timer A interrupt service routine
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A()
{
       if(counter == 10 & !Lockhigh ) {// this is when the PIR indicate no motion for 10min
        counter = 0;
        txPacket.message[1] = 'O';
        Radio.transmit(ADDRESS_REMOTE, (unsigned char*)&txPacket, sizeof(txPacket));
        P1OUT =~BIT0; // RED LED OFF
        Lockhigh=true;
       }
        else {// this is when PIR indicate motion or while no motion w/time <Total Wait Time
         counter++;
            
      }
}
  
// Port 1 interrupt service routine
//__interrupt void Port_1()
void Port_1(void)
{
 
   if (digitalRead(P1_3) && Lockhigh){
   P1OUT = BIT0; // Trun on RED LED in case of motion being detected
   txPacket.message[1] = 'A';//
   Radio.transmit(ADDRESS_REMOTE, (unsigned char*)&txPacket, sizeof(txPacket));
   Lockhigh=!Lockhigh;//Toggel Lock (indicate no motion period /end of no motion period)
   }
    else {counter=0;}//any other signal from PIR rests timer
 }


Next, we will talk about the final product including hardware, enclosure, mounting and power source. Note that Anaren Booster Pack can be a stand alone; you can mount the TI MSP430G2553 onto the board and connect led, push button and power supply with some capacitors, please see Figure 2 below from Anaren manual. In this project, soldering surface mount components was not possible; the final product used LuanchPad to hold the MCU and Anaren Booster Pack as shown in figure 1 above. Since PIR sensor has to sticking outside the mount, you need to choose a mount with flat surface on one side. Drill through the flat surface a hole such you can mount the PIR sensor with its lens outside as shown in figure 3. Note in this figure; the power source is sticking to the side of the enclosure; a simple phone charger with USB output has been used.
 
Figure 2 Picture courtesy of Anaren
Figure 3 Enclosure with PIR sensor sticking out of it


Trouble shooting:
Possible problems that you may face are as follow
1-      Failed communication between the unit holding the sensor and unit responsible for turning TV ON. If this happens you will note indicator led, shown in figure one above, tuned ON while the TV is OFF or visa versa. Just rest the unit by unplugging the power from the unit with PIR and make sure the TV is turn off .Then plug power to the MCU connected to PIR, make sure to allow some period of no motion while the PIR learns the environment.
2-       Wires are loose; this may happen and it will cause the unit to not function correctly. Refer to figure 1 for correct connection and secure the wire to pins.
3-      Infra Red LED on the unit responsible for turning TV ON may get out of focus with the Infra Red detector on the TV. Just make sure the Infra Red LED on the MCU is in front of the Infra Red detector on the TV.
4-      If MCU goes bad then they can be replaced and programmed via the LaunchPad using the code provided.


Please stay tuned to read a nice post about a simple modification to Anaren sample code to include acknowledgment mechanism.