I've got custom PCB with Atmega328 without oscilator (fuses are set for internal 8 MHz). I've got code which works on Arduino, but it looks like i've got a problem with IR communication on my custom device. Is it a problem with program? My device doesnt respond to any codes from remote, everything else works fine.
The obvious answer is, the library likely depends on a certain CPU clock frequency. So look into the library for clues about that, ideas about fixing it. There might be less obvious problems. Difficult to say without more investigation. Is millis() accurate?
I cant check millis on PCB, when IRremote doesnt work at all It was working fine on Arduino. I am gonna check library files.
Why would different CPU frequency destroy my whole program? I understand that something may work different (slower, glitched etc), but in my case device doesnt react on IR codes at all.
Oh man @aarg, thats crazy, but my program works perfectly fine after changing 1 value in library files (from 16k to 8k of course). Thank you very much!
hardtofindanynick:
Why would different CPU frequency destroy my whole program? I understand that something may work different (slower, glitched etc), but in my case device doesnt react on IR codes at all.
The IR pulses consist of specific intervals of a carrier frequency (typically around 38 kHz). When you are using the 8 MHz internal RC oscillator instead of an external 16 MHz crystal or resonator, your processor is running at half speed. That means that the timer used to generate the 38 kHz carrier will be generating a 19 kHz carrier. If you send a 19 kHz carrier, no normal IR receiver will be able to sense the signal. The timer will also be sampling the input every 100 microseconds instead of the usual 50 microseconds. All of the pulses will appear to be half the length of what is expected so input won't be recognized.
The IRremote library should have used the 'F_CPU' value set as part of the compiling process. That would adjust the timing for the target board.
johnwasser:
The IRremote library should have used the 'F_CPU' value set as part of the compiling process. That would adjust the timing for the target board.
johnwasser:
The IR pulses consist of specific intervals of a carrier frequency (typically around 38 kHz). When you are using the 8 MHz internal RC oscillator instead of an external 16 MHz crystal or resonator, your processor is running at half speed. That means that the timer used to generate the 38 kHz carrier will be generating a 19 kHz carrier. If you send a 19 kHz carrier, no normal IR receiver will be able to sense the signal. The timer will also be sampling the input every 100 microseconds instead of the usual 50 microseconds. All of the pulses will appear to be half the length of what is expected so input won't be recognized.
The IRremote library should have used the 'F_CPU' value set as part of the compiling process. That would adjust the timing for the target board.
It makes sense, thanks for explaining.
It might also be that the OP didn't update F_CPU.
I added "F_CPU 8000000; on the top of my program, i hope its enough to make it work properly.
This is what I tend to do when I have an arduino with a 16MHz crystal, but need to run it at 4 or 8 MHz for lower voltage operation, and that is is to (a) ensure that the desired effective clock frequency is selected by choosing an appropriate board in the IDE (or creating your own entry in boards.txt) and (b) using the prescaler to reduce the effective clock frequency down from 16MHz to either 8 or 4 MHz.
It has the advantage that you benefit from the accuracy of a crystal and can still use a bootloader compiled for 16MHz, but keep a low clock rate for battery operation. Timing functions (for correctly written applications) should still work.
This code then goes in setup():
// prescaler from http://forum.arduino.cc/index.php?topic=271364.0
// combined with "board" and selected clock frequency.
// locate early in script
// note: this block is to allow a 16MHz crystal to be used with different effective clock speeds.
// If you are using another crystal value adapt or delete this block.
if (F_CPU == 8000000L) clock_prescale_set(clock_div_2);
else if (F_CPU == 4000000L) clock_prescale_set(clock_div_4);
else if (F_CPU == 2000000L) clock_prescale_set(clock_div_8);
else if (F_CPU == 1000000L) clock_prescale_set(clock_div_16);
hardtofindanynick:
It makes sense, thanks for explaining.
I added "F_CPU 8000000; on the top of my program, i hope its enough to make it work properly.
It will if it is defined with an #ifdef/#ifndef elsewhere