LoneCoder
LoneCoder

Reputation: 45

Moving through code using a Push Button switch

I am trying to incorporate a push button switch to control my software for a stepper motor.

I have three functions for the motor where it would rotate at three different angles (from 0-180 degrees forward, 90 degrees reverse and 90 reverse again back to 0) in a sequence, one after the other.

I would like to use one push button switch to step through these functions in an order.

Would anyone have any suggestions on how to do this? I am imagining I have to create a case statement but have been going in circles with no progress.

This is my current code below, at the moment pressing the switch will just run the first "if" function rotating the motor clockwise by 180 degrees:

#define F_CPU 1000000

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

#define A PINB0
#define C PINB1
#define B PINB4
#define D PINB3

int16_t i=0; // Auxiliary variable ()

void HalfStep(uint8_t step);
void Forward_180(void);
void Reverse_90(void);
void Reverse_90_2(void);

/********************************* MAIN ********************************/
int main(void)
{
    DDRB |= (1<<A) | (1<<B) | (1<<C) | (1<<D);  // Set output pins

    DDRB &= ~(1<<PINB5);        // Set input pin for switch 

    while(1)
    {

        if(bit_is_clear(PINB, 5))
        {
            Forward_180();              // Clockwise 180 degrees 
        }

        if(bit_is_clear(PINB, 5))       // Anti-clockwise 90 degrees
        {
            Reverse_90();
        }

        if(bit_is_clear(PINB, 5))       // Anti-clockwise 90 degrees again 
        {
            Reverse_90_2();
        }
    }

    return 0;
}

/***************** HALF STEPPING & DIRECITON FUNCTIONS *****************/
void HalfStep(uint8_t step)
{
    switch (step)
    {
        case 0: // whole number after i%8
        PORTB |= (1<<A) | (1<<D);
        PORTB &= ~((1<<B) | (1<<C));
        break;

        case 1: // 0.125
        PORTB |= (1<<A);
        PORTB &= ~((1<<B)|(1<<C)|(1<<D));
        break;

        case 2: // 0.25
        PORTB |= (1<<A)|(1<<C);
        PORTB &= ~((1<<B)|(1<<D));
        break;

        case 3: // 0.375
        PORTB |= (1<<C);
        PORTB &= ~((1<<A)|(1<<B)|(1<<D));
        break;

        case 4: // 0.5
        PORTB |= (1<<B)|(1<<C);
        PORTB &= ~((1<<A)|(1<<D));
        break;

        case 5: // 0.625
        PORTB |= (1<<C);
        PORTB &= ~((1<<A)|(1<<B)|(1<<D));
        break;

        case 6: // 0.75
        PORTB |= (1<<D)|(1<<C);
        PORTB &= ~((1<<A)|(1<<B));
        break;

        case 7: // 0.875
        PORTB |= (1<<D);
        PORTB &= ~((1<<A)|(1<<B)|(1<<C));
        break;
    }
}

void Forward_180(void)
{
    while (i<=48)
    {
        HalfStep(i%8);
        i++;
        _delay_ms(5);
    };
}

void Reverse_90(void)
{
    while (i>=24)
    {
        HalfStep(i%8);
        i--;
        _delay_ms(10);
    };
}

void Reverse_90_2(void)
{
    while (i>=0)
    {
        HalfStep(i%8);
        i--;
        _delay_ms(10);
    };
}

Upvotes: 1

Views: 557

Answers (1)

Marcos
Marcos

Reputation: 138

I would suggest using a state machine.

Something like this (I'm assuming you need to write some code to do a demo only):

/* States */
typedef enum EnumStates
{
    ST_IDLE,
    ST_FORWARD_180,
    ST_WAIT_FOR_STEP_2,
    ST_REVERSE_90,
    ST_WAIT_FOR_STEP_3,
    ST_REVERSE_90_2,
}
EState;

/* to know if the switch was pressed */
char _keypressed = 0;

/* state variable */
EState _state = ST_IDLE;

/* very simple keyboard process */
void SwitchTask(void)
{
    /* The keypressed flag will be valid for one cycle of the while loop */
    _keypressed = 0;
    if (bit_is_clear(PINB, 5))
    {
        _keypressed = 1; 
        /* this is a simple way to implement debouncing */
        /* I assume you do not have timing requirements */
        _delay_ms(100);
    }
}

/* demo task */
/* This task implements a simple state machine */
void DemoTask(void)
{
    switch(_state)
    {
        case ST_FORWARD_180:
            Forward_180();
            _state = ST_WAIT_FOR_STEP_2;
            break;
        case ST_REVERSE_90:
            Reverse_90();
            _state = ST_WAIT_FOR_STEP_3;
            break;
        case ST_REVERSE_90_2:
            Reverse_90_2();
            _state = ST_IDLE;
            break;
        case ST_IDLE:
        case ST_WAIT_FOR_STEP_2:
        case ST_WAIT_FOR_STEP_3:
            if (_keypressed > 0)
            {
                _state++;
            }
            break;
        default:
            break;
    }
}

int main(void)
{
    /* initialization */
    DDRB |= (1<<A) | (1<<B) | (1<<C) | (1<<D);  // Set output pins
    DDRB &= ~(1<<PINB5);        // Set input pin for switch 
    _keypressed = 0;

    while(1)
    {
        SwitchTask();
        DemoTask();
    }   
    return 0;
}

Upvotes: 1

Related Questions