Timer1...can't enable/disable.

Hi.

I am using an ATTiny841.

I can get an IR LED on the PB2 (TOCC07) pin to turn on and off...so doesn't appear to be a hardware issue.

I need to modulate the IR LED at ~38KHz so decided to use timer 1 in CTC mode and toggle the PB2 pin (which is to a transistors base through a resistor).

When I run my setUpLed() the LED does appear to function. It triggered the TSOP reciever of another project of mine anyway...and can see it in a cameraphone.

The issue is I then want to turn it on and off as it is modulated at 38KHz. The LED doesn't function (remains off) when I use the iroff/iron declarations (basically setting timer 1A register to 0 for off and setting TCCR1A to set the COM0A0 bit to a 1 when wanting it on).

Why is this occurring. Been playing messing with the PINB/DDRB options and all sorts and can't figure it out!

#define BA PA3
#define BB PA6
#define BC PA5
#define BD PA4
#define B1 PA0
#define B2 PA1
#define B3 PA2
#define B4 PA7

#define irled PB2
#define led PB0

#define iron TCCR1A |=(1 << COM1A0); // Toggle on match with OCR1A
#define iroff TCCR1A |=(0<<COM1A0);



void setup() {

  // Set buttons with pullups...
  PUEA = 0xFF;
  //Set buttons as inputs
  DDRA = 0;
  pinMode(led, OUTPUT);
  pinMode(irled, OUTPUT);

  setupIRLed();   // Initialise the settings for the IR Led.
}

void loop() {
  // put your main code here, to run repeatedly:

  iron;
  delay(1000);
  iroff;
  delay(1000);

}

void setupIRLed() {
  // TOCC7 i.e. PB2 will run on the OC1A output...
  TOCPMSA1 = 0;
  TOCPMSA0 = 0;
  TOCPMSA1 |= (1 << TOCC7S0); // TOCC7S[1:0] = 01 = OC1A on PB2.
  TOCPMCOE |= (1 << TOCC7OE); // Enable the output on TOCC7 (PB2).


  TCCR1A = 0;
  TCCR1A |= (1 << COM1A0); // Toggle on match with OCR1A

  TCCR1B = 0;
  TCCR1B |= (1 << WGM12) | (1 << CS10); // CTC mode (WGM[3:0] = 0100) and no clock pre-scale (CS[12:10] =  001)

  OCR1A = 105;    // 105 ticks @ 8MHz = half period for 38KHz.

}

I wonder would the code in this Serial IR Thread be of some help?

...R

#define iron TCCR1A |=(1 << COM1A0); // Toggle on match with OCR1A
#define iroff TCCR1A |=(0<<COM1A0);

That's how you turn a bit ON but not how you turn a bit OFF. Shifting a 0 always produces a 0. ORing anything with 0 leaves it unchanged.

Try:

#define iroff TCCR1A &= ^(1<<COM1A0);

The '^' operator is the binary inversion. It turns the 1 bit to a 0 and all the 0 bits to 1s.
The AND operator '&' then leaves anything ANDed with a 1 bit unchanged and anything ANDed with a 0 bit set to 0.

johnwasser:
Try:

#define iroff TCCR1A &= ^(1<<COM1A0);

The '^' operator is the binary inversion. It turns the 1 bit to a 0 and all the 0 bits to 1s.
The AND operator '&' then leaves anything ANDed with a 1 bit unchanged and anything ANDed with a 0 bit set to 0.

Thanks! I see why what I was doing is wrong. I understand the thinking of flipping the bit and AND the whole byte to preserve the other bits, but get this error using your snippet:

/home/johnny/Dropbox/Arduino/IR Voter/ATTiny841_Tx_Ver2/ATTiny841_Tx_Ver2.ino:37:3: note: in expansion of macro 'iroff'
   iroff;
   ^
exit status 1
expected primary-expression before '^' token

#define doesn't end in a semicolon.

^ is bitwise xor - it requires two operands.

~ is bitwise not, which is I think what was meant.

I would use the timer in PWM mode, and turn on and off the output compare to get the data out, rather than using interrupts and CTC mode.

DrAzzy:
^ is bitwise xor - it requires two operands.

~ is bitwise not, which is I think what was meant.

I would use the timer in PWM mode, and turn on and off the output compare to get the data out, rather than using interrupts and CTC mode.

Sounds like a better idea! I am out getting lost in the mountains for 3 days now so may be back with further issues early next week. Thanks for the help and suggestions.

DrAzzy:
^ is bitwise xor - it requires two operands.
~ is bitwise not, which is I think what was meant.

Yes. That's what I meant. :frowning:

DrAzzy:
^ is bitwise xor - it requires two operands.

~ is bitwise not, which is I think what was meant.

I would use the timer in PWM mode, and turn on and off the output compare to get the data out, rather than using interrupts and CTC mode.

I have re-written my code somewhat and think I have a working prototype...

void setupIRLed() {

  // TOCC7 i.e. PB2 will run on the OC1A output...
  TOCPMSA1 = 0;
  TOCPMSA0 = 0;
  TOCPMSA1 |= (1 << TOCC7S0); // TOCC7S[1:0] = 01 = OC1A on PB2.
 

  //FAST 8-bit PWM: WGM[13:10] = 0101 (mode 5) 13=0 WGM12=1 WGM11=0 WGM10=1
  TCCR1C = 0;
  TCCR1A = 0;
  TCCR1A |= (1 << WGM10) | (1 << COM1A1);   // Clear on compare.  Set on Bottom.
  TCCR1B = 0;
  TCCR1B |= (1 << WGM12) | (1 << CS10); // No pre-scale...so 8MHz per tick.

  TIMSK1 |= (1 << OCIE1A);
  /* In 8-but FAST PWM mode, the OCR1A port is set (goes high) at BOTTOM (0). 
   *  When it then reaches OCR1A, the bit is cleared. 
   *  The timer continues to TOP (ICR1) value.
   *  
   *  As pin goes high at 0 for 105 counts, then low for 105 (till 210)...
   *  that is a period of 210 counts.
   *  8MHz / 210 =~ 38KHz
   */
  
  OCR1A = 105;
  ICR1 = 210;

  // Set timer to 0 to avoid the "miss".
  TCNT1 = 0;

}

I am then using the following code to "turn on and off" the modulated PWM pin...

#define iron   TOCPMCOE |= (1 << TOCC7OE) // Enable the output on TOCC7 (PB2).
#define iroff  TOCPMCOE =0

Is this a reasonable approach?

I am unsure if the LED is under-powered or there is an issue with my code mind...

I can see it in my phone camera but it seems to have to get pretty close to a TSOP receiver to trigger it.

The schematic is here, I have used a 220 ohm on the transistor base and a 15ohm on the LED mind.

you probably know this but just in case: 38kHz is way too fast for human eye so if PWM duty cycle/ratio is too low LED will just seem dim or off all the time.

If you are really using CR2032 cells, keep in mind that they are typically rated for 15 mA maximum current. The voltage will drop substantially if you try to draw much more.

jremington:
If you are really using CR2032 cells, keep in mind that they are typically rated for 15 mA maximum current. The voltage will drop substantially if you try to draw much more.

Thanks! Guessing putting in the capacitor will give me a nice "power bank" for short bursts ? Would say 100uF @ 16V suffice?

CR2032 droop above a few of mA, 5mA is perhaps pushing it, 15mA is way too much.

Johnny010:
Thanks! Guessing putting in the capacitor will give me a nice "power bank" for short bursts ? Would say 100uF @ 16V suffice?

Why guess? You can do the calculations.