Starter Set

Start 

Now that you know some background about electronics, microcontrollers, and Arduino, let's get started!

Modules 

Gather the following parts to complete this project.

Parts

All Parts
All Parts
Seeeduino
USB Cable
Rotary Potentiometer
Grove connector cable
LEDs
PartQuantity
Seeeduino 1
USB Cable 1
Rotary Potentiometer 1
Grove connector cable 1
LEDs 1

Blinking an LED 

To start with, we only need the USB cable, the Seeeduino, and a computer. Just as we did in the Arduino section, we're going to make the LED blink.

All the parts you'll need
All the parts you'll need
Take the USB cable...
Plug one side into the Seeeduino
... and the other into the computer
Grab an LED...
... and place the long side into pin 13 and the short side into the pin marked GND

Upload

Upload the following code.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Blink
*/

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second (1000 milliseconds)
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second (1000 milliseconds)
}

Observe

Watch the LED on the Seeeduino blink. The code is explained in the comments, as well as in the paragraph below.

The setup() function initializes the inputs and outputs we will use within our sketch. In this case, pinMode(LED_BUILTIN, OUTPUT) sets the built-in LED to be an output. LED_BUILTIN is a variable defined in the Arduino header file that is included automatically in every Arduino sketch.

The loop() function runs forever (over and over and over again). It runs through each line of code and when it gets to the end of the loop, it starts again at the beginning.

digitalWrite(LED_BUILTIN, HIGH) sets the LED_BUILTIN pin to HIGH , turning the LED on.

delay(1000) tells the microcontroller to wait for 1000 milliseconds (or one second).

digitalWrite(LED_BUILTIN, LOW) sets the LED_BUILTIN pin to LOW , turning the LED off.

delay(1000) again tells the microcontroller to wait for 1000 milliseconds (or one second).

And then the loop repeats, forever.

Modify

Let's change the speed of the blinking. If we change delay(1000) to delay(100) , what will happen? Take a guess, then upload the code below to test. Does it blink faster or slower?

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);                        // wait for 100 milliseconds
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(100);                        // wait for 100 milliseconds
}

Experiment

Continue modifying the code. Get rid of one of the delays completely. What happens to the LED? The microcontroller is operating at 16 MHz, meaning it executes 16 million instructions per second.

How Does this all Work?

An LED is either on or off, based on the voltage across it. By using digitalWrite(LED_BUILTIN, HIGH) , we set the voltage on the LED pin to high. When the other side of the LED is connected to ground (0V), the LED turns on. A simplified schematic for what is happening is shown below.

We're going to get very technical real quick, then take a step back to explain this at a higher level. A microcontroller's general purpose Input/Output (I/O) pins can either source (push) or sink (pull) current (the flow of electricity). Internally, there is a tristate buffer on each pin that can either be connected to ground (0V) through an internal pull-down resistor, connected to VCC (5V) through an internal pull-up resistor, or left "floating" (disconnected). You can think of a tristate buffer as the same as a switch.

Tristate buffers act like a switchTristate buffers act like a switch

In this example, the tristate buffer output (C) is connected to the input (A) only when the enable (B) is on. So, if B is on, the switch is closed. If B is off, the switch is open. For a more in-depth understanding, you can read more here.

For a higher level understanding of this, we're going to introduce the concept of digital voltage. The Seeeduino we uses runs on either 3.3V or 5V, based on the position of the switch.

We're going to set the switch to 5V. In this setting, A LOW signal is 0V and a HIGH signal is roughly 5V.

Fading LED 

Now that we've made the LED blink, let's make it fade in and fade out.

Upload Fade Code

Upload the following code.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
  Fade

  This example shows how to fade an LED on pin 9 using the analogWrite()
  function.

  The analogWrite() function uses PWM, so if you want to change the pin you're
  using, be sure to use another PWM capable pin. On most Arduino, the PWM pins
  are identified with a "~" sign, like ~3, ~5, ~6, ~9, ~10 and ~11.

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Fade
*/


#define LED_BLUE 3
#define LED_BLUE_GND 4

int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by

// the setup routine runs once when you press reset:
void setup() {
  pinMode(LED_BLUE, OUTPUT);
  digitalWrite(LED_BLUE_GND, LOW);
}

// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of the Green LED:
  analogWrite(LED_BLUE, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

Observe

This code makes the LED fade in and out using the analogWrite() function. This function uses the microcontroller's 8-bit PWM digital I/O pins. These pins allow the microcontroller to set the duty cycle of the output, meaning for a given amount of time, how long the output is on. You might have noticed during the previous activity if you make the delay shorter and shorter, it looks like the LED is flickering really fast and maybe even dimming (or even solidly on). This same idea is used in this sketch to get the LED to blink!

Reading a Potentiometer 

Controlling the LED from code is an awesome thing, so congratulate yourself on that! Blinking LEDs is very often the first test code an engineer writes for a new microcontroller. It's useful as a quick visual inspection that your code is running as you intended it to. But, what if you wanted to control that LED based on some action taken in the real world, not just in code?

You'd need some kind of an input. For this set, we have included a potentiometer, also known as a variable resitor. You've probably seen potentiometers used as volume knobs before. They are most commonly seen as one of two types: a knob or a slider.

In this set, we've included a knob potentiometer.

Internally, a potentiometer consists of three primary components: a resistive element, a wiper, and terminals. The wiper varies the resistance between the terminals by sliding along the resistive element. Two terminals are connected to opposite ends of the resistive element and the third terminal is connected to the wiper. The position of the wiper determines the resistance between the outside terminals and the wiper terminal.

How a potentiometer worksHow a potentiometer works

Using a graphite pencil and some wire, you could make your own potentiometer.

All the parts you'll need
All the parts you'll need
Take the cable ...
Plug one side into the Seeeduino
... and the other into the potentiometer

Upload

Upload the following code.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog A5 
  // (note: internally on the circuit board, SCL/SDA are attached to A4/A5):
  int sensorValue = analogRead(A5);
  // print out the value you read:
  Serial.println(sensorValue);
  delay(1);        // delay in between reads for stability
}

Observe

First, let's open up the Serial Monitor.

The Serial Monitor shows us what is being printed to the Serial port by the Arduino. In the screenshot above, we can see that the value 1023 is being printed over and over again. If you change the position of the knob, the value changes. If you are not seeing data, double check to make sure you are connected to the correct port and that you have set the Baud Rate correctly.

For numeric data like this, a graph can be much easier to read. The Arduino IDE provides a simple plotting tool called the Serial Plotter. Let's open it up.

In the screenshot above, we were rotating the knob back and forth from one extreme to the other.

Modify

Let's change this code so that the potentiometer controls the brightness of the LED.

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#define LED_BLUE 3
#define LED_BLUE_GND 4
// the setup routine runs once when you press reset:
void setup() {
  // initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  pinMode(LED_BLUE_GND, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  digitalWrite(LED_BLUE_GND, LOW);
}

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog A5 
  // (note: internally on the circuit board, SCL/SDA are attached to A4/A5):
  int sensorValue = analogRead(A5);
  // Control the brightness of the LED
  analogWrite(LED_BLUE, sensorValue / 4);
}

How Does the microcontroller read the potentiometer?

Microcontrollers are digital computers, and can only process digital signals. As we discussed when talking about how a microcontroller is able to control an LED, for digital signals there are logic voltage levels (0V for LOW and 5V for HIGH) that the microcontroller is able to output.

On the input side, the Arduino (and compatible) microcontrollers have both digital and analog inputs. Digital inputs are either HIGH (5V) or LOW (0V). Analog values, on the other hand, are quantized to be represented as digital numbers. Quantized is a math term for the process of mapping values from one set (ie: infinite) to a smaller (countable) set. For Arduino, this means that instead of having infinte possible values between 0V and 5V, there are 2^10 (1024) possible values. So, 0V is mapped to 0 and 5V is mapped to 1023. 1024 is not an arbitrary number. The microcontroller in the Arduino has a 10-bit analog-to-digital converter.

To read analog signals in code, we utilize Arduino's analogRead() function, described in detail here. The line int sensorValue = analogRead(A5); tells the the microcontroller to read the value from the potentiometer and store it as an integer in the variable sensorValue . The potentiometer is connected to pin A5 through the cable and Arduino's circuit board. If you look closely at the connector, you will see SCL SDA VCC GND written on the board next to the wires. Internally, SDA is connected to pin A5, which is why we use this value. GND is 0V and VCC is 5V.

In this example, the tristate buffer output (C) is connected to the input (A) only when the enable (B) is on. So, if B is on, the switch is closed. If B is off, the switch is open. For a more in-depth understanding, you can read more here.

For a higher level understanding of this, we're going to introduce the concept of digital voltage. The Seeeduino we uses runs on either 3.3V or 5V, based on the position of the switch.

We're going to set the switch to 5V. In this setting, A LOW signal is ~0V and a HIGH signal is roughly

Make a game 

We've successfully controlled an LED to make it Blink and Fade. We've successfully read the value of a potentiometer. Let's put all of this together and make it into a game! We'll use 3 LEDs and the potentiometer to make a reaction game. The Blue and Green LEDs will light up and tell us which way to move the potentiometer. We'll score points each time we move it in the correct direction and we'll also measure the total time it takes us to react.

First, we'll put it all together:

All the parts you'll need
All the parts you'll need
Grab the RED LED...
... and place the long side into pin 13 and the short side into the pin marked GND
Grab the Blue LED...
... and place the long side into pin 3 and the short side into pin 4
Grab the Green LED...
... and place the long side into pin 6 and the short side into pin 7
All together

Code for the Reaction Game

Upload the code below, open the Serial monitor, and play the game!

Download file Copy to clipboard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
  Reaction Game
*/

// We use #define to declare macros.
// ie: Wherever LED_BLUE appears, the Arduino IDE's preprocessor will automatically replace it with 3 when it is uploaded.
// These are used to make our code easier to modify if we ever want to change values in the future
#define LED_BLUE 3
#define LED_BLUE_GND 4
#define LED_GREEN 6
#define LED_GREEN_GND 7

#define LOW_THRESHOLD 256
#define HIGH_THRESHOLD 768

enum gameState {
  start,
  countdown,
  pickRandom,
  settle,
  userInput,
  correct,
  incorrect,
  checkDone,
  done,
  first
};

// Declare variables
int randNumber;
long counter;
bool green = false;
bool blue = false;
int points = 0;
int roundCount = 0;
long reactionTime = 0;

// State represents the current state of the game
gameState state = start;
// nextState is used to transition between states
gameState nextState = start;

// the setup routine runs once
void setup() {
  // Tell the microcontroller which pins are used for outputs.
  pinMode(A4, OUTPUT);
  pinMode(LED_BLUE_GND, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(LED_GREEN_GND, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  // initialize serial communication at 9600 bits per second
  Serial.begin(9600);
  // initialize the random number generator with a random seed taken from the ADC
  randomSeed(analogRead(0));
}

// the loop routine runs over and over again forever:
void loop() {
  // Read our potentiometer
  int sensorValue = analogRead(A5);
  // A switch statement looks at the variable (state) and matches the case based on the current value
  switch (state) {
    case first:
      // Print instructions to the serial console
      Serial.println("Both LEDs will flash 3 times, then one LED will illuminate.");
      Serial.println("If only the Green LED is on, rotate the potentiometer CCW (to the left).");
      Serial.println("If only the Blue LED is on, rotate the potentiometer CW (to the right).");
      Serial.println("This game measures your reaction time, so be quick.");
      Serial.println("And always move the potentiometer to center position to begin.");
      // Wait 2 seconds so players can read the instructions
      delay(2000);
      // Wait 3 seconds and then start the game
      Serial.print("Starting a new game in 3 Seconds");
      delay(3000);
      // Print instructions on how to start the game
      Serial.println("Move the potentiometer to center position to begin.");
      // set nextState to "start" so the game will be in the start state the next time through the loop
      nextState = start;
      // break out of the switch statement
      break;
    case start:
      // Start represents the start of a new game
      // Turn off all of the LEDs
      digitalWrite(A4, LOW);
      digitalWrite(LED_BLUE_GND, LOW);
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
      digitalWrite(LED_GREEN_GND, LOW);
      digitalWrite(LED_BUILTIN, LOW);
      // Since it is a new game, 0 all of the variables
      roundCount = 0;
      points = 0;
      reactionTime = 0;
      // Do not transition to the next state unless the potentiometer is in the middle position
      if (sensorValue >=  LOW_THRESHOLD && sensorValue <= HIGH_THRESHOLD) {
        // If it is, the next state is the countdown
        nextState = countdown;
      }
      // Otherwise, stay in the start state until the potentiometer is in the middle and break out of the switch
      break;
    case countdown:
      // Countdown flashes the LEDs 3 times
      // Increment the round counter
      roundCount++;
      // Print the current round to the serial console
      Serial.print("Round ");
      Serial.print(roundCount);
      Serial.println(" starting..");
      // Flash the blue and green LEDs 3 times
      // First flash
      // Turn on and wait 500ms
      digitalWrite(LED_BLUE, HIGH);
      digitalWrite(LED_GREEN, HIGH);
      delay(500);
      // Turn off and wait 500ms
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
      delay(500);
      //Second flash
      // Turn on and wait 500ms
      digitalWrite(LED_BLUE, HIGH);
      digitalWrite(LED_GREEN, HIGH);
      delay(500);
      // Turn off and wait 500ms
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
      delay(500);
      // Third flash
      // Turn on and wait 500ms
      digitalWrite(LED_BLUE, HIGH);
      digitalWrite(LED_GREEN, HIGH);
      delay(500);
      // Turn off and wait 500ms
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
      delay(500);
      // Turn on the LEDs for 1 second
      digitalWrite(LED_BLUE, HIGH);
      digitalWrite(LED_GREEN, HIGH);
      delay(1000);
      // Turn off the LEDs
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
      // Go to the random number state
      nextState = pickRandom;
      break;
    case pickRandom:
      // Grab the current "timestamp" from millis()
      // We will use this to determine reaction time
      counter = millis();
      // Generate a random number (0-9)
      randNumber = random(10);
      // If the number is less than 5
      if (randNumber < 5) {
        // Turn on the green LED and set the flag to true
        green = true;
        digitalWrite(LED_GREEN, HIGH);
        // Print to the serial console
        Serial.println("Green LED");
      }
      // otherwise,
      else if (randNumber >= 5) {
        // Turn on the blue LED and set the flag to true
        blue = true;
        digitalWrite(LED_BLUE, HIGH);
        // Print to the serial console
        Serial.println("Blue LED");
      }
      // Go to the settle state
      nextState = settle;
      break;
    case settle:
      //Serial.println("settle");
      if (millis() - counter >= 100) {
        nextState = userInput;
        Serial.println("Move to the correct position");
      }
      break;
    case userInput:
      //Serial.println("userinput");
      if (green) {
        if (sensorValue <= LOW_THRESHOLD) {
          nextState = incorrect;
        } else if (sensorValue >= HIGH_THRESHOLD) {
          nextState = correct;
        }
      } else if (blue) {
        if (sensorValue >= HIGH_THRESHOLD) {
          nextState = incorrect;
        } else if (sensorValue <= LOW_THRESHOLD) {
          nextState = correct;
        }
      }
      break;
    case correct:
      Serial.println("correct...");
      counter = millis() - counter;
      points++;
      Serial.println("Correct! You score 1 point!");
      Serial.print("Your reaction time was ");
      Serial.print(counter);
      Serial.println("ms.");
      reactionTime += counter;
      nextState = checkDone;
      break;
    case incorrect:
      Serial.println("incorrect");
      Serial.println("You moved in the wrong direction :(");
      nextState = checkDone;
      break;
    case checkDone:
      Serial.println("Move back to center position and get ready!");
      digitalWrite(LED_BLUE, LOW);
      digitalWrite(LED_GREEN, LOW);
      blue = false;
      green = false;
      if (roundCount >= 5) {
        nextState = done;
      } else {
        nextState = countdown;
        //Serial.println("going to countdown");
      }
      break;
    case done:
      Serial.print("You scored a total of ");
      Serial.print(points);
      Serial.println(" points.");
      Serial.print("Your total reaction time was: ");
      Serial.print(reactionTime);
      Serial.println("ms.");
      digitalWrite(LED_BUILTIN, HIGH);
      nextState = first;
      break;

    default:
      Serial.println("in default state..");
      break;
  }
  // Transition to the nextState on the next iteration of the main loop.
  state = nextState;
  delay(1);        // delay in between reads for stability
}

End 

You have finished the Main Project for this kit. You can continue to explore on your own. You may also want to check out the Creator Set.

Discussion and Comments for the Starter Set block