Grzegorz GolbaDenisse ReyesBryan Gutierrez
Published

ICL VKEY KEYPAD

For this project, we used a keypad to determine which counselors at our school were visited the most and by what grade level.

BeginnerFull instructions provided3 hours628
ICL VKEY KEYPAD

Things used in this project

Hardware components

Photon
Particle Photon
×1
Breadboard (generic)
Breadboard (generic)
×1
SparkFun VKey Voltage Keypad
×1
Jumper wires (generic)
Jumper wires (generic)
×1

Hand tools and fabrication machines

Laser cutter (generic)
Laser cutter (generic)

Story

Read more

Custom parts and enclosures

Enclosure Plans

Illustrator file used to laser cut the enclosure used in this project.

Enclosure Plans Preview

Schematics

Voltage Keypad Fritzing

The SparkFun Voltage Keypad was not available on the Fritzing application so we used a SparkFun pin header as a substitute

Keypad Fritzing Diagram Screenshot

Code

loft703.io

Arduino
// This #include statement was automatically added by the Particle IDE.
#include <SparkFunPhant.h>

// This #include statement was automatically added by the Particle IDE.
#include "SparkFunVKeyVoltageKeypad.h"

/******************************************************************************
 VKey_demo_main.ino
 VKey Voltage Keypad decoding demo
 By Byron Jacquot @ @ SparkFun Electronics
 February 4, 2014
 https://github.com/sparkfun/VKey_Voltage_Keypad

 This demonstrates interfacing the SparkFun VKey voltage keypad using 
 the VKey Arduino library.

 The VKey has an array of 12 pushbuttons, each producing a unique analog 
 voltage when  pushed.  A microcontroller can read the voltage, and determine 
 which key has been pressed.  The VKey library keeps track of the analog pin 
 connection, key status, and voltage calibration details.

 The VKey was connected to the Arduino as follows:
 VKey GND  -> Arduino GND
 VKey Vout -> Arduino analog input A1
 VKey V+   -> Arduino VCC 

 To use the library, instantiate a VKey object and periodically check for input 
 using the checkKeys() function.

 Resources:
 no additional library requirements

 Development environment specifics:
 Developed on Arduino IDE 1.0.5
 Tested on a 5V Redboard and 3.3V Pro Mini

 This code is beerware; if you see me (or any other SparkFun employee) at the
 local, and you've found our code helpful, please buy us a round!

 Distributed as-is; no warranty is given.
******************************************************************************/

//#include <VKey.h>

// Global declaration of the VKey class
// Initialized with analog pin number and supply voltage
VKey keypad(A1, VKey::FIVE );

int buttonArray[13] = {0};
int button = 0 ;
int count = 0 ;

const char server[] = "data.sparkfun.com"; // Phant destination server
const char publicKey[] = "OGM2933XA6up8nYAdOzO"; // Phant public key - HAS TO BE CHANGED
const char privateKey[] = "8bKy0ddorzTJNbzy9aWa"; // Phant private key  - HAS TO BE CHANGED
Phant phant(server, publicKey, privateKey); // Create a Phant object

const int POST_RATE = 3000; // Time between posts, in ms.
unsigned long lastPost = 0; // global variable to keep track of last post time
void setup()
{
  // Initialize serial port for text output
  Serial.begin(9600);
  Serial.println("Welcome to VKey example");

  // No VKey specific initialization required.
}

void loop() 
{
  VKey::eKeynum k;  // Variable to receive the key indication

    /* CheckKeys will always return the current key in parameter k.
       The boolean return value indicates whether that value is different than
       the previous value.
     */
     
  
  if((keypad.checkKeys(k)) && (k >0))
  {
    // Only print when value has changed
    Serial.print("Got key: ");
    Serial.println(k);
    buttonArray[k] = buttonArray[k] + 1 ;
    
    button = k ;
    count = buttonArray[k] ;
    postToPhant();
    button = 0 ;
    count = 0 ;
  
 }
 
  // The responsiveness of the keypad depends on how frequently it is checked. 
  // 50 milliseconds seems to be a reasonable poll interval.
  delay(50);
}

int postToPhant()
{    
    
     
    // Use phant.add(<field>, <value>) to add data to each field.
    // Phant requires you to update each and every field before posting,
    // make sure all fields defined in the stream are added here.
    phant.add("button", button) ;
    phant.add("count", count) ;
    // phant.add("Andros", value1);
    // phant.add("Atkocaitis", value2);
    // phant.add("Freshman ",value3);
    // phant.add("Bantz",value4);
    // phant.add("Morgan",value5);
    // phant.add("Sophomore",value6);
    // phant.add("Console",value7);
    // phant.add("Constantine",value8);
    // phant.add("Junior",value9);
    // phant.add("Fuhrmann",value10);
    // phant.add("Hoof",value11);
    // phant.add("Senior",value12);
        	
    TCPClient client;
    char response[512];
    int i = 0;
    int retVal = 0;
    
    if (client.connect(server, 80)) // Connect to the server
    {
		// Post message to indicate connect success
        Serial.println("Posting!"); 
		
		// phant.post() will return a string formatted as an HTTP POST.
		// It'll include all of the field/data values we added before.
		// Use client.print() to send that string to the server.
        client.print(phant.post());
        delay(1000);
		// Now we'll do some simple checking to see what (if any) response
		// the server gives us.
        while (client.available())
        {
            char c = client.read();
            Serial.print(c);	// Print the response for debugging help.
            if (i < 512)
                response[i++] = c; // Add character to response string
        }
		// Search the response string for "200 OK", if that's found the post
		// succeeded.
        if (strstr(response, "200 OK"))
        {
            Serial.println("Post success!");
            retVal = 1;
        }
        else if (strstr(response, "400 Bad Request"))
        {	// "400 Bad Request" means the Phant POST was formatted incorrectly.
			// This most commonly ocurrs because a field is either missing,
			// duplicated, or misspelled.
            Serial.println("Bad request");
            retVal = -1;
        }
        else
        {
			// Otherwise we got a response we weren't looking for.
            retVal = -2;
        }
    }
    else
    {	// If the connection failed, print a message:
        Serial.println("connection failed");
        retVal = -3;
    }
    client.stop();	// Close the connection to server.
    return retVal;	// Return error (or success) code.
}


   

SparkFunVKeyVoltageKeypad.h

Arduino
/******************************************************************************
 VKey.h
 VKey Voltage Keypad library
 By Byron Jacquot @ SparkFun Electronics
 February 4, 2014
 https://github.com/sparkfun/VKey_Voltage_Keypad
 This library interfaces with the VKey analog keypad.  It relies on the 
 Arduino analogRead functionality.
 The keypad has 12 keys, and outputs a unique Voltage for each key.  It allows
 an application to interface with up to 12 keys using only one ADC line.
 To use the library, instantiate a VKey object, then call checkKeys() to
 read the keypad.
 See SparkFun_VKey_demo_main.ino for a usage example.
 
 Also, see the contents of the /documents/ directory for information about 
 scaling and calibration.  They'll be useful if you're porting the library to 
 other supply or reference voltages, or ADC bit widths.
 
 Resources:
 no additional library requirements.
 Development environment specifics:
 Developed on Arduino IDE 1.0.5
 Tested on a 5V Redboard and 3.3V Pro Mini
 
  **UPDATED FOR ARDUINO 1.6.4 5/2015**
 This code is beerware; if you see me (or any other SparkFun employee) at the
 local, and you've found our code helpful, please buy us a round!
 Distributed as-is; no warranty is given.
******************************************************************************/
 
#ifndef __VKEY_H__
#define __VKEY_H__

#include <Arduino.h>

/**
 * A class to interface with a single VKey analog voltage keypad.
 * To interface with multiple keypads, instantiate multiple instance of this
 * class, each reading a unique analog input pin. 
 */
class VKey
{
  public:
  
    /* Definition of power supply/converter reference voltages
     */
    enum eVref
    {
      THREE, // 3.3V power supply and Vref
      FIVE,  // 5V  power supply and Vref
      MAX    // Do not use: used for range checking only
    };
    
    /* Enumerated values returned by the class to represent 
     * the current key combination.
     */
    enum eKeynum
    {
      // Keys map directly to regular integers
      KEY_NONE = 0,
      KEY_1,
      KEY_2,
      KEY_3,
      KEY_4,
      KEY_5,
      KEY_6,
      KEY_7,
      KEY_8,
      KEY_9,
      KEY_10,
      KEY_11,
      KEY_12
    };
    
    /* Constructor - used to create an instance of the VKey object.
     * 
     * Parameters:
     *    - pin: define which ADC pin the VKey is attached to.
     *    - reference: which voltage is powering the keypad, and being used 
     *      as the ADC reference?  (use the enum VKey::THREE or VKey::FIVE) 
     */
    VKey(uint8_t pin,
         eVref reference);
         
    /* CheckKeys - Return the currently pressed key (or KEY_NONE), and
     *            Indicate whether the reading has changed since the last poll
     *
     * This function can be used one of two ways.
     *
     * First, it can be used to simply query the current keypad status.  It will 
     * return the present key in the pass-by-reference parameter k.
     *
     * Second, it can be used to detect changed in keypad status.
     * The function returns a boolean value that
     * indicates whether the input has changed since the last query, then check 
     * the value of k and respond appropriately.  For example:
     *
     * Usage Example:
     *
     * #include <VKey.h>
     *
     * VKey keypad(0, FIVE);
     *
     * void setup() 
     * {
     *
     * }
     *
     * void loop() 
     * {
     *   eKeynum newKey;
     *
     *   if(keypad.CheckKey(newKey)
     *   {
     *      Serial.print("Got new key value: ");
     *      Serial.println(newkey);
     *   }
     * }
     * The responsiveness of the keypad depends on the rate the application 
     * calls this routine.
     */
    bool checkKeys(eKeynum & k);
    
  private:
    /* default constructor won't construct a valid object,
     * therefore it's hidden by making it private
     */
    VKey();
    
    /* Internal routine that takes an ADC value, and interpolates the 
     * corresponding key value.
     */
    eKeynum voltageToKey(int v);
    
    /* Internal structure to hold the calibration tables for the different
     * reference voltages
     */
    struct VKeyScale
    {
      PROGMEM const uint16_t offset;
      PROGMEM const uint16_t step_size;
      PROGMEM const uint16_t top;
    };

    /* Declaration of an array of Scale structures
     *
     * It's static because we can share one instance of the data with 
     * multiple VKeys.
     * Since it's constant, it's placed in PROGMEM to avoid using RAM.
     */
    static const PROGMEM VKeyScale scales[MAX];
    
    // Pointer to active row of the above table.
    const PROGMEM  VKeyScale* scale_p;
    
    /* Member variables
     */
          int      analog_pin;
          eKeynum  last_key;
};

#endif

SparkFunVKeyVoltageKeypad.cpp

Arduino
 To use the library, instantiate a VKey object, then call checkKeys() to
 read the keypad.
 See SparkFun_VKey_demo_main.ino for a usage example.
 
 Also, see the contents of the /documents/ directory for information about 
 scaling and calibration.  They'll be useful if you're porting the library to 
 other supply or reference voltages, or ADC bit widths.
 
 Resources:
 no additional library requirements.
 Development environment specifics:
 Developed on Arduino IDE 1.0.5
 Tested on a 5V Redboard and 3.3V Pro Mini
 **UPDATED FOR ARDUINO 1.6.4 5/2015**
 
 This code is beerware; if you see me (or any other SparkFun employee) at the
 local, and you've found our code helpful, please buy us a round!
 Distributed as-is; no warranty is given.
******************************************************************************/
 
#include "SparkFunVKeyVoltageKeypad.h"

/* Calibration data for each supply/reference voltage.
 * Unchanging, so declared as progmem.
 * 
 * See theory/ADC.ods for the derivation of these values, or
 * use that sheet to calculate for other voltages.
 */
const PROGMEM VKey::VKeyScale VKey::scales[MAX] =
{
   // min, step, max
   {115,    230,   2875},
   {115,    230,   2875}
};

/* Constructor.
 * Parameters specify details about the class:
 *    -pin = ADC pin number that the VKey output is attached to
 *    -reference = enumerated indication of supply & reference voltage
 */
VKey::VKey(uint8_t pin,
         eVref reference)
{
  // Store parameters as member data
  analog_pin = pin;
  scale_p    = &scales[reference];  
  
  // Initialize internal variables
  last_key   = KEY_NONE;
  
  // Configure related hardware
  pinMode(pin, INPUT);
}

/* checkKeys()
 * Sample the ADC.
 * Convert the sample into a key number.
 *
 * If the key is different than the last key seen, 
 * return true to indicate the change, otherwise return false.
 *
 * Always returns the current value in reference parameter k.
 *
 * This allows clients to query the present value,
 * or ignore the value when it is unchanging.
 */
bool VKey::checkKeys(eKeynum & k)
{
  int value;
  
  // Read the input voltage
  value = analogRead(analog_pin);

  // convert voltage to a key number
  k = voltageToKey(value);
  
  // Check to see if current key number is different than last seen 
  if(k != last_key)
  {
    // Update value in last_key
    last_key = k; 
    return true;
  }
  
  return false;
}

/* voltageToKey()
 * Private, internal conversion routine.
 * Given a raw value from the ADC, apply the data from the scale table, 
 * and calculate which key is pressed.
 */
VKey::eKeynum VKey::voltageToKey(int v)
{
  /* See theory/ADC.ods for the nitty-gritty.
   */

  VKey::eKeynum k;
  
  uint16_t bottom, step, top;
  
  // Read the constants from program memory
  bottom = pgm_read_word_near(&scale_p->offset);
  step = pgm_read_word_near(&scale_p->step_size);
  top = pgm_read_word_near(&scale_p->top);
  
  if( (v < bottom) || (v > top) )
  {
    // Value is in invalid range - equation doesn't apply
    k = KEY_NONE;
  }
  else
  {
    // Apply the calculation based on the configured constants.
    
    k = VKey::eKeynum(12 - ((v - bottom)/step));
  }
  
  return k;
}

Credits

Grzegorz Golba

Grzegorz Golba

1 project • 0 followers
Denisse Reyes

Denisse Reyes

1 project • 0 followers
Bryan Gutierrez

Bryan Gutierrez

1 project • 0 followers

Comments