/ #arduino #raspberrypi 

Infrared LED Control With iPhone & Raspberrypi

I’ve always wanted to be able to turn off my lights from bed. Using the provided remote was about as convientant as getting out of bed though. It was never near and it was just another thing to keep track of. Originally this project was using RF for a light switch but the RF light switch from China was of questionable quality and didn’t fit in the socket for that matter. I resorted to controlling my infared LED strip instead. You can find them here.

For this I wanted to be able to control the lights with my phone, which I almost always have near. My phone is jailbroken and there is an app called Activator that allows you to bind actions like holding volume buttons up or down to terminal commands. My plan was to bind an action to a command that ssh’d into a raspberrypi that was connected to the arduino and then executed something to turn my lights on/off.

I started off by capturing the values that the remote was sending using the IRremote library. Once I had those I could send the same values back myself. I will include the code at the end that I used to capture the values. The core for my arduino looks like this slimmed down. I have a command structure of name/function pointer. The arduino listens over serial until it gets a newline and attempts to parse/match a command sequence in the format “command:value”. Most actions are not value dependent and default to 1.

void light_on(int dud);

struct command {
  char* functionName;
  void (*function)(int z);
};

struct command commands[] = {
  {"light_off",light_off},
  {"light_on",light_on},
}

void light_on(int dud) {
   irsend.sendNEC(0xF740BF, 32); // Lights on
   delay(14);
}

// Main loop //
void loop() {
  if (stringComplete) { // If serialEvent() found complete newline it would put it into inputString and set stringComplete true
    bool matched_command = false;
    String cmd_opt = getValue(inputString, ':', 1);
    if (cmd_opt.length() > 1) {
       inputString = getValue(inputString, ':', 0);
    }
    for(int i=0;i < (sizeof(commands)/sizeof(commands[0]));i++){
      if(inputString.equals(commands[i].functionName)){
        commands[i].function(cmd_opt.toInt()); // Executes function
        Serial.println("200");
        matched_command = true;
        break;
      }
    }
    inputString = "";
    stringComplete = false;
    if (matched_command == false) {
      Serial.println("404");
    }
  }
}

/*
  SerialEvent occurs whenever a new data comes in the
 hardware serial RX.  This routine is run between each
 time loop() runs, so using delay inside loop can delay
 response.  Multiple bytes of data may be available.
 */
void serialEvent() {
  int count = 0;
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

The next part to this is to interact with the arduino from the raspberrypi. The raspberrypi is pretty much plug and play. The only real configuration I had to do after imaging the SD card was to repartition and extend the disk to use the entire sd card. I had to run “sudo raspi-config” and it was the first option listed. Setting up a static IP would be a good idea too. I wanted my phone to be able to connect to the raspberrypi without any hesitation so I setup ssh keys between my phone/raspberrypi. You can read more about using them here.

I now needed a terminal/interface to talk to my arduino though. I ended up writing what is below. It works as a terminal to send mutiple commands in a row. I also added the functionality for it to just run commands included in arguments like “python arduino_terminal.py lights_on:1”

#!/usr/bin/python
import time
import serial
import sys

# configure the serial connections (the parameters differs on the device you are connecting to)
ser=serial.Serial(port="/dev/ttyACM0",baudrate=9600) # common usb port on linux
time.sleep(1.5)
ser.isOpen()

# print 'Enter your commands below.\nType "exit" to leave prompt.'
def arduino_input(input=None, sendCmd = False):
    if (sendCmd == True):
        # input = raw_input('>') # For Python 3 use input = input(">> ")
        if input == 'exit':
            ser.close()
            sys.exit()
        elif input != '':
            ser.write(input + '\n')

    out = ''
    # let's wait 1 seconds before reading output (gives device time to return reply)
    time.sleep(1)
    while ser.inWaiting() > 0:
        out += ser.read(1)
    if out != '':
        return out.strip()
    else:
        return arduino_input()

ran=False
while 1:
    if ran == True:
       sys.exit()
    if len(sys.argv) > 1:
        input = sys.argv[1]
        ran=True
    else:
        input = raw_input('>')
    if input.strip() == '':
        continue
    arduino_response = arduino_input(input,sendCmd = True)
    if arduino_response:
        if arduino_response == "404":
            print "Invalid Command"
            sys.stdout.flush()
        else:
            print arduino_response
            sys.stdout.flush()

Next I setup an action in Activator on my phone to execute the two commands lights_on/off.

ssh -f pi@192.168.1.16 "cd ~/Desktop/ ; python arduino_terminal.py light_on:1"
ssh -f pi@192.168.1.16 "cd ~/Desktop/ ; python arduino_terminal.py light_off:1"

You can go checkout the code for yourself here. https://github.com/andrewfree/infrared-lights