Jeenode infrared project part 3: sending test


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()

Maarten

Hi, I am Maarten and I am the owner of this weblog. I post on various IT subjects that matter in my life as an IT professional.

Recent Posts