Arduino Interactivity

Interactive pattern cheat sheet

To make interesting things with code one need to think in terms of combining the different programming components into basic structures. These structures are called patterns. Programming patterns differ depending on what kind of programming one is doing. When working with interaction design there is a set of commonly known strategies for making interactive elements. In the following we walk you through the different common strategies.


The secret trick to mastering programming is to recognize the patterns that makes up structures for common solutions to problems. In the following we have collected the most common patterns that everry interaction design programmer needs to know to create basic interactions.

We have tried to make the examples as generic as possible. Where there are only an example for one platform it should be relatively simple to convert it to the other. Be aware that the main method in processing is called draw() and it is called loop() in Arduino. Simply change the words depending on the platform used.

void setup()
{
  pinMode(2, INPUT_PULLUP);
}

void loop()
{
  boolean btnPressed = !digitalRead(2);
  if (btnPressed == true)
  {
    // button has been pressed.
  }
  else
  {
    // button isn not pressed
  }
}

Doing something while a button is pressed

To change something while a button is pressed. The code looks like this.

(diagram of using input_pullup)
boolean btnPressedOld = false;
void setup()
{
  pinMode(3, INPUT_PULLUP);
}

void loop()
{
  boolean btnPressed = !digitalRead(3);
  if (btnPressed == true && btnPressedOld == false)
  {
    // button has been pressed.
  }
  btnPressedOld = btnPressed;
}

Detecting a push button event

The above extample only works when you do something WHILE pressed. This is not the same as an event. An event is when something changes from one state to another. E.g. you want to do something when the button was released => Going from a pressed state to a not pressed state. This requires us to "remember" the old state an compare it to detect the change.

boolean btnPressedOld = false;
boolean toggle = false;

void setup()
{
  pinMode(3, INPUT_PULLUP);
}

void loop()
{
  boolean btnPressed = !digitalRead(3);
  if (btnPressed == true && btnPressedOld == false)
  {
    // button has been pressed.
    toggle = !toggle;

  }
  btnPressedOld = btnPressed;

  if (toggle == true)
  {
    // the butten has been toggled on.
  }
}

Make a toggle button

Toggling with a pushbutton is a common solution to turning things on an off. This is one way to do it.

unsigned long timer = 0;
void setup()
{

}

void loop()
{
  if (millis() - timer > 2000) // do something every two seconds)
  {
    timer = millis();
    //do something here
  }
}

Make an interval timer

To make something happen every x miliseconds. This pattern is a generic solution.

Since the timer increases at a fast pace at some point it will run out of space in the memory. When this happens it will overflow. This means that it will return to zero and start to count again. This can be embraced by letting your timer and millis overflow crazefully together. This pattern does this.

float activity = 0;
float signalOld = 0;
float signal = 0;
void setup()
{
}

void loop()
{
  signal = analogRead(0);
  activity = activity * 0.1f + 0.9f * abs(signal - signalOld);
  signalOld = signal;
}

Smoothen a noisy signal

If your signal is noisy or you want to have a more soft reaction pattern, then you can use a running avarage.

The two numbers should always add up to 1. If you want it to be more smooth then make 0.1 smaller e.g.: "..* 0.99f + 0.01f *..".

float smoothValue = 0;
void setup()
{}

void draw()
{
    float inputValue = analogRead(0); 
    smoothValue = smoothValue * 0.9f + 0.1f * inputValue;
}

Detecting activity

When you have a fluctuating signal it can in your interest to measure the amount of activity / change. This can be something like a microphone input etc.


float value = 0;
float speed = 0.04;
float direction = 1;

void setup() {}

void loop()
{
  
  value = value + direction * speed;
  if (value > 255 || value < 0)
  {
    value = constrain(value, 0, 255);
    direction = direction * -1;
  }
  analogWrite(11, value);
}

Fade in and fade out

To make something fade in and fade out you need to created a counter and add/subtract from it over time.

int currentState = 0;
int btnPressedOld = 0;

void setup()
{
  pinMode(2, INPUT_PULLUP);
}

void loop() {

  if (digitalRead(2) == false && btnPressedOld == true) {
    currentState = currentState + 1;
    if (currentState > 2) {
      currentState = 0;
    }
  }

  btnPressedOld = digitalRead(2);

  if (currentState == 0) {
    background(0);
  } else if (currentState == 1) {
    background(0, 255, 0);
  } else if (currentState == 2) {
    background(0, 255, 255);

  }
}

Creating a state machine

As the complexity of your code grows you will need to have multiple states where different lines of code should happpen:

long buttonPushedTime = 0;
const int buttonPin = 6; // whichever pin you actually have the button connected to. The button should connect the pin to ground when pushed.

void setup()
{
  // In setup:
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  // In loop:
  if (!digitalRead(buttonPin) && lastButtonState) {
    buttonPushedTime = millis();
  }
  if (!digitalRead(buttonPin) && millis() - buttonPushedTime > 3000) {
    //DO SOMETHING HERE
  }
  lastButtonState = digitalRead(buttonPin);
}

Detecting a long press

Check if a button has been pressed for a particular minimum time (in this example 3 seconds). This can provide safety (e.g. for a reset button, check that someone actually means it, not just touched the button by accident) and provides implicit debouncing of a glitchy signal.