From f1f837bc9e7d644d44edee7453c4bfb7551d0eaf Mon Sep 17 00:00:00 2001 From: asb Date: Sun, 25 Sep 2022 21:29:30 +1000 Subject: [PATCH] V2.3 --- 4ButtonKeypad/4ButtonKeypad.ino | 406 +++++++++++++++++++++----------- 1 file changed, 273 insertions(+), 133 deletions(-) diff --git a/4ButtonKeypad/4ButtonKeypad.ino b/4ButtonKeypad/4ButtonKeypad.ino index f10c347..4f8d83d 100644 --- a/4ButtonKeypad/4ButtonKeypad.ino +++ b/4ButtonKeypad/4ButtonKeypad.ino @@ -1,11 +1,41 @@ -//Recommend reading: https://www.arduino.cc/reference/en/ +//######################################################################################################### +//# PROGRAM NAME: 'ClareButtons' +//######################################################################################################### +//# Purpose : Controlled by an Arduino Board, this code programs preset actions on up to 6 Buttons (currently only 4 defined). +//# For example, the buttons may be defined as: +//# * 'Keyboard Keys' (eg. Ctrl, Alt, Shift) +//# * 'KeyBoard combinations' shortcuts (eg. Crtl + C, Crtl + V) +//# * 'Whole Text' (eg. "Hello World") +//# Code Type : MAIN PROGRAM: C - Arduino Leonardo (Arduino IDE) +//# Usage : Ideal for one-handed keyboard usage +//# Prereqs : 1) May Require 'USB Driver' for Arduio Board (Chinese Board): +//# * CH341SER_EXE (from http://www.wch-ic.com/downloads/CH341SER_EXE.html) +//# 2) Requires 'Board' Selection via Tools > Board: If the Board is not in the dropdown list the install\update via 'Tools > Board > Board Manager'. +//# * Arduino Leonardo (Arduino Pro Micro) +//# 3) Requires 'Port' to be specified. 'Tools > Port' (The 'Board' should be clearly identified with the corresponding Port): +//# * eg. COM3(Arduino Leonardo) +//# 4) Requires 'Librarys' to be Installed via 'Sketch > Incldue Library > Manage Libraries': +//# * EasyButton.h +//# * HID-Project.h +//# Author(s) : Zachery Seibel-Barnes and Anthony Seibel-Barnes +//# Date : 17/09/2022 (Ver 2.1) +//# Notes : 1) Hardware: Buttons are defined as '1' to '4' from Top (furthest from USB lead) to Bottom (closest to USB lead) +//# 2) IMPORTANT: A 'Button Press' action needs to have corresponding a 'Button Release' action (either 'implicidly defined' or as a generic 'release all') +//# 2) Testing: To check parameters values (as generated by run code), use 'Serial Monitor' (Ctrl+Shft+M). Examples: +//# Serial.print("Led Brightness = "); +//# Serial.print(ledBrightness); +//# Serial.print("\t Led State = "); +//# Serial.println(ledOn); +//######################################################################################################### + -//Buttons go 1-4 from Top to bottom - -//This project uses an Arduino Pro Micro (also known as an Arduino Leonardo) +//********************************************* +//*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* +//* INITIALISE * +//*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* +//********************************************* //Includes -//These can be installed in the arduino IDE by clicking on tools in the top bar, then manage libraries. #include //Used to define a button and debounces it #include "HID-Project.h" //Lets us simulate keyboard presses. @@ -22,18 +52,18 @@ #define BUTTON3 A1 #define BUTTON4 A0 -const int cintLedOffTime = 1000; //LED 'OFF' time (milliseconds) is how long LED will remain on for after a button was pressed (For reference: 60,000 = 1 minute) -const int cintDebounceTime = 200; //DebounceTime (milliseconds) is used with the 'Delay' function to pause code after a button press. This helps to slow 'extra' commands from +const int cintLedOffTime = 10000; //LED 'OFF' time (milliseconds) is how long LED will remain on for after a button was pressed (For reference: 60,000 = 1 minute) +const int cintLedMaxBrightness = 100; //LED Maximum brightness level (0 will be off, and 255 is brightest... like the SUN !!) +const int cintLedDimmerStepTime = 10; //Time interval for LED Dimmer (milliseconds) +const int cintLedDimmerStep = 1; //Step interval for LED Dimmer (1 = slow fade ; 10 = quick fade) +const int cintDebounceTime = 180; //DebounceTime (milliseconds) is used with the 'Delay' function to pause code after a button press. This helps to slow 'extra' commands from //a Button like 'PASTING repeated data'). Increase the 'time' if wishing to 'hold' an action from happening (or repeating) for longer. - //This is currently only used when 'blnDelayActions' becomes 'true'. If it is 'false', then the delay is 'zero'. + //This is currently only used when 'blnDelayActions' is set to 'true'. If it is 'false', then the delay is effectively 'zero'. unsigned long ledTickTime = 0; unsigned long lastPressTime = 0; -uint8_t ledBrightness = 100; -bool ledOn = true; -bool blnDelayActions = false; //Used to SLOW 'button actions' from repeating (ie. it is a simple debounce to retard 'extra' or 'unwanted' actions from Buttons). -bool blnReleaseALLKeys = false; //Used to control when 'ALL Keyboard Keys should be released'.... OR NOT, where (in some cases) 'Multi-button combinations are required' (eg. 'Hold-Key' actions like Ctr+Alt+Del). - //If 'blnReleaseALLKeys' is set to false (in the running code), then you must also implicitly state what keys should be released (and when). +uint8_t ledBrightness = cintLedMaxBrightness; +bool blnLEDsOn = true; //Used to flag when 'LEDs' are ON at any Brightness level (ie. when LEDs are NOT off). Initated to True for initial illumination. bool blnButtonActivty = false; //Used to flag when a Button action has actually occured. This is used primarily so it can correctly turn off LEDs after the specified activity time (ie. indirectly works with 'cintLedOffTime') @@ -45,7 +75,8 @@ EasyButton button3(BUTTON3, 35, false, false); EasyButton button4(BUTTON4, 35, false, false); //Standard Arduino setup function. Code that only needs to run once goes here -void setup() { +void setup() +{ // Send a clean report to the host. This is important on any Arduino type. Keyboard.begin(); Keyboard.end(); @@ -56,7 +87,7 @@ void setup() { pinMode(LED3, OUTPUT); pinMode(LED4, OUTPUT); - //Here we output a PWM signal to the LEDs, where 0 will be off, and 255 is brightest + //Here we output a PWM signal to the LEDs. This is the INITIAL LEDs illumination when the device is plugged in (prior to any button actions or dimming checks occur). analogWrite(LED1, ledBrightness); analogWrite(LED2, ledBrightness); analogWrite(LED3, ledBrightness); @@ -66,12 +97,18 @@ void setup() { button1.begin(); button2.begin(); button3.begin(); - button4.begin(); + button4.begin(); } - -//Code that is run constantly goes here +//********************************************* +//*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* +//* MAIN * +//*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~* +//********************************************* +//Code that is runs constantly goes here void loop() { + //Reset 'Button Activity' flag (when False it sits in a wait-state for someone to press a button) + blnButtonActivty=false; //Read all the buttons button1.read(); @@ -79,96 +116,53 @@ void loop() { button3.read(); button4.read(); - - //This should be pretty self explanitory. Make sure to always release a button. - //Note1: 'Keyboard.press' code options (for reference) - // Keyboard.press(KEY_LEFT_CTRL) - // Keyboard.press(KEY_LEFT_ALT) - // Keyboard.press(KEY_LEFT_SHIFT) - //Note2: 'Keyboard.release' code options (for use when blnReleaseALLKeys = false) - // Keyboard.release(KEY_SPACE) - // Keyboard.release(KEY_LEFT_CTRL) - + //--------------------------------- + //--- Button Activity --- + //--------------------------------- if(button1.isPressed()) { - // PASTE COMMAND (Ctrl+V) - Keyboard.press(KEY_LEFT_CTRL); - Keyboard.write('v'); - blnDelayActions = true; - blnButtonActivty = true; - //lastPressTime = millis(); + blnButtonActivty = ButtonPressAction(1); } else if(button1.wasReleased()) { - //lastPressTime = millis(); - blnDelayActions = false; - blnReleaseALLKeys = true; - blnButtonActivty = true; + blnButtonActivty = ButtonReleaseAction(1,true); } if(button2.isPressed()) { - // COPY COMMAND (Ctrl+C) - Keyboard.press(KEY_LEFT_CTRL); - Keyboard.write('c'); - blnDelayActions = false; - blnButtonActivty = true; - //lastPressTime = millis(); + blnButtonActivty = ButtonPressAction(2); } else if(button2.wasReleased()) { - //lastPressTime = millis(); - blnDelayActions = false; - blnReleaseALLKeys = true; - blnButtonActivty = true; + blnButtonActivty = ButtonReleaseAction(2,true); } if(button3.isPressed()) { - //CUSTOM TEXT (Message) - //Keyboard.println("Hi"); - //Keyboard.println(); - Keyboard.println("Just confirming that your item is in the mail (and may have already been delivered)... See pics."); - //Keyboard.println(); - //Keyboard.println("Tracking is available via Australia Post: TMP40083004070052454xxxxx"); - //Keyboard.println("Tracking progress applies on business days as it processes through Australia Post facilities.."); - //Keyboard.println(); - //Keyboard.print("Thank-you and All the best ;)"); - - //lastPressTime = millis(); - blnDelayActions = true; - blnButtonActivty = true; + blnButtonActivty = ButtonPressAction(3); } else if(button3.wasReleased()) { - //lastPressTime = millis(); - blnDelayActions = false; - blnReleaseALLKeys = true; - blnButtonActivty = true; + blnButtonActivty = ButtonReleaseAction(3,true); } if(button4.isPressed()) { - // 'SHIFT' KEY (Only) - Keyboard.press(KEY_LEFT_SHIFT); - blnDelayActions = false; - //lastPressTime = millis(); - blnButtonActivty = true; + blnButtonActivty = ButtonPressAction(4); } else if(button4.wasReleased()) { - //lastPressTime = millis(); - blnDelayActions = false; - blnReleaseALLKeys = false; //When FALSE - you must implicidly release Keys (below) - Keyboard.release(KEY_LEFT_SHIFT); - blnButtonActivty = true; + blnButtonActivty = ButtonReleaseAction(4,false); } + //--------------------------------------------------------- + //--- LED Illumination: Full ON (when Button Activity) --- + //--------------------------------------------------------- // Check if a 'Button action' has recently occurred. switch (blnButtonActivty) { @@ -178,86 +172,232 @@ void loop() { //Reset the 'lastPressTime' timer variable to current time(r). lastPressTime = millis(); - // Check if a 'Pause' is required while performing 'Button' action(s): This stops (or rather 'SLOWS') 'repeated button actions' if a button is 'held down too long' (eg. helps stop extra 'PASTE data' commands) - switch (blnDelayActions) + //Increase LEDs to 'MAX Brightness' + if(ledBrightness < cintLedMaxBrightness) { - case true: - // Pause - delay(cintDebounceTime); - blnDelayActions = false; - break; - default: - // No Delay, or maybe repeat action(s) - delay(0); - break; + ledBrightness = cintLedMaxBrightness; + + analogWrite(LED1, ledBrightness); + analogWrite(LED2, ledBrightness); + analogWrite(LED3, ledBrightness); + analogWrite(LED4, ledBrightness); } - - // Check if ALL Keyboard Keys should now be released (Usually 'true', but perhaps 'false' if 'multi-button hold combinations' are required) - switch (blnReleaseALLKeys) - { - case true: - // Release ALL Keyboard Keys (this should almost always be the case). Then reset 'ReleaseAllKeys' flag. - Keyboard.releaseAll(); - blnReleaseALLKeys = false; - break; - default: - // Do NOT Release Keys (IMPORTANT: If here not by default, then you should have already implicidly set what Keys have been (or are to be) released.) - break; - } - - //Reset the Button Activity Flag - blnButtonActivty = false; - + //Set flag indicating that 'LEDs are ON' and reset 'LED ON timer' + blnLEDsOn = true; break; default: // A 'Button Activty' HAS NOT Occurred. No need to do anything - This will also retain the 'lastPressTime' time value. break; } - - //If LED is ON.... Check timer since last Button Activity. - switch (ledOn) + + //--------------------------------------------------------- + //--- LED Illumination: DIM to OFF (Standby) --- + //--------------------------------------------------------- + //If the LEDs are ON at ANY Brightness level (ie. LED NOT Off) .... Check timer since last Button Activity. + switch (blnLEDsOn) { case true: - //If Max time has elapsed, then turn off LEDS + //If MAX time has elapsed (for LEDs to be ON), then turn off LEDS if((millis() - lastPressTime) > cintLedOffTime) { - ledOn = false; - //lastPressTime = 0; + lastPressTime = 0; //Reset (no button action) + ledBrightness = 0; //LEDs Off + + analogWrite(LED1, ledBrightness); + analogWrite(LED2, ledBrightness); + analogWrite(LED3, ledBrightness); + analogWrite(LED4, ledBrightness); + + //Set flag 'LEDs are OFF' + blnLEDsOn = false; } - else + else if(lastPressTime>0) { - ledOn = true; - } - - //If certain time has elapsed, then adjust LEDs brightness - if ((millis() - ledTickTime) > 10) + //Check if certain time has elapsed, then adjust LEDs brightness (Dimmer) + if ((millis() - ledTickTime) > cintLedDimmerStepTime) { ledTickTime = millis(); - if(!ledOn && (ledBrightness > 0)) + + if(ledBrightness > 0) { - ledBrightness=ledBrightness-1; + ledBrightness = ledBrightness-cintLedDimmerStep; + analogWrite(LED1, ledBrightness); + analogWrite(LED2, ledBrightness); + analogWrite(LED3, ledBrightness); + analogWrite(LED4, ledBrightness); } - - else if(ledOn && (ledBrightness < 100)) - { - ledBrightness=ledBrightness+10; - } - - analogWrite(LED1, ledBrightness); - analogWrite(LED2, ledBrightness); - analogWrite(LED3, ledBrightness); - analogWrite(LED4, ledBrightness); } - //} + } break; default: // LEDs are Off.... Do nothing break; } -// Serial.print("Led Brightness = "); -// Serial.print(ledBrightness); -// Serial.print("\t Led State = "); -// Serial.println(ledOn); - + // LOOP MAIN +} + + +//******************************************************************************************** +//* FUNCTION NAME: 'ButtonPressAction' +//******************************************************************************************** +//* Purpose : Performs pre-defined action(s) when an Arduino Board button is PRESSED. +//* Code Type : FUCTION CALL: C - Arduino Leonardo (Arduino IDE) +//* Usage : Can be called anytime. Function call example: blnButtonActivty = ButtonPressAction(1); +//* Where: * 'ButtonPressAction(1)' specifies the button for which the defined action(s) will execute. +//* * 'blnButtonActivty' receives the return result (treated as 'success' or 'fail'). It should +//* only fail when the 'Button ID is not 1-6'. +//* Returns : 'True' if successful, otherwise 'False' where button is undefined. +//* Parameters: 'intButtonNumber' - Corresponds to the Arduino Board button ID number. +//* Prereqs : Keyboard Library (HID-Project.h) should be set in MAIN PROGRAM +//* Author : A. Seibel-Barnes (from original source by Z. Seibel-Barnes) +//* Date : 17/09/2022 (Ver 1.0) +//* Notes : 'Keyboard.press' code options (examples for reference) +//* * Keyboard.press(KEY_LEFT_CTRL) +//* * Keyboard.press(KEY_LEFT_ALT) +//* * Keyboard.press(KEY_LEFT_SHIFT) +//'********************************************************************************************** +bool ButtonPressAction(int intButtonNumber) +{ + bool blnButtonActioned = false; + bool blnDelayActions = false; //Used to SLOW 'button actions' from repeating (ie. it is a simple debounce to retard 'extra' or 'unwanted' actions from Buttons). + + // Perform 'Button PRESS' action + switch (intButtonNumber) + { + case 1: + // DEFINITION: PASTE COMMAND (Ctrl+v) + Keyboard.press(KEY_LEFT_CTRL); + Keyboard.write('v'); + blnDelayActions = true; + blnButtonActioned = true; + break; + case 2: + // DEFINITION: COPY COMMAND (Ctrl+c) + Keyboard.press(KEY_LEFT_CTRL); + Keyboard.write('c'); + blnDelayActions = false; + blnButtonActioned = true; + break; + case 3: + // DEFINITION: 'SHIFT' KEY (Only) + Keyboard.press(KEY_LEFT_SHIFT); + blnDelayActions = false; + blnButtonActioned = true; + break; + case 4: + // DEFINITION: CUSTOM TEXT (Message) + //Keyboard.println("Hi"); + //Keyboard.println(); + Keyboard.println("Just confirming that your item is in the mail (and may have already been delivered)... See pics."); + //Keyboard.println(); + //Keyboard.println("Tracking is available via Australia Post: TMP40083004070052454xxxxx"); + //Keyboard.println("Tracking progress applies on business days as it processes through Australia Post facilities.."); + //Keyboard.println(); + //Keyboard.print("Thank-you and All the best ;)"); + blnDelayActions = true; + blnButtonActioned = true; + break; + case 5: + // DEFINITION: TBA + blnDelayActions = false; + blnButtonActioned = true; + break; + case 6: + // DEFINITION: TBA + blnDelayActions = false; + blnButtonActioned = true; + break; + default: + //Returns a 'fail' if the 'Button ID' was not specified between 1-6. + break; + } + + // Check if a 'Pause' is required while performing 'Button' action(s): This stops (or rather 'SLOWS') 'repeated button actions' if a button is 'held down too long' (eg. helps stop extra 'PASTE data' commands) + switch (blnDelayActions) + { + case true: + // Pause + delay(cintDebounceTime); + blnDelayActions = false; + break; + default: + // No Delay, or maybe repeat action(s) + delay(0); + break; + } + + return blnButtonActioned; +} + + +//******************************************************************************************** +//* FUNCTION NAME: 'ButtonReleaseAction' +//******************************************************************************************** +//* Purpose : Performs pre-defined action(s) when an Arduino Board button is RELEASED. +//* Code Type : FUCTION CALL: C - Arduino Leonardo (Arduino IDE) +//* Usage : Can be called anytime. Function call example: blnButtonActivty = ButtonReleaseAction(1,false); +//* Where: * 'ButtonReleaseAction(1,false)' specifies the button for which the implicidly defined Key-release action(s) will execute (when false specified). Or, +//* (when true) 'Releases ALL keys' irrelevant of which 'Button ID' was released. +//* * 'blnButtonActivty' receives the return result (treated as 'success' or 'fail'). Should only fail when 'blnReleaseALLKeys is false' AND the 'Button ID is not 1-6'. +//* Returns : 'True' if successful, otherwise 'False' where button is undefined. +//* Parameters: 'intButtonNumber' - Corresponds to the Arduino Board 'Button ID' number (1-6) +//* 'blnReleaseALLKeys' - When 'true' it simply 'Releases ALL Keys' (and ignores the 'Button ID' since there are no specific Key-release requirements). +//* When 'false' it requires that specific Key(s) are implicidly released. +//* Prereqs : Keyboard Library (HID-Project.h) should be set in MAIN PROGRAM +//* Author : A. Seibel-Barnes (from original source by Z. Seibel-Barnes) +//* Date : 17/09/2022 (Ver 1.0) +//* Notes : 'Keyboard.release' code options (for use when blnReleaseALLKeys = false) +//* * Keyboard.release(KEY_SPACE) +//* * Keyboard.release(KEY_LEFT_CTRL) +//'********************************************************************************************** +bool ButtonReleaseAction(int intButtonNumber, bool blnReleaseALLKeys) +{ + bool blnButtonActioned = false; + + // Check if ALL Keyboard Keys should now be released (Usually 'true', but perhaps 'false' if 'multi-button hold combinations' are required) + switch (blnReleaseALLKeys) + { + case true: + // SIMPLE - 'Release 'ALL Keyboard Keys' (this should almost always be the case). + Keyboard.releaseAll(); + blnButtonActioned = true; + break; + default: + // SPECIFIC - 'Implicidly set what Key(s)' need to be released. This is REQUIRED when Key-hold combination are required. + switch (intButtonNumber) + { + case 1: + // DEFINITION: TBA + blnButtonActioned = true; + break; + case 2: + // DEFINITION: TBA + blnButtonActioned = true; + break; + case 3: + // DEFINITION: 'SHIFT' KEY (Only) + Keyboard.release(KEY_LEFT_SHIFT); + blnButtonActioned = true; + break; + case 4: + // DEFINITION: TBA + blnButtonActioned = true; + break; + case 5: + // DEFINITION: TBA + blnButtonActioned = true; + break; + case 6: + // DEFINITION: TBA + blnButtonActioned = true; + break; + default: + //Returns a 'fail' if the 'Button ID' was not specified between 1-6. + break; + } + break; + } + + return blnButtonActioned; }