Lecture Sample Code
This collection of short Arduino sketches introduces a variety of programming
concepts. The comments are minimal as these are intended to be starting points
for explanation.
getting started
blink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 | // 1. blink the onboard Arduino LED on pin 13.
// 2. demonstrate setup(), loop()
// 3. demonstrate pinMode(), digitalWrite(), delay()
void setup()
{
pinMode(13, OUTPUT);
}
void loop()
{
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
delay(1000);
}
|
plots
1
2
3
4
5
6
7
8
9
10
11
12 | #include <Servo.h>
// 1. demonstrate use of Serial port for debugging output
// 2. demonstrate IDE graphing: see Tools/Serial Plotter
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.println(sin(4 * 6.28 * 0.001 * millis()));
}
|
plotting
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | // 1. use the Arduino IDE plotting utility to visualize an analog signal
// 2. demonstrate analogRead()
void setup()
{
Serial.begin(115200);
}
void loop()
{
int input = analogRead(A0);
Serial.println(input);
delay(20);
}
|
clocks
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 | // 1. measure execution time
// 2. demonstrate the firmware clock
// 3. demonstrate debugging on the serial port
void setup()
{
Serial.begin(115200);
}
long last_time = 0;
void loop()
{
long now = micros();
Serial.print(millis());
Serial.print(" ");
Serial.print(micros());
Serial.print(" ");
Serial.println(now - last_time);
last_time = now;
}
|
sos
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 | // Demonstration of the following:
// 1. digitalWrite() to the onboard LED
// 2. delay()
// 3. Morse code signaling
void setup()
{
pinMode(13, OUTPUT);
}
void dot()
{
digitalWrite(13, HIGH);
delay(200);
digitalWrite(13, LOW);
delay(200);
}
void dash()
{
digitalWrite(13, HIGH);
delay(600);
digitalWrite(13, LOW);
delay(200);
}
void endchar()
{
delay(400);
}
void loop()
{
dot(); dot(); dot(); endchar(); // S
dash(); dash(); dash(); endchar(); // O
dot(); dot(); dot(); endchar(); // S
delay(1000);
}
|
digitalio
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | // Demonstration of the following:
// 1. digitalRead() from external switch
// 2. digitalWrite() to external LED
const int SWITCH_PIN = 8;
const int LED_PIN = 4;
void setup()
{
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
pinMode(SWITCH_PIN, INPUT);
}
void loop()
{
int value = digitalRead(SWITCH_PIN);
Serial.println(value);
digitalWrite(LED_PIN, value);
delay(50);
}
|
sounds
tones
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | // 1. generate tones on a speaker on pin 5
// 2. demonstrate tone(), noTone(), delay()
const int SPEAKER_PIN = 5;
void setup()
{
// empty body, tone() configures a pin for output
}
void loop()
{
// play A4 "concert A"
tone(SPEAKER_PIN, 440);
delay(1000);
// silence
noTone(SPEAKER_PIN);
delay(1000);
// play E5 perfect fifth using 3/2 "just intonation" ratio
tone(SPEAKER_PIN, 660);
delay(1000);
}
|
bit-bang-two-tone
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | // 1. generate complex waveform on a speaker on pin 5
// 2. demonstrate execution speed, firmware clocks, bit-banging logic
const int SPEAKER_PIN = 5;
void setup()
{
pinMode(SPEAKER_PIN, OUTPUT);
}
void loop()
{
long now = micros();
// 2274 usec period ~= 439.75 Hz ~= A4
bool square1 = (now % 2274) < 1136;
// 1516 usec period ~= 659.63 HZ ~= E5
bool square2 = (now % 1516) < 758;
digitalWrite(SPEAKER_PIN, square1 ^ square2);
}
|
scale
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | // 1. generate chromatic tones on a speaker on pin 5
// 2. demonstrate for loops, int and float variables
const int SPEAKER_PIN = 5;
void setup()
{
}
void loop()
{
float freq = 440.0;
for (int i = 0; i < 24; i = i + 1) {
tone(SPEAKER_PIN, freq);
delay(200);
freq = freq * 1.0595;
}
noTone(SPEAKER_PIN);
delay(1000);
}
|
melody
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 | // 1. generate tones on a speaker on pin 5
// 2. demonstrate table lookup
// 3. demonstrate Serial debugging
const int SPEAKER_PIN = 5;
void setup()
{
Serial.begin(115200);
Serial.println("Hello!");
}
const float note_table[] = {
440.0, 523.25, 659.26, 523.25, 659.26, 523.25/2, 440.0,
659.26, 659.26*2, 523.25, -1.0 };
void loop()
{
for (int i = 0; note_table[i] > 0.0 ; i = i + 1) {
Serial.print("Note: ");
Serial.println(note_table[i]);
tone(SPEAKER_PIN, note_table[i]);
delay(200);
}
noTone(SPEAKER_PIN);
delay(500);
}
|
note-table
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 | // 1. generate tones on a speaker on pin 5
// 2. demonstrate MIDI notes and equal temperament scales
// 3. use of a const byte table (unsigned 8 bit integers)
const int SPEAKER_PIN = 5;
const byte notes[] = {60, 62, 64, 65, 67, 69, 71, 72};
const int notes_len = sizeof(notes) / sizeof(byte);
const int MIDI_A0 = 21;
const float freq_A0 = 27.5;
void setup()
{
Serial.begin(115200);
}
void loop()
{
for (int i = 0; i < notes_len; i = i + 1) {
int note = notes[i];
float freq = freq_A0 * pow(2.0, ((float)(note - MIDI_A0)) / 12.0);
Serial.println(freq);
tone(SPEAKER_PIN, freq);
delay(500);
}
noTone(SPEAKER_PIN);
delay(1000);
}
|
arpeggio
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 | // 1. generate tones on a speaker on pin 5
// 2. demonstrate functional abstraction
// 3. demonstrate MIDI notes and equal temperament scales
// 4. demonstrate for loop with multiple expressions
// 5. demonstate global constants with 'const float' and 'const int'
const int SPEAKER_PIN = 5;
void setup()
{
Serial.begin(115200);
}
void loop()
{
arpeggio(60, 3, 4); // 60 is the MIDI number for note C4
silence();
arpeggio(60, 3, 8);
arpeggio(85, -6, 8);
silence();
silence();
}
void arpeggio(int start, int interval, int length)
{
for (int note = start, count = 0; count < length; note = note + interval, count = count + 1) {
float freq = midi_to_freq(note);
Serial.println(freq);
tone(SPEAKER_PIN, freq);
delay(200);
}
}
const int MIDI_A0 = 21;
const float freq_A0 = 27.5;
float midi_to_freq(int midi_note)
{
return freq_A0 * pow(2.0, ((float)(midi_note - MIDI_A0)) / 12.0);
}
void silence(void)
{
noTone(SPEAKER_PIN);
delay(500);
}
|
tonestep
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 | // 1. read a switch input on pin 9
// 2. generate tones on a speaker on pin 5
// 3. demonstrate a simple state machine
// 4. demonstrate Serial debugging
const int SWITCH_PIN = 9;
const int SPEAKER_PIN = 5;
void setup()
{
Serial.begin(115200);
Serial.println("Hello!");
}
const float note_table[] = { 440.0, 523.25, 659.26, 523.25, 659.26, 523.25/2, 440.0,
659.26, 659.26*2, 523.25, -1 };
int nextnote = 0;
/// The loop function is called repeatedly by the Arduino system. In this
/// example, it executes once per cycle of the switch input.
void loop()
{
while(digitalRead(SWITCH_PIN) != 0) {
// Busywait for the switch to be pressed. Note that the body of the while
// is empty, this just loops reading the switch input until it goes low.
}
// The following is executed once per switch cycle, right after the switch is pressed.
float freq = note_table[nextnote];
Serial.print("Note: ");
Serial.println(freq);
tone(SPEAKER_PIN, freq);
// advance to the next note, looping at the end
nextnote = nextnote + 1;
if (note_table[nextnote] < 0) nextnote = 0;
// Busywait for the switch to be released: loop until the switch input goes high.
while(digitalRead(SWITCH_PIN) == 0) { }
// The following is executed once, right after the switch is released.
noTone(SPEAKER_PIN);
}
|
servos
metronome
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | // demo use of a library, hobby servo output
#include <Servo.h>
Servo your_chosen_servo_name;
void setup()
{
your_chosen_servo_name.attach(9);
}
void loop()
{
your_chosen_servo_name.write(45);
delay(500);
your_chosen_servo_name.write(135);
delay(500);
}
|
sine-servo
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 | #include <Servo.h>
Servo indicator;
const int SERVO_PIN = 6;
void setup()
{
Serial.begin(115200);
indicator.attach(SERVO_PIN);
}
// global step counter
int step = 0;
void loop()
{
// Perform a smooth sinusoidal movement around the center.
float phase = step * (2*M_PI/60);
float angle = 90 + 90*sin(phase);
step = step + 1;
indicator.write(angle); // degrees
Serial.println(angle);
delay(50); // milliseconds
}
|
sine-metronome
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 | // demo use of a trajectory generator function
#include <Servo.h>
const int SERVO_PIN = 9;
Servo wiggling_servo;
void setup(void)
{
Serial.begin(115200);
wiggling_servo.attach(SERVO_PIN);
}
void loop(void)
{
// Perform a smooth movement around the center several times.
for (int i = 0; i < 4; i = i+1) {
// Define a few constants governing the motion. Note that this example
// uses a C++ style of declaration which looks more like a normal variable
// declaration, but whose value cannot be changed.
const float center = 90.0; // in degrees
const float magnitude = 30.0; // in degrees
const float period = 4.0; // in seconds, duration of cycle
const float interval = 0.020; // in seconds, duration of each step
int cycle_steps = period / interval;
for (int step = 0; step < cycle_steps; step++) {
// Compute the 'phase angle' for the sine function. Note that the sin()
// function requires an angle in radians.
float phase = step * (2*M_PI/cycle_steps);
// Compute the angle to send to the servo.
float angle = center + magnitude * sin(phase);
wiggling_servo.write(angle);
// Wait for one sampling period.
delay(1000*interval);
}
}
Serial.println("cycle done.");
}
|
table-metronome
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | // demo use of a lookup table
#include <Servo.h>
const int SERVO_PIN = 9;
Servo svo;
void setup(void)
{
svo.attach(SERVO_PIN);
}
const int angles[12] = { 45, 0, 135, 0, 90, 0, 90, 45, 135, 90, 180, 0 };
void loop(void)
{
for (int idx = 0; idx < 12; idx = idx + 1) {
svo.write(angles[idx]);
delay(500);
}
}
|
shm-servo
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 | // 1. demonstrate use of a differential equation generator function
// 2. demonstrate use of a function as motion primitive
#include <Servo.h>
const int SERVO_PIN = 9;
Servo svo;
// ================================================================
// Simple Harmonic Motion oscillator, e.g. unit-mass on spring with damping.
const float k1 = 4*M_PI*M_PI; // 1 Hz; freq = (1/2*pi) * sqrt(k/m); k = (freq*2*pi)^2
const float b1 = 2.0; // default damping
const float dt = 0.02; // integration time step (same as command rate)
float q = 0.0; // initial position
float qd = 0.0; // initial velocity
// ================================================================
void setup(void)
{
Serial.begin(115200);
svo.attach(SERVO_PIN);
}
// ================================================================
void loop()
{
ringing_servo(90.0, k1, b1, 1.5);
ringing_servo(45.0, k1, b1, 1.5);
ringing_servo(90.0, k1, b1, 2.5);
}
// ================================================================
// Create a simple harmonic motion around position 'q_d' using spring constant 'k' and
// damping 'b' for 'duration' seconds.
void ringing_servo(float q_d, float k, float b, float duration)
{
while (duration > 0.0) {
// calculate the derivatives
float qdd = k * (q_d - q) - b * qd;
// integrate one time step
q += qd * dt;
qd += qdd * dt;
// update the servo
svo.write(q);
// print the output for plotting
Serial.println(q);
// delay to control timing
delay((int)(1000*dt));
duration -= dt;
}
}
|
event loops
non-blocking
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 | // 1. Blink the onboard Arduino LED on pin 13.
// 2. Demonstrate a non-blocking event loop.
// 3. Demonstrate micros() and timing calculations.
// 4. Note the absence of delay(). For comparison, see blink.ino.
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
}
void loop(void)
{
static unsigned long last_update_clock = 0;
unsigned long now = micros();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
static long led_blink_timer = 0;
static bool led_blink_state = false;
const long led_blink_interval = 500000;
led_blink_timer -= interval;
if (led_blink_timer <= 0) {
led_blink_timer += led_blink_interval;
led_blink_state = !led_blink_state;
digitalWrite(LED_BUILTIN, led_blink_state);
}
}
|
delay-with-poll
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 | void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
}
/****************************************************************/
void delay_and_poll(long microseconds)
{
unsigned long last_update_clock = micros();
while (microseconds > 0) {
unsigned long now = micros();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
microseconds -= interval;
static long led_blink_timer = 0;
static bool led_blink_state = false;
const long led_blink_interval = 500000;
led_blink_timer -= interval;
if (led_blink_timer <= 0) {
led_blink_timer += led_blink_interval;
led_blink_state = !led_blink_state;
digitalWrite(LED_BUILTIN, led_blink_state);
}
}
}
/****************************************************************/
void loop(void)
{
// entering state 0
delay_and_poll(1000000);
// entering state 1
delay_and_poll(1000000);
// entering state 2
delay_and_poll(1000000);
// entering state 3
while (true) delay_and_poll(1000000);
}
|
responsive-delay
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 | // 1. Demonstrate polling hardware inputs while waiting.
const int SPEAKER_PIN = 5;
const int SWITCH_PIN = 3;
void setup(void)
{
Serial.begin(115200);
pinMode(SWITCH_PIN, INPUT);
}
void loop(void)
{
// start the main script
Serial.println("siren...");
play_siren();
// always wait for a brief silence before repeating
Serial.println("silence.");
noTone(SPEAKER_PIN);
delay(1000);
}
void play_siren(void)
{
// begin an interruptible sequence
for (int i = 0; i < 3; i++) {
tone(SPEAKER_PIN, 622);
if (cond_delay(300)) return;
tone(SPEAKER_PIN, 440);
if (cond_delay(300)) return;
}
}
// A conditional delay. This will wait for the given number of milliseconds
// unless the switch is pressed. Returns false if time is reached or true if
// interrupted.
bool cond_delay(int milliseconds)
{
unsigned long last_update_clock = millis();
while (milliseconds > 0) {
unsigned long now = millis();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
milliseconds -= interval;
// check if the switch input has gone low (active-low switch circuit)
if (digitalRead(SWITCH_PIN) == 0) return true;
}
return false;
}
|
state machines
state-machine
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 | // 1. Simultaneous blink the onboard Arduino LED on pin 13 and play a melody in pin 5.
// 2. Demonstrate a non-blocking event loop with multiple tasks.
// 3. Demonstrate micros() and timing calculations.
// 4. Demonstrate switch-case state machine structure.
void setup(void)
{
pinMode(LED_BUILTIN, OUTPUT);
}
/****************************************************************/
void loop(void)
{
static unsigned long last_update_clock = 0;
unsigned long now = micros();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
// simultaneously run several independent tasks
poll_led(interval);
poll_melody(interval);
}
/****************************************************************/
// State variables for the LED blinker.
long led_blink_timer = 0;
bool led_blink_state = false;
const long led_blink_interval = 500000;
void poll_led(unsigned long interval)
{
// This task uses the decrementing timer idiom (led_blink_timer).
led_blink_timer -= interval;
if (led_blink_timer <= 0) {
// Reset the LED timer.
led_blink_timer += led_blink_interval;
// Toggle the LED to blink it.
led_blink_state = !led_blink_state;
digitalWrite(LED_BUILTIN, led_blink_state);
}
}
/****************************************************************/
// State variables for the melody player.
int melody_index = 0;
long melody_elapsed = 0;
const int SPEAKER_PIN = 5;
const int NOTE_FS4 = 370;
const int NOTE_C4 = 262;
void poll_melody(unsigned long interval)
{
// This task uses the incrementing timer idiom (melody_elapsed). The elapsed
// time value is increased on each cycle, then reset at state transitions.
melody_elapsed += interval;
// Following is a state machine implemented using switch-case. This example
// executes state 0-5 in sequence then remains in state 5. Each state
// transition is conditioned purely on elapsed time; transitions have the side
// effect of changing the speaker pitch. Note that in a more general case
// each state could transition to any other state or be conditioned on sensor
// values.
switch(melody_index) {
case 0:
// Initialization state: start the speaker tone and immediately transition to state 1.
melody_elapsed = 0;
melody_index += 1;
tone(SPEAKER_PIN, NOTE_FS4);
break;
case 1:
case 3:
// Allow a tone to play for an interval, then change the tone and advance.
if (melody_elapsed > 1000000) {
melody_elapsed = 0;
melody_index += 1;
tone(SPEAKER_PIN, NOTE_C4);
}
break;
case 2:
case 4:
// Allow a tone to play for an interval, then change the tone and advance.
if (melody_elapsed > 1000000) {
melody_elapsed = 0;
melody_index += 1;
tone(SPEAKER_PIN, NOTE_FS4);
}
break;
case 5:
default:
// terminal state: script is done
noTone(SPEAKER_PIN);
break;
}
}
|
signal processing
smoothing
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 | /****************************************************************/
void setup(void)
{
Serial.begin(115200);
}
/****************************************************************/
void loop(void)
{
static unsigned long last_update_clock = 0;
unsigned long now = micros();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
const long sample_interval = 10000; // 10 msec, 100 Hz sampling
static long sample_timer = 0;
sample_timer -= interval;
if (sample_timer <= 0) {
sample_timer += sample_interval;
int raw_value = analogRead(0); // read the current input
float calibrated = ((float)raw_value) / 1024.0; // scale to normalized units
static float smoothed_value = 0.0; // filtered value of the input
float difference = calibrated - smoothed_value; // compute the 'error'
smoothed_value += 0.1 * difference; // apply a constant gain to move the smoothed value toward the reading
Serial.println(smoothed_value);
}
}
|
ringfilter
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 | /****************************************************************/
void setup(void)
{
Serial.begin(115200);
}
/****************************************************************/
void loop(void)
{
static unsigned long last_update_clock = 0;
unsigned long now = micros();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
const long sample_interval = 10000; // 10 msec, 100 Hz sampling
static long sample_timer = 0;
sample_timer -= interval;
if (sample_timer <= 0) {
sample_timer += sample_interval;
int raw_value = analogRead(0);
float calibrated = ((float)raw_value) / 1024.0;
ringfilter_put(calibrated);
float velocity = ringfilter_deriv(0.01);
float quadratic_params[3];
ringfilter_fit_quadratic(quadratic_params);
Serial.print("v: "); Serial.print(velocity);
Serial.print(" q: "); Serial.print(quadratic_params[0]);
Serial.print(" "); Serial.print(quadratic_params[1]);
Serial.print(" "); Serial.println(quadratic_params[2]);
}
}
|
feedback
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 | // 1. apply proportional feedback using a dual H-bridge driver and analog position sensor
// 2. demonstrate non-blocking event-loop structure
// 3. demonstrate DRV8833 motor driver pulse width modulation
// 4. demonstrate a smoothing filter on an analog input
// Define DRV8833 control pin wiring as per CKS-1 shield board.
const int MOT_A1_PIN = 5;
const int MOT_A2_PIN = 6;
const int MOT_B1_PIN = 10;
const int MOT_B2_PIN = 9;
const int POS_SENSOR_PIN = A0;
/****************************************************************/
void setup(void)
{
// Configure the four DRV8833 control lines and set them to a quiescent state.
pinMode(MOT_A1_PIN, OUTPUT);
pinMode(MOT_A2_PIN, OUTPUT);
pinMode(MOT_B1_PIN, OUTPUT);
pinMode(MOT_B2_PIN, OUTPUT);
digitalWrite(MOT_A1_PIN, LOW);
digitalWrite(MOT_A2_PIN, LOW);
digitalWrite(MOT_B1_PIN, LOW);
digitalWrite(MOT_B2_PIN, LOW);
// Start the serial port for the console.
Serial.begin(115200);
}
/****************************************************************/
void loop(void)
{
static unsigned long last_update_clock = 0;
unsigned long now = micros();
unsigned long interval = now - last_update_clock;
last_update_clock = now;
poll_feedback_loop(interval);
}
/****************************************************************/
// Polling function for the feedback process: reads an analog position sensor at
// regular sampling intervals, calculates a new motor speed and configures the
// DRV8833 motor driver PWM outputs.
const long sample_interval = 10000; // 10 msec, 100 Hz sampling
long sample_timer = 0;
float position = 0.0; // filtered value of the input (unit normalization)
float target = 0.5; // target position (unit normalization)
void poll_feedback_loop(unsigned long interval)
{
sample_timer -= interval;
if (sample_timer <= 0) {
sample_timer += sample_interval;
int raw_value = analogRead(POS_SENSOR_PIN); // read the current input
float calibrated = ((float)raw_value) / 1024.0; // scale to normalized units
// first-order smoothing filter to reduce noise in the position estimate
float difference = calibrated - position; // compute the 'error' in the sensor reading
position += 0.2 * difference; // apply a constant gain to move the smoothed value toward the reading
// calculate a proportional position control update
float position_error = target - position; // compute the position error
float control_output = 2.0 * position_error; // apply a proportional position gain
int control_pwm = constrain((int)(256.0 * control_output), -255, 255);
set_motor_pwm(control_pwm, MOT_A1_PIN, MOT_A2_PIN);
}
}
/****************************************************************/
// Set the current speed and direction for either of the DRV8833 channels.
//
// Parameters:
// pwm : integer velocity ranging from -255 to 255.
// IN1_PIN : either MOT_A1_PIN or MOT_B1_PIN
// IN2_PIN : either MOT_A2_PIN or MOT_B2_PIN
//
// (Note: uses 'fast-decay' mode: coast not brake.)
void set_motor_pwm(int pwm, int IN1_PIN, int IN2_PIN)
{
if (pwm < 0) { // reverse speeds
analogWrite(IN1_PIN, -pwm);
digitalWrite(IN2_PIN, LOW);
} else { // stop or forward
digitalWrite(IN1_PIN, LOW);
analogWrite(IN2_PIN, pwm);
}
}
/****************************************************************/
|
shm-metronome
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 | // demo use of a differential equation generator function
#include <Servo.h>
const int SERVO_PIN = 9;
Servo svo;
// ================================================================
// Simple Harmonic Motion oscillator, e.g. unit-mass on spring with damping.
const float k = 4*M_PI*M_PI; // 1 Hz; freq = (1/2*pi) * sqrt(k/m); k = (freq*2*pi)^2
const float b = 1.0; // damping
const float q_d = 90.0; // neutral spring position
const float dt = 0.01; // integration time step
float q = 0.0; // initial position
float qd = 0.0; // initial velocity
// ================================================================
void setup(void)
{
Serial.begin(115200);
svo.attach(SERVO_PIN);
}
// ================================================================
void loop()
{
// calculate the derivatives
float qdd = k * (q_d - q) - b * qd;
// integrate one time step
q += qd * dt;
qd += qdd * dt;
// update the servo
svo.write(q);
// logic to reset the oscillator after a cycle has completed
if (fabs(qd) < 0.1 && fabs(q_d - q) < 0.1) q = 0.0;
// print the output for plotting
Serial.println(q);
// delay to control timing
delay((int)(1000*dt));
}
|
miscellaneous
numbers
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 | // Demonstration of the following:
// 1. properties of Arduino Uno numeric types
// 2. use of Serial port for debugging output
// 3. properties of Arduino numbers
// Include optional floating-point numeric constants.
#include <float.h>
void setup()
{
Serial.begin(115200);
}
void loop()
{
int normal = 0; // 16 bit integer, values range from -32768 to 32767
long large = 0; // 32 bit integer, values range from -2147483648 to 2147483647
float number = 0.0; // 32 bit float, positive values range as high as 3.4028235E+38
Serial.print("bytes in an int: "); Serial.println(sizeof(normal));
Serial.print("bytes in a long: "); Serial.println(sizeof(large));
Serial.print("bytes in a float: "); Serial.println(sizeof(number));
// ----- int : 16 bits -------------------------------------------
normal = 0x7fff;
Serial.print("Maximum int value: ");
Serial.println(normal);
// use the properties of twos-complement arithmetic to roll over to negative numbers
normal = normal + 1;
Serial.print("Minimum int value: ");
Serial.println(normal);
normal = LOW;
Serial.print("Value of LOW: ");
Serial.println(normal);
normal = HIGH;
Serial.print("Value of HIGH: ");
Serial.println(normal);
// ----- long : 32 bits -------------------------------------------
large = 0x7fffffff;
Serial.print("Maximum long value: ");
Serial.println(large);
// use the properties of twos-complement arithmetic to roll over to negative numbers
large = large + 1;
Serial.print("Minimum int value: ");
Serial.println(large);
// ----- float: 32 bits -------------------------------------------
number = 0.123456789;
Serial.print("0.123456789 with float precision: ");
Serial.println(number, 10); // 10 decimal places
number = M_PI;
Serial.print("Value of pi as a float: ");
Serial.println(number, 10);
Serial.println("Please note, the print function does not work as expected for very large or small numbers:");
number = FLT_MAX;
Serial.print("Maximum positive float value: ");
Serial.println(number, 10);
number = FLT_MIN;
Serial.print("Minimum positive float value: ");
Serial.println(number, 10);
delay(1000);
}
|
rocker
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 | // 1. rock the toy with a servo
// 2. demonstrate the Servo library
#include <Servo.h>
const int ARDUINO_LED = 13;
const int SERVO1_PIN = 23; // on the Mega Pinball Shield
const int PHOTO1_PIN = A0; // on the Mega Pinball Shield
const int TILT_X_PIN = A8; // on the Mega Pinball Shield
const int TILT_Y_PIN = A9; // on the Mega Pinball Shield
const int TILT_Z_PIN = A10; // on the Mega Pinball Shield
Servo rocker_servo;
void setup()
{
pinMode(ARDUINO_LED, OUTPUT);
rocker_servo.attach(SERVO1_PIN);
Serial.begin(115200);
}
int lower = 60;
int upper = 80;
int pause1 = 100;
int pause2 = 500;
void loop()
{
digitalWrite(ARDUINO_LED, HIGH);
rocker_servo.write(lower);
delay(pause1);
digitalWrite(ARDUINO_LED, LOW);
rocker_servo.write(upper);
delay(pause2);
int photo1 = analogRead(PHOTO1_PIN);
int tilt_x = analogRead(TILT_X_PIN);
int tilt_y = analogRead(TILT_Y_PIN);
int tilt_z = analogRead(TILT_Z_PIN);
Serial.print("Photo1: "); Serial.print(photo1); Serial.print(" ");
Serial.print("Servo lower upper pause1 pause2: ");
Serial.print(lower); Serial.print(" ");
Serial.print(upper); Serial.print(" ");
Serial.print(pause1); Serial.print(" ");
Serial.print(pause2); Serial.print(" ");
Serial.print("Tilt XYZ: ");
Serial.print(tilt_x); Serial.print(" ");
Serial.print(tilt_y); Serial.print(" ");
Serial.println(tilt_z);
if (Serial.available() > 0) {
lower = Serial.parseInt();
upper = Serial.parseInt();
pause1 = Serial.parseInt();
pause2 = Serial.parseInt();
while(Serial.available() > 0) Serial.read();
}
}
|
new
switch-counter-servo
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 | #include <Servo.h>
const int SERVO_PIN = 6;
const int SWITCH_PIN = 10;
Servo svo;
void setup(void)
{
pinMode(SWITCH_PIN, INPUT);
svo.attach(SERVO_PIN);
}
bool previously_pressed = false;
int angle = 0;
void loop(void)
{
bool input = digitalRead(SWITCH_PIN);
if (input) {
// if the switch has not been pressed
if (previously_pressed) {
if (switchPressed) {
// wait for the switch to be pressed
while (digitalRead(SWITCH_PIN)) {
// do nothing
}
while
for (int idx = 0; idx < 12; idx = idx + 1) {
svo.write(angles[idx]);
delay(500);
}
}
|
iteration
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 | // Demonstration of the following:
// 1. essential program structure and logic
// 2. logic using if () {}
// 3. iteration using loop(), while(){}, and for(){}
// 4. use of Serial port for debugging output
void setup()
{
Serial.begin(115200);
}
int count = 32700;
// The following shows several possible loop functions, each demonstrating
// different features. The '#if 0/#endif' pairs are instructions to the
// compiler to ignore an entire block of code.
#if 0
void loop()
{
count = count + 1;
Serial.println(count);
delay(100);
}
#endif
#if 0
void loop()
{
count = count + 1;
Serial.println(count);
if (count == 32767) {
count = 32700;
}
delay(100);
}
#endif
#if 0
void loop()
{
while (count < 32767) {
count = count + 1;
Serial.println(count);
delay(100);
}
count = 32700;
}
#endif
#if 0
void loop()
{
for (count = 32700; count < 32767; count = count+1) {
Serial.println(count);
delay(100);
}
}
#endif
|
tilt-ball-demo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | // 1. demonstrate a tilt ball switch as digital input
// 2. generate tones on a speaker on pin 5
const int SPEAKER_PIN = 5;
const int SWITCH_PIN = 2;
void setup()
{
pinMode(SWITCH_PIN, INPUT);
Serial.begin(115200);
}
void loop()
{
if (digitalRead(SWITCH_PIN)) {
noTone(SPEAKER_PIN); // silence
Serial.println("1");
} else {
tone(SPEAKER_PIN, 440); // play A4 "concert A"
Serial.println("0");
}
}
|