Go Down

Topic: IR Remote Timer Register ändern (Read 623 times) previous topic - next topic

xacenash

Jun 28, 2013, 03:01 pm Last Edit: Jun 28, 2013, 04:57 pm by xacenash Reason: 1
Hallo,
Die IR Remote verwendet das Timer Register 2 diese möchte ich gerne ändern wegen Konflikt mit einer anderer Lib.
Nach Stunden langem Datenblatt stöbern konnte ich keine Lösung finden wenn ich den Timer 4 verwenden möchte.
Habe die IRremote umgeschrieben mit allen Timer 4 Registern.
Die ir diode sendet den Code was das Empfangsgerät benötigt regiert aber nicht, vermutlich stimmt die HZ  nicht da ja Timer 2 auf 8 bit und Timer 4 auf 16 läuft.
Für jeden kleinen Tip bin ich dankbar um es zum Laufen zu bekommen.
Board ist ein mega 2560
hier noch die Änderungen wo ich vorgenommen habe.

Code: [Select]
#include "IRremote.h"
#include "IRremoteInt.h"

// Provides ISR
#include <avr/interrupt.h>

volatile irparams_t irparams;

// These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging.
// To use them, set DEBUG in IRremoteInt.h
// Normally macros are used for efficiency
#ifdef DEBUG
int MATCH(int measured, int desired) {
 Serial.print("Testing: ");
 Serial.print(TICKS_LOW(desired), DEC);
 Serial.print(" <= ");
 Serial.print(measured, DEC);
 Serial.print(" <= ");
 Serial.println(TICKS_HIGH(desired), DEC);
 return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);
}

int MATCH_MARK(int measured_ticks, int desired_us) {
 Serial.print("Testing mark ");
 Serial.print(measured_ticks * USECPERTICK, DEC);
 Serial.print(" vs ");
 Serial.print(desired_us, DEC);
 Serial.print(": ");
 Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC);
 Serial.print(" <= ");
 Serial.print(measured_ticks, DEC);
 Serial.print(" <= ");
 Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);
 return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS);
}

int MATCH_SPACE(int measured_ticks, int desired_us) {
 Serial.print("Testing space ");
 Serial.print(measured_ticks * USECPERTICK, DEC);
 Serial.print(" vs ");
 Serial.print(desired_us, DEC);
 Serial.print(": ");
 Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC);
 Serial.print(" <= ");
 Serial.print(measured_ticks, DEC);
 Serial.print(" <= ");
 Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
 return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);
}
#endif

void IRsend::sendNEC(unsigned long data, int nbits)
{
 enableIROut(38);
 mark(NEC_HDR_MARK);
 space(NEC_HDR_SPACE);
 data = data << (32 - nbits);
 for (int i = 0; i < nbits; i++) {
   if (data & TOPBIT) {
     mark(NEC_BIT_MARK);
     space(NEC_ONE_SPACE);
   }
   else {
     mark(NEC_BIT_MARK);
     space(NEC_ZERO_SPACE);
   }
   data <<= 1;
 }
 mark(NEC_BIT_MARK);
 space(0);
}

void IRsend::sendSony(unsigned long data, int nbits) {
 enableIROut(40);
 mark(SONY_HDR_MARK);
 space(SONY_HDR_SPACE);
 data = data << (32 - nbits);
 for (int i = 0; i < nbits; i++) {
   if (data & TOPBIT) {
     mark(SONY_ONE_MARK);
     space(SONY_HDR_SPACE);
   }
   else {
     mark(SONY_ZERO_MARK);
     space(SONY_HDR_SPACE);
   }
   data <<= 1;
 }
}

void IRsend::sendRaw(unsigned int buf[], int len, int hz)
{
 enableIROut(hz);
 for (int i = 0; i < len; i++) {
   if (i & 1) {
     space(buf[i]);
   }
   else {
     mark(buf[i]);
   }
 }
 space(0); // Just to be sure
}

// Note: first bit must be a one (start bit)
void IRsend::sendRC5(unsigned long data, int nbits)
{
 enableIROut(36);
 data = data << (32 - nbits);
 mark(RC5_T1); // First start bit
 space(RC5_T1); // Second start bit
 mark(RC5_T1); // Second start bit
 for (int i = 0; i < nbits; i++) {
   if (data & TOPBIT) {
     space(RC5_T1); // 1 is space, then mark
     mark(RC5_T1);
   }
   else {
     mark(RC5_T1);
     space(RC5_T1);
   }
   data <<= 1;
 }
 space(0); // Turn off at end
}

// Caller needs to take care of flipping the toggle bit
void IRsend::sendRC6(unsigned long data, int nbits)
{
 enableIROut(36);
 data = data << (32 - nbits);
 mark(RC6_HDR_MARK);
 space(RC6_HDR_SPACE);
 mark(RC6_T1); // start bit
 space(RC6_T1);
 int t;
 for (int i = 0; i < nbits; i++) {
   if (i == 3) {
     // double-wide trailer bit
     t = 2 * RC6_T1;
   }
   else {
     t = RC6_T1;
   }
   if (data & TOPBIT) {
     mark(t);
     space(t);
   }
   else {
     space(t);
     mark(t);
   }

   data <<= 1;
 }
 space(0); // Turn off at end
}

void IRsend::mark(int time) {
 // Sends an IR mark for the specified number of microseconds.
 // The mark output is modulated at the PWM frequency.
 TCCR4A |= _BV(COM4B1); // Enable pin 3 PWM output
 delayMicroseconds(time);
}

/* Leave pin off for time (given in microseconds) */
void IRsend::space(int time) {
 // Sends an IR space for the specified number of microseconds.
 // A space is no output, so the PWM output is disabled.
 TCCR4A &= ~(_BV(COM4B1)); // Disable pin 3 PWM output
 delayMicroseconds(time);
}

void IRsend::enableIROut(int khz) {
 // Enables IR output.  The khz value controls the modulation frequency in kilohertz.
 // The IR output will be on pin 3 (OC2B).
 // This routine is designed for 36-40KHz; if you use it for other values, it's up to you
 // to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)
 // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B
 // controlling the duty cycle.
 // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)
 // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
 // A few hours staring at the ATmega documentation and this will all make sense.
 // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.

 
 // Disable the Timer2 Interrupt (which is used for receiving IR)
 TIMSK4 &= ~_BV(TOIE4); //Timer2 Overflow Interrupt

 pinMode(7, OUTPUT);
 digitalWrite(7, LOW); // When not sending PWM, we want it low
 
 // COM2A = 00: disconnect OC2A
 // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted
 // WGM2 = 101: phase-correct PWM with OCRA as top
 // CS2 = 000: no prescaling
 TCCR4A = _BV(WGM40);
 TCCR4B = _BV(WGM42) | _BV(CS40);

 // The top value for the timer.  The modulation frequency will be SYSCLOCK / 2 / OCR2A.
 OCR4A = SYSCLOCK / 2 / khz / 1000;
 OCR4B = OCR4A / 3; // 33% duty cycle
}

IRrecv::IRrecv(int recvpin)
{
 irparams.recvpin = recvpin;
 irparams.blinkflag = 0;
}

// initialization
void IRrecv::enableIRIn() {
 // setup pulse clock timer interrupt
 TCCR4A = 0;  // normal mode

 //Prescale /8 (16M/8 = 0.5 microseconds per tick)
 // Therefore, the timer interval can range from 0.5 to 128 microseconds
 // depending on the reset value (255 to 0)
 cbi(TCCR4B,CS42);
 sbi(TCCR4B,CS41);
 cbi(TCCR4B,CS40);

 //Timer2 Overflow Interrupt Enable
 sbi(TIMSK4,TOIE4);

 RESET_TIMER4;

 sei();  // enable interrupts

 // initialize state machine variables
 irparams.rcvstate = STATE_IDLE;
 irparams.rawlen = 0;


 // set pin modes
 pinMode(irparams.recvpin, INPUT);
}

// enable/disable blinking of pin 13 on IR processing
void IRrecv::blink13(int blinkflag)
{
 irparams.blinkflag = blinkflag;
 if (blinkflag)
   pinMode(BLINKLED, OUTPUT);
}

// TIMER2 interrupt code to collect raw data.
// Widths of alternating SPACE, MARK are recorded in rawbuf.
// Recorded in ticks of 50 microseconds.
// rawlen counts the number of entries recorded so far.
// First entry is the SPACE between transmissions.
// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.
// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts
ISR(TIMER4_OVF_vect)
{
 RESET_TIMER4;

 uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);

 irparams.timer++; // One more 50us tick
 if (irparams.rawlen >= RAWBUF) {
   // Buffer overflow
   irparams.rcvstate = STATE_STOP;
 }


[EDIT] Code Tags hinzugefügt. Uwe [/EDIT]

pylon

#1
Jun 28, 2013, 08:34 pm Last Edit: Jun 28, 2013, 08:36 pm by pylon Reason: 1
Wieso so kompliziert? Wenn Du das Precompiler-Flag IR_USE_TIMER4 definierst setzt, wird automatisch Timer4 genommen. Oder ist Deine eigene Routine eher akademischer Natur?

Edit: Wird in Zeile 36 von IRremoteInt.h gemacht.

xacenash

:smiley-sleep:
Vielen Dank alles geht nun  XD
Habe mich festgebissen an der IRremote wollte was umschreiben auf dem Akademischem Stiel.Zum Glück machte dies ein anderer.
multi IR lib gefunden.
Vielen Dank

Go Up