Home » Projects » Electronics Projects » Arduino AD9850 Control – Reading Button Commands

Arduino AD9850 Control – Reading Button Commands

The main program loop for my Arduino AD9850 control program begins by checking for button commands from the LCD 1602 Keypad. Then it moves on to checking the status of the KY-040 optical encoder. The encoder outputs are translated to equivalent button commands, depending on the direction of turn and closing the push switch. After this, the program moves on to processing the button commands, which tell the signal generator what to do.

void loop()
	int btn = BUTTON_NONE;

	* Get the Inputs. Priority given to LCD Keypad buttons.
	* Turning encoder produces BUTTON_UP or BUTTON_DOWN
	* Pressing encoder switch produces BUTTON_SELECT or BUTTON_SELECTLONG
	btn = ReadLCDBtn();
	if (btn == BUTTON_NONE) {
		btn = CheckEncoderTurning();
	if (btn == BUTTON_NONE) {
		btn = CheckEncoderSwitch();
	/* Deal with Menu activities, if any */
	btn = ProcessMenu(btn);


A separate function is used to read the LCB buttons. The cheap and easy LCD 1602 Keypad shield uses a single Arduino analog output pin (A0) to tell you which button is pushed, if any. To do this, it uses a simple voltage divider circuit. Each button triggers a different voltage which is converted into a number by the Arduino ADC (analog to digital converter). These numbers range from near 1023 (for no button pushed) down to 0 (for right button pushed).

These button commands (values) vary a little bit in each keypad. They also vary depending on how much current is being used by the Arduino. For example, since the AD9850 draws a lot of current, the button values are quite different when the AD9850 module is connected. So, I suggest that you check these values under load. If you are using the Visual Micro debugger, this is easy to do by setting a break point at Voltage = analogRead(LCD_BUTTON_PIN).

int ReadLCDBtn() {
	 * My current Button ADC values: N=1020, R=0, U=140, D=325, L=500, S=736
	 * Make sure your check yours and modify buttonValues[] if necessary!!!
	 * Button values > 0 are only returned when the button is released.
	 * This function is checked at beginning of each program loop.
	 * Trigger is used to measure elapsed time since button was pressed.
	 * Triggered=true means waiting for button released
	static const int buttonValues[6] = { 900, 50, 200, 400, 650, 850 };
	static int LastButton = BUTTON_NONE;
	static unsigned long Trigger = 0;
	static boolean Triggered = false;
	int Voltage;
	int Button;
	int i;
	boolean Release;

	Voltage = analogRead(LCD_BUTTON_PIN);

	/* Find which button was pressed, if any */
	if (Voltage > buttonValues[0])
		Button = BUTTON_NONE;
		// Return immediately if this is not a button release
		if (!Triggered) return Button;
		for (i = 1; i < 5; i++) if (Voltage < buttonValues[i]) break;
		Button = i;

	if ((Repeating) && ((Button == BUTTON_UP) || (Button == BUTTON_DOWN)))
		/* Return immediately if we are repeating frequency changes */
		return Button;

	/* New button press triggered. Trigger=time press started */
	if ((Button > BUTTON_NONE) && (!Triggered)) {
		Triggered = true;
		Trigger = millis();
	/* Check to see if this loop is a button release */
	Release = ((Button == BUTTON_NONE) && (Triggered));

	if (Release)
		Button = LastButton;
		// Each button press could be normal OR long
		if ((millis() - Trigger) > PRESS_LONG) Button += PRESS_LONG_INC;
		Triggered = false;
		Release = false;
		LastButton = BUTTON_NONE;
		return Button;
		// Otherwise just store the button ID for later release
		LastButton = Button;
		return BUTTON_NONE;

Button Commands are just numbers

In normal operation, the ReadLCDBtn() function returns immediately if no button has been pushed, and only sends button commands when a button is released. It does this by remembering what button is pushed (LastButton) and then returning that value only when the button is released. The routine uses a variable called Triggered, which is set true when any button is pushed, and then set false when released. The variable Trigger measures the elapsed time for the button press, so that it can differentiate between short and long presses. In my code, a long press is one more than half a second long.

The button commands value is simply an integer called Button, which is really just an index into an array of possible button commands which are described in #define statements.

I found that I did not need to de-bounce the button commands. In part, this might be because I added a 5 millisecond delay in each loop of the main program. Your mileage may differ. You should be able to use these software routines to read button commands from the LCD 1602 Keypad in almost any Arduino project.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.