0

The code is for LED cube and I want to add new feature. When someone click on pushbutton which is conected to PORTB0 current light effect should be changed.

I try sommething but it doesn't work.

The program is for ATmega16, and code is written in Atmer Studio 6

code

2 Answers2

0
void delay_ms(uint16_t x)
{
 uint8_t y, z;
  for ( ; x ; x--){  
    for ( y = 0 ; y < 90 ; y++)
     {   
      for ( z = 0 ; z < 6 ; z++)
      {   
          if(PINB)
              {   
                  ++i%=4;                  
                  return;                 
              }    
       asm volatile ("nop");

       }              
    }
}
perilbrain
  • 7,961
  • 2
  • 27
  • 35
0

What does the circuit connected to B0 look like?

Assuming one side of the switch goes to B0 and the other goes to ground, your direction and pullup values are good, but your if statement should be looking for bit 0 of PINB to go from 1 to 0 when the button is pressed. With the pullup turned on, the bit will be 1 when the button isn't pressed and 0 when it is.

In your code you are treating the input as an "edge" but really it's a "level" What I mean by that is that pressing the button changes the input signal for a long period of time from the perspective of the CPU. You want to change the effect on the transition

There is another issue here, which is switch debouncing. When the switch is pressed, it doesn't go directly from off to on. There is noise during the transition which will look like many button presses to your code.

Debouncing can be done in hardware or software. In software, I would do something like this in your inner loop in delay_ms:

static unsigned int debounce; 
static const unsigned int presscount = 500;
if ((PINB&1)==0) { // switch is pressed
    if (debounce < presscount ) {
        ++debounce;
    }
} 
else {
    if (debounce > 0) {
        --debounce;
    }
}
if (debounce == presscount ) {
    // switch has been pressed long enough 
    debounce = 0; // reset
    i = (i+1)%4;
    return;
}

This will increment the effect at most once every 500 loop times. If you keep holding the button the effects will continue to change. You might want to modify the code so that it doesn't increment the effect again until after the switch has been off for a while, so that each press does only one increment no matter how long it's held. For the code above you can play around with the 'presscount' constant to see what it does.

Hope that helps.

kday
  • 60
  • 4
  • This help me to wrote this inside delay_ms `unsigned short int b_was=1; if ((PINB&1)==0 && b_was==1) b_was=0; else if ( PINB&1==1 && b_was==0) { b_was=1; i = (i+1)%4; launch_effect(i); }` I wondering if this can be done somehow without losing the meaning of delay_ms function? –  Aug 17 '12 at 17:10
  • Ideally the delay_ms function would do nothing but delay. You could call delay_ms(1) in the main loop and interleave that with your pin checking. This would be cleaner. Your b_was idea is on the right track but you still need to account for the debouncing, unless it's done in hardware already. – kday Aug 17 '12 at 19:14