Introduction: How to Make a Carrot Keyboard With Multi-Control

About: We're an ambitious team for developing STEM education by Arduino and Raspberry Pi learning kits as well as robots and aircraft models/drones. Happy to bring you more fun projects and works. Welcome to visit ou…

Last time, we share how to make a Whack-a-Mole game, which uses the Multi-Control’s gamepad function. As a multi-function board, it’s also equipped with keyboard function, which is to realize the same function as keyboard.

Any available conductor at home can be used as a key on keyboard. I happen to have a succulent carrot left, so let’s make a carrot keyboard.

Step 1: Prepare Materials

Multi-Control board - http://bit.ly/2sTJYxx

USB cable

Some alligator clip cables (included in Multi-Control kit)

Some Dupont wires (male to male) - http://bit.ly/2tXqPZN

Carrot (juicy one)

Utility knife

Computer

Step 2: Slice the Carrot Into Pieces

First, we should slice the carrot into pieces, ensure the slices are the same in thickness. And prepare two more slices just in case.

This step would be easy for you if you often cook. We prefer a fresh and juicy carrot to ensure good conductibility.

Step 3: Carve Into Letters

Cut those slices into the letters you like. Here I make them to SUNFOUNDER.

Note: the knife is quite sharp, so be careful to operate to prevent getting injured.

Step 4: Complete Wiring

First, clip each alligator clip cable to each male-to-male wire. Then connect the carrot pieces “SUNFOUNDER” to the holes of Multi-Control board one by one as follows:

Carrot pieces----------------------Multi-Control

S------------------------------------------UP

U----------------------------------------LEFT

N---------------------------------------DOWN

F----------------------------------------RIGHT

O--------------------------------------SELECT

U----------------------------------------START

N--------------------------------------------A

D--------------------------------------------B

E--------------------------------------------X

R--------------------------------------------Y

Extend the GND of Multi-Control with an alligator clip cable.

Step 5: Download the Code

Visit the WiKi page of Multi-Control, you can see the related resources.

Then go to Github page and download the code.

Or copy the code here:

/**********************************************************************
* Filename : multi-control-keyboard.ino * Description : SunFounder multi-control keyboard driver * Author : Dream * Brand : SunFounder * E-mail : service@sunfounder.com * Website : www.sunfounder.com * Update : V1.0.0 2017-3-15 * * * This code fits SunFounder multi-control product,which is used to simulate PC keyboard functions. * 1.joystick is mapped to the keyboard key * A->left ctrl, B->left alt, X-> key Z, Y->key X, * SELECT->SPACE, START->ENTER * easy-to-do DIY: * DEBUG When it is 1, it will print the debugging information. * JOYSTICK_SENSITIVITY 100 adjust the sensitivity of joystick, ranging 0-500 * MINTOUCH 938 sensitivity of holes(0-1023), the larger the parameter is, the more sensitive they will be. * In header file keymap.h, you can modify the holes' keyboard mapping **********************************************************************/ #include "Keyboard.h" #include "keymap.h"

#define DEBUG 0 // When it is 1, it will print the debugging information. #define JOYSTICK_SENSITIVITY 100 // adjust the sensitivity of joystick, ranging 0-500 #define MINTOUCH 938 // sensitivity of holes(0-1023), the larger the parameter is, the more sensitive they will be. #define Y_AXIS 1 // define axis X/Y,used in joystickHandle #define X_AXIS 0 #define debounceDelay 20

#define AxisUp 0 #define AxisDown 1 #define AxisLeft 2 #define AxisRight 3 #define PinUp 4 #define PinDown 5 #define PinLeft 6 #define PinRight 7 #define HoleUp 8 #define HoleDown 9 #define HoleLeft 10 #define HoleRight 11 #define PinA 12 #define PinB 13 #define PinX 14 #define PinY 15 #define PinStart 16 #define PinSelect 17 #define HoleA 18 #define HoleB 19 #define HoleX 20 #define HoleY 21 #define HoleStart 22 #define HoleSelect 23

// threshold of the joystick to shift to digital value, if larger than MAX, UP input; if smaller than MAX, DOWN input. int MAXJOYSTICK = 1023 - JOYSTICK_SENSITIVITY; int MINJOYSTICK = 0 + JOYSTICK_SENSITIVITY;

//============================================== // set pin numbers for the buttons: const int joystickXAxis = A0; const int joystickYAxis = A11; const int pinUp = 16; const int pinLeft = 15; const int pinDown = 14; const int pinRight = 13; const int pinA = 3; const int pinB = 2; const int pinX = 11; const int pinY = 5; const int pinStart = 0; const int pinSelect = 1; const int Mode = 7;

// analog clip hole: const int holeUp = A1; const int holeLeft = A2; const int holeDown = A3; const int holeRight = A4; const int holeSelect = A5; const int holeStart = A6; const int holeA = A7; const int holeB = A8; const int holeX = A9; const int holeY = A10; //==============================================

int statusMode = 0;// if mode on left(==0),hole key enable

//============================================== // Creat a struct type named status_struct struct status_struct{ int pin; // pin number int cStatus; // current_status int lStatus; // last_status int key; // key value bool isXY; // is x or y axis unsigned long dTime; // lastDebounceTime bool sent; // sent flag }; //============================================== // Creat an array, the member type is status_struct status_struct state[] = { // pin cStatus lStatus key isXY dTime sent {joystickYAxis, 0, 0, KEYBOARD_UP, Y_AXIS, 0, 0}, {joystickXAxis, 0, 0, KEYBOARD_LEFT, X_AXIS, 0, 0}, {joystickYAxis, 0, 0, KEYBOARD_DOWN, Y_AXIS, 0, 0}, {joystickXAxis, 0, 0, KEYBOARD_RIGHT, X_AXIS, 0, 0}, {pinUp, 0, 0, KEYBOARD_UP, Y_AXIS, 0, 0}, {pinDown, 0, 0, KEYBOARD_DOWN, Y_AXIS, 0, 0}, {pinLeft, 0, 0, KEYBOARD_LEFT, X_AXIS, 0, 0}, {pinRight, 0, 0, KEYBOARD_RIGHT, X_AXIS, 0, 0}, {holeUp, 0, 0, KEYBOARD_UP, Y_AXIS, 0, 0}, {holeDown, 0, 0, KEYBOARD_DOWN, Y_AXIS, 0, 0}, {holeLeft, 0, 0, KEYBOARD_LEFT, X_AXIS, 0, 0}, {holeRight, 0, 0, KEYBOARD_RIGHT, X_AXIS, 0, 0}, {pinA, 0, 0, KEYBOARD_A, NULL, 0, 0}, {pinB, 0, 0, KEYBOARD_B, NULL, 0, 0}, {pinX, 0, 0, KEYBOARD_X, NULL, 0, 0}, {pinY, 0, 0, KEYBOARD_Y, NULL, 0, 0}, {pinStart, 0, 0, KEYBOARD_START, NULL, 0, 0}, {pinSelect, 0, 0, KEYBOARD_SELECT, NULL, 0, 0}, {holeA, 0, 0, KEYBOARD_A, NULL, 0, 0}, {holeB, 0, 0, KEYBOARD_B, NULL, 0, 0}, {holeX, 0, 0, KEYBOARD_X, NULL, 0, 0}, {holeY, 0, 0, KEYBOARD_Y, NULL, 0, 0}, {holeStart, 0, 0, KEYBOARD_START, NULL, 0, 0}, {holeSelect, 0, 0, KEYBOARD_SELECT, NULL, 0, 0}}; //==============================================

// initialize the buttons' inputs: void setup() { pinMode(pinUp, INPUT_PULLUP); pinMode(pinLeft, INPUT_PULLUP); pinMode(pinDown, INPUT_PULLUP); pinMode(pinRight, INPUT_PULLUP); pinMode(pinA, INPUT_PULLUP); pinMode(pinB, INPUT_PULLUP); pinMode(pinX, INPUT_PULLUP); pinMode(pinY, INPUT_PULLUP); pinMode(pinStart, INPUT_PULLUP); pinMode(pinSelect, INPUT_PULLUP); pinMode(Mode, INPUT_PULLUP);

Serial.begin(9600); Keyboard.begin(); }

void debounced_read(int num){ // digitalRead and dithering elimination int reading = digitalRead(state[num].pin);

if (reading != state[num].lStatus) { state[num].dTime = millis(); }

if ((millis() - state[num].dTime) > debounceDelay) { if (reading != state[num].cStatus) { state[num].cStatus = reading; Serial.println("have a input"); state[num].sent = 1; } } state[num].lStatus = reading; }

void analog_read(int num){ // analogRead, and shift to digital one to store bool threshold; int value = analogRead(state[num].pin); if(num < 4){ // if is joystick pin if(num==0 || num==3) // if is up or right threshold = (value > MAXJOYSTICK); else if (num==1 || num==2) // if is down or left threshold = (value < MINJOYSTICK); } else // if is hole pin threshold = (value < MINTOUCH);

if (threshold) // the status is pressed state[num].cStatus = 0; else // the status is released state[num].cStatus = 1;

if (state[num].lStatus != state[num].cStatus) { // handle it when its state changes state[num].sent = 1; state[num].lStatus = state[num].cStatus; } }

void readStatus() { // read status debounced_read(PinUp); debounced_read(PinDown); debounced_read(PinLeft); debounced_read(PinRight); debounced_read(PinA); debounced_read(PinB); debounced_read(PinX); debounced_read(PinY); debounced_read(PinStart); debounced_read(PinSelect);

analog_read(AxisUp); analog_read(AxisDown); analog_read(AxisLeft); analog_read(AxisRight);

statusMode = digitalRead(Mode); if (statusMode == 0){ // Enable Hole Mode analog_read(HoleUp); analog_read(HoleLeft); analog_read(HoleDown); analog_read(HoleRight); analog_read(HoleA); analog_read(HoleB); analog_read(HoleX); analog_read(HoleY); analog_read(HoleStart); analog_read(HoleSelect); } }

// Serial Plotter void debug(int value){ Serial.print(value);Serial.print(','); } void printValue(bool holes, bool axis, bool pins){ if (holes){ // printValue holes status debug(state[HoleUp].cStatus); debug(state[HoleLeft].cStatus); debug(state[HoleDown].cStatus); debug(state[HoleRight].cStatus); debug(state[HoleSelect].cStatus); debug(state[HoleStart].cStatus); debug(state[HoleA].cStatus); debug(state[HoleB].cStatus); debug(state[HoleX].cStatus); debug(state[HoleY].cStatus); debug(MINTOUCH); } if (axis){ // printValue axis status debug(state[AxisUp].cStatus); debug(state[AxisDown].cStatus); debug(state[AxisLeft].cStatus); debug(state[AxisRight].cStatus); debug(state[AxisUp].lStatus); debug(state[AxisDown].lStatus); debug(state[AxisLeft].lStatus); debug(state[AxisRight].lStatus); } if (pins){ // printValue pins status debug(state[PinUp].cStatus); debug(state[PinDown].cStatus); debug(state[PinLeft].cStatus); debug(state[PinRight].cStatus); debug(state[PinA].cStatus); debug(state[PinB].cStatus); debug(state[PinX].cStatus); debug(state[PinY].cStatus); debug(state[PinStart].cStatus); debug(state[PinSelect].cStatus); } Serial.println(' '); }

// Handle press command void pressHandle(int key) { Keyboard.press(key); }

// Handle release command void releaseHandle(int key) { Keyboard.release(key); }

// Handle for Buttons functions void keyHandle(int num){ if (state[num].sent) { if (state[num].cStatus == 0){ debug(state[num].cStatus);debug(state[num].lStatus); //Serial.print(num);Serial.println(" pressed"); pressHandle(state[num].key); } else releaseHandle(state[num].key); state[num].sent = 0; } delay(1); }

// Scan all the buttons status void scan() { // Buttons keyHandle(PinUp); keyHandle(AxisUp); keyHandle(PinDown); keyHandle(AxisDown); keyHandle(PinLeft); keyHandle(AxisLeft); keyHandle(PinRight); keyHandle(AxisRight); keyHandle(PinA); keyHandle(PinB); keyHandle(PinX); keyHandle(PinY); keyHandle(PinStart); keyHandle(PinSelect);

if (statusMode == 0){ // Enable Hole Mode keyHandle(HoleUp); keyHandle(HoleDown); keyHandle(HoleLeft); keyHandle(HoleRight); keyHandle(HoleA); keyHandle(HoleB); keyHandle(HoleX); keyHandle(HoleY); keyHandle(HoleStart); keyHandle(HoleSelect); } }

void loop() { readStatus(); //printValue(1,1,1); // holes, axis, pins scan(); }

Step 6: Modify and Upload the Code

Unzip the download package. Open multi-control-keyboard.ino code, and click kepmap.h to modify the mapping of keyboard values.

Then select the board type (Leonardo) and port, and upload the code.

Step 7: Carrot Keyboard! So Cool!!

After uploading successfully, create and open a new file. Hold the GND cable at one hand, and touch those carrot slices to type the corresponding words. Enjoy the intriguing carrot keyboard!

Note:

1. Remember to turn on the Caps Lock before typing;

2. You need to turn on the Touch Input Control switch.