Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 16 of 16

Thread: Range sensor MIDI instrument

  1. #1
    Junior Member
    Join Date
    Nov 2019
    Posts
    15

    Range sensor MIDI instrument

    Hi, coders! I know enough to be dangerous, but not enough to nail my first code project for Teensy 4.0. I probably won't be coding again in the near future, so learning everything from scratch doesn't make sense for me. If I could get some help fixing and finishing this code, I would greatly appreciate it. Here's the project: I'm using 8 Sharp GP2Y0A02YK0F Infrared Proximity Sensors as a MIDI instrument. To start, I just want to program one sensor to send a MIDI note via USB MIDI. If it's fast enough, I'll add the other 7. The idea is, when I put my hand over a sensor, the voltage changes and sends the MIDI note (from there I'll patch the MIDI signal to my software synth for actual sound).

    Here is the code I've cobbled together. I'm sure I'm missing some definitions or initializations. The error I'm currently getting is "usbMIDI was not declared within this scope". Please give this a look and tell me what I'm obviously doing wrong. TIA

    Code:
    int noteIsOn;
    
    void setup() {
    
    }
    
    void loop() {
    
      if (noteIsOn == false) {
        if (analogRead(0) > 200) {
          usbMIDI.sendNoteOn(60, 100, 1);
          noteIsOn = true;
        }
      } else {
        if (analogRead(0) < 200) {
          usbMIDI.sendNoteOff (60, 0, 1);
          noteIsOn = false;
        }
      }
      while (usbMIDI.read()) {}
      delay(5);
    
    }

  2. #2
    Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    38
    You need to choose a USB type Midi in Tools so the compiler knows to use it. I don't think T4 supports USB Mid yet.

  3. #3
    Junior Member
    Join Date
    Nov 2019
    Posts
    15
    Uh oh! I was wondering why I didn't see it as an option under "port". So, I need a 3.2? Or is there another simple option I should look at? This needs to be performance-ready fast. Any direction would be appreciated.

  4. #4
    Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    38
    Any Teensy from LC to 3_6 should do it.

  5. #5
    Junior Member
    Join Date
    Nov 2019
    Posts
    15
    I bought a 3.2 and have it up and running. Everything works well. I've expanded it to 3 sensors and need to go to 8. I'm sure there's a way to loop the code rather than put it in 8 times, but I'm not sure how to do it. Any help appreciated. Here is what I have for 3 sensors:

    Code:
    int noteIsOn1;
    int noteIsOn2;
    int noteIsOn3;
    int thresh;
    
    void setup() {
    
    thresh = 225;
    
    }
    
    void loop() {
    
    /// Sensor 1
      if (noteIsOn1 == false) {
        if (analogRead(0) > thresh) {
          usbMIDI.sendNoteOn(60, 100, 1);
          noteIsOn1 = true;
        }
      } else {
        if (analogRead(0) < thresh) {
          usbMIDI.sendNoteOff (60, 0, 1);
          noteIsOn1 = false;
        }
      }
    /// Sensor 2
      if (noteIsOn2 == false) {
        if (analogRead(1) > thresh) {
          usbMIDI.sendNoteOn(64, 100, 1);
          noteIsOn2 = true;
        }
      } else {
        if (analogRead(1) < thresh) {
          usbMIDI.sendNoteOff (64, 0, 1);
          noteIsOn2 = false;
        }    
      }
    /// Sensor 3
      if (noteIsOn3 == false) {
        if (analogRead(2) > thresh) {
          usbMIDI.sendNoteOn(67, 100, 1);
          noteIsOn3 = true;
        }
      } else {
        if (analogRead(2) < thresh) {
          usbMIDI.sendNoteOff (67, 0, 1);
          noteIsOn3 = false;
        }    
      }
      while (usbMIDI.read()) {}
      delay(5);
    
    }

  6. #6
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    165
    Here is a way to loop the code, it compiles but did not test.
    Code:
    int thresh;
    
    struct Sensor{
      const uint8_t pin;  //analog sensor pin nr
      uint8_t note; //sensor midi note
      bool noteIsOn; //sensor status
    };
    
    const uint8_t sensor_nr = 8;
    
    //define sensor pin_nr and midi_note
    Sensor sensor[sensor_nr]{
      {0, 60, false},
      {1, 64, false},
      {2, 67, false},
      {3, 70, false},
      {6, 71, false},
      {7, 72, false},
      {8, 73, false},
      {9, 74, false}
    };
    
    void setup() {
    
      thresh = 225;
    
    }
    
    void loop() {
    
      for(uint8_t s = 0; s < sensor_nr; s++) {
        if (sensor[s].noteIsOn == false) {
          if (analogRead(sensor[s].pin) > thresh) {
            usbMIDI.sendNoteOn(sensor[s].note, 100, 1);
            sensor[s].noteIsOn = true;
          }
        } else {
          if (analogRead(sensor[s].pin) < thresh) {
            usbMIDI.sendNoteOff(sensor[s].note, 0, 1);
            sensor[s].noteIsOn = false;
          }
        }
      }
    
      while (usbMIDI.read()) {}
      delay(5);
    
    }

  7. #7
    Junior Member
    Join Date
    Nov 2019
    Posts
    15
    Cool! I'll give a try. Thanks!

  8. #8
    Senior Member oddson's Avatar
    Join Date
    Feb 2013
    Location
    Isle in the Salish Sea
    Posts
    1,238
    That's fairly slick...

    I haven't been using structures with Teensyduino but seeing how easy it looks I think I might start.



    @OP
    The delay(5); is likely keeping this code fairly stable in its output. Without it Teensy would run thousands of times faster and likely give some MIDI chatter when you are near threshold values from the sensors.

    If you have other code to run and can't afford dead time consider using the ResponsiveAnalogRead() library to stabilise the signal.

    Alternately, separate off and on thresholds could also work since you are already tracking a state variable. (Dead-band hysteresis.)

  9. #9
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    165
    Quote Originally Posted by oddson View Post
    That's fairly slick...

    I haven't been using structures with Teensyduino but seeing how easy it looks I think I might start.
    And in this case it is easy to extend the structure to contain velocity, midi channel and even different threshold values for every sensor.
    Code:
    struct Sensor{
      const uint8_t pin;  //analog sensor pin nr
      uint8_t note; //sensor midi note
      uint8_t velocity;
      uint8_t midi_channel;
      uint16_t threshold_on;
      uint16_t threshold_off;
      bool noteIsOn; //sensor status
    };

  10. #10
    Junior Member
    Join Date
    Nov 2019
    Posts
    15
    Great! I was already thinking about this! For velocity, I'm adding in random(95,110) to give the notes a more natural feel. I'm also playing with the idea of adding in MIDI controller 1 data (modulation/expression) as you get closer and further from the sensor, giving you another level of expression.

    Question: Can I -- or should I -- use an external 5V power source for the sensors? Or just use what's coming in through USB and pull the power from the Teensy pins?

  11. #11
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    165
    Quote Originally Posted by Synchrony View Post
    Question: Can I -- or should I -- use an external 5V power source for the sensors? Or just use what's coming in through USB and pull the power from the Teensy pins?
    According to the datasheet for the Sharp sensor,
    typical supply current is 33mA
    max supply current is 50mA

    Assuming you only want to power 8 sensors and 1 T3.2 then
    total supply current = 8 x 33mA + ~50ma = ~314mA

    Worst case scenario
    total supply current = 8 x 50mA + ~50ma = ~450mA

    This is within the limits of the 500mA of a usb port.

    As soon as you add some other peripherals to your project, it would be wise to switch to an external power supply.
    You can also choose not to take any risks blowing your usb port because of an accidental short or so and just go with the external power supply.
    If so, don't forget to cut the VUSB trace of the teensy.

    Another way to protect your possibly expensive computer is to power your project through a powered usb hub.

  12. #12
    Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    38
    Are those range sensors polite enough to let you power them up, read then power them down in sequence so as to spread out the power drain?

    I hope I'm not getting Off-topic here but a hand up from the back of class re neurofun's post:-

    Code:
    struct Sensor{
      const uint8_t pin;  //analog sensor pin nr
      uint8_t note; //sensor midi note
      bool noteIsOn; //sensor status
    };
    
    const uint8_t sensor_nr = 8;
    
    //define sensor pin_nr and midi_note
    Sensor sensor[sensor_nr]{
      {0, 60, false},
      {1, 64, false},
      {2, 67, false},
      {3, 70, false},
      {6, 71, false},
      {7, 72, false},
      {8, 73, false},
      {9, 74, false}
    };
    How would you attach responsiveAnalogRead or bounce objects to each element (if that's the right word) of the struct ?

  13. #13
    Senior Member
    Join Date
    Nov 2017
    Location
    Belgium
    Posts
    165
    Quote Originally Posted by MatrixRat View Post
    How would you attach responsiveAnalogRead or bounce objects to each element (if that's the right word) of the struct ?
    First you have to declare a pointer to the object you want in your struct and then you need to instantiate that object.
    Members of the objects inside the struct can then be accessed with ->

    Here are 2 versions of an example(tested on a T3.6) that will read an analog input when the corresponding pushbutton is pressed. The only difference is how the objects are instantiated, functionality is the same.
    Code:
    #include "Bounce.h"
    #include "ResponsiveAnalogRead.h"
    
    struct Sensor{
      Bounce* button;
      ResponsiveAnalogRead* analog_input;
    };
    
    const uint8_t sensor_nr = 4;
    
    Sensor sensor[sensor_nr]{
      {new Bounce(0, 20), new ResponsiveAnalogRead(0, false)},
      {new Bounce(1, 20), new ResponsiveAnalogRead(1, false)},
      {new Bounce(2, 20), new ResponsiveAnalogRead(2, false)},
      {new Bounce(3, 20), new ResponsiveAnalogRead(3, false)}
    };
    
    void setup() {
    
      Serial.begin(1000000);
      for(uint8_t s = 0; s < sensor_nr; s++) {
        pinMode(s, INPUT_PULLUP);
      }
    }
    
    void loop() {
    
      for(uint8_t s = 0; s < sensor_nr; s++) {
        sensor[s].analog_input->update();
        if (sensor[s].button->update()) {
          if (sensor[s].button->fallingEdge()) {
            int sample = sensor[s].analog_input->getValue();
            Serial.print("sensor ");
            Serial.print(s);
            Serial.print(" value ");
            Serial.println(sample);
          }
        }
      }
    
    }
    Code:
    #include "Bounce.h"
    #include "ResponsiveAnalogRead.h"
    
    struct Sensor{
      Bounce* button;
      ResponsiveAnalogRead* analog_input;
    };
    
    const uint8_t sensor_nr = 4;
    
    Sensor sensor[sensor_nr];
    
    void setup() {
    
      Serial.begin(1000000);
      for(uint8_t s = 0; s < sensor_nr; s++) {
        pinMode(s, INPUT_PULLUP);
        sensor[s].button = new Bounce(s, 20);
        sensor[s].analog_input = new ResponsiveAnalogRead(s, false);
      }
    }
    
    void loop() {
    
      for(uint8_t s = 0; s < sensor_nr; s++) {
        sensor[s].analog_input->update();
        if (sensor[s].button->update()) {
          if (sensor[s].button->fallingEdge()) {
            int sample = sensor[s].analog_input->getValue();
            Serial.print("sensor ");
            Serial.print(s);
            Serial.print(" value ");
            Serial.println(sample);
          }
        }
      }
    
    }

  14. #14
    Member
    Join Date
    Aug 2019
    Location
    Melbourne Australia
    Posts
    38
    Thanks neurofun. Will play with that and start a new thread if needed.

  15. #15
    Junior Member
    Join Date
    Nov 2019
    Posts
    15
    I've built the first version and it's working fairly well. Here is a video of me playing it: https://youtu.be/VMS8y9XyK0A

    Next: I want to add a potentiometer to adjust the threshold. I've found that the sensors act different depending on the ceiling and other factors. So, I need code for to adjust the "thresh" variable on the fly. Any help appreciated.

    Then: I'm going to put the sensors on top of acrylic tubes and add LEDs to the bottom of the tubes. I'd like them to change colors when the sensor is activated. I have absolutely NO IDEA how to this. And I'd like to use this LED: https://www.adafruit.com/product/2524. Can a Teensy 3.2 handle this type of LED?

    Problem: Today I tried the instrument in an auditorium with a smoke machine. The smoke freaked out the sensors and I had to increase the threshold significantly. I don't know if there's anything I can do about that...

    I'll post everything in an instructable-type thing once everything is done. Thanks for your help!

    Video: https://youtu.be/VMS8y9XyK0A
    Images: https://imgur.com/5UsVyRW
    https://imgur.com/H30AUpI
    https://imgur.com/b1ulnFd

  16. #16
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    10,098
    Quote Originally Posted by Synchrony View Post
    I've built the first version and it's working fairly well. Here is a video of me playing it: https://youtu.be/VMS8y9XyK0A

    ...
    JUST FYI : Seems "to be performance-ready" ... I was playing the uTube and my wife came from next room telling me what it was ... and singing

    For the LED's pick 7 digital pins and when the sensor triggers turn it on - and off on the release. Those can be simple LED's test with. For the high power LED's - you'll need a capable switch for the Teensy pin to trigger and then have it control the current/voltage needed for the higher output LED. I followed the Adafruit links and they don't suggest the proper wiring to power/switch them. Others here or a web search will point to a Mosfet or proper EE thingy to make it work.

    <edit> DOCS on this page show hookup that might be good:
    LED - 3W Aluminum PCB (5 Pack, Cool White) ... www.sparkfun.com/products/13105

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •