My idea was to create a program that allows the arduino to read, decode, and resend the signal of an IR remote, such as a TV remote. I combined you push one button (on pin 5) to record the signal from a remote, and another button (on pin 4) to playback the signal from an IR LED (with a transistor on pin 7). Then I got an OLED display (.96", 128x64, white, I2C) and decided to try to use that along with the sketch. I wanted the OLED to show when the sketch starts up and when it preforms the various functions.
So, when the program records a signal, it prints it to the serial monitor. It shows the high times and the low times of the signal, like this:
64392 , 340
1720 , 340
700 , 320
720 , 340
680 , 360
680 , 320
720 , 320
1740 , 320
1740 , 320
740 , 280
1800 , 280
740 , 300
760 , 280
740 , 280
1780 , 280
760 , 280
44120 , 380
1680 , 360
680 , 340
700 , 340
700 , 340
700 , 340
1720 , 340
700 , 340
700 , 340
1740 , 280
720 , 320
1740 , 320
1740 , 320
1740 , 320
720 , 340
1760 , 280
44120 , 360
1700 , 340
700 , 360
680 , 340
680 , 320
720 , 360
680 , 340
1720 , 340
1720 , 320
720 , 320
1740 , 320
720 , 320
720 , 320
760 , 260
1740 , 320
720 , 320
44120 , 380
1680 , 380
660 , 340
700 , 340
700 , 340
700 , 340
1720 , 340
700 , 320
720 , 300
1740 , 320
720 , 340
1720 , 320
1740 , 340
1760 , 280
720 , 320
1740 , 300
In the code I'm using, if I comment out everything related to the display it works flawlessly, but when I try to use the display, it reads part of the signal and stops. I have absolutely no idea what is going on, but occasionally when I leave the display connected to the arduino (even if it's not being used) , the sketch fails in the same way. This is the code I'm using:
#include <SPI.h> //display files
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
#define IRpin_PIN PIND
#define IRpin 2
#define MAXPULSE 65000
#define RESOLUTION 20
uint16_t pulses[100][2]; // pair is high and low pulse //number of pulses per set, number of sets
uint8_t currentpulse = 0; // index for pulses we're storing
int IRledPin = 7;
int state = 0;
void setup(void) {
Serial.begin(9600);
Serial.println("Beginning code");// just to show it's actually started
pinMode(4, INPUT_PULLUP);// button pin for reading code
pinMode(5, INPUT_PULLUP);// button pin for sending code
pinMode(IRledPin, OUTPUT);
//display.begin(SSD1306_SWITCHCAPVCC, 0x3C);//begins display obviously
//display.clearDisplay();//not sure if necessary
//display.setTextSize(1);
//display.setTextColor(WHITE);
//display.setCursor(0,0);
//display.println("Beginning...");//***
//display.display(); //
//delay(1000); //
//display.setCursor(0,8); //
//display.println("Ready"); // Just looks cool and shows the program has started
//display.display(); //
//delay(1000); //
//display.clearDisplay(); //
//delay(100); //***
}
void loop(void) {
//code for reading, decoding, and recording IR signal of a remote
if(digitalRead(5) == LOW) {
int Time = millis();// allows for tracking of time
// display.clearDisplay();
// display.setCursor(0,0);
// display.println("Ready to decode IR");
// display.display();
Serial.println("Ready to decode IR!");
for(int i = 0; i < 200; i++) {
readPulses();
//without this the code gets stuck here. This allows it to return after 1 second
if(millis() > Time + 1000) {
return;
}
}
}
//code for sending the signal once it has been recorded
if(digitalRead(4) == LOW) {
// prevents it from trying to send a code that hasn't been created/recorded yet
if(state != 1) {
// display.clearDisplay();
// display.setCursor(0,0);
// display.println("No Code!");
// display.display();
Serial.println("No Code!");
delay(250);
return;
}
// display.clearDisplay();
// display.setCursor(0,0);
//display.println("Sending Code");
// display.display();
Serial.println("Sending code");
sendPowerCode2();
delay(50);
// display.clearDisplay();
// display.setCursor(0,0);
// display.println("Code sent");
//display.display();
Serial.println("Code sent");
delay(1000);
}
}
void printpulses(void) {
for (uint8_t i = 0; i < currentpulse; i++) {
Serial.print(pulses[i][0] * RESOLUTION, DEC);// low pulses
Serial.print(" , ");
Serial.println(pulses[i][1] * RESOLUTION, DEC);//high pulses
}
}
void readPulses() {
uint16_t highpulse, lowpulse; // temporary storage timing
highpulse = lowpulse = 0; // start out with no pulse length
while (IRpin_PIN & (1 << IRpin)) {
// pin is still HIGH
// count off another few microseconds
highpulse++;
delayMicroseconds(RESOLUTION);
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
// we didn't time out so lets stash the reading
pulses[currentpulse][0] = highpulse;
// same as above
while (! (IRpin_PIN & _BV(IRpin))) {
// pin is still LOW
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
//display.clearDisplay();
//display.setCursor(0,0);
//display.println("Finished decoding");
// display.display();
return;
}
}
pulses[currentpulse][1] = lowpulse;
// we read one high-low pulse successfully, continue!
currentpulse++;
state = 1;// this indicates that the code is available to be sent
}
void pulseIR(long microsecs) {
// we'll count down from the number of microseconds we are told to wait
cli(); // this turns off any background interrupts
while (microsecs > 0) {
// 38 kHz is about 13 microseconds high and 13 microseconds low
digitalWrite(IRledPin, HIGH); // this takes about 3 microseconds to happen
delayMicroseconds(10); // hang out for 10 microseconds
digitalWrite(IRledPin, LOW); // this also takes about 3 microseconds
delayMicroseconds(10); // hang out for 10 microseconds
// so 26 microseconds altogether
microsecs -= 26;
}
sei(); // this turns them back on
}
void sendPowerCode2() {
int Time2 = millis();//allows for tracking of time again
for(int i = 0; i < 100; i++) {
delayMicroseconds(pulses[i][0]*RESOLUTION);
pulseIR(pulses[i][1]*RESOLUTION);
//returns if sending gets stuck for longer than 500 milliseconds
if(millis() > Time2 + 500) {
return;
}
}
}
I tried to explain as much as possible in the code, but if anyone has any questions I'll be happy to (try) to answer them. The actual circuit I'm using is four parts; an IR LED and a transistor for the emitter, an IR receiver, three buttons (one for reading signals, one for sending signals, and one for reset), and an OLED display connected via I2C (pins A4 and A5).
Any suggestions or ideas would be greatly appreciated.
Thanks
~Josh