ronbentley1
Published

Music & Lights Workbench for those new to programming

Educational - to spark early interest in youngsters in computing, with easy constructions of cool music and light commands.

BeginnerFull instructions provided1,039
Music & Lights Workbench for those new to programming

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
Or other Arduino board of suitable digital pin mappings
×1
LED (generic)
LED (generic)
standard LEDs, use whatever is to hand, or select common colour or mixed colours
×8
Speaker: 0.25W, 8 ohms
Speaker: 0.25W, 8 ohms
any suitable 0.25W/8 ohm speaker or use piezo buzzers (active or passive). I used a reclaimed speaker from an old desktop pc.
×1
Jumper wires (generic)
Jumper wires (generic)
×11
Resistor 220 ohm
Resistor 220 ohm
×8
Breadboard (generic)
Breadboard (generic)
a small board will suffice so long as the 8 x LEDs can be accommodated.
×1
Resistor 100 ohm
Resistor 100 ohm
Use to connect speaker/piezo buzzer
×1

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Custom parts and enclosures

View of all components

View of microcontroller (UNO) pin connections

View of lights (LEDs) board layout

Schematics

MLWB Circuit Diagram/Layout

Code

MLWB, Introduction tab

C/C++
An overview of the Music & Lights Workbench
/*
Ron D Bentley, Stafford, UK, July 2021

This example and code is in the public domain and
may be used without restriction and without warranty.

Introduction
^^^^^^^^^^^^
The Music and Lights Workbench (MLWB) has been designed to introduce anyone not familiar with or 
new to the subject of computer programming.  The approach taken is to provide a set of simple to use
and logically applied commands (functions) that link the computer to the outside world through the
playing musical notes and/or the lighting of LEDs.

The MLWB commands are largely independent of each other and may be used for playing just music, 
illuminating just LEDs (lights) or a combination of both. The MLWB does not require the use of
any programming functions, techniques or logic other than the simple statement of its commands.

Whilst, conditional constructs like if/then, do/while, etc, or for-loops , etc. can be used for
more advanced use under suitable teaching, they are not necessary to achieve immediate results
from the MLWB.

Anyone trying to get to grips with a new subject, here basic computer programming, benefits from
some direction by someone versed in the subject. The MLWB is no different and its use and application
is best achieved through guidance and mentoring from a someone taking the lead of tutor to the student.

Motivation
^^^^^^^^^^
The MLWB was designed for the author's grand children, to provide them with some opportunity to
understand how a computer program can be easily created to produce effects in the real world. 
It was hoped that through thinking about the logical steps needed to play simple music and/or 
turn lights (LEDs) on and off that this would peak and stimulate their desire to explore the potential
of programming more deeply.

Prerequisites
^^^^^^^^^^^^^
- a target audience - the student, young or old, who has a willingness to explore how a computer program
  can do something quickly, easily and interesting,

- a supervisor - tutor, to act as educator - mentor and teacher of the MLWB.  
  The tutor should have some experience of Arduino and IDE and its programming, 
  but this can be at a rudimentary level,
  
- if the music element of the MLWB is to be explored/used then it is helpful for both tutor and student
  to have some musical knowledge, but, again, this can be at a rudimentary level,

- hardware configured as below,

- ARDUINO IDE installed on a Windows PC,

- ahead of use by the student, the tutor to gain thorough familiarisation with the MLWB through exploration
  of its commands and inbuilt examples. Download the crib sheet as a guide an aide memoir,
  
- and finally, a plan for what the tutor will introduce to the student, building from session to session.

A Note About Terminology & Index Referencing
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Youngsters and those new to doing anything computing related often find it difficult to understand computing
related terms and that referencing can start at 0. Therefore, the MLWB tries to avoid computing terms
wherever possible and support a students desire to reference from 1, not 0. For example, the first LED (0)
is referred to as light1, the second LED (1) as light2, etc.

MLWB Commands
^^^^^^^^^^^^^
The MLWB command set falls largely into two groups - those performing musical instructions and those
performing actions with lights. However, there is one command that bridges both 'camps'. This is the
play command which is an overloaded function. It can be used either to:

  1. play a given note for a given duration, or
  2. as for 1. but with an additional parameter specifying a light number (LED) to be illuminated 
     whilst the note is playing. It is an overloaded function which can be used in either way.

Music Commands
^^^^^^^^^^^^^^
play      - will play the given note for the given duration. eg play(note_C4, minim), play(note_FS2, crot + quav), etc.
play      - an overloaded version of the command, this one allowing a light (LED) to be specified for illumination
            whist the given note is playing. eg play(note_C4, minim, light5), play(note_FS2, crot + quav, light1),
            etc.
rest      - rests for the given duration, during which time silence is maintained,. eg rest(quav), rest(0.5), etc.
set_tempo - sets the pace of a musical piece in beats per minute. eg set_tempo(allegro), set_tempo(144), etc.

Light Commands
^^^^^^^^^^^^^^
light_on       - turns on the given light (LED). eg light_on(light1), light_on(7), etc.
light_off      - turns off the given light (LED). eg light_off(light1), light_off(7), etc.
all_lights_on  - turns on all 8 lights. eg all_lights_on().
all_lights_off - turns off all 8 lights. eg all_lights_off().
flash_light    - flashes the given light for the given flash interval until redefined by another command.
                 eg flash_light(light3, 0.5), flash frequency is 1 second. This command is controlled by
                 the microcontroller's timer1, via an ISR. In this way, flash sequences will continue to
                 run even though other commands may be executed subsequent to a flash_light command. 
                 Flashing continues until another command is executed on the same light (LED).
strobe_all_lights
               - strobes all lights for the given number of cycles illuminating each light for the
                 given time.
wait           - waits for the given duration (seconds) halting any processing other than existing flash_light 
                 commands. eg wait(5.5), waits for 5.5 seconds.

Shrink-wrapped Examples
^^^^^^^^^^^^^^^^^^^^^^^
To kick things off, two tabs are included that provided examples for musical melodies/tunes and lighting sequences. 
Use these to see how each native command (function) can be used, individually and together. Indeed, these may
also be used as instructional guides between tutor and student.

MLWB Layout
^^^^^^^^^^^
The MLWB software is written in Arduino C++ and comprises six tabs. The tabs are:

- music_and_lights_workbench - this tab provides an overview of the MLWB, and echoes much of this article.
- functions_lights - this tab defines the functions underpinning the MLWB commands dealing with LED control.
- functions_tones - this tab defines the functions underpinning the MLWB commands dealing with music/tone 
  control. Additionally, this tab also defines the setup() function.
- main_work_area - this is were a student's coding should be inserted and be the central focus for teaching, 
  exploring and consolidating ideas.
- xample_lights - the MLWB is provided out of the box (OOTB) with several readymade examples demonstrating
  the use of commands for controlling LEDs (lights). These can be used as instructional examples between tutor
  and student.
- xample_tunes - the MLWB is also provided OOTB with several other readymade examples demonstrating the use
  of commands for playing tones (music) on the attached speaker/buzzer. Again, these can be used as instructional
  examples between tutor and student.

The Crib Sheet
^^^^^^^^^^^^^^
The crib sheet documents all of the preset values and commands available for use by the MLWB. Download this 
as an aide memoir and ready reference.

Finally
^^^^^^^
I feel I need to declare that my musical knowledge, skill and prowess is next to nil - I would think that a 
post box is musically more gifted!

My approach in all matters musical has been mechanistic with much use of the internet in constructing the 
musical elements of this workbench, so I apologise to anyone that may be affronted by inadequate terms or 
implementation. My defence is that it seems to work as I intended and my grand children seem to be quite happy, 
one of whom is more knowledgeable about music than I.

I hope you enjoy your experiences.
*/

MLWB, Light Functions/Commands Tab

C/C++
The tab contains all of the light functions/commands
//
// Ron D Bentley, Stafford, UK, July 2021
//
// This example and code is in the public domain and
// may be used without restriction and without warranty.
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// LED/light data and functions...
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
//

#define max_lights  8
#define off   0
#define on    1
#define flash 2

#define forwards   0
#define reverse    1
#define backwards  1

#define light1  1
#define light2  2
#define light3  3
#define light4  4
#define light5  5
#define light6  6
#define light7  7
#define light8  8

volatile int pins[max_lights] = {
  2, 3, 4, 5, 6, 7, 8, 9
};

//
// define a structure to record the status and process requirements
// for each light (led).
//
volatile struct led_control {
  uint8_t status;    // led mode - on, off or flash
  uint32_t start;    // used by flash function
  float duration; // used by flash function
  bool horl;         // used by flash function - led is alternated between LOW/HIGH
} lights[max_lights];

//
// turn on the given light (led).
//
void light_on(int light) {
  light = light - 1;
  if (light >= 0 && light < max_lights) {
    digitalWrite(pins[light], HIGH);
    noInterrupts();
    lights[light].status = on;
    lights[light].horl = HIGH;
    interrupts();
  }
}

//
// turn off the given light (led).
//
void light_off(int light) {
  light = light - 1;
  if (light >= 0 && light < max_lights) {
    digitalWrite(pins[light], LOW);
    noInterrupts();
    lights[light].status = off;
    lights[light].horl = LOW;
    interrupts();
  }
}

//
// turn on all defined lights (leds).
//
void all_lights_on() {
  for (uint8_t light = 1; light <= max_lights; light++) {
    light_on(light);
  }
}

//
// turn off all defined lights (leds).
//
void all_lights_off() {
  for (uint8_t light = 1; light <= max_lights; light++) {
    light_off(light);
  }
}

//
// start the flash cycle for the given light (led),
// with given 1/2 frequency.  ie frequency = 2 x duration.
// Note that flashing is controlled by the timer1 ISR and so
// is non-blocking.
//
void flash_light(int light, float duration) {
  light = light - 1;
  if (lights[light].status != flash) {
    lights[light].duration = duration * 1000;
    lights[light].start = millis();
    noInterrupts();
    lights[light].status = flash;
    lights[light].horl = HIGH;
    interrupts();
    digitalWrite(pins[light], HIGH);
  }
}

//
// strobe all lights the number of complete cycles illuminating
// each light for the given time, either forwards or backwards
//
//
void strobe_all_lights(bool direction, uint16_t num_cycles, float duration) {
  all_lights_off();
  for (uint16_t cycle = 0; cycle < num_cycles; cycle++) {
    if (direction == forwards) {
      for (uint8_t light = 1; light <= max_lights; light++) {
        light_on(light);
        wait(duration);
        light_off(light);
      }
    } else {
      for (uint8_t light = max_lights; light >= 1; light--) {
        light_on(light);
        wait(duration);
        light_off(light);
      }
    }
  }
}

//
// wait for the given time.
// Note that the timer1 ISR will continue whilst this function is 
// delaying the main program flow - any lights that are fashing will
// continue to flash.
//
void wait(float secs) {
  uint32_t start, duration;
  start = millis();
  duration = secs * 1000;
  do {
  } while (millis() - start <= duration);
}

//
// Timer1 interrupt routine - used to process any light (led) defined as 'flash'.
//
ISR(TIMER1_COMPA_vect)
{
  for (uint8_t light = 0; light < max_lights; light++) {
    if (lights[light].status == flash) {
      // flash cycle active for his led
      if (millis() - lights[light].start >= lights[light].duration) {
        lights[light].horl = !lights[light].horl; // invert light (led) status
        digitalWrite(pins[light], lights[light].horl);
        lights[light].start = millis(); // restart counter
      }
    }
  }
}

MLWB, Music Functions/Commands Tab

C/C++
This tab contains all of the music functions/commands plus the setup() function
//
// Ron D Bentley, Stafford, UK, July 2021
//
// This example and code is in the public domain and
// may be used without restriction and without warranty.
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// tone data and functions...
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

//
// tempos
//

#define  grave          40
#define  largo          46
#define  lento          52
#define  adagio         56
#define  larghetto      60
#define  adagietto      66
#define  andante        72
#define  andantino      80
#define  maestroso      88
#define  moderato      100
#define  allegretto    104
#define  animato       120
#define  allegro       132
#define  allegro_assai 144
#define  vivace        160
#define  presto        184
#define  prestissimo   208

//
// public constants - reflects the 'pitches.h' file, but latgely in lower case
//
#define note_B0  31
#define note_C1  33
#define note_CS1 35
#define note_D1  37
#define note_DS1 39
#define note_E1  41
#define note_F1  44
#define note_FS1 46
#define note_G1  49
#define note_GS1 52
#define note_A1  55
#define note_AS1 58
#define note_B1  62
#define note_C2  65
#define note_CS2 69
#define note_D2  73
#define note_DS2 78
#define note_E2  82
#define note_F2  87
#define note_FS2 93
#define note_G2  98
#define note_GS2 104
#define note_A2  110
#define note_AS2 117
#define note_B2  123
#define note_C3  131
#define note_CS3 139
#define note_D3  147
#define note_DS3 156
#define note_E3  165
#define note_F3  175
#define note_FS3 185
#define note_G3  196
#define note_GS3 208
#define note_A3  220
#define note_AS3 233
#define note_B3  247
#define note_C4  262 // <--------- middle C
#define note_CS4 277
#define note_D4  294
#define note_DS4 311
#define note_E4  330
#define note_F4  349
#define note_FS4 370
#define note_G4  392
#define note_GS4 415
#define note_A4  440
#define note_AS4 466
#define note_B4  494
#define note_C5  523
#define note_CS5 554
#define note_D5  587
#define note_DS5 622
#define note_E5  659
#define note_F5  698
#define note_FS5 740
#define note_G5  784
#define note_GS5 831
#define note_A5  880
#define note_AS5 932
#define note_B5  988
#define note_C6  1047
#define note_CS6 1109
#define note_D6  1175
#define note_DS6 1245
#define note_E6  1319
#define note_F6  1397
#define note_FS6 1480
#define note_G6  1568
#define note_GS6 1661
#define note_A6  1760
#define note_AS6 1865
#define note_B6  1976
#define note_C7  2093
#define note_CS7 2217
#define note_D7  2349
#define note_DS7 2489
#define note_E7  2637
#define note_F7  2794
#define note_FS7 2960
#define note_G7  3136
#define note_GS7 3322
#define note_A7  3520
#define note_AS7 3729
#define note_B7  3951
#define note_C8  4186
#define note_CS8 4435
#define note_D8  4699
#define note_DS8 4978

#define speaker  11 // digital pin number for buzzer/speaker

float default_tempo = float(animato); // default tempo - beats per minute

float current_tempo = default_tempo;

float timings[6];                     // holds timings for each defined note/rest duration

//
// standard note duration names
//
#define semib     timings[0] // 4 beats
#define dot_minim timings[1] // 3 beats
#define minim     timings[2] // 2 beats
#define crot      timings[3] // 1 beat
#define quav      timings[4] // 1/2 beat
#define semiq     timings[5] // 1/4 beat

//
// set tempo by adjusting durations of note durations
//
void set_tempo(float new_tempo) {
  float crotchet_duration;
  current_tempo = new_tempo; // keep current tempo up to date in case it needs to be queried
  crotchet_duration = 60 / new_tempo;// timing in seconds for 1 beat
  semib     = crotchet_duration * 4; // semibrieve, 4 beats
  dot_minim = crotchet_duration * 3; // dotted mimin, 3 beats
  minim     = crotchet_duration * 2; // minim, 2 beats
  crot      = crotchet_duration;     // crotchet, 1 beat
  quav      = crotchet_duration / 2; // quaver, 1/2 beat
  semiq     = crotchet_duration / 4; // semiquaver, 1/4 beat
}

//
// play given note for given duration.
// observe that this function is 'blocking', although the tone
// function is 'non-blocking', ie control stays with the function
// until note has completed.
//
void play(int note, float duration) {
  tone(speaker, note, duration * 1000); // play the given note for the given duration
  wait(duration);                       // wait for note to complete
}

//
// play given note for given duration and illuminate given light (led).
// observe that this function is 'blocking', although the tone
// function is 'non-blocking', ie control stays with the function
// until note has completed.
//
void play(int note, float duration, int light) {
  tone(speaker, note, duration * 1000); // play the given note for the given duration
  light_on(light);                     // switch on the given light
  wait(duration);                      // wait for note to complete
  light_off(light);                    // switch off the given light
}

//
// rest for given duration.
//
void rest(float duration) {
  noTone(speaker); // ensure no tone is currently playing
  wait(duration);  // wait for given rest to complete
}

void setup() {
  //
  // set up timer1 interrupt for 1000hz interrupts, ie for 1 millisecond interrupts.
  // this is used to process any defined flash function calls.
  //
  noInterrupts();
  TCCR1A = 0;     // set TCCR1A register to 0
  TCCR1B = 0;     // SET TCCR1B register to 0
  TCNT1  = 0;     // initialize counter to 0
  // set Compare Match Register (CMR) for 1msec (1khz) increments
  OCR1A = 249;    // OCR1A = (16,000,000)/(64*1,000)) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);              // WGM12 = 3
  // Set CS11 bit for 64 prescaler
  TCCR1B |= (1 << CS11) | (1 << CS10); // CS11 = 1 and CS10 = 0
  // enable timer1 compare interrupt
  TIMSK1 |= (1 << OCIE1A);             // OCIE1A = 1
  interrupts();

  //
  // now set each defined light (led) output pin and
  // test prior to main loop processing - visual check
  //
  for (int light = 0; light < max_lights; light++) {
    pinMode(pins[light], OUTPUT);
    light_on(light + 1);
    wait(0.05);
    light_off(light + 1);
    wait(0.05);
  }

  //
  // finally set up tone requirements and default tempo
  //
  pinMode(speaker, OUTPUT);
  // set up note timings, base on the default unit beat time (default_tempo)
  set_tempo(default_tempo);
}

MLWB, Main Work Area Tab

C/C++
This is the place (tab) where student commands should be included. Out of the box it contains examples of light and music commands
//
// Ron D Bentley, Stafford, UK, July 2021
//
// This example and code is in the public domain and
// may be used without restriction and without warranty.
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// Add your commands here below, and note that when the last command has
// been actioned the program will restart.
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void loop() {
  /*%%%%%%%%%%%%%%%%%%%%% tasters & example features %%%%%%%%%%%%%%%%%%%%%%
    The following code is provided as a taster and example of what features
    the workbench can provide and how they can be used.
    Once familiar with these features, strip out this code and add your own.
  */

  // some music examples...

  middle_C();
  wait(3);

  twinkle_twinkle();
  wait(3);

  jingle_bells();
  wait(3);

  happy_birthday();
  wait(3);

  ditty_1(); // music with lights
  wait(3);

  door_bell_1(); // music with lights
  wait(3);

  door_bell_2(); // music with lights
  wait(3);

  ode_to_joy();
  wait(3);

  // some light examples...

  sweep_lights();
  wait(3);

  chasing_lights();
  wait(3);

  marching_lights();
  wait(3);

  // flash all lights for 10 seconds
  flash_all_lights();
  wait(10);

  // strobe all lights backwards - 10 cycles, with 0.1 secs delay bewteen lights
  strobe_all_lights(backwards, 10, 0.1);
  // strobe all lights forwards - 20 cycles, with 0.05 secs delay bewteen lights
  strobe_all_lights(forwards, 20, 0.05);

  // more flash flash examples
  flash_light(light2, 0.1);
  flash_light(light4, 0.2);
  flash_light(light6, 0.25);
  flash_light(light8, 0.5);
  wait(3);

  // 4 cycles of morse code
  sos_morse_code();
  sos_morse_code();
  sos_morse_code();
  sos_morse_code();
  wait(3);

  // trafic lights
  traffic_lights();
  all_lights_off();
  // back to the beginning...
}

MLWB, Light examples tab

C/C++
A tab containing examples of light projects
//
// Ron D Bentley, Stafford, UK, July 2021
//
// This example and code is in the public domain and
// may be used without restriction and without warranty.
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %                  Example 'shrink-wrapped' light               %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


void sweep_lights() {// sweep lights to the centre
  all_lights_off();  // start with 'clean slate'

  light_on(light1);
  light_on(light8);
  wait(0.25);
  light_off(light1);
  light_off(light8);

  light_on(light2);
  light_on(light7);
  wait(0.25);
  light_off(light2);
  light_off(light7);

  light_on(light3);
  light_on(light6);
  wait(0.25);
  light_off(light3);
  light_off(light6);

  light_on(light4);
  light_on(light5);
  wait(0.25);
  light_off(light4);
  light_off(light5);

  wait(0.1);

  light_on(light4);
  light_on(light5);
  wait(0.25);
  light_off(light4);
  light_off(light5);

  light_on(light3);
  light_on(light6);
  wait(0.25);
  light_off(light3);
  light_off(light6);

  light_on(light2);
  light_on(light7);
  wait(0.25);
  light_off(light2);
  light_off(light7);

  light_on(light1);
  light_on(light8);
  wait(0.25);
  light_off(light1);
  light_off(light8);
}

void chasing_lights() {// light chase
  all_lights_off();    // start with 'clean slate'

  light_on(light1);
  wait(0.1);
  light_on(light2);
  wait(0.1);
  light_on(light3);
  wait(0.1);
  light_on(light4);
  wait(0.1);
  light_on(light5);
  wait(0.1);
  light_on(light6);
  wait(0.1);
  light_on(light7);
  wait(0.1);
  light_on(light8);
  wait(0.1);

  light_off(light1);
  wait(0.1);
  light_off(light2);
  wait(0.1);
  light_off(light3);
  wait(0.1);
  light_off(light4);
  wait(0.1);
  light_off(light5);
  wait(0.1);
  light_off(light6);
  wait(0.1);
  light_off(light7);
  wait(0.1);
  light_off(light8);
  wait(0.1);
}

void marching_lights() {// marching lights
  all_lights_off();     // start with 'clean slate'
  light_on(light1);
  wait(0.1);
  light_off(light1);
  wait(0.1);
  light_on(light1);
  light_on(light2);
  wait(0.1);
  light_off(light1);
  light_off(light2);
  wait(0.1);
  light_on(light1);
  light_on(light2);
  light_on(light3);
  wait(0.1);
  light_off(light1);
  light_off(light2);
  light_off(light3);
  wait(0.1);
  light_on(light1);
  light_on(light2);
  light_on(light3);
  light_on(light4);
  wait(0.1);
  light_off(light1);
  light_off(light2);
  light_off(light3);
  light_off(light4);
  wait(0.1);
  light_on(light2);
  light_on(light3);
  light_on(light4);
  light_on(light5);
  wait(0.1);
  light_off(light2);
  light_off(light3);
  light_off(light4);
  light_off(light5);
  wait(0.1);
  light_on(light3);
  light_on(light4);
  light_on(light5);
  light_on(light6);
  wait(0.1);
  light_off(light3);
  light_off(light4);
  light_off(light5);
  light_off(light6);
  wait(0.1);
  light_on(light4);
  light_on(light5);
  light_on(light6);
  light_on(light7);
  wait(0.1);
  light_off(light4);
  light_off(light5);
  light_off(light6);
  light_off(light7);
  wait(0.1);
  light_on(light5);
  light_on(light6);
  light_on(light7);
  light_on(light8);
  wait(0.1);
  light_off(light5);
  light_off(light6);
  light_off(light7);
  light_off(light8);
  wait(0.1);
  light_on(light6);
  light_on(light7);
  light_on(light8);
  wait(0.1);
  light_off(light6);
  light_off(light7);
  light_off(light8);
  wait(0.1);
  light_on(light7);
  light_on(light8);
  wait(0.1);
  light_off(light7);
  light_off(light8);
  wait(0.1);
  light_on(light8);
  wait(0.1);
  light_off(light8);
  wait(0.1);






}

void flash_all_lights() {
  // commands stated indivually rather than use of for-loop
  // as we do not introduce such constructs in this workbench
  flash_light(light1, 0.1);
  flash_light(light2, 0.2);
  flash_light(light3, 0.3);
  flash_light(light4, 0.4);
  flash_light(light5, 0.5);
  flash_light(light6, 0.6);
  flash_light(light7, 0.7);
  flash_light(light8, 0.8);
}

void sos_morse_code() {// performs 1 cycle
  // sos morse code, - - -  . . . etc
  // dash, dash, dash
  all_lights_on();
  wait(0.5);
  all_lights_off();
  wait(0.5);
  all_lights_on();
  wait(0.5);
  all_lights_off();
  wait(0.5);
  all_lights_on();
  wait(0.5);
  all_lights_off();
  // change signal to dot, dot, dot
  wait(1);
  all_lights_on();
  wait(0.25);
  all_lights_off();
  wait(0.25);
  all_lights_on();
  wait(0.25);
  all_lights_off();
  wait(0.25);
  all_lights_on();
  wait(0.25);
  all_lights_off();
  wait(1);
}

// traffic lights
// this function assumes that the leds are arranged in colurs:
// light1 - red
// light2 - yellow
// light3 - green
// light4 - n/a
// light5 - red
// light6 - yellow
// light7 - green
// light8 - n/a
//
void traffic_lights() {
  all_lights_off();
  // start with road 1 on red and road 2 on green
  light_on(light1); // turn on road 1 red
  light_on(light7); // turn road 2 green
  wait(5);

  // now transition
  light_on(light6);  // turn on road 2 amber
  light_off(light7); // turn off road 2 green
  wait(3);

  light_on(light2);  // turn on road 1 amber
  light_on(light5);  // turn on road 1 red
  light_off(light6); // turn off road 2 amber
  wait(3);

  light_off(light1);  // turn off road 1 red
  light_off(light2);  // turn off road 1 amber
  light_on(light3);   // turn on road 1 green
  wait(5);

}

MLWB, Music examples tab

C/C++
A tab containing several examples of music melodies, with & with light effects
//
// Ron D Bentley, Stafford, UK, July 2021
//
// This eplay(note_ample and code is in the public domain and
// may be used without restriction and without warranty.
//
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// %                      'shrink-wrapped' music examples                  %
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

void middle_C() {
  // 4/4 time
  // C major scale - up
  // bar 1
  play(note_C4, crot);
  play(note_D4, crot);
  play(note_E4, crot);
  play(note_F4, crot);
  // bar 2
  play(note_G4, crot);
  play(note_A4, crot);
  play(note_B4, crot);
  play(note_C5, crot);
  // bar 3
  rest(semib);
  // C major scale - down
  // bar 4
  play(note_C5, crot);
  play(note_B4, crot);
  play(note_A4, crot);
  play(note_G4, crot);
  // bar 5
  play(note_F4, crot);
  play(note_E4, crot);
  play(note_D4, crot);
  play(note_C4, crot);
}

void twinkle_twinkle() {
  set_tempo(default_tempo * 2);

  //Twinkle, twinkle, little star, C' C' G' G' A' A' G'
  play(note_C4, minim);
  play(note_C4, minim);
  play(note_G4, minim);
  play(note_G4, minim);
  play(note_A4, minim);
  play(note_A4, minim);
  play(note_G4, minim);
  rest(minim);

  //How I wonder what you are, F' F' E' E' D' D' C'
  play(note_F4, minim);
  play(note_F4, minim);
  play(note_E4, minim);
  play(note_E4, minim);
  play(note_D4, minim);
  play(note_D4, minim);
  play(note_C4, minim);
  rest(minim);

  //Up above the world so high, G' G' F' F' E' E' D'
  play(note_G4, minim);
  play(note_G4, minim);
  play(note_F4, minim);
  play(note_F4, minim);
  play(note_E4, minim);
  play(note_E4, minim);
  play(note_D4, minim);
  rest(minim);

  //Like a diamond in the sky, G' G' F' F' E' E' D'
  play(note_G4, minim);
  play(note_G4, minim);
  play(note_F4, minim);
  play(note_F4, minim);
  play(note_E4, minim);
  play(note_E4, minim);
  play(note_D4, minim);
  rest(minim);

  //Twinkle, twinkle, little star, C' C' G' G' A' A' G'
  play(note_C4, minim);
  play(note_C4, minim);
  play(note_G4, minim);
  play(note_G4, minim);
  play(note_A4, minim);
  play(note_A4, minim);
  play(note_G4, minim);
  rest(minim);

  //How I wonder what you are, F' F' E' E' D' D' C'
  play(note_F4, minim);
  play(note_F4, minim);
  play(note_E4, minim);
  play(note_E4, minim);
  play(note_D4, minim);
  play(note_D4, minim);
  play(note_C4, minim);

  rest(crot);

  set_tempo(default_tempo);  // reset tempo
}

void jingle_bells() {
  set_tempo(default_tempo * 2); // very lively

  play(note_B3, crot);
  play(note_B3, crot);
  play(note_B3, minim);

  play(note_B3, crot);
  play(note_B3, crot);
  play(note_B3, minim);

  play(note_B3, crot);
  play(note_D4, crot);
  play(note_G3, crot);
  play(note_A3, crot);

  play(note_B3, semib);

  play(note_C4, crot);
  play(note_C4, crot);
  play(note_C4, crot);
  play(note_C4, crot);

  play(note_C4, crot);
  play(note_B3, crot);
  play(note_B3, crot);
  play(note_B3, crot);

  play(note_B3, crot);
  play(note_A3, crot);
  play(note_A3, crot);
  play(note_B3, crot);

  play(note_A3, minim);
  play(note_D4, minim);

  play(note_B3, crot);
  play(note_B3, crot);
  play(note_B3, minim);

  play(note_B3, crot);
  play(note_B3, crot);
  play(note_B3, minim);

  play(note_B3, crot);
  play(note_D4, crot);
  play(note_G3, crot);
  play(note_A3, crot);

  play(note_B3, semib);

  play(note_C4, crot);
  play(note_C4, crot);
  play(note_C4, crot);
  play(note_C4, crot);

  play(note_C4, crot);
  play(note_B3, crot);
  play(note_B3, crot);
  play(note_B3, crot);

  play(note_D4, crot);
  play(note_D4, crot);
  play(note_C4, crot);
  play(note_A3, crot);

  play(note_G3, semib);

  set_tempo(default_tempo); // reset tempo
}

void happy_birthday() {
  play(note_G3, quav);
  play(note_G3, quav);
  play(note_A3, crot);
  play(note_G3, crot);

  play(note_C4, crot);
  play(note_B3, minim);

  play(note_G3, quav);
  play(note_G3, quav);
  play(note_A3, crot);
  play(note_G3, crot);

  play(note_D4, crot);
  play(note_C4, minim);

  play(note_G3, quav);
  play(note_G3, quav);
  play(note_G4, crot);
  play(note_E4, crot);

  play(note_C4, crot);
  play(note_B3, crot);
  play(note_A3, crot);

  play(note_F4, quav);
  play(note_F4, quav);
  play(note_E4, crot);
  play(note_C4, crot);

  play(note_D4, crot);
  play(note_C4, minim);

  rest(crot);
}

void ditty_1() {// music with light effects
  set_tempo(default_tempo * 2); // lively pace

  play(note_C4, minim, light1);
  play(note_G3, crot, light2);
  play(note_G3, crot, light3);
  play(note_GS3, minim, light4);
  play(note_G3, minim, light5);
  rest(crot + quav);
  play(note_B3, minim, light6);
  play(note_C4, crot, light7);

  rest(crot);

  set_tempo(default_tempo); // reset tempo
}

void door_bell_1() {// illuminating door bell chime
  play(note_E4, minim, light1);
  play(note_C4, minim, light2);
  play(note_D4, minim, light3);
  play(note_G3, minim, light4);

  rest(minim);

  play(note_G3, minim, light4);
  play(note_D4, minim, light3);
  play(note_E4, minim, light2);
  play(note_C4, minim, light1);

  rest(crot);
}

void door_bell_2() {// basic bing/bong door chime
  set_tempo(default_tempo * 2); // lively pace

  play(note_E5, dot_minim, light1);
  play(note_C5, dot_minim, light2);

  rest(dot_minim);

  play(note_E5, dot_minim, light1);
  play(note_C5, dot_minim, light2);

  rest(crot);

  set_tempo(default_tempo);   // reset tempo
}

void ode_to_joy() {
  set_tempo(allegro);
  // 4/4 time
  //bar 1 
  play(note_B4, crot);
  play(note_B4, crot);
  play(note_C5, crot);
  play(note_D5, crot);
  //bar 2 
  play(note_D5, crot);
  play(note_C5, crot);
  play(note_B4, crot);
  play(note_A4, crot);
  //bar 3 
  play(note_G4, crot);
  play(note_G4, crot);
  play(note_A4, crot);
  play(note_B4, crot);
  //bar 4 
  play(note_B4, crot + quav);
  play(note_A4, quav);
  play(note_A4, minim);
  //bar 5 
  play(note_B4, crot);
  play(note_B4, crot);
  play(note_C5, crot);
  play(note_D5, crot);
  //bar 6 
  play(note_D5, crot);
  play(note_C5, crot);
  play(note_B4, crot);
  play(note_A4, crot);
  //bar 7 
  play(note_G4, crot);
  play(note_G4, crot);
  play(note_A4, crot);
  play(note_B4, crot);
  //bar 8 
  play(note_A4, crot + quav);
  play(note_G4, quav);
  play(note_G4, minim);
  //bar 9 
  play(note_A4, crot);
  play(note_A4, crot);
  play(note_B4, crot);
  play(note_G4, crot);
  //bar 10 
  play(note_A4, crot);
  play(note_B4, quav);
  play(note_C5, quav);
  play(note_B4, crot);
  play(note_G4, crot);
  //bar 11 
  play(note_A4, crot);
  play(note_B4, quav);
  play(note_C5, quav);
  play(note_B4, crot);
  play(note_A4, crot);
  //bar 12 
  play(note_G4, crot);
  play(note_A4, crot);
  play(note_D4, minim);
  //bar 13 
  play(note_B4, crot);
  play(note_B4, crot);
  play(note_C5, crot);
  play(note_D5, crot);
  //bar 14 
  play(note_D5, crot);
  play(note_C5, crot);
  play(note_B4, crot);
  play(note_A4, crot);
  //bar 15 
  play(note_G4, crot);
  play(note_G4, crot);
  play(note_A4, crot);
  play(note_B4, crot);
  //bar 16 
  play(note_A4, crot + quav);
  play(note_G4, quav);
  play(note_G4, minim);
}

Credits

ronbentley1

ronbentley1

25 projects • 13 followers

Comments