In the first and second part of this series I introduced my idea’s about the IR project.
I also showed some basic receiving, and even receiving over the air.
What was left out, was the sending part.
Today I found some time to get a sending setup together.
Here’s the setup:
- A Jeelink containing a sketch which translates serial commands to IR codes and sends them over the air;
- A Jeenode on the receiving side, which receives the IR commands and sends them out to an IR led;
- A python script to send commands to the serial port, to create a basic zapping demo.
Here’s a little video demonstrating the sketches and python script below:
The Jeelink has the following sketch:
/* * mdRFReceive - Generic home automation RF12 receiver. * Version 0.1 June, 2010 * Copyright 2010 Maarten Damen * http://www.maartendamen.com */ #include <Ports.h> #include <RF12.h> #define MAX_STRING_LEN 20 byte needToSend; long unsigned int sendbuf; char buffer[MAX_STRING_LEN]; int bufferIndex = 0; void setup() { Serial.begin(57600); rf12_config(); } static void sendIR(long unsigned int code) { sendbuf = code; needToSend = 1; } char* subStr (char* str, char *delim, int index) { char *act, *sub, *ptr; char output; static char copy[MAX_STRING_LEN]; int i; // Since strtok consumes the first arg, make a copy strcpy(copy, str); for (i = 1, act = copy; i <= index; i++, act = NULL) { sub = strtok_r(act, delim, &ptr); if (sub == NULL) break; } return sub; } unsigned long long conv64(char* str) { unsigned long long res = 0; // remove 0x or 0X part if((strstr(str, "0x") == str) || (strstr(str, "0X") == str)) str += 2; // do the conversion... for(; *str != 0; str++) { // multiply by 16 (remember, hexadecimal == base 16) res <<= 4; if(strchr("0123456789", *str) != NULL) // if within 0-9... res |= *str - '0'; else if(strchr("ABCDEF", *str) != NULL) // if within A-F... res |= *str + 10 - 'A'; else if(strchr("abcdef", *str) != NULL) // if within a-f... res |= *str + 10 - 'a'; else { res >>= 4; break; } } return res; } static void handleInput (char* command, char* argument) { if (strcmp(command, "send_tv") == 0) { long unsigned int test = conv64(argument); sendIR(test); } } void loop() { if (Serial.available()) { char ch = Serial.read(); if (ch == '\n') { bufferIndex = 0; handleInput(subStr(buffer, " ", 1), subStr(buffer, " ", 2)); } else { buffer[bufferIndex++] = ch; } } if (rf12_recvDone() && rf12_crc == 0) { byte n = rf12_len; Serial.println("Packet CRC OK"); Serial.print((int) rf12_hdr); for (byte i = 0; i < n; i++) { Serial.print(' '); Serial.print((int) rf12_data[i]); } Serial.println(); } if (needToSend && rf12_canSend()) { needToSend = 0; rf12_sendStart(0, &sendbuf, sizeof sendbuf); } }
The Jeenode has the following receiving sketch:
/* * mdIR - IR interface for home automation. * Version 0.1 May, 2010 * Copyright 2010 Maarten Damen * http://www.maartendamen.com */ #include <RF12.h> #include <Ports.h> #include <IRremote.h> IRsend irsend; int RECV_PIN = 4; IRrecv irrecv(RECV_PIN); MilliTimer sendTimer; byte needToSend; decode_results results; long unsigned int sendbuf; long unsigned int received; struct { byte decode; // IR decode } payload; void setup () { Serial.begin(57600); Serial.println(57600); Serial.println("mdIR started..."); rf12_config(); irrecv.enableIRIn(); // Start the IR receiver } void loop () { if (irrecv.decode(&results)) { needToSend = 1; sendbuf = results.value; Serial.println(results.value); Serial.println(results.value, HEX); irrecv.resume(); // Receive the next value } /* TODO: rf12_canSend doesn't work if I remove this... (needs to check incoming packets?) */ if (rf12_recvDone() && rf12_crc == 0 && (int) rf12_hdr == 10) { byte n = rf12_len; Serial.println("Packet CRC OK"); Serial.println((int) n); for (byte i = 0; i < n; i++) { Serial.print(' '); Serial.print((int) rf12_data[i]); } Serial.println(); received = ( ((long) rf12_data[3] << 24) + ((long) rf12_data[2] << 16) + ((long) rf12_data[1] << 8) + ((long) rf12_data[0] ) ); irsend.sendSamsung(received, 32); /* Re-enable receiving mode */ irrecv.enableIRIn(); Serial.println(); } if (needToSend && rf12_canSend()) { needToSend = 0; Serial.println("need to send"); rf12_sendStart(0, &sendbuf, sizeof sendbuf); } }
The python scripts looks like this:
from twisted.internet.serialport import SerialPort import sys from twisted.protocols import basic if sys.platform == 'win32': from twisted.internet import win32eventreactor win32eventreactor.install() from twisted.internet import reactor class IRProtocol(basic.LineReceiver): def __init__(self): # Power on the tv reactor.callLater(10.0, self.send_tv, "0xE0E040BF") # Zap a bit reactor.callLater(15.0, self.send_tv, "0xE0E020DF") reactor.callLater(20.0, self.send_tv, "0xE0E0A05F") reactor.callLater(25.0, self.send_tv, "0xE0E0609F") reactor.callLater(30.0, self.send_tv, "0xE0E010EF") reactor.callLater(35.0, self.send_tv, "0xE0E0906F") def lineReceived(self, line): """ Do nothing with received lines yet """ def send_tv(self, command): """ Send's an IR command. """ self.transport.write('send_tv ' + command + '\n') SerialPort(IRProtocol(), 6 , reactor, '57600') reactor.run()