0
\$\begingroup\$

so what I am trying to do is that I am trying to make the led blink for a certain number of times before it turns off. I want to avoid using delays so I tried
utilizing the interrupt and I also used a placeholder value like x to count the number of times it goes through interrupt, so one it reaches that value it will turn off, however I am having trouble getting it to work, any ideas

            /*
             * GccApplication3.c
             *
             * Created: 2015-04-01 6:13:58 AM
             *  Author: Bangladesh
             */ 


            #include <avr/io.h>   
            #include <util/delay.h> 
            #include <avr/interrupt.h> 
            #define stp_led PB0 
            #define dir_led PB1
            #define led_port PORTB
            #define led_ddr DDRB
            #define F_CPU 16000000UL 
            int x = 0;


            int main(void)
            { 
                ///////////////////////////////////////////////////////
                led_ddr |= (1 << stp_led); //enable led as an output pin  
                led_ddr |= (1 << dir_led);   
                //led_port |= (1<<stp_led);   
                led_port |= (1<<dir_led); 
                ///////////////////////////////////////////////////////
                TCCR1B |= (1 << WGM12);  // configuring timer 1 for ctc mode
                OCR1A = 15625;
                TIMSK1 |= (1 << OCIE1A); // enable ctc interrupt

                TCCR1B |= ((1 << CS12) | (1<< CS10)); //Start at 1024 prescaler 

                sei(); //Enable global interrupts

                 //Sets ctc compare value to 1hz at 1mhz AVR clock, with prescaler of 64




             while(1)  
                {  

                } 
            } //end of while loop 


            ISR(TIMER1_COMPA_vect)
            {   

                function_details (10, 1);

            }

            void function_details (stp,dir){  

                if (dir == 1){ 
                    led_port |= (1 << dir_led); 
                } 
                else if (dir == 0){ 
                    led_port &= ~ (1 << dir_led);
                }    
            while (1){
                led_port ^= (1 << stp_led);
                if (x == stp){ 
                    led_port &= ~ (1 << stp_led);  
                    return 0;
                    }  
                    x++; 
                }

            }
\$\endgroup\$
5
  • \$\begingroup\$ I tried many things to this work including for loops, multiple if statements, and in this case a while loop however nothing seems to be working \$\endgroup\$
    – Redrachet2
    Apr 22, 2015 at 18:50
  • 1
    \$\begingroup\$ Your ISR appears to call a function with a while(1){} in it and no breaks- it will never return. \$\endgroup\$ Apr 22, 2015 at 19:00
  • \$\begingroup\$ Why do you have an infinite loop in the ISR? And if you want to blink an LED without a delay, consider the way I do it using an Arduino. Run a timer that generates an interrupt every 1ms to increment a location in memory. That gives you a 1ms accumulating clock to reference in your code. To make an LED blink for 1 second on and 1 second off you simply setup a loop in main to toggle the LED every 1000 counts. Easy to implement using a few if statements and you can use that accumulating timer for as many software timers as you have memory for. \$\endgroup\$
    – Mister Tea
    Apr 22, 2015 at 19:05
  • \$\begingroup\$ There isn't actually an infinite loop there - notice the if() statement contains a return;, so when x==stp, it will break the loop by returning from the function. That said, there are two problems with that. The first is that x is not set to 0 before the function call, so you won't necessarily get stp blinks as it will start counting from whatever the last x was - in the code above first it will be 10 blinks then INT_MAX-10 after that. Secondly, x should either be local to that function, or set volatile. Now granted the approach is not a good design practice. \$\endgroup\$ Apr 22, 2015 at 19:43
  • \$\begingroup\$ Thank you so much however if it isn't too much of an inconvience could you please explain to me what is volatile how it works in simple terms? \$\endgroup\$
    – Redrachet2
    Apr 22, 2015 at 22:10

3 Answers 3

3
\$\begingroup\$

Try something like this

     ISR(TIMER1_COMPA_vect)
     {   
           if(led_blink_count < 10)
           {
                //Toggle the led state
                led_blink_count++;
           }             
     }

Have the timer trigger at the frequency you want the led to blink at. Set led_blink_count to 0 to restart the blinking.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Also note that led_blink_count needs to be defined as volatile and outside of any functions, so: volatile uint8_t led_blink_count; \$\endgroup\$
    – Golaž
    Apr 22, 2015 at 19:31
  • \$\begingroup\$ @Redrachet2 if this solved your question you can select it as the answer. \$\endgroup\$
    – Axis
    Apr 22, 2015 at 23:23
1
\$\begingroup\$

I am not an AVR programmer but I do for ARM/PIC, so I will put it as barely pseudo-code.

First of all I want to note some things:

-ISR's always should be as short as possible and if can be avoided they should not call functions.

-Using an ISR which blocks the execution until everything is done in this case does not make sense, if you do that then you get the same result as not using an interrupt and using delays.

-Your code has a loop which I cannot understand, you are inverting the port bit at stp_led, then you mask it X times... it's done in just one call so all the cycle will happen in just an interrupt.

So, try to do something like this:

volatile unsigned char currentBlink = 0xFF;

int main(void)
{

    unsigned char processedLastBlink = 255;

    SetupTimer();
    SetupLed();

    ResetBlink();

    while(1)
    {
        if(currentBlink != processedLastBlink)
        {
            LedOutput(currentBlink % 2 ? 0 : 1);
            processedLastBlink = currentBlink
        }

        //You can restart blinking whenever you want with ResetBlink();
    }

    ISR(TIMER1_COMPA_vect)
    {
        if(++currentBlink == 20)
            DisableBlink();
    }

    void SetupTimer(void)
    {
        //Configure timer to fire an interrupt every half a cycle
        //If you want a blink per second configure it to interrupt each 500ms

    }

    void SetupLed(void)
    {
         //Configure GPIO for led as output
         LedOutput(0);
    }

    void ResetBlink(void)
    {
        ResetTimer; //Set timer counter to 0
        currentBlink = 0xFF;
        EnableInterrupts; //sei()?
    }

    inline void DisableBlink(void)
    {
        DisableInterrupts; //sdi()?
    }

    void LedOutput(unsigned char value)
    {
        //Set LED's GPIO to the given value (1 or 0)
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ You can easily toggle the pin with: LED_PORT ^= (1 << LED_PIN)... \$\endgroup\$
    – Golaž
    Apr 23, 2015 at 9:54
0
\$\begingroup\$

Alright I did a bit of research and a friend told me to use boolean values. So lets say if I reach a certain number of increments I can use a boolean value to the x value from incrementing. Here is the code:

         /*
         * avr_cnc.c
         *
         * Created: 2015-04-01 6:13:58 AM
         *  Author: Alvi
         */ 


        #include <avr/io.h>    
        #include <stdio.h>
        #include <util/delay.h> 
        #include <avr/interrupt.h>  
        //axis bools

        //////////////////
        // x-axis
        #define stp_x_led PB0
        #define dir_x_led PB1  

        ////////////// 
        // y-axis
        #define stp_y_led PD6
        #define dir_y_led PD7 

        ////////////  
        // z-zxis  
        #define stp_z_led PD4 
        #define dir_z_led PD5

        // PORTB 
        #define led_portx PORTB
        //////////// 
        /// PORTD
        #define led_portyz PORTD 
        ///////////  
        // PORTC 
        //#define led_portz PORTC 
        // DDR////////
        #define led_x_ddr DDRB  
        #define led_y_ddr DDRD 
        #define led_z_ddr DDRD
        #define F_CPU 16000000UL 


        int x_counter = 0; 
        int x_boolean = 1; 
        int y_counter = 0; 
        int y_boolean = 1;
        int z_counter = 0; 
        int z_boolean = 1;  


        int x_enable = 1; 
        int y_enable = 1; 
        int z_enable = 1;



        int main(void)
        {  

            ////// DDR setups /////////////////////////////////////////////////
            led_x_ddr |= ((1 << stp_x_led) | (1 << dir_x_led));   
            led_y_ddr |= ((1 << stp_y_led) | (1 << dir_y_led)); 
            led_z_ddr |= ((1 << stp_z_led) | (1 << dir_z_led));
            ///////////////////////////////////////////////////////////

            TCCR1B |= (1 << WGM12);  // configuring timer 1 for ctc mode
            OCR1A = 4678;
            TIMSK1 |= (1 << OCIE1A); // enable ctc interrupt

            TCCR1B |= ((1 << CS12) | (1<< CS10)); //Start at 1024 prescaler 

            sei(); //Enable global interrupts

             //Sets ctc compare value to 1hz at 1mhz AVR clock, with prescaler of 64




         while(1)  
            {  

            } 
        } //end of while loop 


        ISR(TIMER1_COMPA_vect)
        {   
            ///////Define which stepper, direction and how many steps in this code
            x_stepper(1,10, 1);  
            y_stepper(1,20,1); 
            z_stepper(0,30,1); 
            ////////////////////////////////////////////////////////////////////
        }

        void x_stepper (axis_x,stp_x,dir_x){ 

            // checks if user enabled x-axis 
            if (axis_x == x_enable){
                //direction
                if (dir_x == 1){ 
                    led_portx |= (1 << dir_x_led); 
                } 
                else if (dir_x == 0){ 
                    led_portx &= ~ (1 << dir_x_led); 
                } 
                ///////////////////////////////
                //stepper logic
                led_portx ^= (1 << stp_x_led);
                    if (x_counter >= stp_x){ 
                        led_portx &= ~ (1 << stp_x_led);  
                        x_boolean = 0; 
                    }      
                if (x_boolean == 1){
                x_counter ++;
                }   
            //////////////////////////////
            }   
        }


        void y_stepper (axis_y,stp_y,dir_y){ 

            // checks if user enabled y-axis 
            if (axis_y == y_enable){
                //direction
                if (dir_y == 1){ 
                    led_portyz |= (1 << dir_y_led); 
                } 
                else if (dir_y == 0){ 
                    led_portyz &= ~ (1 << dir_y_led); 
                }  
                ///////////////////////////////
                //stepper logic
                led_portyz ^= (1 << stp_y_led);
                    if (y_counter >= stp_y){ 
                        led_portyz &= ~ (1 << stp_y_led);  
                        y_boolean = 0; 
                    }      
                if (y_boolean == 1){
                y_counter ++;
                }   
                //////////////////////////////
            }  
        }

         void z_stepper (axis_z,stp_z,dir_z){ 

            // checks if user enabled z-axis 
            if (axis_z == z_enable){
                //direction
                if (dir_z == 1){ 
                    led_portyz |= (1 << dir_z_led); 
                } 
                else if (dir_z == 0){ 
                    led_portyz &= ~ (1 << dir_z_led); 
                } 
                ///////////////////////////////
                //stepper logic
                led_portyz ^= (1 << stp_z_led);
                    if (z_counter >= stp_z){ 
                        led_portyz &= ~ (1 << stp_z_led);  
                        z_boolean = 0; 
                    }      
                if (z_boolean == 1){
                z_counter ++;
                }   
                //////////////////////////////
            }
        } 
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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