/*
* Torsten Amshove <torsten@amshove.net>
*
* IR_433_Board - Selbstgelötetes Board mir IR Sender/Empfänger und 433Mhz Sender/Empfänger
*
* Pin 2 - 433 Mhz Empfänger - Ist vorgegeben, kann nicht geändert werden
* Pin 3 - IR Sender - Ist vorgegeben, kann nicht geändert werden
* Pin 4 - IR Empfänger
* Pin 5 - 433 Mhz Sender
*
* Alle anderen sind unbenutzt.
* Spannungsversorgung über die beiden Kabel:
* links - GND
* rechts - VCC (5V)
*
* Ausgabe über Seriell: 9600 baud 8N1
*
* Zum Senden des letzten Empfangenen Befehls gibt es zwei Möglichkeiten:
* Seriell - Eingabe eines beliebiegen Zeichens in der seriellen Konsole
* Schalter - Durch Drücken eines angeschlossenen Schalters (schaltet auf GND)
*
* Code auf Basis der Beispiele aus der IRLibrary von Ken Shirriff und der RemoteSwitch-Library von Randy Simons
* IRLibrary: http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
* RemoteSwitch: http://randysimons.com/overige/browsable/433MHz/
*/
#include <IRremote.h>
#include <RemoteReceiver.h>
#include <RemoteSwitch.h>
const int RECV_PIN_IR = 4;
const int SEND_PIN_433 = 5;
const int BUTTON_PIN = 12;
const int DEBUG_LED = 13;
// IR Initialisierung
IRrecv irrecv(RECV_PIN_IR);
IRsend irsend;
decode_results results;
// Welches Signal wurde zuletzt empfagen? 1 = IR, 2 = 433 Mhz
int last_method = 0;
void setup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Startet den IR-receiver
RemoteReceiver::init(0, 3, showCode_433); // Startet den 433 Mhz Empfänger - showCode_433 wird bei Empfang eines Signals automatisch aufgerufen
pinMode(BUTTON_PIN,INPUT);
digitalWrite(BUTTON_PIN,HIGH);
pinMode(DEBUG_LED,OUTPUT);
}
// Storage for the recorded code (IR)
int codeType = -1; // The type of code
unsigned long codeValue; // The code value if not raw
unsigned int rawCodes[RAWBUF]; // The durations if raw
int codeLen; // The length of the code
int toggle = 0; // The RC5/6 toggle state
void loop() {
// IR Signal empfangen
if(irrecv.decode(&results)){
digitalWrite(DEBUG_LED,HIGH);
// Zeile zum automatischen Auslesen: - und speichern der Werte
storeCode_ir(&results);
last_method = 1;
// Zeilen mit mehr Details:
Serial.println("#### IR ####");
dump_ir(&results);
Serial.println("");
irrecv.resume(); // Receive the next value
digitalWrite(DEBUG_LED,LOW);
}
// Button gedrückt / Zeichen eingegeben -> Signal senden
if(digitalRead(BUTTON_PIN) == LOW || Serial.read() != -1){
digitalWrite(DEBUG_LED,HIGH);
Serial.println("#### Senden ####");
if(last_method == 0){
Serial.println("# FEHLER: Noch kein Signal empfangen");
}else if(last_method == 1){
Serial.println("## IR");
sendCode_ir(0);
}else if(last_method == 2){
Serial.println("## 433");
sendCode_433();
}
Serial.println("");
digitalWrite(DEBUG_LED,LOW);
}
}
// ######## 433 Mhz ########
unsigned long savedCode;
void showCode_433(unsigned long receivedCode, unsigned int period) {
digitalWrite(DEBUG_LED,HIGH);
RemoteReceiver::disable();
//Need interrupts for delay
interrupts();
unsigned long code;
unsigned long code1;
unsigned long code2;
unsigned long periode2;
//Copy the received code.
code = receivedCode;
code1 = code;
code = code & 0xFFFFF; //truncate to 20 bits for show; receivedCode is never more than 20 bits..
code2 = code;
//Add the period duration to the code. Range: [0..511] (9 bit)
code |= (unsigned long)period << 23;
//Add the number of repeats to the code. Range: [0..7] (3 bit). The actual number of repeats will be 2^(repeats),
//in this case 8
code |= 3L << 20;
// Zeile zum automatischen Auslesen:
Serial.print("433Mhz: ");
Serial.println(code);
// Zeilen mit mehr Details:
Serial.println("#### 433Mhz ####");
Serial.print("# Code ohne shift: ");
Serial.println(code1);
Serial.print("# Code mit Shift 0xFFFFF: ");
Serial.println(code2);
Serial.print("# Periode: ");
Serial.println(period);
periode2 |= (unsigned long)period << 23;
Serial.print("# Periodee mit <<23: ");
Serial.println(periode2);
Serial.print("# Code mit Anzahl Wiederholungen, also komplett: ");
Serial.println(code);
// Code speichern
savedCode = code;
last_method = 2;
Serial.println("");
RemoteReceiver::enable();
digitalWrite(DEBUG_LED,LOW);
}
void sendCode_433(){
//Disable the receiver; otherwise it might pick up the retransmit as well.
RemoteReceiver::disable();
//Need interrupts for delay
interrupts();
Serial.print("# Code: ");
Serial.println(savedCode);
RemoteSwitch::sendTelegram(savedCode,SEND_PIN_433);
RemoteReceiver::enable();
}
// ######## IR ########
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
// decode_results *results = (decode_results *)v
void dump_ir(decode_results *results) {
int count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.println("# Could not decode message");
}
else {
if (results->decode_type == NEC) {
Serial.print("# Decoded NEC: ");
}
else if (results->decode_type == SONY) {
Serial.print("# Decoded SONY: ");
}
else if (results->decode_type == RC5) {
Serial.print("# Decoded RC5: ");
}
else if (results->decode_type == RC6) {
Serial.print("# Decoded RC6: ");
}
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
}
Serial.print("# Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 0; i < count; i++) {
if ((i % 2) == 1) {
Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
}
else {
Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println("");
}
// Stores the code for later playback
// Most of this code is just logging
void storeCode_ir(decode_results *results) {
Serial.print("IR: ");
codeType = results->decode_type;
Serial.print("codeType: ");
Serial.print(codeType);
Serial.print(" (");
if (codeType == NEC) {
Serial.print("NEC");
} else if (codeType == SONY) {
Serial.print("SONY");
} else if (codeType == RC5) {
Serial.print("RC5");
} else if (codeType == RC6) {
Serial.print("RC6");
} else if (codeType == UNKNOWN) {
Serial.print("UNKNOWN");
}
Serial.print(")");
int count = results->rawlen;
if (codeType == UNKNOWN) {
codeLen = results->rawlen - 1;
Serial.print(" rawCodes: ");
// To store raw codes:
// Drop first value (gap)
// Convert from ticks to microseconds
// Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
for (int i = 1; i <= codeLen; i++) {
if (i % 2) {
// Mark
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS;
} else {
// Space
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS;
}
// Serial.print(rawCodes[i - 1], DEC);
Serial.print(rawCodes[i - 1]);
Serial.print(",");
}
} else {
if (results->value != REPEAT) {
// Serial.println(results->value, HEX);
codeValue = results->value;
Serial.print(" codeValue: ");
Serial.print(codeValue);
codeLen = results->bits;
}
}
Serial.print(" codeLen: ");
Serial.print(codeLen);
Serial.println("");
}
/*
codeType = results->decode_type;
int count = results->rawlen;
if (codeType == UNKNOWN) {
Serial.println("# Received unknown code, saving as raw");
codeLen = results->rawlen - 1;
// To store raw codes:
// Drop first value (gap)
// Convert from ticks to microseconds
// Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
Serial.print("#");
for (int i = 1; i <= codeLen; i++) {
if (i % 2) {
// Mark
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS;
Serial.print(" m");
}
else {
// Space
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS;
Serial.print(" s");
}
Serial.print(rawCodes[i - 1], DEC);
}
Serial.println("");
}
else {
if (codeType == NEC) {
Serial.print("# Received NEC: ");
if (results->value == REPEAT) {
// Don't record a NEC repeat value as that's useless.
Serial.println("repeat; ignoring.");
return;
}
}
else if (codeType == SONY) {
Serial.print("# Received SONY: ");
}
else if (codeType == RC5) {
Serial.print("# Received RC5: ");
}
else if (codeType == RC6) {
Serial.print("# Received RC6: ");
}
else {
Serial.print("# Unexpected codeType ");
Serial.print(codeType, DEC);
Serial.println("");
}
Serial.println(results->value, HEX);
codeValue = results->value;
codeLen = results->bits;
}
}
*/
void sendCode_ir(int repeat) {
if (codeType == NEC) {
if (repeat) {
irsend.sendNEC(REPEAT, codeLen);
Serial.println("# Sent NEC repeat");
}
else {
irsend.sendNEC(codeValue, codeLen);
Serial.print("# Sent NEC ");
Serial.println(codeValue, HEX);
}
}
else if (codeType == SONY) {
irsend.sendSony(codeValue, codeLen);
Serial.print("# Sent Sony ");
Serial.println(codeValue, HEX);
}
else if (codeType == RC5 || codeType == RC6) {
if (!repeat) {
// Flip the toggle bit for a new button press
toggle = 1 - toggle;
}
// Put the toggle bit into the code to send
codeValue = codeValue & ~(1 << (codeLen - 1));
codeValue = codeValue | (toggle << (codeLen - 1));
if (codeType == RC5) {
Serial.print("# Sent RC5 ");
Serial.println(codeValue, HEX);
irsend.sendRC5(codeValue, codeLen);
}
else {
irsend.sendRC6(codeValue, codeLen);
Serial.print("# Sent RC6 ");
Serial.println(codeValue, HEX);
}
}
else if (codeType == UNKNOWN /* i.e. raw */) {
// Assume 38 KHz
irsend.sendRaw(rawCodes, codeLen, 38);
Serial.println("# Sent raw");
}
}