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.
}
#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.
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
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.
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.