Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Problem in keypad programming

Status
Not open for further replies.

NIKO BELLIC

Newbie level 6
Joined
Aug 1, 2011
Messages
14
Helped
6
Reputation
12
Reaction score
5
Trophy points
1,283
Location
Kansas City, MO
Activity points
1,389
Hi all,
I want to operate a stepper motor in different modes using single keypad. That is, based on Full step, Half step, high torque, low torque and its direction. For this, in proteus ISIS, I've created a keypad consisting of all those operations. With my basic knowledge, I've prepared a code for it. But, that ain't working properly. The main problem is, once I press a key in the keypad, it starts doing that corresponding operation but if I press another key it is just ignoring... I could not able to program it properly... Can someone help me..!!

Microcontroller - ATmega 16
Compiler - WinAVR 20100110

Code:
// This program is used to control the stepper motor in desired direction and torque as given by inputs

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

#define keypad PORTA
#define stepper PORTD

void main()
{
 DDRA=0x0F;					// configuring keypad pins 
 DDRD=0xFF;					// configuring ULN2003A pins as output
 
 keypad=0xF0;
 
 scan_keypad();
}

scan_keypad()
{
 unsigned char value;
 while(1)
 {
  keypad=0xF0;
  value=PINA;
  if(value!=0xF0)
  {
   check_row_1();
   check_row_2();
   check_row_3();
   check_row_4();
  }
 }
}

check_row_1()
{
 keypad=0b11111110;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 full_step_high_torque_left();
 if(bit_is_clear(PINA,PA5))
 full_step_high_torque_right();
}

check_row_2()
{
 keypad=0b11111101;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 full_step_low_torque_left();
 if(bit_is_clear(PINA,PA5))
 full_step_low_torque_right();
}

check_row_3()
{ 
 keypad=0b11111011;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 half_step_left();
 if(bit_is_clear(PINA,PA5))
 half_step_right();
}

check_row_4()
{
 keypad=0b11110111;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 stop();
 if(bit_is_clear(PINA,PA5))
 ;
}

full_step_high_torque_left()
{
 while(1)
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
 }
}

full_step_high_torque_right()
{
 while(1)
 {
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
 }
}

full_step_low_torque_left()
{
 while(1)
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
 }
}

full_step_low_torque_right()
{
 while(1)
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
 }
}

half_step_left()
{
 while(1)
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
 }
}

half_step_right()
{
 while(1)
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
 }
}

stop()
{
 while(1)
 stepper=0x00;
}


Circuit Diagram:
Unipolar_Stepper_Motor.jpg
 

as soon as you enter any of the step functions you can never get out because you use while(1) {} and it is an endless loop, the execution will never return to main to scan the keys

---------- Post added at 12:34 ---------- Previous post was at 12:20 ----------

You can probably use while (PINA==0xF0) so that it exits when a key is pressed

also add in each check_row an else statement, like this

if(bit_is_clear(PINA,PA4)) full_step_high_torque_left();
else if(bit_is_clear(PINA,PA5)) full_step_high_torque_right();
 

You can probably use while (PINA==0xF0) so that it exits when a key is pressed

it is not working.. now, the motor is not even running.. may be because, when we press and release a key PINA automatically equals 0xF0 or some other value...!!
 

in your code you have if(value!=0xF0) so the default value when nothing is pressed is 0xF0,
in that case the loop while (PINA==0xF0) will execute as long as nothing is pressed so when you press the button for the first time it will call a step function that will execute in a loop until a button is pressed but I think I can see the problem, when the step function is called the key is not released yet so the while condition is false and gets out of the function.

modify this also

Code:
scan_keypad()
{
 unsigned char value;
 while(1)
 {
  keypad=0xF0;
  value=PINA;
  if(value!=0xF0)
  { [COLOR="#0000FF"]lastvalue=value;[/COLOR]
   check_row_1();
   check_row_2();
   check_row_3();
   check_row_4();
  }
 }
}

make last value a global variable and in every step function use while ((PINA==0xF0) | (PINA==lastvalue)) { insert here the steps }

this is still not the correct way but I think it can work, the best way in my opinion is to use a timer and poll the keyboard every 50ms or 100ms and then use that value in a case statement to execute different steps sequence depending on the key value.
 

It is also not working....

...the best way in my opinion is to use a timer and poll the keyboard every 50ms or 100ms and then use that value in a case statement to execute different steps sequence depending on the key value.

this sounds interesting... I think we need to implement timer interrupts. Can you give a brief explanation about this...
 

can you please post your modified code because I think it should work.

in which part you want explanation?
have you used timer interrupts before?
 

Modified Code...
Code:
#include <avr/io.h>
#include <util/delay.h>

#define keypad PORTA
#define stepper PORTD

char lastvalue;

void main()
{
 DDRA=0x0F;					// configuring keypad pins 
 DDRD=0xFF;					// configuring ULN2003A pins as output
 
 keypad=0xF0;
 
 scan_keypad();
}

scan_keypad()
{
 unsigned char value;
 while(1)
 {
  keypad=0xF0;
  value=PINA;
  if(value!=0xF0)
  {
   lastvalue=value;
   check_row_1();
   check_row_2();
   check_row_3();
   check_row_4();
  }
 }
}

check_row_1()
{
 keypad=0b11111110;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 full_step_high_torque_left();
 else if(bit_is_clear(PINA,PA5))
 full_step_high_torque_right();
}

check_row_2()
{
 keypad=0b11111101;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 full_step_low_torque_left();
 else if(bit_is_clear(PINA,PA5))
 full_step_low_torque_right();
}

check_row_3()
{ 
 keypad=0b11111011;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 half_step_left();
 else if(bit_is_clear(PINA,PA5))
 half_step_right();
}

check_row_4()
{
 keypad=0b11110111;
 _delay_ms(4);
 if(bit_is_clear(PINA,PA4))
 stop();
 else if(bit_is_clear(PINA,PA5))
 ;
}

full_step_high_torque_left()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
 }
}

full_step_high_torque_right()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 {
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
 }
}

full_step_low_torque_left()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
 }
}

full_step_low_torque_right()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
 }
}

half_step_left()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
 }
}

half_step_right()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 {
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
  stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
  _delay_ms(50);
 }
}

stop()
{
 while((PINA==0xF0)|(PINA==lastvalue))
 stepper=0x00;
}

I never used any interrupts before, I need explanation about using timers and case statements as you stated above...
 

I mean something like

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

#define keypad PORTA
#define stepper PORTD

// global variables
uint8_t overflow_counter;
uint8_t pressed_key=0;
// 0=stop();
// 1=full_step_high_torque_left()
// 2=full_step_high_torque_right();
// 3=full_step_low_torque_left();
// 4=full_step_low_torque_right();
// 5=half_step_left();
// 6=half_step_right();
// 7=full_step_low_torque_left();
// 8=full_step_low_torque_right();


scan_keypad()
{
    unsigned char value;

    keypad=0xF0;
    value=PINA;
    if(value!=0xF0)
    {
        check_row_1();
        check_row_2();
        check_row_3();
        check_row_4();
    }
}

check_row_1()
{
    keypad=0b11111110;
    _delay_ms(4);
    if(bit_is_clear(PINA,PA4))
        pressed_key=1;
    else if(bit_is_clear(PINA,PA5))
        pressed_key=2;
}

check_row_2()
{
    keypad=0b11111101;
    _delay_ms(4);
    if(bit_is_clear(PINA,PA4))
        pressed_key=3;
    else if(bit_is_clear(PINA,PA5))
        pressed_key=4;
}

check_row_3()
{
    keypad=0b11111011;
    _delay_ms(4);
    if(bit_is_clear(PINA,PA4))
        pressed_key=5;
    else if(bit_is_clear(PINA,PA5))
        pressed_key=6;
}

check_row_4()
{
    keypad=0b11110111;
    _delay_ms(4);
    if(bit_is_clear(PINA,PA4))
        pressed_key=0;
    else if(bit_is_clear(PINA,PA5))
        ;
}

full_step_high_torque_left()
{
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
}

full_step_high_torque_right()
{
    stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
}

full_step_low_torque_left()
{
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
}

full_step_low_torque_right()
{
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
}

half_step_left()
{
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
}

half_step_right()
{
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(1<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(0<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(1<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(0<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(1<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(0<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
    stepper=(1<<PD0)|(0<<PD1)|(0<<PD2)|(1<<PD3);
    _delay_ms(50);
}

stop()
{
    stepper=0x00;
}

// Timer 0 overflow interrupt service routine
ISR (TIMER0_OVF_vect)
{
    if (overflow_counter==2)
    {   overflow_counter=0; 	// reset variable
        scan_keypad(); 		//scan the keys
    }
    else overflow_counter++;
}

void main(void)
{

    DDRA=0x0F;					// configuring keypad pins
    DDRD=0xFF;					// configuring ULN2003A pins as output

    keypad=0xF0;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
    TCCR0=0x05;
    TCNT0=0x00;
    OCR0=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK=0x01;

// Global enable interrupts
    sei();

    while (1)
    {
        // Place your code here

        switch (pressed_key) {
        case 0:
            stop();
            break;
        case 1:
            full_step_high_torque_left();
            break;
        case 2:
            full_step_high_torque_right();
            break;
        case 3:
            full_step_low_torque_left();
            break;
        case 4:
            full_step_low_torque_right();
            break;
        case 5:
            half_step_left();
            break;
        case 6:
            half_step_right();
            break;
        case 7:
            full_step_low_torque_left();
            break;
        case 8:
            full_step_low_torque_right();
        }
    };
}

the interrupt is executing about every 100ms (assuming 8MHz cpu clock) and checks if a key is pressed, then is also a switch/case statement inside main that executes the step function depending on the button pressed

Alex
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top