2

I have a Parallax 27800 2-Axis Joystick wired up to a AVR 14 Pin 20MHz 8K 12A/D - ATtiny84. The joy stick sends out a x y analog signal. I have programmed the Attiny84 to read the signals and set one of the attiny84 pins (high or low) depending on the direction of the joystick. In this example, each pin is wired up to a LED. The problem I am having is there is about a 1 second delay for the LED to light. The Attiny84 has a built in 8MHz clock. Would connecting an external 20MHz crystal fix this issue?

int UD = 0;
int LR = 0;

int DWN = 0;
int UP = 1;
int LEFT = 4;
int RT = 5;

int LRMID = 0;
int UPMID = 0;
void setup(){

  pinMode(DWN, OUTPUT);
  pinMode(UP, OUTPUT);  
  pinMode(LEFT, OUTPUT); 
  pinMode(RT, OUTPUT);

  digitalWrite(DWN, LOW);
  digitalWrite(UP, LOW);
  digitalWrite(LEFT, LOW);
  digitalWrite(RT, LOW);

  //calabrate center
  LRMID = analogRead(3);
  UPMID = analogRead(2);
}

void loop(){

  UD = analogRead(2);
  LR = analogRead(3);
  // UP-DOWN
  if(UD < UPMID - 5){
   digitalWrite(DWN, HIGH);
  }else{
   digitalWrite(DWN, LOW);
  }

  if(UD > UPMID + 5){
   digitalWrite(UP, HIGH);
  }else{
   digitalWrite(UP, LOW);
  }
  // LEFT-RIGHT
  if(LR < LRMID-5){
   digitalWrite(LEFT, HIGH);
  }else{
   digitalWrite(LEFT, LOW);
  }

  if(LR > LRMID +5){
   digitalWrite(RT, HIGH);
  }else{
   digitalWrite(RT, LOW);
  }

  delay(100);


}
3
  • 1
    Have you tried removing the delay? – Ignacio Vazquez-Abrams Mar 13 '14 at 3:42
  • Do you have capacities somewhere in your circuit? – jfpoilpret Mar 13 '14 at 6:31
  • Thee delay(100) is only 1/10th of a second, and its there to give the code time to respond. And there are no caps in the circuit. Its pretty straight forward design. – PhillyNJ Mar 13 '14 at 11:25
3

While @alexan_e’s suggestion fixed your practical problem, I would argue that it did not address your root cause, which is that whatever board setting you’re working from in boards.txt assumes a clock rate of 8MHz, while in reality your fuses are set to boot the microcontroller at 1MHz. This caused your delay(100) to take 800ms, and was the entire reason for the slowdown.

Instead of fixing this at runtime, as aleman_e suggested, it seems more natural to me to bring your fuse settings into alignment with your compiler settings, using the “burn boot loader” Arduino command (which on Attinys generally does NOT burn a boot loader, but only sets the fuses to be in sync with the compiler settings).

If your application is not going to become much more complex, running at 1MHz might be a more efficient choice than running at 8MHz.

4
  • Thank you. I will give it a try. I thought I ran the "burn boot loader" at 8Mhz. I'll try again. – PhillyNJ Mar 13 '14 at 18:41
  • 1
    Fair point, although I originally suggested the runtime function so that he could check if that was indeed the problem, when we were not sure that this was the actual cause. In my reply I explained both methods to change the prescaler and just repeated the same suggestion I made in the comments because he asked me to post it as an answer, but it didn't occur to me to make a suggestion about changing the fuse. – alexan_e Mar 13 '14 at 20:48
  • 1
    @alexan_e I did not mean to disparage your runtime function (It did, after all, help diagnose the issue correctly), I was merely arguing that it was not necessarily the best solution for a permanent fix. – microtherion Mar 13 '14 at 21:04
  • Running the boot loader did indeed fix the issue. – PhillyNJ Mar 14 '14 at 22:19
1

Several AVR devices including ATtiny 84, have a clock prescaler that can be used to lower the core frequency.

The divider can be controlled two ways.

The first way is the CKDIV8 fuse that controls the default loaded value to CLKPR (Clock prescale register) to either

  • fuse disabled: Clock Division Factor 1 (clk/1)
  • fuse enabled: Clock Division Factor 8 (clk/8)

The fuse is enabled by default and applies the clk/8 setting, it can be changed with a programmer.

The second way is by changing the prescaler value during runtime. All you need to do is to include the following header

#include <avr/power.h>

and call one of following functions with the appropriate value you want to use

   clock_prescale_set(clock_div_1);    // Clock Division Factor 1
   clock_prescale_set(clock_div_2);    // Clock Division Factor 2
   clock_prescale_set(clock_div_4);    // Clock Division Factor 4
   clock_prescale_set(clock_div_8);    // Clock Division Factor 8
   clock_prescale_set(clock_div_16);   // Clock Division Factor 16
   clock_prescale_set(clock_div_32);   // Clock Division Factor 32
   clock_prescale_set(clock_div_64);   // Clock Division Factor 64
   clock_prescale_set(lock_div_128);   // Clock Division Factor 128
   clock_prescale_set(clock_div_256);  // Clock Division Factor 256

power.h manual

Note that the above functions can be applied at any part of the program, for example you can lower the cpu frequency to reserve battery and then set it higher again for intensive tasks. Just be aware that all peripheral will work with the divided clock too so PWM, timers, SPI, UART etc will all be affected.

If the problem you are facing is caused by the clock divider being in the /8 setting then you can change it at runtime.

Add the header at the start of the sketch

#include <avr/power.h>

And then set the prescaler value to 1 at the start of setup()

void setup() {
               clock_prescale_set(clock_div_1);  // set the clock prescaler to /1
}
2
  • Also note that changing the prescaler will affect delay() and millis(), since they assume a (predetermined) fixed clock frequency. – Ignacio Vazquez-Abrams Mar 13 '14 at 14:09
  • @IgnacioVazquez-Abrams The mentioned functions are based on the use of timers, and I mentioned that they get affected. In any case it's worth pointing for users that are not aware of that. – alexan_e Mar 13 '14 at 14:14
0
  • Are you absolutely sure your AVR is running at 8MHz, because default I believe it is scaling the 8MHz internal RC-oscillator down to 1MHz system clock. Change your F_CPU macro to 1MHz to see what happens.
7
  • ..the internal 16MHz clock What are you referring to? The only available internal clocks for the mentioned device are 125KHz and 8MHz – alexan_e Mar 13 '14 at 10:15
  • 1
    I'm probably confused with ATtiny85 which does. @alexan_e – jippie Mar 13 '14 at 10:37
  • @PhilVallone If the problem is caused by the clock divider (CKDIV8 fuse) then you can set the divider to 1 in run time by including power.h #include <avr/power.h> and using clock_prescale_set(clock_div_1); in setup(). Although if this was related to the clock divider I would have expected problems during programing too, caused by the low UART BAUD rate. – alexan_e Mar 13 '14 at 11:14
  • 1
    @jippie - once the code is was uploaded I burned the bootloader at 8Mhz. Would I be doing harm to the chip if I try the bootloader again? – PhillyNJ Mar 13 '14 at 11:28
  • @alexan_e - I'll try your suggestions and report back – PhillyNJ Mar 13 '14 at 11:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.