14 March 2021

Scaffoldig: NIME Music box - Lidstrument

    For my project, I have created an instrument I call the Lidstrument, due to the fact that the controls are placed on top of a jar like a lid. The instrument is made up of  a cardboard box, glass jar, a micro servo with wire and a toy ball attached, 3 potentiometers, and the circuit playground express.

Built prototype:                                                          Schematics:     

    

    Using the internal speaker of the Circuit Playground, the built-in left button will play a single note, while the built in right button will play a sequence of 5 notes within a five note range of the main note. The main note is defined by the left potentiometer, while the duration of the notes are defined by the right-top potentiometer. The speed of the micro servo is controlled by the right-side potentiometer.    

Video Demonstration:


Concept Creation

    For the concept of the instrument, I had originally wanted to use a number pad in order to be able to place certain sounds on each number, but I soon found out that the limitations of the Circuit Playground express prevented me from using it as well as other requirements such as the servo and the potentiometer, since the feedback from the number pad would have taken up nearly all of the analog ports. Due to this I made a revised concept version. I still wanted the user to be able to control which note they wanted to play, so I opted to use a potentiometer to replace the number pad. The revision is not in the same control layout in the drawing, but the overall form ended up being very similar.

First Concepts:


Revised Concept:

    Other than the digital controls, I knew we were required to have some type of acoustic sound produced by a servo, so I had decided that I would have the use a wire attached to a servo in order to produce the sound required. The wire by itself was not creating the desired amount of sound so I had added the toy ball after the concept phase so that there would be a louder clang against the glass.

Question:

Could my layout of the potentiometers and buttons be better?


Code:

#include <Adafruit_CircuitPlayground.h>
#include <Adafruit_Circuit_Playground.h>
#include <Servo.h>
#include "pitches.h"

//By Kaitlyn Monroe 2021

//Servo
Servo myServo;

//Constants=============================
//inputs/outputs-----------------------------------
const int speaker = 5;       // CP speaker output
const int beatPin = A3; //red- delay input
const int notePin = A2; //yellow - note input
const int servoPin = A1; //black - servo rotation output
const int spinPin = A7; //white -rotation control imput

//number of notes in melody----------------------------
const int numNotes = 5;
const int pauseDuration= 4;
 
//Variables:===========================

  //potentio reads-------------
  int beatvalue; //save beat potentio analog value
  int notevalue; //note range potentio
  int spinvalue; // servo rotation speed

  //note frequency range array----------
  
  int range[] = {
    31, 33, 35, 37, 39, 41, 44, 46, 49, 52, 55, 58, 62, 65, 69, 73, 78, 82, 87, 93, 98, 104, 110, 117, 123, 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247, 262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, 523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, 2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, 4186, 4435, 4699, 4978
  };

  //servo--------------
  int servoPos; //servo position
  int inc = 1;//position increments
 
  //button reads------------
  int LCurrent = 0;
  int LPrevious =0;

  int RCurrent = 0;
  int RPrevious =0;

//Timer=================================
  
  //servo timers--------
  unsigned long previousMillis = 0;        // will store last time servo was updated
  long interval = 0;           // interval at which to move (milliseconds)
 
  //note timers----------
  unsigned long lastPeriodStart = 0;        // will store last time note was updated
  long duration = 0;           // interval at which to play sound (milliseconds)
  unsigned long lastPeriodEnd = 0; 

//========================================================================
void setup() {
  // INT PLAYGROUND
  CircuitPlayground.begin();

  //INT SERIAL
  Serial.begin(9600);
  
  pinMode(speaker, OUTPUT);     // Output - speaker
  myServo.attach(servoPin);

  pinMode (beatPin, INPUT); // Input - metronome Potentio.
  pinMode (notePin, INPUT); // Input - note select Potentio.
  pinMode (spinPin,INPUT);// Input - servo rotation potentio.
  pinMode(CPLAY_LEFTBUTTON , INPUT_PULLDOWN);//Button A
  pinMode(CPLAY_RIGHTBUTTON , INPUT_PULLDOWN);//Button B
}

//========================================================================
void loop() {
  //set timer
  unsigned long currentMillis = millis();
  
  //read beat potentio-----------------------------------------------------------------
  beatvalue = analogRead(beatPin);   
  Serial.print (beatvalue);
  Serial.print ("   ");
  //Read and save analog value from potentiometer
  beatvalue = map(beatvalue, 0, 1023, 10, 1000); // affects delay in play tone
  duration = beatvalue;
  
   //read note potentio--------------------------------------------------------------
  notevalue = analogRead(notePin); 
  Serial.print (notevalue);
  Serial.print ("   "); //Read and save analog value from potentiometer
  notevalue = map(notevalue, 0, 1023, 0, 87); //88 potential notes
  int frequency = range [notevalue];


  
  
 //Check if L button is pressed--------------------------------------------------
  LCurrent = digitalRead(CPLAY_LEFTBUTTON);
  
  //when pressed toggle and play note 
    if (LCurrent == 1  && LPrevious == 0){
      //play note
  CircuitPlayground.playTone(frequency, duration);
  
  //update button read
    LCurrent = digitalRead(CPLAY_LEFTBUTTON);
  }

//set back to 0 when not pressed
   LPrevious = LCurrent;

// Check if R button is pressed---------------------------------------------------
RCurrent = digitalRead(CPLAY_RIGHTBUTTON);
if(RCurrent == 1 && RPrevious == 0) {   // play when we press the right button
  
    for (int thisNote = 0; thisNote < numNotes; thisNote++) { // play notes of the melody
    // calculate random notes for melody
      int randomNote = rand() % (4 + 1 - 0) + 0;

      int randFrequency = notevalue + randomNote;

     int randRange = range[randFrequency];

     //melody creation
  
      int melody[] = {
        frequency, randRange, randRange, randRange, randRange
       };
     //play melody
      CircuitPlayground.playTone(melody[thisNote], duration);
 
      //pause between notes
      int pauseBetweenNotes = pauseDuration;
      delay(pauseBetweenNotes);
    }
    //update button read
    RCurrent = digitalRead(CPLAY_RIGHTBUTTON);
  }
 //set back to 0 when not pressed
RPrevious = RCurrent;

    //read spin potentio-----------------------------------------------------------
  spinvalue = analogRead(spinPin);  
  Serial.print (spinvalue);
  Serial.println ("   "); //Read and save analog value from potentiometer
  spinvalue = map(spinvalue, 0, 1023, 1, 20); //maps 1-20 to affect delay of servo
  
  //reverse spin if at 180
  if(servoPos == 180) inc = -1;
  
  //reverse spin if at 0
  if(servoPos == 0) inc = 1;

  

// define interval
  interval = spinvalue;

  //use timer instead of delay to get constant movement
  
  if (currentMillis - previousMillis >= interval) {
    // save the last time 
    previousMillis = currentMillis;
    
    // continuous servo movement
     servoPos += inc;
     
     // write servo speed
     myServo.write(servoPos);
  }
}
 

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.