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