1

I'm trying to make a type of Arduino alarm clock, which when the time I inputed is equals to the current time, a servo will turn on my lights. It basically consists of a Keypad, an RTC DS1307 and a TM1637 seven segment display. The basic idea is that the RTC module would print time to the display until I decide to write something on the keypad, which would clear the time on the display to let me write the alarm. My problem is that the display manages to both show time on the display and write to the display but this only works on separate code, not together.

The keypad has a '*' and '#' character, when i decide to write the time i want the lights to turn on, after writing it i press the '*' character to save that time and then the idea would be to compare the time written and the present time, if i press '#', then all would be canceled and the RTC module would continue to show the time on the display. (i have not manage to advance that much due to my error on not being able to clear the display when i want to write on the keypad)

#include "Arduino.h"

// KEYPAD
#include "Keypad.h"

const byte ROWS = 4; //four rows
const byte COLS = 3; //three columns

//define the symbols on the buttons of the keypads
char hexaKeys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};

char customKey;

byte rowPins[ROWS] = {12, 11, 10, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad

//initialize an instance of class NewKeypad
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);


// DISPLAY
#include "SevenSegmentTM1637.h"
#include "SevenSegmentExtended.h"

const byte PIN_CLK = 4;   // define CLK pin (any digital pin)
const byte PIN_DIO = 5;   // define DIO pin (any digital pin)
SevenSegmentExtended      display(PIN_CLK, PIN_DIO);

// RTC

#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>

void setup(){
    Serial.begin(9600);         // initializes the Serial connection @ 9600 baud
    display.init();
    display.setBacklight(100);  // set the brightness to 10 %
    display.print("ON");      // display INIT on the display
    delay(1000);                // wait 1000 ms
    display.clear();
}

// OTROS

#define digit 4

byte data_count = 0;
char Data[digit];

void loop(){

    tmElements_t tm; // CLOCK

    display.setColonOn(true);
    customKey = customKeypad.getKey();

    if (RTC.read(tm)) {       
        display.printTime(tm.Hour, tm.Minute, true);
    }


    if (customKey) { // ACTIVATE KEYPAD

        display.clear();

        if (customKey == '*') { // IF *
            display.blink();

            if (Data[data_count] < 3) {
                error();
            }

        } else if (customKey == '#') { // IF #
            display.blink();
            display.setColonOn(false);
            display.clear();
            clearData();
        } else { // WRITE ON DISPLAY

            Data[data_count] = customKey;
            display.setCursor(0,data_count);
            display.print(Data[data_count]);

            if (data_count < 4) {
                data_count++;
            } else {
                error();
            }       
        } // END DISPLAY WRITE

    } // END KEYPAD IF

} // END LOOP


void error() { // DISPLAY ERROR AND DELETE DATA
    display.clear();
    display.setColonOn(false);
    display.print("ERR");
    delay(1000);
    display.clear();
    clearData();
}

void clearData() { // CLEAR DATA
    while (data_count != 0) {
        Data[data_count--] = 0;
    }
}

This are the libraries i'm using if it helps: https://github.com/bremme/arduino-tm1637, https://github.com/PaulStoffregen/DS1307RTC and the Keypad library from Arduino library manager

Hope I made myself clear with my problem, english is not my first language, if you want more clarification then let me know!

That is basically what i've got, i'm sorry if the post is too long, i have been struggling with this problem for two days and i don't know how to proceed. Hope you all can help. Thanks!

1 Answer 1

2

I think your problem is here:

if (RTC.read(tm)) {       
    display.printTime(tm.Hour, tm.Minute, true);
}

This code displays the current time, and it runs on every single loop iteration. This is visibly not what you want. Your project should have at least two distinct operational modes: “display the current time” and “allow the user to input data”. You need a variable to remember which is the current mode, e.g.

enum { MODE_DISPLAY_TIME, MODE_DATA_INPUT } mode;

You need to precisely define the events that make your program switch modes, and code specific behaviors for each mode. For example:

if (mode == MODE_DISPLAY_TIME) {
    if (RTC.read(tm)) {       
        display.printTime(tm.Hour, tm.Minute, true);
    }
} else if (mode == MODE_DATA_INPUT) {
    // Handle user input.
}

This general approach is called a “finite state machine”. You can read more about it in this blog article by Majenko.

Your Answer

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

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