I am trying to replicate an infrared trigger for a Nikon dslr as described [here.
It basically seems to consist of switching an IR led with these timings.
ON off ON off ON off ON off
2250us 27600us 650us 1375us 575us 3350us 650us
Once it’s done that it repeats once more after 63ms. Additionally, for an ON state the IR has to cycled at ~40Khz.
I cannot for the life of me get my code to work. It definitely does something as evidenced by a red LED I tried but it won’t trigger. Was hoping somebody might have a trawl through my code as i’ve gone through it over and over and can’t see anything wrong.
Here is the code i’ve got. I’m very new to C and avr’s so i’m unaware of bad practices right now.
// mll3 infrared transmitter
// have a feeling util/delay requires timer0 with no prescale
// making do without it
#include <avr/io.h>
#include <avr/interrupt.h>
// setting up a 1MHz clock signal for creating counters
void realtimeclock_setup() {
TCCR0A |= (1<<WGM01);
TCCR0B |= (1<<CS01); // 0.5us or 2Mhz
OCR0A = 0x01; // a 1MHz signal
TIMSK0 |= (1<<OCIE0A);
}
volatile uint16_t clk1, clk2;
// what to do on the TIMER0 compares
SIGNAL(SIG_OUTPUT_COMPARE0A) {
clk1++;
clk2++; // meh
}
// the util/delay.h seems to be massively
// wrong if I create a timer
int delay_us(uint16_t val) {
clk1 = 0;
while ( clk1 < val ){
}
return 0;
}
// creates a 38.5KHz signal for
// a specified duration val (us)
int gensig (uint16_t val) {
clk2 = 0;
while ( clk2 < val ) {
PORTB ^= 0x04;
delay_us(13);
}
return 0;
}
// when the button is pressed perform the trigger signal
int snap(void) {
int i = 0;
// has to do this twice
while ( i <= 1 ) {
gensig(2250); // # of 2250 cycles in 2000us @ 1MHz
PORTB &= ~0x04;
delay_us(27600);
gensig(650); // # 650 of cycles in 650us
PORTB &= ~0x04;
delay_us(1375);
gensig(575); // # 575 of cycles in 575us
PORTB &= ~0x04;
delay_us(3350);
gensig(650); // # 650 of cycles in 650us
PORTB &= ~0x04;
i++;
delay_us(63000); // 63ms
}
return 0;
}
int main (void){
realtimeclock_setup();
DDRB |= 0x04; // an LED
DDRD &= 0xFB;
PORTD |= 0x04; //enable pullup
sei();
while (1) {
if ( PIND & 0x04 )
PORTB &= ~0x04;
else
snap(); // perform trigger signal
}
return 0;
}
For reference this is an atmega168 (Arduino) and I have a PIC programmed with the hexfile at the aforementioned website which triggers the camera fine.](http://users.tkk.fi/jwagner/electr/d70remote/)
leon_heller:
Why not use the PIC, it’s much cheaper and smaller.
Leon
Because I want to incorporate this design into a much larger one. Also, if I was to board my design i’ll have to put a PIC on it in place of just a wire to the LED.
while (1) {
if ( PIND & 0x04 ){
PORTB ^= 0x04;
delay_us(500000);
}
else {
snap(); // perform trigger signal
}
}
This creates a 0.2Hz signal instead of the 1Hz I was expecting. Therefore my timer seems to be out by a factor of 5.
What the realtimeclock_setup() function is supposed to do is prescale the 16MHz clock signal by 8. This is supposed to now create a 2MHz signal. Now I add a clock compare thingy of 2, i.e. on every other clock signal an interrupt is created. This interrupt increments a variable at a rate of 1MHz.
Now all of that is what I believe is supposed to be happening yet I can’t see any evidence against this. Could anybody point anything stupid i’ve done as i’m confused.
[note] Before somebody points out using 500000 with an unit16_t that’s changed at the moment to a 32.
theatrus:
Do you have an oscilloscope to confirm what your timing is?
Have you broken your code down to the smallest possible factor (such as checking the rate of output compares)?
Are all your routines taking as long as you think?
Are your fuses set correctly for your clock?
Unfortunately no about the oscilloscope.
I’m not sure what you mean by “checking the rate of output compares”. I have stripped the code right down to try and create a 1HZ LED with the timers i’ve set up but it’s x5 out.
I’ve seen fuses mentioned elsewhere but i’m not sure what they do or how to change them. When I divided the 16MHz by 1024 and then created a 100Hz interrupt I got an expected 1HZ LED.
an interrupt at 1MHz on a system that runs at 8/16/20 (?) MHz. Doesn’t leave many cpu cycles for other stuff. ie- You are getting interrupted every 8/16/20 instructions. How much of that is the interrupt overhead?
Your biggest problem is the 38.5 kHz signal. That’s a 26 usec period. Can you get the PWM hardware to help you out with this. ie- generate it in hardware without software supervision?
The rest of the pulse timing is relatively coarse and could be handled by a state machine that pokes various values into the output compare register. You may need to use two timers. ie- one to generate the 38.5 kHz and the other to turn it on/off at the right time.
The clk1 variable is 16 bit, and this is an 8 bit processor. It is being written by an ISR. You are reading it with interrupts turned on. You will
Source available. And circuit diagrams. Different AVR chip, but close enough.
You should set the OCs for the 38khz carrier. You can get IR 38khz receivers/detectors (at Radio Shack or other places) which will get the carrier going.