Introduction: A Piano With Banana As Keyboard Powered by PcDuino
we will detail how to use Touch key USB Shield and pcDuino to implement a piano with banana as keyboard.
Step 1: How to Simulate Keyboard Input?
(1) In order to inject keystrokes, we need to map the touch events from banana to standard keystrokes event, such as KEY_0, KEY_Z, etc, which corresponds to keystrokes from 0-9, X_Z. More specifically, we need to use a file ‘/dev/input/event/X’, and write a data structure named input_event to it to inject a certain keystroke. To find out all the input devices, we can use the following command: $cat /proc/bus/input/devices. We found out that in our case, event1 is the keyboard.
(2) Now that we found out the input file, we need to write the data structure input_event to it. The event is defined in /usr/include/linux/input.h. We need to fill it with the keystroke we want to inject. The structure is defined as following:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
}
type: The type of event.
EV_KEY: the keystroke event, for example, which key is pressed in keyboard, and if left button or right button of the mouse is pressed.
EV_REL: The relative coordinates, which mainly refers to the movement of mouse
EV_ABS: absolute coordinates, which mainly refers to the touch screen.
code: the code of event. If the type is EV_KEY, the code is the key code. Code 0-127 refers to the key of keyboard. Code 0×110-0×116 refers to the press code of the mouse, where 0×110 (BTM_LEFT) means the left button of the mouse, 0×111 (BTN_RIGHT) means the right button of the mouse, 0×112 (BTN_MIDDLE) means the middle button of the mouse. For other code, please refer to file “/usr/include/linux /input.h”.
Value: the value of the event. When the type is EV_KEY, when the key is pressed down, the value is 1, and 0 when it is released. If the type is EV_REL, the positive and negative value means the relative movement in two different directions.
Makey Makey use USB-HID to simulate keyboard event to the host PC. In pcDuino, scratch is running itself on pcDuino, so we can directly inject keystroke.
(2) Now that we found out the input file, we need to write the data structure input_event to it. The event is defined in /usr/include/linux/input.h. We need to fill it with the keystroke we want to inject. The structure is defined as following:
struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
}
type: The type of event.
EV_KEY: the keystroke event, for example, which key is pressed in keyboard, and if left button or right button of the mouse is pressed.
EV_REL: The relative coordinates, which mainly refers to the movement of mouse
EV_ABS: absolute coordinates, which mainly refers to the touch screen.
code: the code of event. If the type is EV_KEY, the code is the key code. Code 0-127 refers to the key of keyboard. Code 0×110-0×116 refers to the press code of the mouse, where 0×110 (BTM_LEFT) means the left button of the mouse, 0×111 (BTN_RIGHT) means the right button of the mouse, 0×112 (BTN_MIDDLE) means the middle button of the mouse. For other code, please refer to file “/usr/include/linux /input.h”.
Value: the value of the event. When the type is EV_KEY, when the key is pressed down, the value is 1, and 0 when it is released. If the type is EV_REL, the positive and negative value means the relative movement in two different directions.
Makey Makey use USB-HID to simulate keyboard event to the host PC. In pcDuino, scratch is running itself on pcDuino, so we can directly inject keystroke.
Step 2: Hardware Setup
Hardware List:
1 x pcDuino
1x Touch keyUSB shield
Several clamp wires
5 bananas
If your monitor doesn’t have speakers, you will also need a usb sound card and a speaker (or headset).
In case you want to use USB sound card, you must modify the pcDunio audio output device.
Check the sound card of pcDuino:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ubuntu@ubuntu:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Device [Generic USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 1: sun4isndhdmi [sun4i-sndhdmi], device 0: SUN4I-HDMIAUDIO sndhdmi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
From the above message you can see my pcDuino has two sound cards.
Note: You need to power on pcDuino with USB sound card installed in order for pcDuino to load the sound card drive automatically.
Configure pcDuino to use the usb sound card as sound card:
1
2
3
4
5
6
7
$vim /etc/asound.conf
default.pcm.card 0
default.pcm.device 0
default.ctl.card 0
Reboot pcDuino by using:
$ sudo reboot
1 x pcDuino
1x Touch keyUSB shield
Several clamp wires
5 bananas
If your monitor doesn’t have speakers, you will also need a usb sound card and a speaker (or headset).
In case you want to use USB sound card, you must modify the pcDunio audio output device.
Check the sound card of pcDuino:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ubuntu@ubuntu:~$ aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Device [Generic USB Audio Device], device 0: USB Audio [USB Audio]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 1: sun4isndhdmi [sun4i-sndhdmi], device 0: SUN4I-HDMIAUDIO sndhdmi-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
From the above message you can see my pcDuino has two sound cards.
Note: You need to power on pcDuino with USB sound card installed in order for pcDuino to load the sound card drive automatically.
Configure pcDuino to use the usb sound card as sound card:
1
2
3
4
5
6
7
$vim /etc/asound.conf
default.pcm.card 0
default.pcm.device 0
default.ctl.card 0
Reboot pcDuino by using:
$ sudo reboot
Step 3: Code
#include <core.h>
#include <stdio.h>
#include <string.h>
#include <linux/input.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>
int InData1 = 0;
int InData2 = 0;
int InData3 = 0;
int InData4 = 0;
int InData5 = 0;
int TouchSensitivity = 800;
int num = 38;
void simulate_key(int fd, int kval)
{
struct input_event event;
gettimeofday(&event.time, 0);
event.type = EV_KEY;
event.value = 1;
event.code = kval;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, 0);
event.type = EV_KEY;
event.value = 0;
event.code = kval;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}
void simulate_mouse(int fd, int rel_x, int rel_y)
{
struct input_event event;
gettimeofday(&event.time, 0);
event.type = EV_REL;
event.value = rel_x;
event.code = REL_X;
write(fd, &event, sizeof(event));
event.type = EV_REL;
event.value = rel_y;
event.code = REL_Y;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}
void setup()
{
for(int i = 6; i <= 12; i++)
{
pinMode(i, OUTPUT);
}
}
void loop()
{
int fd_mouse ;
int fd_kbd ;
int i = 0;
fd_kbd = open("/dev/input/event1", O_RDWR);
if(fd_kbd <= 0)
{
printf("Can not open keyboard input file\n");
while(1);
}
while(1)
{
InData1 = analogRead(A1);
InData2 = analogRead(A2);
InData3 = analogRead(A3);
InData4 = analogRead(A4);
InData5 = analogRead(A5);
if(InData1 <= num)
{
digitalWrite(7, HIGH);
simulate_key(fd_kbd, KEY_S);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(7, LOW);
if(InData2 <= TouchSensitivity)
{
digitalWrite(8, HIGH);
simulate_key(fd_kbd, KEY_D);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(8, LOW);
if(InData3 <= TouchSensitivity)
{
digitalWrite(9, HIGH);
simulate_key(fd_kbd, KEY_F);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(9, LOW);
if(InData4 <= TouchSensitivity)
{
digitalWrite(10, HIGH);
simulate_key(fd_kbd, KEY_G);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(10, LOW);
if(InData5 <= TouchSensitivity)
{
digitalWrite(11, HIGH);
simulate_key(fd_kbd, KEY_H);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(11, LOW);
delay(100);
}
}
The code can be downloaded from here (https://github.com/pcduino/scratch4pcduino_project/blob/master/TestCode.ino).
#include <stdio.h>
#include <string.h>
#include <linux/input.h>
#include <fcntl.h>
#include <sys/time.h>
#include <unistd.h>
int InData1 = 0;
int InData2 = 0;
int InData3 = 0;
int InData4 = 0;
int InData5 = 0;
int TouchSensitivity = 800;
int num = 38;
void simulate_key(int fd, int kval)
{
struct input_event event;
gettimeofday(&event.time, 0);
event.type = EV_KEY;
event.value = 1;
event.code = kval;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
memset(&event, 0, sizeof(event));
gettimeofday(&event.time, 0);
event.type = EV_KEY;
event.value = 0;
event.code = kval;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}
void simulate_mouse(int fd, int rel_x, int rel_y)
{
struct input_event event;
gettimeofday(&event.time, 0);
event.type = EV_REL;
event.value = rel_x;
event.code = REL_X;
write(fd, &event, sizeof(event));
event.type = EV_REL;
event.value = rel_y;
event.code = REL_Y;
write(fd, &event, sizeof(event));
event.type = EV_SYN;
event.value = 0;
event.code = SYN_REPORT;
write(fd, &event, sizeof(event));
}
void setup()
{
for(int i = 6; i <= 12; i++)
{
pinMode(i, OUTPUT);
}
}
void loop()
{
int fd_mouse ;
int fd_kbd ;
int i = 0;
fd_kbd = open("/dev/input/event1", O_RDWR);
if(fd_kbd <= 0)
{
printf("Can not open keyboard input file\n");
while(1);
}
while(1)
{
InData1 = analogRead(A1);
InData2 = analogRead(A2);
InData3 = analogRead(A3);
InData4 = analogRead(A4);
InData5 = analogRead(A5);
if(InData1 <= num)
{
digitalWrite(7, HIGH);
simulate_key(fd_kbd, KEY_S);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(7, LOW);
if(InData2 <= TouchSensitivity)
{
digitalWrite(8, HIGH);
simulate_key(fd_kbd, KEY_D);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(8, LOW);
if(InData3 <= TouchSensitivity)
{
digitalWrite(9, HIGH);
simulate_key(fd_kbd, KEY_F);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(9, LOW);
if(InData4 <= TouchSensitivity)
{
digitalWrite(10, HIGH);
simulate_key(fd_kbd, KEY_G);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(10, LOW);
if(InData5 <= TouchSensitivity)
{
digitalWrite(11, HIGH);
simulate_key(fd_kbd, KEY_H);
delay(500);
InData1 = 2000;
InData2 = 2000;
InData3 = 2000;
InData4 = 2000;
InData5 = 2000;
}
else digitalWrite(11, LOW);
delay(100);
}
}
The code can be downloaded from here (https://github.com/pcduino/scratch4pcduino_project/blob/master/TestCode.ino).
Step 4: Enjoy!
Install scratch:$sudo apt-get install pcduino-scratch
The scratch project can be downloaded here. (banana_piano).
Run the code (the sample code from previous section) used to make banana as keyboard.
Run the the banana project in scratch.
Enjoy!
https://github.com/pcduino/scratch4pcduino_project/blob/master/banana_piano.sb
The scratch project can be downloaded here. (banana_piano).
Run the code (the sample code from previous section) used to make banana as keyboard.
Run the the banana project in scratch.
Enjoy!
https://github.com/pcduino/scratch4pcduino_project/blob/master/banana_piano.sb