ITIC:Hardware workshop with Arduino

From Juneday education
Jump to: navigation, search

Goal

The idea and goal of this workshop is to hopefully give a better understanding of how hardware is communicating with the computer (and operating system). In this workshop you will also get an idea of how software is written, in this case a software to read buttons (actually the state of the button: pressed or released) and send signals to a computer. So we will see some of the constructs we will look into in the chapter ITIC:Software_and_programming_introduction.

Disclaimer

Some of the picture on this page shows an Arduino UNO instead of an Arduino Leonardo. This was because the authors had limited access to the Leonardo board. Where an UNO is displayed the UNO will suffice, but when it comes to using code to send keyboard signals to the computer an Arduino Leonardo MUST BE USED.

Introduction

In this workshop we will an Arduino which is a company and also refers to a whole bunch of different microcontrollers (small computers and in this case without an operating system) and software to program these microcontrollers. We use Arduino to demonstrate how hardware (the Arduino) and software (which we will write) interacts with a computer. We will do everything in small steps and discuss these steps so we (hopefully) get a clearer understanding.

Hardware and software requirements

Hardware

  • Some kind of component kit (easier than buying separate components) containing:
    • 4 buttons
    • 4 leds
    • 13 cables
    • 1 breadboard

The authors have a tendency to destroy hardware and perhaps you're on of us..... so make sure you have some in spare.

In Sweden you can buy Arduino stuff at many places, e g:

Software

You need a suite of programs to build and transfer the program from your program to the Arduino. We suggest to start with Arduino IDE (not the web editor). Download and install this program.

This software is a suite of many programs which will be briefly discussed below:

  • compiler - in its broadest sense. A compiler can be divided into a suite of smaller programs as well.
  • editor - (and possibly also check out Editor
  • download/upload/manipulate the memory of an Arduino

Workshop - building a keyboard

In this workshop we will build a keyboard using cheap hardware and software to program this hardware.

Part I - physical keyboard

Let's start with looking at a USB keyboard. You connect such a keyboard to a computer and hopefully you will be able to get the keys you press on the keyboard in some way "transferred" to the computer. Of course there are no letters transferred. Instead it is electrical signals sent back and forth between the keyboard and the keyboard. Of course there is a standardised way to send for example an a from the keyboard (using electrical signals). This standard makes it, as you probably have figured out already, easy to write both keyboard and software on the computer to handle the keyboard signals. Every keyboard talks to the computer the same way - and if they don't you need separate drivers (software components extending the operating system).

So let's have a look two keyboards, one connected internally and one via USB:

Laptop-kbd.jpg Keyboard-usb.jpg

If we open up the USB keyboard we can see the following:

Keyboard-inner.jpg

There are a lot of wires going all over the plastic film. These are connected to a small integrated circuit in the top left corner - perhaps a bit hard to see. Looking at this we can hopefully be ok with the keyboard having some way (electrical) to notice if a key is pressed. When noticing this the integrated circuit sends some signal to the computer (or what ever is connected) via the USB cable. This is all we need to understand for now.

Part II - one button

We should now start building a keyboard ourselves. Let's start with a simple button with 2 connectors. When pressing this we want a led to be lit and when releasing it the led shall be unlit. So we need a button and a led. These both components need to have ground (GND) and some voltage. Let's start with the button alone (no led).

Prepare the hardware

Connect the button to GND and to the input pin 9 using wires. The picture below show you how:

Arduino-button-2pin.jpg


Write the software

Start up the Arduino IDE. Create a new sketch, called "button-led". Add the following code:

// Variables for our button
int button = 9;


/**********************************************************
 * 
 * void setup()
 * 
 * description:
 *  Sets up the hardware 
 * 
 ***********************************************************/
void setup() {
  // Set the mode of our Button pin to INPUT
  pinMode(button, INPUT);

  // Setup Serial 
  Serial.begin(9600);
}


/**********************************************************
 * 
 * int read_button(int button)
 * 
 * parameters:
 *   button  - the pin to read the value from
 * 
 * return:
 *   int - 1 if button is pressed, 0 otherwise
 * 
 * description:
 *  reads and returns the INPUT pin value
 * 
 ***********************************************************/
int read_button(int button) {

  // Set pin to high (before read)
  digitalWrite(button, HIGH);

  // read and return the reversed value
  return !digitalRead(button);
}


/***********************************************************
 *  loop()
 *  
 *  After setup this function is called repeatedly
 *  
 ***********************************************************/
void loop() {

  // Set led to LOW to not fuke things up when reading button
  digitalWrite(led,LOW); 

  if ( read_button(button) ) {
    Serial.println(1);
  } else {
    Serial.println(0);
  }
  
  // response delay might be up to 200 ms, 5 repeats per second should be ok
  delay(200);
}
 1 void loop() {
 2 
 3   // Set led to LOW to not fuke things up when reading button
 4   digitalWrite(led,LOW); 
 5 
 6   if ( read_button(button) ) {
 7     Serial.println(1);
 8   } else {
 9     Serial.println(0);
10   }
11   
12   // response delay might be up to 200 ms, 5 repeats per second should be ok
13   delay(200);
14 }

This code is executed repeatedly (until the power goes off). Let's see what the code does:

  • line 3: a comment - not part of the program. Merely for the developers
  • line 4: a fix for the hardware, we can ignore this
  • line 6: checks if the button is pressed
  • line 7: button is pressed, print 1 to the serial monitor
  • line 8: else (that is, if the button is not pressed
  • line 7: button is released, print 0 to the serial monitor
  • line 13: sleep for a while (200 ms)

Build and upload the software to the hardware

In Arduino IDE:

  • save (Ctrl-S), compile (Ctrl-R) and upload (Ctrl-U) the code to the Arduino.
  • start the serial monitor (Shift-Ctrl-M)

Now you should be able to see the number 0 printed to the serial monitor and when pressing the button the number 1 should be written to the serial monitor.

Part III - one button with one led

Prepare the hardware

Connect the led's short pin to GND and the led's long pin to pin 4 using wires. You should keep the wirings for the button. The pictures below show you how both the button and led are connected:

Arduino-button-led-2pin.jpg Arduino-kbd-wiring.jpg

Write the software

Continue with the sketch, called "button-led". Change the loop() part of the code to the following:

 1 void loop() {
 2 
 3   // Set led to LOW to not fuke things up when reading button
 4   digitalWrite(led,LOW); 
 5 
 6   if ( read_button(button) ) {
 7     Serial.println(1);
 8     digitalWrite(led, HIGH);
 9   } else {
10     Serial.println(0);
11     digitalWrite(led, LOW);
12   }
13   
14   // response delay might be up to 200 ms, 5 repeats per second should be ok
15   delay(200);
16 }

This code is executed repeatedly (until the power goes off). Let's see what the code does:

  • line 3: a comment - not part of the program. Merely for the developers
  • line 4: a fix for the hardware, we can ignore this
  • line 6: checks if the button is pressed
  • line 7: button is pressed, print 1 to the serial monitor
  • line 8: button is pressed, set pin led (variable withe value 4, so pin 4) to high
  • line 9: else (that is, if the button is not pressed
  • line 10: button is released, print 0 to the serial monitor
  • line 11: button is released, set pin led (variable withe value 4, so pin 4) to low
  • line 15: sleep for a while (200 ms)

You also need to add one line (the highlighted), like this:

// Variables for our button
int button = 9;
int led = 4;

Part IV - five button with five leds

Hardware

Now let's extend our button/led board to five button/led pairs. This will give us a very limited keyboard - only five keys. We will not write any code to send signal to generate a letter to the keyboard - that is we will still send letters to the serial monitor but we will not write code to make the Arduino act as a keyboard.

Arduino-kbd-pins.jpg Arduino-kbd-pins-II.jpg

Arduino-kbd-pins-III.jpg

The led/button pairs will (in the next section) be parts of our limited keyboard according to the picture below.

Arduino-kbd-layout.jpg

Software

The code to handle this will need to be restructured a bit. Some of the things we will do with one button and led is similar to what we do with another. So we will generalise our code and write a new function (a block of code) to achieve this.

Open a new sketch, called keyboard, in the Arduino IDE. Here's some code to copy/paste into the IDE.

/*
 *
 *  keyboard.ino - use button to send keys via USB
 *
 *  This code is written with some pedagogical concerns in mind.
 *  The code is not in any way written to be optimal or flexible.
 *  A struct and an array would, as two examples, make the code way better.
 *  
 *  (c) Henrik Sandklef and Rikard Fröberg (juneday.se) 2019
 * 
 *  License: none, consider this code to be under Public Domain
 * 
 */
#include "Keyboard.h"


// Variables for our leds
int led_L = 4;
int led_P = 5;
int led_S = 6;
int led_BackSpace = 7;
int led_Enter = 8;

// Variables for our button
int button_L = 9;
int button_P = 10;
int button_S = 11;
int button_BackSpace = 12;
int button_Enter = 13;


/**********************************************************
 * 
 * void setup()
 * 
 * description:
 *  Sets up the hardware 
 * 
 ***********************************************************/
void setup() {
  // Set the mode of our BUtton pins to INPUT
  pinMode(button_L, INPUT);
  pinMode(button_P, INPUT);
  pinMode(button_S, INPUT);
  pinMode(button_BackSpace, INPUT);
  pinMode(button_Enter, INPUT);

  // Set the mode of our Led pins to OUTPUT
  pinMode(led_L, OUTPUT);
  pinMode(led_P, OUTPUT);
  pinMode(led_S, OUTPUT);
  pinMode(led_BackSpace, OUTPUT);
  pinMode(led_Enter, OUTPUT);

  // Setup Serial 
  //  Serial.begin(9600);
}


/**********************************************************
 * 
 * int read_button(int button)
 * 
 * parameters:
 *   button  - the pin to read the value from
 * 
 * return:
 *   int - 1 if button is pressed, 0 otherwise
 * 
 * description:
 *  reads and returns the INPUT pin value
 * 
 ***********************************************************/
int read_button(int button) {

  // Set pin to high (before read)
  digitalWrite(button, HIGH);

  // read and return the reversed value
  return !digitalRead(button);
}

/***********************************************************
 *
 * void handle_button(int button, int led, int character) 
 * 
 * parameters:
 *   button  - the pin to read the value from
 *   led     - the led to lit if button is pressed
 *   character - the character to send to the computer connected via USB
 * 
 * description:
 *  if the button is pressed the led is lit and the character is sent via USB
 *  if the button is not pressed, nothing is done
 *
 ***********************************************************/
void handle_button(int button, int led, int character) {

  // Set led to LOW to not fuke things up when reading button
  digitalWrite(led,LOW); 

  if ( read_button(button) ) {
    digitalWrite(led,HIGH);
    Serial.write(character);
  } else {
    digitalWrite(led,LOW); 
  }
  
}

/***********************************************************
 *  loop()
 *  
 *  After setup this function is called repeatedly
 *  
 ***********************************************************/
void loop() {

  // Handle the buttons
  handle_button(button_L, led_L, 'l');  
  handle_button(button_P, led_P, 'p');  
  handle_button(button_S, led_S, 's');  
  handle_button(button_BackSpace, led_BackSpace, '\b');  
  handle_button(button_Enter, led_Enter, '\n'); 

  // 3 repeats per second is ok, so sleep 300 ms
  // Probably an ok balance between responsiveness and repeat
  delay(300);
}

Part V - five button with five leds

Hardware

Now let's extend our five button/led pairs with some code to acto as a keyboard. This will give us a very limited keyboard - only five keys. We will not write any code to send signal to generate a letter to the keyboard - that is we will still send letters to the serial monitor but we will not write code to make the Arduino act as a keyboard.

Part VI - five key keyboard - with serial monitor printouts

Software

Continue sketch, called keyboard, in the Arduino IDE. We're going to change the code in the function (block of code) setup and handle_button.

setup
void setup() {
  // Set the mode of our BUtton pins to INPUT
  pinMode(button_L, INPUT);
  pinMode(button_P, INPUT);
  pinMode(button_S, INPUT);
  pinMode(button_BackSpace, INPUT);
  pinMode(button_Enter, INPUT);

  // Set the mode of our Led pins to OUTPUT
  pinMode(led_L, OUTPUT);
  pinMode(led_P, OUTPUT);
  pinMode(led_S, OUTPUT);
  pinMode(led_BackSpace, OUTPUT);
  pinMode(led_Enter, OUTPUT);

  // Setup keyboard 
  Keyboard.begin();

  // Setup Serial 
  Serial.begin(9600);
}

The change made is the call to Keyboard.begin() initializes the keyboard module to make it possible to send keyboard signals to the computer.

handle_button
void handle_button(int button, int led, int character) {
  // Set led to LOW to not fuke things up when reading button
  digitalWrite(led,LOW); 

  if ( read_button(button) ) {
    // if the user has pressed the button, send the character
    Keyboard.write(character);    
    digitalWrite(led,HIGH);
    Serial.write(character);
  } else {
    digitalWrite(led,LOW); 
  }
  
}

The change made is that we're now sending a keyboard signal (passed as argument (extra information) to the function) to the computer when the button is pressed. No need to do anything when the button is released.

Five key keyboard - with NO serial monitor printouts

Remove the code dealing with the serial monitor. We can do this by turning that code to comments:

  // Setup Serial 
  // Serial.begin(9600);

and

  // Serial.write(character);

Conclusion

We now have a pieace of hardware (the Arduino Leonardo) and some software (keyboard.ino), which you can find over at github that acts as a keyboard.

Hopefully you will get an idea of how a keyboard reacts on a user pressing a key and also how to transfer data between (external) hardware and a computer via USB. This should also give some ideas on what programming is all about.

Links

Videos

Further reading

More on this wiki

If you follow the [to IT and Computing] teaching materials, you may want to get back to the module on Computers and hardware.