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

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}