Hi. I'm working on a project where I have a number of objects that physically change shape depending on how a person arranges them. I'm using infra red (IR) to send messages between the objects e.g. if the correct sides are facing each other, if one object sees another etc.
I've taken Walter Anderson's code that detects IR signals (see below), which works fine when you press some buttons on a universal TV remote control). But I have two problems:
- I don't know how to get it to differentiate between different signals. I tried comparing the value of
change_count
whenBit stream detected!
is true, but I keep getting the same combination of "1" and "0". - When I try sending IR signals with this other piece of code I found (also see below), the IR detection only seems to pick it up some of the time. I've tried to figure out why this happens, and my best guess is that it has to do with the modulation at which I'm sending my custom messages. So, what do I need to modify in my IR transmission code so that the IR detection code picks it up every time?
Walter Anderson's IR detection code:
/*
* File....... IRanalyzer.pde
* Purpose.... Records up to 128 signal changes
* Author..... Walter Anderson
* E-mail..... wandrson@walteranderson.us
* Started.... 18 May 2007
* Updated.... 18 May 2007
*
*
*/
#include <avr/interrupt.h>
#include <avr/io.h>
#define TIMER_RESET TCNT1 = 0
#define SAMPLE_SIZE 64
int IRpin = 2;
unsigned int TimerValue[SAMPLE_SIZE];
char direction[SAMPLE_SIZE];
byte change_count;
long time;
void setup() {
Serial.begin(115200);
Serial.println("Analyze IR Remote");
TCCR1A = 0x00; // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
// ICNC1=0 => Capture Noise Canceler disabled -- ICES1=0 => Input Capture Edge Select (not used) -- CTC1=0 => Clear Timer/Counter 1 on Compare/Match
// CS12=0 CS11=1 CS10=1 => Set prescaler to clock/64
TCCR1B = 0x03; // 16MHz clock with prescaler means TCNT1 increments every 4uS
// ICIE1=0 => Timer/Counter 1, Input Capture Interrupt Enable -- OCIE1A=0 => Output Compare A Match Interrupt Enable -- OCIE1B=0 => Output Compare B Match Interrupt Enable
// TOIE1=0 => Timer 1 Overflow Interrupt Enable
TIMSK1 = 0x00;
pinMode(IRpin, INPUT);
}
void loop()
{
Serial.println("Waiting...");
change_count = 0;
while(digitalRead(IRpin) == HIGH) {}
TIMER_RESET;
TimerValue[change_count] = TCNT1;
direction[change_count++] = '0';
while (change_count < SAMPLE_SIZE) {
if (direction[change_count-1] == '0') {
while(digitalRead(IRpin) == LOW) {}
TimerValue[change_count] = TCNT1;
direction[change_count++] = '1';
} else {
while(digitalRead(IRpin) == HIGH) {}
TimerValue[change_count] = TCNT1;
direction[change_count++] = '0';
}
}
Serial.println("Bit stream detected!");
change_count = 0;
time = (long) TimerValue[change_count] * 4;
Serial.print(time);
Serial.print("\t");
Serial.println(direction[change_count++]);
while (change_count < SAMPLE_SIZE) {
time = (long) TimerValue[change_count] * 4;
Serial.print(time);
Serial.print("\t");
Serial.println(direction[change_count-1]);
Serial.print(time);
Serial.print("\t");
Serial.println(direction[change_count++]);
}
Serial.println("Bit stream end!");
delay(2000);
}
Code that sends custom IR signals:
/* Control a Lutron Maestro light dimmer */
#define BIT_IS_SET(i, bits) (1 << i & bits)
// LED connected to digital pin 9
const int LED_PIN = 9;
// Width of a pulse, in microseconds
const int PULSE_WIDTH = 2300;
// # of bytes per command
const int COMMAND_LENGTH = 4;
const int FORWARD[] = {130};
const int UP[] = {255, 136, 130, 34};
const int DOWN[] = {255, 136, 130, 20};
const int ON[] = {255, 136, 132, 184};
const int OFF[] = {255, 136, 189, 18};
const int RECALL[] = {255, 136, 132, 183};
void setup()
{
pinMode(LED_PIN, OUTPUT);
}
/* Modulate pin at 38 kHz for give number of microseconds */
void on(int pin, int time) {
static const int period = 25;
// found wait_time by measuring with oscilloscope
static const int wait_time = 9;
for (time = time/period; time > 0; time--) {
digitalWrite(pin, HIGH);
delayMicroseconds(wait_time);
digitalWrite(pin, LOW);
delayMicroseconds(wait_time);
}
}
/* Leave pin off for time (given in microseconds) */
void off(int pin, int time) {
digitalWrite(pin, LOW);
delayMicroseconds(time);
}
/* Send a byte over the IR LED */
void send_byte(int bits) {
for (int i = 7; i >= 0; i--)
{
if (BIT_IS_SET(i, bits)) {
on(LED_PIN, PULSE_WIDTH);
} else {
off(LED_PIN, PULSE_WIDTH);
}
}
}
/* Send a full command */
void command(const int bytes[]) {
for (int i = 0; i < COMMAND_LENGTH; i++) {
send_byte(bytes[i]);
}
off(LED_PIN, 4 * PULSE_WIDTH);
}
void loop()
{
command(FORWARD);
delay(1000);
}