Saturday, November 12, 2011

Use sonar to control a TV!

Also with a sonar module, i have controled my TVs volume, power, and channel functions. The Arduino reads the position of my hand(whether it is in motion, or in a not moving in a certain range), and the acts depending on where my hand is.

How to get and send IR  codes:
Use the IRRecvDump program and library for Arduino from here: Ken Shirriff's blog: A Multi-Protocol Infrared Remote Library for the Arduino. Then hook up a IR receiver module(shown how in the link) and IR LED(to send the ir codes) to the Arduino. Run IRRecvDump and point a remote at the Arduino and press one of the remote's buttons. The Arduino will send the code to the Arduino serial monitor. It should look something like:
Raw (26): 23420m 2400m 650m 1150m 600m 600m 600m 1200m 600m 650m 550m 1150m 650m 650m 550m 550m 650m 1150m 650m 550m 650m 550m 600m 600m 600m 600m
Take out the first string of numbers (so "23420m" in my case), then remove all the "m " and replace with ","s. It should look like:
Raw (26): 2400,650,1150,600,600,600,1200,600,650,550,1150,650,650,550,550,650,1150,650,550,650,550,600,600,600,600
now in the arduino code like this(Note: 26 in the snippit below is the length of the array, not from "Raw (26):"):
unsigned int powerOn[26] = {2400,650,1150,600,600,600,1200,600,650,550,1150,650,650,550,550,650,1150,650,550,650,550,600,600,600,600};
Then to send the IR code with arduino:
irsend.sendRaw(powerOn,26,38);
The 26 here is from "Raw (26):". 38 is the IR frequency, which is the same every where for TV pretty much.

Now if you get something like: "Received SONY: A90" when you used the IRRecvDump program with arduino; all you have to send that IR code with a Arduino is:
irsend.sendSony(0xa90, 12);

Also, in the case of sony IR codes, they have to be sent 3 times with 50ms or so delay between each, so like:

    irsend.sendRaw(powerOn,26,38);
    delay(50);
    irsend.sendRaw(powerOn,26,38);
    delay(50);
    irsend.sendRaw(powerOn,26,38);

Arduino Code to send IR codes:

#include <IRremote.h>
IRsend irsend;

const int numReadings = 5;   // set a variable for the number of readings to take
int index = 0;                // the index of the current reading
int total = 0;                // the total of all readings
int average = 0;              // the average
int oldAverage = 0;           // the old average
int echoPin = 6;              // the SRF05's echo pin
int initPin = 7;              // the SRF05's init pin
unsigned long pulseTime = 0;  // variable for reading the pulse
unsigned long distance = 0;   // variable for storing distance

// setup my arrays for each signal I want to send
unsigned int powerOn[26] = {
  2400,650,1150,600,600,600,1200,600,650,550,1150,650,650,550,550,650,1150,650,550,650,550,600,600,600,600};
unsigned int soundUp[26] = {
  2350,600,600,600,1200,600,600,600,550,650,1150,650,550,650,600,650,1100,600,600,600,600,600,550,650,550};
unsigned int soundDown[26] = {
  2350,650,1150,650,1150,600,600,600,600,600,1250,550,550,650,550,650,1150,650,550,650,550,600,600,600,600};
unsigned int channelUp[68] = {
  8950,4550,500,650,450,1750,500,600,500,650,450,1800,400,650,450,700,450,550,550,700,400,650,500,1700,500,650,450,1750,500,1700,450,700,450,700,400,800,350,600,500,600,500,1700,550,600,450,650,450,700,400,700,450,1750,500,1700,500,1750,450,650,450,1750,500,1700,500,1750,500,1750,450,};
unsigned int channelDown[68] = {
  8950,4600,400,650,500,1750,450,650,450,700,400,1750,500,650,450,650,450,700,450,600,500,650,450,1700,550,550,550,1750,400,1850,400,650,450,650,500,1750,450,650,450,650,550,1650,500,650,550,550,650,450,500,600,550,550,500,1750,500,1700,500,600,500,1750,450,1750,600,1650,450,1750,500};

void setup()
{
  // make the init pin an output:
  pinMode(initPin, OUTPUT);
  // make the echo pin an input:
  pinMode(echoPin, INPUT);
  // initialize the serial port:
  Serial.begin(9600);
}

void loop()
{
  // loop for a number of readings on the SRF-05 to get an average to smooth the results. Much like all my other examples
  for (index = 0; index<=numReadings;index++) {
    digitalWrite(initPin, LOW);
    delayMicroseconds(50);
    digitalWrite(initPin, HIGH);
    delayMicroseconds(50);
    digitalWrite(initPin, LOW);
    pulseTime = pulseIn(echoPin, HIGH);
    distance = pulseTime/58;
    total = total + distance;
    delay(10);
  }
  // store the previous reading
  oldAverage = average;
  // store the current reading
  average = total/numReadings;
  // debug to check for spikes in the sensor etc..
  Serial.println(average);

  // now the fun part...
  // if my distance is less than 5...
  if (average <= 5)
  {
    Serial.println("Power");
    // use Kens IR library to send my signal (array, number of items in array, Khz)
    irsend.sendRaw(powerOn,26,38);
    delay(50);
    irsend.sendRaw(powerOn,26,38);
    delay(50);
    irsend.sendRaw(powerOn,26,38);
    // these delays depend on how long it take my device to recognise the signal sent and to act - I don't want to send signals that aren
    //getting read etc..
      delay(4000);
    // otherwise if my hand is higher
  }
  else
  {
    // check to see if my hand is in the registered space above the sensor
    if (average <=20 && average >=10 && oldAverage >=10)
    {
      // the below statement is our sensitive the readings are so if the current and previous readings are different with a tolerance of +/
      //we can look at the direction of movement
        if ((average != oldAverage) && (average+1 != oldAverage) && (average-1 != oldAverage))
      {
        // if the current reading is higher than the previous, then my hand is moving upwards
        if (average > oldAverage)
        {
          Serial.println("Channel Up");
          irsend.sendRaw(channelUp,68,38);
          delay(2000);
        }
        else
        {
          // otherwise if it is below then my hand is moving downwards
          if (average < oldAverage && oldAverage <=20)
          {
            Serial.println("Channel Down");
            irsend.sendRaw(channelDown,68,38);            
            delay(2000);
          }
        }
        // otherwise my hand must be stationary so check where it is.
      }
      else
      {
        // if my hand is stationary between 10 and 15 cms away from the sensor
        if (average >= 10 && average <=15)
        {
          Serial.println("Sound down");
          irsend.sendRaw(soundDown,26,38);
          delay(50);
          irsend.sendRaw(soundDown,26,38);
          delay(50);
          irsend.sendRaw(soundDown,26,38);
        }
        else
        {
          // if my hand is a bit higher up...
          if (average >= 16 && average <=20)
          {
            Serial.println("Sound up");
            irsend.sendRaw(soundUp,26,38);
            delay(50);
            irsend.sendRaw(soundUp,26,38);
            delay(50);
            irsend.sendRaw(soundUp,26,38);
          }
        }
      }
    }
  }
  // clear our index and total for the next reading just in case
  if (index >= numReadings)
  {
    index = 0;
    total = 0;
  }
}


Note: mostly not my code, just modified for my IR codes.

2 comments:

  1. Iam using freeduino board for ir emitting.
    I have included IRremote library. but it gives

    sketch_jan27a:4: error: 'IRsend' does not name a type
    sketch_jan27a.ino: In function 'void loop()':
    sketch_jan27a:15: error: 'irsend' was not declared in this scope


    #include
    #include

    IRsend irsend;

    unsigned int powerOn[26] = {2400,650,1150,600,600,600,1200,600,650,550,1150,650,650,550,550,650,1150,650,550,650,550,600,600,600,600};

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

    void loop()
    {
    irsend.sendRaw(powerOn,26,38);
    delay(40);
    }

    ReplyDelete
    Replies
    1. make sure you have the irsend library and itis included correctly (i think thats your problem).

      the part:
      #include
      #include

      should be like:
      #include

      also you may want to move your irsend.sendRaw command to your setup function or consider increasing the delay as its will probably send the code out so much it will confuse whatever you are sending it to.

      Delete