Fun Projects with Arduino
Authors
In this lesson, we will play around with Wokwi Arduino simulator using Arduino Uno. Copy the code below to diagram.json in the WokWi simulator to setup the circuit.
{
"version": 1,
"author": "Ben Hastings",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 135, "left": 28.2, "attrs": {} },
{
"type": "wokwi-resistor",
"id": "r1",
"top": 33.6,
"left": 220.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{ "type": "wokwi-led", "id": "led", "top": -51.6, "left": 224.6, "attrs": { "color": "red" } },
{
"type": "wokwi-led",
"id": "led1",
"top": -51.6,
"left": 176.6,
"attrs": { "color": "green" }
},
{
"type": "wokwi-led",
"id": "led2",
"top": -51.6,
"left": 128.6,
"attrs": { "color": "purple" }
},
{
"type": "wokwi-resistor",
"id": "r2",
"top": 24,
"left": 124.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-resistor",
"id": "r3",
"top": 33.6,
"left": 172.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": 255.8,
"left": 345.6,
"attrs": { "color": "red" }
},
{
"type": "wokwi-pushbutton",
"id": "btn2",
"top": 179,
"left": 345.6,
"attrs": { "color": "yellow" }
},
{
"type": "wokwi-pushbutton",
"id": "btn3",
"top": 92.6,
"left": 345.6,
"attrs": { "color": "green" }
}
],
"connections": [
[ "r1:1", "led:A", "red", [] ],
[ "uno:3", "r1:2", "red", [ "v0" ] ],
[ "led:C", "uno:GND.1", "black", [ "h-18.8", "v96", "h-77.1" ] ],
[ "r3:2", "uno:4", "green", [ "h0" ] ],
[ "led1:C", "uno:GND.1", "black", [ "h-18.8", "v86.4", "h-29.1" ] ],
[ "led1:A", "r3:1", "green", [ "v0" ] ],
[ "r2:2", "uno:5", "purple", [ "v37.2", "h76.8", "v48" ] ],
[ "r2:1", "led2:A", "purple", [ "h0" ] ],
[ "led2:C", "uno:GND.1", "black", [ "h-76.4", "v115.2", "h76.5" ] ],
[ "btn1:2.r", "uno:GND.3", "black", [ "v67.4", "h-205.4" ] ],
[ "btn2:2.r", "uno:GND.3", "black", [ "h9.8", "v153.8", "h-215.2" ] ],
[ "btn3:2.r", "uno:GND.3", "black", [ "h19.4", "v249.8", "h-224.8" ] ],
[ "btn3:1.l", "uno:9", "green", [ "h-153.6", "v38.4" ] ],
[ "btn2:1.l", "uno:10", "yellow", [ "v-67.2", "h-163.9" ] ],
[ "btn1:1.l", "uno:11", "red", [ "h-38.4", "v-153.6", "h-135" ] ]
],
"dependencies": {}
}Section 1: Flashing LEDs
In this section, we will create programs that turn different LEDs on and off by using the Arduino’s digitalWrite() function.
For each exercise, write the code to the sketch.ino tab in the Wokwi simulator and click on the green arrow to run the program and observe its effects.
Exercises
Example: Write a program that sets the 3rd digital output pin to HIGH to turn on the red LED.
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(3, OUTPUT);
digitalWrite(3, HIGH);
}
void loop() {
}Exercise: Write a program that sets the 3rd and 4th digital output pin to HIGH to turn on the red and greed LEDs
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
}
void loop() {
}Exercise: Write a program that sets the 3rd, 4th and 5th digital output pin to HIGH to turn on all three LEDs.
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
}
void loop() {
}Exercise: Write a program that:
- turns on all LEDs
- waits 300 milliseconds
- turns off the blue LED (attached to digitial output pin 5)
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
delay(300);
digitalWrite(5, LOW);
}
void loop() {
}Exercise: Write a program with a loop() that turns the red LED on and off, every second (forever).
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(3, OUTPUT);
}
void loop() {
digitalWrite(3, HIGH);
delay(1000);
digitalWrite(3, LOW);
delay(1000);
}Exercise: Write a program with a loop() that turns the green LED on and off, every half second (forever).
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(4, OUTPUT);
}
void loop() {
digitalWrite(4, HIGH);
delay(500);
digitalWrite(4, LOW);
delay(500);
}Exercise: Write a program with a loop() that turns the blue and green LEDs on and off every half second so that the blue LED is off when the green LED is on and vice versa.
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
}
void loop() {
digitalWrite(4, HIGH);
digitalWrite(5, LOW);
delay(500);
digitalWrite(4, LOW);
digitalWrite(5, HIGH);
delay(500);
}Section 2: What Would Happen If…?
In this session we will learn to control the flow of programs with if statements, and to make code more adaptable by using variables.
For the following exercises copy and paste the content from the cell below to the diagram.json tab in the Wokwi simulator.
Exercises
{
"version": 1,
"author": "Ben Hastings",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 135, "left": 28.2, "attrs": {} },
{
"type": "wokwi-resistor",
"id": "r1",
"top": 24,
"left": 220.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{ "type": "wokwi-led", "id": "led", "top": -51.6, "left": 224.6, "attrs": { "color": "red" } },
{
"type": "wokwi-led",
"id": "led1",
"top": -51.6,
"left": 176.6,
"attrs": { "color": "green" }
},
{
"type": "wokwi-led",
"id": "led2",
"top": -51.6,
"left": 128.6,
"attrs": { "color": "purple" }
},
{
"type": "wokwi-resistor",
"id": "r2",
"top": 24,
"left": 124.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-resistor",
"id": "r3",
"top": 24,
"left": 172.25,
"rotate": 90,
"attrs": { "value": "220" }
},
{
"type": "wokwi-pushbutton",
"id": "btn1",
"top": 255.8,
"left": 345.6,
"attrs": { "color": "red" }
},
{
"type": "wokwi-pushbutton",
"id": "btn2",
"top": 179,
"left": 345.6,
"attrs": { "color": "green" }
},
{
"type": "wokwi-pushbutton",
"id": "btn3",
"top": 92.6,
"left": 345.6,
"attrs": { "color": "purple" }
}
],
"connections": [
[ "r1:1", "led:A", "red", [] ],
[ "uno:3", "r1:2", "red", [ "v0" ] ],
[ "led:C", "uno:GND.1", "black", [ "h-9.2", "v96", "h-86.7" ] ],
[ "r3:2", "uno:4", "green", [ "h38.4", "v85.2" ] ],
[ "led1:C", "uno:GND.1", "black", [ "h-18.8", "v86.4", "h-29.1" ] ],
[ "led1:A", "r3:1", "green", [ "v0" ] ],
[ "r2:2", "uno:5", "purple", [ "v37.2", "h76.8", "v48" ] ],
[ "r2:1", "led2:A", "purple", [ "h0" ] ],
[ "led2:C", "uno:GND.1", "black", [ "h-76.4", "v115.2", "h76.5" ] ],
[ "btn1:2.r", "uno:GND.3", "black", [ "v67.4", "h-205.4" ] ],
[ "btn2:2.r", "uno:GND.3", "black", [ "h9.8", "v153.8", "h-215.2" ] ],
[ "btn3:2.r", "uno:GND.3", "black", [ "h19.4", "v249.8", "h-224.8" ] ],
[ "btn3:1.l", "uno:9", "purple", [ "h-153.6", "v38.4" ] ],
[ "btn2:1.l", "uno:10", "green", [ "h-19.2", "v-67.2", "h-144.7" ] ],
[ "btn1:1.l", "uno:11", "red", [ "h-38.4", "v-153.6", "h-135" ] ]
],
"dependencies": {}
}Example: Write a program that turns the red LED on and off every 50 milliseconds.
// content of sketch.ino
#include <Arduino.h>
const int redLED = 3;
void setup() {
pinMode(redLED, OUTPUT);
}
void loop() {
digitalWrite(redLED, HIGH);
delay(50);
digitalWrite(redLED, LOW);
delay(50);
}Example: Write a program that turns the red LED on and off every 50 milliseconds only if one of the buttons is being pressed.
// content of sketch.ino
#include <Arduino.h>
const int redLED = 3;
const int redButton = 11;
const int greenButton = 10;
const int purpleButton = 9;
void setup() {
pinMode(redLED, OUTPUT);
pinMode(redButton, INPUT);
pinMode(greenButton, INPUT);
pinMode(purpleButton, INPUT);
}
void loop() {
int redPressed = digitalRead(redButton);
int greenPressed = digitalRead(greenButton);
int purplePressed = digitalRead(purpleButton);
if (redPressed == HIGH || greenPressed == HIGH || purplePressed == HIGH) {
digitalWrite(redLED, HIGH);
delay(50);
digitalWrite(redLED, LOW);
delay(50);
} else {
digitalWrite(redLED, LOW);
}
}Exercise: Write a program that turns on an LED when the button of the corresponding color is held down.
Solution
// content of sketch.ino
#include <Arduino.h>
const int redLED = 3;
const int greenLED = 4;
const int purpleLED = 5;
const int redButton = 11;
const int greenButton = 10;
const int purpleButton = 9;
void setup() {
pinMode(redLED, OUTPUT);
pinMode(greenLED, OUTPUT);
pinMode(purpleLED, OUTPUT);
pinMode(redButton, INPUT);
pinMode(greenButton, INPUT);
pinMode(purpleButton, INPUT);
}
void loop() {
int redState = digitalRead(redButton);
int greenState = digitalRead(greenButton);
int purpleState = digitalRead(purpleButton);
if (redState == HIGH) digitalWrite(redLED, HIGH);
else digitalWrite(redLED, LOW);
if (greenState == HIGH) digitalWrite(greenLED, HIGH);
else digitalWrite(greenLED, LOW);
if (purpleState == HIGH) digitalWrite(purpleLED, HIGH);
else digitalWrite(purpleLED, LOW);
}Exercise: Write a program that turns the purple LED on when the corresponding button is not pressed.
Solution
// content of sketch.ino
#include <Arduino.h>
const int purpleLED = 5;
const int purpleButton = 9;
void setup() {
pinMode(purpleLED, OUTPUT);
pinMode(purpleButton, INPUT);
}
void loop() {
int purpleState = digitalRead(purpleButton);
if (purpleState == HIGH) {
digitalWrite(purpleLED, LOW);
} else {
digitalWrite(purpleLED, HIGH);
}
}Exercise: Write a program that switches the green LED from on to off when the corresponing button is pressed. It should change from staying on to staying off, then go back the next time it’s pressed.
Solution
// content of sketch.ino
#include <Arduino.h>
const int greenLED = 4;
const int greenButton = 10;
bool isOn = false;
void setup() {
pinMode(greenLED, OUTPUT);
pinMode(greenButton, INPUT);
}
void loop() {
static int lastState = LOW;
int buttonState = digitalRead(greenButton);
if (buttonState == HIGH && lastState == LOW) {
isOn = !isOn;
digitalWrite(greenLED, isOn ? HIGH : LOW);
delay(200); // debounce
}
lastState = buttonState;
}Exercise: Write a program that turns the red LED on when the corresponding button is pressed and then automatically turns it off again after a few seconds.
Solution
// content of sketch.ino
#include <Arduino.h>
const int redLED = 3;
const int redButton = 11;
void setup() {
pinMode(redLED, OUTPUT);
pinMode(redButton, INPUT);
}
void loop() {
int buttonState = digitalRead(redButton);
if (buttonState == HIGH) {
digitalWrite(redLED, HIGH);
delay(2000); // stays on for 2 seconds
digitalWrite(redLED, LOW);
}
}Section 3: More Functions and Print Statements
For this session we will be using an analogue temperature sensor connected to pin A0 of the Arduino.
Copy the content from the cell below to the diagram.json tab to configure the board for the following exercises.
Exercises
{
"version": 1,
"author": "Ben Hastings",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
{
"type": "wokwi-ntc-temperature-sensor",
"id": "ntc1",
"top": 252.2,
"left": -10.2,
"attrs": {}
}
],
"connections": [
[ "ntc1:GND", "uno:GND.2", "black", [ "h0" ] ],
[ "ntc1:VCC", "uno:VIN", "red", [ "h0" ] ],
[ "ntc1:OUT", "uno:A0", "green", [ "h0" ] ]
],
"dependencies": {}
}Exercise: Fill in the Arduino boilerplate code.
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
// initialization code
}
void loop() {
// main code
}Exercise: Print the line "I'm ready!" to the serial port when the device starts
Solution
// content of sketch.ino
#include <Arduino.h>
void setup() {
Serial.begin(9600);
Serial.println("I'm ready!");
}
void loop() {
// main code
}Exercise: Print the line "Still Ready..." every 200 milliseconds. Create a const for this duration called sampleInterval.
Solution
// content of sketch.ino
#include <Arduino.h>
const int sampleInterval = 200;
void setup() {
Serial.begin(9600);
Serial.println("I'm ready!");
}
void loop() {
Serial.println("Still ready...");
delay(sampleInterval);
}Exercise: Instead of “Still Ready”, print the number of times that the loop() function has run.
Solution
// content of sketch.ino
#include <Arduino.h>
const int sampleInterval = 200;
int count = 0;
void setup() {
Serial.begin(9600);
Serial.println("I'm ready!");
}
void loop() {
count++;
Serial.println(count);
delay(sampleInterval);
}Exercise: Print the amount of time the device has been running, as well as which loop it is on, separated by a comma.
Solution
// content of sketch.ino
#include <Arduino.h>
const int sampleInterval = 200;
int count = 0;
void setup() {
Serial.begin(9600);
Serial.println("I'm ready!");
}
void loop() {
count++;
Serial.print(millis());
Serial.print(", ");
Serial.println(count);
delay(sampleInterval);
}Exercise: Change the first text that is printed (currently "I'm ready!") to be column headers: "idx,time".
Solution
// content of sketch.ino
#include <Arduino.h>
const int sampleInterval = 200;
int count = 0;
void setup() {
Serial.begin(9600);
Serial.println("idx,time"); // Changed from "Ready!" to CSV headers
}
void loop() {
count++;
Serial.print(count);
Serial.print(",");
Serial.println(millis());
delay(sampleInterval);
}Exercise: Add another column to what is printed: the temparature sensor’s current value. HINT: In the point-and-click interface of the simulator, you can select the temparature sensor to change the current temparature.
Solution
// content of sketch.ino
#include <Arduino.h>
const int sampleInterval = 200;
int count = 0;
void setup() {
Serial.begin(9600);
Serial.println("idx,time,temperature");
}
void loop() {
count++;
int analog = analogRead(A0);
Serial.print(count);
Serial.print(",");
Serial.print(millis());
Serial.print(",");
Serial.println(analog);
delay(sampleInterval);
}Exercise: Add a function to convert the signal to degrees celsius with the equation 1 / (log(1 / (1023. / analogueInput - 1)) / 3950.0 + 1.0 / 298.15) - 273.15 and print the temparature in degrees celsius.
Solution
// content of sketch.ino
#include <Arduino.h>
#include <math.h> // for log()
const int sampleInterval = 200;
int count = 0;
void setup() {
Serial.begin(9600);
Serial.println("idx,time,temperature");
}
float analogToCelsius(int analogValue) {
float celsius = 1.0 / (log(1.0 / (1023.0 / analogValue - 1.0)) / 3950.0 + 1.0 / 298.15) - 273.15;
return celsius;
}
void loop() {
count++;
int analog = analogRead(A0);
float celsius = analogToCelsius(analog);
Serial.print(count);
Serial.print(",");
Serial.print(millis());
Serial.print(",");
Serial.println(celsius);
delay(sampleInterval);
}Exercise: Add a runningMean function that calculates the mean of the temparature over the last second and add that as a column to the output.
Solution
// content of sketch.ino
#include <Arduino.h>
#include <math.h> // for log()
const int sampleInterval = 200;
const int samplesPerSecond = 1000 / sampleInterval; // 5 samples
int bufferIndex = 0;
float tempBuffer[5]; // store last 5 readings (1 second worth)
int count = 0;
void setup() {
Serial.begin(9600);
Serial.println("idx,time,temperature,mean");
}
float analogToCelsius(int analogValue) {
float celsius = 1.0 / (log(1.0 / (1023.0 / analogValue - 1.0)) / 3950.0 + 1.0 / 298.15) - 273.15;
return celsius;
}
float runningMean() {
float sum = 0;
for (int i = 0; i < samplesPerSecond; i++) {
sum += tempBuffer[i];
}
return sum / samplesPerSecond;
}
void loop() {
count++;
int analog = analogRead(A0);
float celsius = analogToCelsius(analog);
// Store reading in buffer
tempBuffer[bufferIndex] = celsius;
bufferIndex = (bufferIndex + 1) % samplesPerSecond;
float mean = runningMean();
Serial.print(count);
Serial.print(",");
Serial.print(millis());
Serial.print(",");
Serial.print(celsius);
Serial.print(",");
Serial.println(mean);
delay(sampleInterval);
}Exercise: Attach a red abd blue LED to the digital pins 3 and Arduino in the simulation.
Solution
{
"version": 1,
"author": "Ben Hastings",
"editor": "wokwi",
"parts": [
{ "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} },
{
"type": "wokwi-ntc-temperature-sensor",
"id": "ntc1",
"top": 252.2,
"left": -10.2,
"attrs": {}
},
{ "type": "wokwi-led", "id": "led1", "top": -80.4, "left": 215, "attrs": { "color": "red" } },
{
"type": "wokwi-led",
"id": "led2",
"top": -80.4,
"left": 186.2,
"attrs": { "color": "blue" }
}
],
"connections": [
[ "ntc1:GND", "uno:GND.2", "black", [ "h0" ] ],
[ "ntc1:VCC", "uno:VIN", "red", [ "h0" ] ],
[ "ntc1:OUT", "uno:A0", "green", [ "h0" ] ],
[ "led1:C", "uno:GND.1", "green", [ "v0" ] ],
[ "led2:C", "uno:GND.1", "green", [ "v38.4", "h-57.2" ] ],
[ "led1:A", "uno:3", "green", [ "v0" ] ],
[ "led2:A", "uno:4", "green", [ "v0" ] ]
],
"dependencies": {}
}Exercise: Whenever the running mean is increasing, turn on the red LED. Whenever it is decreasing, turn on the blue LED.
Solution
// content of sketch.ino
#include <Arduino.h>
#include <math.h> // for log()
//pins
const int redLED = 3;
const int blueLED = 4;
//variables
const int sampleInterval = 200;
const int samplesPerSecond = 1000 / sampleInterval; // 5 samples
int bufferIndex = 0;
float tempBuffer[5]; // store last 5 readings (1 second worth)
float previousMean = 0;
int count = 0;
void setup() {
Serial.begin(9600);
pinMode(redLED, OUTPUT);
pinMode(blueLED, OUTPUT);
Serial.println("idx,time,temperature,mean");
}
float analogToCelsius(int analogValue) {
float celsius = 1.0 / (log(1.0 / (1023.0 / analogValue - 1.0)) / 3950.0 + 1.0 / 298.15) - 273.15;
return celsius;
}
float runningMean() {
float sum = 0;
for (int i = 0; i < samplesPerSecond; i++) {
sum += tempBuffer[i];
}
return sum / samplesPerSecond;
}
void loop() {
count++;
int analog = analogRead(A0);
float celsius = analogToCelsius(analog);
// Store reading in buffer
tempBuffer[bufferIndex] = celsius;
bufferIndex = (bufferIndex + 1) % samplesPerSecond;
float mean = runningMean();
// Turn LEDs on or off
if (mean > previousMean) {
digitalWrite(redLED, HIGH);
digitalWrite(blueLED, LOW);
} else if (mean < previousMean) {
digitalWrite(redLED, LOW);
digitalWrite(blueLED, HIGH);
} else {
digitalWrite(redLED, LOW);
digitalWrite(blueLED, LOW);
}
previousMean = mean;
Serial.print(count);
Serial.print(",");
Serial.print(millis());
Serial.print(",");
Serial.print(celsius);
Serial.print(",");
Serial.println(mean);
delay(sampleInterval);
}