Tuesday, November 22, 2011

Improved IR code Reciever

Now only a little reformatting is needed on the IR code serial data received before inserting it into a Arduino IR sending program. All you have to do is to remove all digits before the first comma:

Raw (68): 11152,9100,4450,550,600,500,650,500,600,550,600,500,600,550,600,500,650,500,600,500,1750,500,600,550,600,600,1650,550,1750,500,600,500,600,550,1700,550,1750,500,600,550,1750,500,600,500,1750,500,600,550,600,550,600,500,600,550,1750,450,650,500,1750,500,600,550,1750,500,1750,500,1750,500
to
Raw (68): 9100,4450,550,600,500,650,500,600,550,600,500,600,550,600,500,650,500,600,500,1750,500,600,550,600,600,1650,550,1750,500,600,500,600,550,1700,550,1750,500,600,550,1750,500,600,500,1750,500,600,550,600,550,600,500,600,550,1750,450,650,500,1750,500,600,550,1750,500,1750,500,1750,500

But if it is a recognized code, then it will output like(still need to remove all digits before the first comma):
Decoded NEC: 99E817 (32 bits)---OR---Raw (68): 47990,9100,4450,600,550,550,550,550,600,600,550,550,550,550,600,500,600,600,550,600,1650,600,500,600,550,550,1700,600,1650,550,600,500,600,550,1700,550,1750,550,1700,600,1650,550,550,600,1650,550,600,600,550,550,550,600,550,500,600,600,550,500,1750,550,550,550,1750,500,1750,500,1750,500
Look at my previous post on how to use these RAW or DECODED IR codes...


CODE:
#include <IRremote.h>

int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

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

// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
//  decode_results *results = (decode_results *)v
void dump(decode_results *results) {
  int count = results->rawlen;
  if (results->decode_type == UNKNOWN) {
    Serial.println("Could not decode message");
  }
  else {
    if (results->decode_type == NEC) {
      Serial.print("Decoded NEC: ");
    }
    else if (results->decode_type == SONY) {
      Serial.print("Decoded SONY: ");
    }
    else if (results->decode_type == RC5) {
      Serial.print("Decoded RC5: ");
    }
    else if (results->decode_type == RC6) {
      Serial.print("Decoded RC6: ");
    }
    Serial.print(results->value, HEX);
    Serial.print(" (");
    Serial.print(results->bits, DEC);
    Serial.print(" bits)---OR---");
  }
  String Test1 = String();
  Serial.print("Raw (");
  Serial.print(count, DEC);
  Serial.print("): ");

    for (int i = 0; i < count; i++)
  {
    Test1+=(results->rawbuf[i]*USECPERTICK);
    Test1+=(",");
  }
  Serial.println(Test1);
}


void loop() {
  if (irrecv.decode(&results))
  {
    dump(&results);
    irrecv.resume(); // Receive the next value
  }
}

Sunday, November 13, 2011

Arduino PS2 Emulator-Computer Control!

I wanted to control my computer with a Arduino and sonar module, but wasn't exactly sure how to connect the computer and Arduino. I could either send data via serial and have a C# program interpret the data and emulate a key press accordingly, or I found a way for the Arduino to act as a PS2 keyboard. Once i learn more about C# I may redo it, but using the PS2 emulator is the far easier option. The program is pretty similar to the TV sonar control program except it sends PS2 commands for tabbing, volume, copy and paste. To connect it to the computer i just have to connect the two digital pins specified in the code to the appropriate pins in a PS2 connector and plug it in to my computer. The Arduino sends keys using "scan codes"; these are universal to any PS2 keyboard, so it could probably work on a Mac. More after the break.

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.

Analog Joystick with Arduino!

I have a old Gravis Blackhawk joystick that i dug up to use with my Arduino. I opened up the back, and it doesn't have any electronics, just a circuit board splitting out the DB15 connector to all the buttons etc(no ICs etc). It has 3 buttons on the stick, a throttle pot and another button on the base, and of course the X + Y axis slider pots for the stick. All the buttons are each wired to a pin of the DB15 connector and the other side goes to GND. The X + Y axis and the slider are connected to +5v, GND and a pin for each on the DB15.


The Arduino programming was really simple. All i had to do was read 3 analog ports for the X,Y and throttle pots, and 4 Digital pins for the buttons. Then I put them all into a string like: "X,Y,SpeedPot,btn1,btn2,btn3,btn4" and printed to serial. Also, this Arduinio code uses millis() rather than delay to be more precise in delays. 


I finally made the C# interface app, but never posted it, so you can find it HERE as a zip*
*note: the file is .zip but I renamed it to '.zipp' to get around Google's file protection. Download it, then remove a 'p' from the end of the file name and extract! Below in comments, let me know if you have any issues.



Picture and Scheme of joystick:



//-----Axis-------------------------------------------------------//
#define Xaxis 3  //Joystick X axis Analog pin 3
#define Yaxis 4  //Joystick Y axis Analog pin 4
#define SpeedPot 5  //Pot in base for speed, Analog pin 5

int XaxisVar = 0;  //...analog pin 3---X axis
int YaxisVar = 0;  //...analog pin 4---Y axis
int SpeedVar = 0;  //...analog pin 5---Speed pot
//----------------------------------------------------------------//

//-----Buttons----------------------------------------------------//
#define TrigBtn 2  //trigger button, digital 2
#define MidBtn 6  //Button below trigger on joystick, digital 3
#define LowBtn 4  //Lowest button on the joystick, digital 4
#define BaseBtn 5  //button on base of joystick, digital 5

int TrigBtnState = 0;  //Stores the state of TrigBtn
int MidBtnState = 0;  //...MidBtnState
int LowBtnState = 0;  //...LowBtnState
int BaseBtnState = 0;  //...BaseBtnState
//----------------------------------------------------------------//
int HypDelayTime = 100;  //time you want the code to loop at. will be used to figure actual delay time(see end of code).

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

  for (int pin=2; pin<=6; ++pin)  //sets all digital pin 2-5 as input and enables internal pullups.
  {                        
    pinMode(pin, INPUT);  //sets button pins to input
    digitalWrite(pin, HIGH);  // sets the pull up.
  }
}

void loop()
{
  int TimeInt = millis();  //record time at begining of main loop

  XaxisVar = analogRead(Xaxis);  //Read X-Axis postion
  YaxisVar = analogRead(Yaxis);  //Read Y-Axis postion
  SpeedVar = analogRead(SpeedPot);  //Read Speed Pot postion

  TrigBtnState = digitalRead(TrigBtn);  //read status of buttons on joystick
  MidBtnState = digitalRead(MidBtn);  //...
  LowBtnState = digitalRead(LowBtn);  //...
  BaseBtnState = digitalRead(BaseBtn);  //...

  //Just serial ouput formatting...
  String Comma = String(",");
  String Data = String(XaxisVar + Comma + YaxisVar + Comma + SpeedVar + TrigBtnState + Comma + MidBtnState + Comma + LowBtnState + Comma + BaseBtnState);
  Serial.println(Data);

  int TimeEnd = millis();  //record time at the end of main loop

  //the DelayTime is the time so that the code actually repeats at 1000ms.
  //"Time we actualy want to delay"="EndOfCodeTime"-"BeginingOfCodeTime"="time taken for code to execute"-"hypothetical delay"(what we wanted to delay(1000ms))
  int DelayTime = HypDelayTime - (TimeEnd-TimeInt);
  delay(DelayTime);
  //Serial.println(DelayTime); //prints delay time. is about ~980ms, so we can tell that all the signal reading and formating takes 20ms.
}

Saturday, November 5, 2011

Awesome hidden Google features!

Simply search these terms in google, and you'll see:
tilt
do a barrel roll
google gravity (must be searched through "I'm Feeling Lucky")

Direct Links:
http://www.google.com/search?btnG=1&pws=0&q=tilt
http://www.google.com/search?btnG=1&pws=0&q=do+a+barrel+roll
http://mrdoob.com/projects/chromeexperiments/google_gravity/

Note: They may only work in chrome and definitely not in Internet Explorer.




Wednesday, November 2, 2011

Call of Duty: Modern Warfare 3 Countdown Timer!

I made a flash app of a countdown for the up coming COD: MW3 release. I've had it for a while, but here it is:

In full 1080p HD glory...http://dl.dropbox.com/u/28052258/CntDwn-MW3.swf


I cant even remember what it does when it reaches 00:00:00:00:000...

Broken iMac Teardown

I received a broken iMac G5 that someone found in a junk bin. I was told it was a bad PSU since it didn't even turn on, but further investigation revealed otherwise. It didn't even have a back panel or stand when i got it, so its internals were easily accessible. After it didn't turn on the first time, I looked at the logic board(aka Mobo) and found that the Ethernet or wireless IC blew up(or was surged through the LAN port) because the whole area around it was black with soot, and some of ICs were also missing. Also, at least 50 SMD resistors or capacitors were missing from the board(someone exploring the insides of their broken iMac?).

So, i took out all the cool stuff that was left as someone already took the HDD and ODD. I got:
1. 3 - those fancy apple blower fans
2. 2 - 16ohm .5W speakers
3. 1 - scratched, but probably working 1440x900 widescreen 17in LCD
4. PSU
5. Scratched up front case(maybe sand it down, and use for a Hackintosh build case?)
6. Huge heat sink that covered the North Bridge, 1.6Ghz CPU, and Geforce MX Graphics chip
7. 1/8in chuck of copper plate for cooling other side of Logic Board
8. De-soldered all the caps, ICs, interconnects, etc from Logic Board.
9. Sata power cable that connected to Logic Board.
10. A working 24v LCD backlight driver. Note: The LCD driver was built into logic board so i couldn't test it, but the backlight driver was separate.


I figured out the pinout for the 6 and 4 pin fan power connectors(I haven't quite exactly figured out what the solid grey wire is, I'm guessing something with RPMs):



Pics below:
Front Case

Sata power cable, LCD backlight driver, and caps/connectors etc from Logic Board

Heatsink


Speakers, and blower fans powered from a benchtop PSU



Logic Board mounting hardware inside front case, PSU, and copper plate :)
Lots of fun stuff to tinker with!