Coding a sticky shift that activates a secondary set of keys

Hi everyone,
I am a new user of Arduino (my first time using it). I am working on programming a keyboard for MD patients. I have only 16 inputs to map 26 keys, and so I thought about a sticky shift concept:
A sticky shift works like this. You press a key that activates the sticky shift. This activates a secondary set of key definitions. When the second key is pressed, the key mappings revert back to the original. The concept is similar to phone keyboards where after typing a period (to end a sentence) often the shift key will automatically activate giving you temporary access to capital letters for the start of the next sentence.
However, I am having trouble implementing the idea.
Would appreciate any suggestions and orientation.

Before you get into sticky keys, you might want to read about keyboard/button matrices.

up to this point, I have managed to connect the sensors (Force sensor) with my Arduino and written a basic code that encodes 16 letters. This is an example of code for two sensors:

#include <Keyboard.h>
const int threshold = 800;
int up4 = 0;
int down4 = 0;
int right4 = 0;
int left4 = 0;

int up5 = 0;
int down5 = 0;
int right5 = 0;
int left5 = 0;

int yellow4= A0; // down
int white4 = A1;//left
int red4 = A2;//up
int blue4 = A3;//right 

int yellow5=A4;//down
int white5= A5;//left
int red5= A6;//up
int blue5 = A7;//right

void setup() 
{
  pinMode(red4, INPUT); 
  pinMode(blue4, INPUT);
  pinMode(white4, INPUT); 
  pinMode(yellow4, INPUT);

    pinMode(red5, INPUT); 
  pinMode(blue5, INPUT);
  pinMode(white5, INPUT); 
  pinMode(yellow5, INPUT);
  Serial.begin(9600);
  Keyboard.begin();
}

void loop()
{
  int up4 = analogRead(red4); 
  int right4 = analogRead(blue4);
  int down4 = analogRead(yellow4); 
  int left4 = analogRead(white4);

  int up5 = analogRead(red5); 
  int right5 = analogRead(blue5);
  int down5=analogRead(yellow5); 
  int left5 = analogRead(white5);

  if (right4>threshold & up4<threshold & down4<threshold & left4<threshold){
   Serial.println("right4");
   Keyboard.write('L');
   delay(300);
   
   Keyboard.releaseAll();
  }
  
    if (right5>threshold & up5<threshold & down5<threshold & left5<threshold){
   Serial.println("right5");
   Keyboard.write('Y');
   delay(300);
   Keyboard.releaseAll();
  }
  if (right4<threshold & up4>threshold & down4<threshold & left4<threshold){
   Serial.println("up4");
   Keyboard.write('M');
   delay(300);
   Keyboard.releaseAll();
  }
  if (right5<threshold & up5>threshold & down5<threshold & left5<threshold){
   Serial.println("up5");
   Keyboard.write('R');
   delay(300);
   Keyboard.releaseAll();
  }

   if (right4<threshold & up4<threshold & down4>threshold & left4<threshold){
    Serial.println("down4");
    Keyboard.write('N');
     delay(300);
     Keyboard.releaseAll();
  }
  if (right5<threshold & up5<threshold & down5>threshold & left5<threshold){
   Serial.println("down5");
   Keyboard.write('Z');
   delay(300);
   Keyboard.releaseAll();
  }
  if (right4<threshold & up4<threshold & down4<threshold & left4>threshold){
    Serial.println("left4");
    Keyboard.write('O');
     delay(300);
     Keyboard.releaseAll();
  }
      if (right5<threshold & up5<threshold & down5<threshold & left5>threshold){
   Serial.println("left5");
   Keyboard.write('P');
   delay(300);
   Keyboard.releaseAll();
  }

    
  
} 

MD as in muscular dystrophy? What about a button on a table or attached to a pedal depending on how the user is able to interact that "activates" the secondary set of key definitions? Would a momentary off-on-off (or on-off-on and use the internal pullup resistor in setup() which reverses the logic) work for you?

So

#include <Keyboard.h>
const int threshold = 800;
int up4 = 0;
int down4 = 0;
int right4 = 0;
int left4 = 0;

int up5 = 0;
int down5 = 0;
int right5 = 0;
int left5 = 0;

int yellow4 = A0; // down
int white4 = A1;//left
int red4 = A2;//up
int blue4 = A3;//right

int yellow5 = A4; //down
int white5 = A5; //left
int red5 = A6; //up
int blue5 = A7;//right

const int userPedal = 2;
int pedalState;

void setup() {
  pinMode(userPedal, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // initialize LED key set indicator to, say, on
  pedalState == HIGH; //initialize to key set A
}

void loop() {
  if (digitalRead(userPedal) == LOW) {
    delay(10); // read again below
    pedalState = digitalRead(userPedal); // stabilize first read, this will debounce button in basic way
    while (pedalState == LOW) {
      digitalWrite(LED_BUILTIN, LOW);
      keyDefsB();
    }
  }

  if (digitalRead(userPedal) == HIGH) {
    delay(10);
    pedalState = digitalRead(userPedal);
    while (pedalState == HIGH) {
      digitalWrite(LED_BUILTIN, HIGH);
      keyDefsA();
    }
  }
}

void keyDefsA() {
  int up4 = analogRead(red4);
  int right4 = analogRead(blue4);
  int down4 = analogRead(yellow4);
  int left4 = analogRead(white4);

  int up5 = analogRead(red5);
  int right5 = analogRead(blue5);
  int down5 = analogRead(yellow5);
  int left5 = analogRead(white5);

  if (right4 > threshold & up4 < threshold & down4 < threshold & left4 < threshold) {
    Serial.println("right4");
    Keyboard.write('L');
    delay(300);

    Keyboard.releaseAll();
  }

  if (right5 > threshold & up5 < threshold & down5 < threshold & left5 < threshold) {
    Serial.println("right5");
    Keyboard.write('Y');
    delay(300);
    Keyboard.releaseAll();
  }
  if (right4<threshold & up4>threshold & down4 < threshold & left4 < threshold) {
    Serial.println("up4");
    Keyboard.write('M');
    delay(300);
    Keyboard.releaseAll();
  }
  if (right5<threshold & up5>threshold & down5 < threshold & left5 < threshold) {
    Serial.println("up5");
    Keyboard.write('R');
    delay(300);
    Keyboard.releaseAll();
  }

  if (right4 < threshold & up4<threshold & down4>threshold & left4 < threshold) {
    Serial.println("down4");
    Keyboard.write('N');
    delay(300);
    Keyboard.releaseAll();
  }
  if (right5 < threshold & up5<threshold & down5>threshold & left5 < threshold) {
    Serial.println("down5");
    Keyboard.write('Z');
    delay(300);
    Keyboard.releaseAll();
  }
  if (right4 < threshold & up4 < threshold & down4<threshold & left4>threshold) {
    Serial.println("left4");
    Keyboard.write('O');
    delay(300);
    Keyboard.releaseAll();
  }
  if (right5 < threshold & up5 < threshold & down5<threshold & left5>threshold) {
    Serial.println("left5");
    Keyboard.write('P');
    delay(300);
    Keyboard.releaseAll();
  }
}

void keyDefsB() {
  // whatever your secondary set is
}

(this compiled for me with Due(Programming port) selected as I know that board supports this library)

1 Like

Thank you!
I want to try this, however, can any sensor be used as a pullup_input?

1 Like

You need a global or a static variable to hold a mode indicating if sticky keys is active or not. Below is to give you the idea.

void loop()
{
  static bool stickykeyActive = false;
  if(digitalRead(stickykeyButtonPin) == ISPRESSED)
  {
    stickykeyActive = true;
  }

  if(any of the buttons pressed)
  {
    if(stickykeyActive == true)
    {
      send alternate key

      stickykeyActive = false;
    }
    else
    {
      send normal key
    }
  }
}

I have never tried the INPUT_PULLUP with anything other than a pushbutton, but I think its a 20k resistor value so however you use that, I suppose it would work. Take a look at this, explains better than I could:
https://www.arduino.cc/en/Tutorial/Foundations/DigitalPins

Any sensor that has an active pull down (low impedance switch to ground) can. Most don't, they have a sink-source digital level signal.

Never really thought about this. Learn something every day!

Is there any way to know if my sensor has n active pull down?
this is my sensor : Force Sensor Interlink
Data Sheet : https://media.digikey.com/pdf/Data%20Sheets/Interlink%20Electronics.PDF/4-Zone_Mouse_Sensor_RevB.pdf

That device has no active circuitry or switches, just an internal resistor array. So you need to interface it to a circuit that responds to resistance changes. I guess you could find a way to interface it to the analog input pins.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.