Kevin Demon Melon Lee
Kevin Demon Melon Lee

Reputation: 11

Why isn't the 0 on my keypad being recognised?

I was trying to finish my project using an physical OUSB-IO board on a ATmega32A board using Microchip Studio's C to create a stopwatch and timer on the same LED board to indicate that it's working. Every detail works from switching a timer to stopwatch and back, setting the timer up (besides 0 which is the major issue due to the fact I can't make it seconds and only minutes) and having a reset/stop button to stop the whole program.

Could anyone help me understand or show me why my 0 doesn't work on the keypad when every button works?

#define F_CPU 1000000UL  // 1 MHz clock speed
#include <avr/io.h>
#include <util/delay.h>

// Define keypad and LED ports
#define KEYPAD_PORT PORTC
#define KEYPAD_DDR  DDRC
#define KEYPAD_PIN  PINC
#define LED_PORT PORTB
#define LED_DDR  DDRB

// Stopwatch/Timer variables
uint8_t mode = 0;  // 0 = stopwatch, 1 = timer
uint16_t time_left = 0;  // Time remaining (timer) or elapsed (stopwatch)
uint8_t is_running = 0;  // Running flag for the timer/stopwatch
uint8_t flash_leds = 0;  // Flag to flash LEDs when timer ends
uint8_t digit_count = 0;  // Track input digits
uint8_t input_digits[4];  // Store digits for MM:SS input

// Keypad initialization
void keypad_init() {
    KEYPAD_DDR = 0xF0;  // Upper 4 bits as output, lower 4 bits as input
    KEYPAD_PORT = 0x0F; // Enable pull-up resistors for the lower 4 bits
}

// Scan the keypad and return the key pressed
char keypad_scan() {
    const char keys[4][4] = {
        {'1', '2', '3', 'A'},
        {'4', '5', '6', 'B'},
        {'7', '8', '9', 'C'},
        {'*', '0', '#', 'D'}
    };

    for (uint8_t row = 0; row < 4; row++) {
        KEYPAD_PORT = ~(1 << (row + 4));  // Ground one row at a time
        _delay_ms(5);  // Debounce delay

        for (uint8_t col = 0; col < 4; col++) {
            if (!(KEYPAD_PIN & (1 << col))) {  // Check if the key is pressed
                _delay_ms(20);  // Additional debounce delay
                while (!(KEYPAD_PIN & (1 << col)));  // Wait for key release
                return keys[row][col];  // Return the pressed key
            }
        }
    }
    return 0xFF;  // No key pressed
}

// Initialize LEDs
void led_init() {
    LED_DDR = 0xFF;  // Set all PORTB pins as outputs (for LEDs)
    LED_PORT = 0x00; // Turn off all LEDs initially
}

// Display the time on the LEDs
void display_time(uint16_t time) {
    uint8_t minutes = time / 60;
    uint8_t seconds = time % 60;
    LED_PORT = (minutes << 4) | (seconds & 0x0F);  // Show minutes and seconds
}

// Convert MM:SS format into total seconds
uint16_t convert_mmss_to_seconds() {
    uint8_t minutes = input_digits[0] * 10 + input_digits[1];
    uint8_t seconds = input_digits[2] * 10 + input_digits[3];
    return minutes * 60 + seconds;  // Total time in seconds
}

// Flash all LEDs when the timer hits zero
void flash_all_leds() {
    LED_PORT ^= 0xFF;  // Toggle all LEDs
    _delay_ms(500);  // 500ms delay for flashing
}

// Main function
int main(void) {
    led_init();     // Initialize LEDs
    keypad_init();  // Initialize the keypad

    while (1) {
        char key = keypad_scan();  // Get the key input

        if (key != 0xFF) {  // If a key is pressed
            // Handle only number inputs (including 0) for setting the time
            if ((key >= '0' && key <= '9') && digit_count < 4) {  // Treat '0' as input along with '1-9'
                input_digits[digit_count++] = key - '0';  // Store the digit, including '0'
                display_time(convert_mmss_to_seconds());  // Show entered time
            }

            // Switch between Timer and Stopwatch modes
            if (key == '*') {
                mode = !mode;  // Toggle the mode
                LED_PORT = (mode == 1) ? 0x01 : 0x02;  // Indicate mode (Timer: LED 0, Stopwatch: LED 1)
            }

            // Start/Stop the timer or stopwatch
            if (key == 'A') {
                if (!is_running) {
                    if (mode == 1) {
                        time_left = convert_mmss_to_seconds();  // Set time_left for Timer mode
                        digit_count = 0;  // Reset digit count
                    } else {
                        time_left = 0;  // In Stopwatch mode, start from 0
                    }
                }
                is_running = !is_running;  // Toggle running state
            }

            // Stop and reset Timer/Stopwatch
            if (key == 'C') {
                time_left = 0;
                is_running = 0;
                flash_leds = 0;
                LED_PORT = 0x00;  // Turn off all LEDs
                digit_count = 0;  // Reset digit count
            }
        }

        // Timer/Stopwatch logic
        if (is_running) {
            _delay_ms(1000);  // 1-second delay

            if (mode == 1 && time_left > 0) {  // Timer mode: countdown
                time_left--;
            } else if (mode == 0) {  // Stopwatch mode: count up
                time_left++;
            }

            display_time(time_left);  // Update the time on the LEDs

            // Check if timer has reached zero
            if (mode == 1 && time_left == 0 && is_running) {
                flash_leds = 1;  // Start flashing LEDs when timer hits 0
                is_running = 0;  // Stop the timer
            }
        }

        // Flash LEDs when the timer hits zero
        if (flash_leds && mode == 1) {
            flash_all_leds();  // Flash all LEDs when timer hits 0
        }
    }
}

I've tried isolating the 0 button and making it a function like A, * and #, but it doesn't work, I've tried making it a normal key_pad scan with 1-9, but it doesn't work. When i press 0 at first the button doesnt register so i would click on 1-9 to create the timer after i set the timer using 1-9, Button 0 would then only pause the timer and nothing else.

Upvotes: 1

Views: 80

Answers (0)

Related Questions