FINAL CODE

The .INO file for the project is available here:

https://drive.google.com/file/d/1ygoEk5vHlqo9QrRrLRIgKR5FZhLrtrbQ/view?usp=sharing

Below is a copy of the same annotated code. Note that for the program to work properly both the FastLED and WIRE libraries must be installed.

This project also requires the use the ‘hairless’ serial to midi software available here: https://projectgus.github.io/hairless-midiserial/

It also requires a virtual MIDI port to connect to Ableton or any other DAW. Many of these are available, I use ‘LoopMIDI’.

FULL CODE:


// Include NewPing Library
#include "NewPing.h"

//include LED library
#include <FastLED.h>

//set sonar pins
#define TRIGGER_PIN1  3
#define ECHO_PIN1     2
#define TRIGGER_PIN2  5
#define ECHO_PIN2     4

//set max distance to avoid crossing the sonar streams
#define MAX_DISTANCE 30

//number of LED strips, there are 3 total but two of them do the same thing so are treated as one
#define NUM_STRIPS 2

// How many leds in each strip
#define NUM_LEDS 8
#define NUM_LEDS2 8

// LFO LEDs output pin
#define DATA_PIN 7
#define PIN 6

// Define the array of leds
CRGB leds[NUM_LEDS];
CRGB leds2[NUM_LEDS2];

//FastLED uses a global brightness variable by default. This allows multiple variables with a controler array. 
CLEDController *controllers[NUM_STRIPS];

//setup library for distance sensors 
NewPing sonar1(TRIGGER_PIN1, ECHO_PIN1, MAX_DISTANCE);

NewPing sonar2(TRIGGER_PIN2, ECHO_PIN2, MAX_DISTANCE);

//declare vars for distance sensor
int duration1, distance1;
int duration2, distance2;

int pitchOut1;
int pitchOut2;

//this sets the number of pings sent by the sonars per ms for increased acuracy. 
//More than 1 slows down my arduino Leonardo but a more powerful one could handle it. 
int iterations = 1;

//var for LFO brightness
int LFO;

//vars for sonar LED
int hand1;
int hand2;
int handCol;
int handColRev;

//declare vars for MIDI CCs
int val = 0; //Our initial pot values. We need one for the first value and a second to test if there has been a change made. This needs to be done for all 3 pots.
int lastVal = 0;
int val2 = 0;
int lastVal2 = 0;

void setup() {

  //open serial port
  Serial.begin (9600);

  //fastLED setup/pin set (LFO)
   controllers[0] = &FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);  // GRB ordering is assumed

   //fast LED setup/pin set (OSC)
    controllers[1] = &FastLED.addLeds<WS2811, PIN, GRB>(leds2, NUM_LEDS2).setCorrection( TypicalLEDStrip );
}

void loop() {

  //Readings and output for LFO LEDS.

  int sensorValue = analogRead(A0); // read the input on analog pin 0:
  
  float voltage = sensorValue;// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
  
  //Serial.println(voltage); // print out the value:
  
  LFO = map(voltage, 0, 1500, 0, 255); //scale LFO volt readings to LED peramiters

  //control LED pulses / colours for LFO
  for(int i = 0; i < NUM_LEDS; (i++)) {
    
    leds[i] = CRGB::Blue;
    controllers[0]->showLeds(LFO);
}



   //fire pulses from distance sensors
  duration1 = sonar1.ping_median(iterations);
  duration2 = sonar2.ping_median(iterations);
  
  // Determine distance from duration
  // Use 343 metres per second as speed of sound
  
  distance1 = (duration1 / 2) * 0.0343;
  distance2 = (duration2 / 2) * 0.0343;


  //set limits and create sonar reading, if no reading from sonar the value is set to 30 which will be 0 within Ableton.
  if (distance1 >= 30 || distance1 <= 0) {
    pitchOut1 = 30;
  }
  else {
    pitchOut1 = distance1;
    //delay(10);
  }
  //delay(10);

    if (distance2 >= 30 || distance2 <= 0) {
    pitchOut2 = 30;
  }
  else {
    pitchOut2 = distance2;
    //delay(10);
  }
  //delay(10);

//map sonar reading to midi scaling
     pitchOut1 = map(distance1, 0, 30 , 0, 127);
     pitchOut2 = map(distance2, 0, 30 , 0, 127);


//MIDI message conversion     
   val = pitchOut1;   
   if (val != lastVal) // If the value does not = the last value the midi data flow stops. This makes it possible to map the MIDI CCs properly in Ableton
   {
   MIDImessage(176,1,val);}         // 176 = CC command (channel 1 control change), 1 = Which Control, val = value read from sensor 1
   lastVal = val;

   val2 = pitchOut2;   
  if (val2 != lastVal2) 
   {
   MIDImessage(176,2,val2);}         // 176 = CC command, 2 = Which Control, val = value read from sensor 2
   lastVal2 = val2;

//mapping the sensor values for FastLED.
   hand1 = map(distance2, 30, 0 , 0, 8);
   hand2 = map(distance2, 30, 0 , 255, 0);
   handCol = map(distance1, 30, 0 , 55, 0);
   handColRev = map(distance1, 30, 0 , 0, 155);

//controlling colour and brightness of sonar LEDs
  for(int i = 0; i < (NUM_LEDS2); i++) {
    
    leds2[i] = CRGB(handCol, 255, handColRev);;
    controllers[1]->showLeds(hand2);

  }
   
}

//pass MIDI values out through standard Midi Command via serial port
void MIDImessage(byte command, byte data1, byte data2) 
{
   Serial.write(command);
   Serial.write(data1);
   Serial.write(data2);
}



      

Leave a comment

Your email address will not be published. Required fields are marked *