HC-SR04, New Ping and MIDI

Hello,

I’m trying to take a reading from a HC-SR04 ultrasonic sensor and sending that via MIDI as a continuous controller. I am evidently doing something wrong however, as on the MIDI side I get a lot of noise / unwanted signal, and a small amount of the desired signal but not scaled as I wanted.

I’m using the example sketch from New Ping library, which works fine at the default baud rate, but when I use the code below, I run into problems. I’m guessing this isn’t a hard thing to do; I’ve looked around on the forums and other people have had similar problems but unfortunately no-one posted how they fixed them.

Suggestions on how I can fix this are as ever appreciated.

// ---------------------------------------------------------------------------
// Example NewPing library sketch that does a ping about 20 times per second.
// ---------------------------------------------------------------------------

#include <NewPing.h>

#define TRIGGER_PIN  12  // Arduino pin tied to trigger pin on the ultrasonic sensor.
#define ECHO_PIN     11  // Arduino pin tied to echo pin on the ultrasonic sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.

void setup() {
  Serial.begin(31250);//(115200); // Open serial monitor at 115200 baud to see ping results.
}

void loop() {
 //    CC(0, 1, 2);  
  delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
  unsigned int uS = sonar.ping(); // Send ping, get ping time in microseconds (uS).
  int ccVal = uS / US_ROUNDTRIP_CM;
  int scaled =map(ccVal, 0, 200, 0, 127);
   CC(0, 1, scaled);   // send out MIDI CC values on channel 1, controller 1
 // Serial.print("Ping: ");
//  Serial.print(uS / US_ROUNDTRIP_CM); // Convert ping time to distance in cm and print result (0 = outside set distance range)
//  Serial.println("cm");
}

// Continuos Controller Function
void CC(int ChannelByte,int ControlNumber,int ControlValue){
  Serial.write(ChannelByte + 0xb0);
  Serial.write(ControlNumber);
  Serial.write(ControlValue);
}

This method works for me using the NEWPING library and MIDIUSB library.

I borrowed bits from this example: https://www.arduino.cc/en/Tutorial/MidiDevice

I’m not entirely sure why, but making the mappedVal value a ‘uint8_t’ data type has made my outputted values stable.

The lines

  controlChange(midiChannel1, 13, mappedVal); // (Channel, CC number, CC value)
  MidiUSB.flush();

must stay out of the ‘echoCheck’ function or the values will jump a bit.

Here’s the code:

#include <NewPing.h>
#define TRIGGER_PIN   6//12 // Arduino pin tied to trigger pin on ping sensor.
#define ECHO_PIN      5//11 // Arduino pin tied to echo pin on ping sensor.
#define MAX_DISTANCE 200 // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
unsigned int pingSpeed = 50; // How frequently are we going to send out a ping (in milliseconds). 50ms would be 20 times a second.
unsigned long pingTimer;     // Holds the next ping time.
 
//MIDI SECTION
#include "MIDIUSB.h" 
int midiChannel1 = 0;  
int cc1 = 13;   

uint8_t mappedVal;


void setup() {
  Serial.begin(115200);   // Initiate a serial communication
  pingTimer = millis(); // Start now.   
}


void loop() {
  if (millis() >= pingTimer) {   // pingSpeed milliseconds since last ping, do another ping.
    pingTimer += pingSpeed;      // Set the next ping time.
    sonar.ping_timer(echoCheck); // Send out the ping, calls "echoCheck" function every 24uS where you can check the ping status.
  }
  controlChange(midiChannel1, 13, mappedVal); // (Channel, CC number, CC value)
  MidiUSB.flush();      
} 


void echoCheck() { 
  if (sonar.check_timer()) { // This is how you check to see if the ping was received.
     Serial.println(sonar.ping_result / US_ROUNDTRIP_CM);
     int val = (sonar.ping_result / US_ROUNDTRIP_CM);
     mappedVal = (uint8_t) (map(val, 0, 20, 127, 0));
  }
}


// These are midi functions specifically for the Arduino Micro Pro
void noteOn(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOn = {0x09, 0x90 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOn);
}

void noteOff(byte channel, byte pitch, byte velocity) {
  midiEventPacket_t noteOff = {0x08, 0x80 | channel, pitch, velocity};
  MidiUSB.sendMIDI(noteOff);
}

void controlChange(byte channel, byte control, byte value) {
  midiEventPacket_t event = {0x0B, 0xB0 | channel, control, value};
  MidiUSB.sendMIDI(event);
}
1 Like

Hello Monoth, thank you for sharing, just tested :slight_smile: It seems that the the MIDI cc value is going from 0 to 127 instantly and not gradually : which one could be the variable to adjust the mistake? Thank you

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.