My first go at combining/merging two sets of code - PLEASE HELP!

Hi all, brand NOOB here! :slight_smile:

I am first and foremost a musician, producer and music practitioner. I co-run a community music therapy service which supports vulnerable young people and people with complex needs.

I am studying for an MA in Bristol, UK at the mo which is focused on innovation in sound. My area of interest is around designing multi sensory experiences and 'adaptive music technology' for young people with complex needs.

For my current project I am attempting to use an Arduino and Max/MSP (for the audio side of things) to design a playable, hands-free musical instrument and controller. As I say, I am totally new to Arduino and C programming, and am pretty new to Max. I enrolled on a course to learn some of the basics, however, I would really appreciate some help as I am totally stuck!

So far, I have created a circuit using some code that a certified trainer dished out to us which enables me to connect a bunch of switches. I have a push button which controls the playback of audio, a variable resister for controlling the speed of the playback, a 'panic' button to stop all audio and a switch. What I would like to do is now connect an ultrasonic sensor (HC-SR04) to the circuit so that I can use that as a controller within the Max/MSP environment.

I have some seperate code for the ultrasonic sensor, so last night I attempted to merge the two sets of code and somehow succeeded after receiving a few errors. The trouble is that the ultrasonic sensor does not seem to register at all (nothing in the serial monitor), whereas before when I used the basic code specifically for the ultrasonic it worked fine, so I MUST be doing something wrong.

I am not a coder, and am very green. I just don't have the time to learn all of it before late December (which is when my assignment is due in!!). I would greatly appreciate it if somebody could take a look at the combined code and tell me what I am doing wrong :slight_smile:

Here is the code.....

/*

  SERIAL INPUT:
  - set pin state (p) og set pin value (v)
    - When setting a pin state you can write 0 (input),1 (output),2 (pwm)
  - set pin number
  - set value
  - Example: [p 3 2] & [v 3 128] == Pin 3 is set to be pwm and addressed with 50/50 duty cycle (medium "speed")
  (just send as char values from any program that can communicate with serial ports ex. Max/MSP)
    - You´ll need "[" and "]" to start and end requests.

  SERIAL OUTPUT:
  - pin number
  - value
  - Example: 7 0 == Pin 7 is set to receive a digital input (a carriage return is send to end request.)
  - The board will only output through serial if an Arduino port is set to input.

*/

#define echoPin 12 // The number of the digital pin connected to the echo input
#define trigPin 11 // The number of the digital pin connected to the trigger output

int maximumRange = 30; // The max distance observed from the sensor
int minimumRange = 0;
long duration, distance; //duration used to calculate distance

unsigned long sendtime;

int portregister[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
String sample = "";
String explodedSample[3];

void setup() {
  sendtime = millis();
  Serial.begin(57600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  while (Serial.available() > 0) {
    char c = (char)Serial.read();
    if (c == '[')
      sample = "";
    else if (c == ']') {
      explodeString(sample);
      if (explodedSample[0].equalsIgnoreCase("v")) {
        setPinValue(convertStringToInt(explodedSample[1]), convertStringToInt(explodedSample[2]));
      }
      else if (explodedSample[0].equalsIgnoreCase("p")) {
        setPinState(convertStringToInt(explodedSample[1]), convertStringToInt(explodedSample[2]));
      }
    }
    else
      sample += c;
  }

  if (millis() > sendtime + 5) {
    readSendInput();
    sendtime = millis();
  }

}

void readSendInput() {
  for (int i = 0; i < 18; i++) {
    if (portregister[i] == 0) {
      if (i < 12) {
        Serial.print(i + 2);
        Serial.print(" ");
        Serial.println(digitalRead(i + 2));
      }
      else {
        Serial.print(i + 2);
        Serial.print(" ");
        Serial.println(analogRead(i + 2));
      }
    }
  }
}

void setPinState(int pin, int pinState) {
  portregister[pin - 2] = pinState;
  if (pinState == 2)
    pinState = 1;
  pinMode(pin, pinState);
}

void setPinValue(int pin, int val) {
  int pinState = portregister[pin - 2];
  if (pinState == 1) {
    digitalWrite(pin, val);
  }
  else if (pinState == 2) {
    analogWrite(pin, val);
  }
}

void explodeString(String s) {
  String tem = "";
  int tempointer = 0;

  for (int i = 0; i < s.length(); i++) {
    if (s[i] == ' ') {
      explodedSample[tempointer++] = tem;
      tem = "";
    }
    else
      tem += s[i];
  }
  explodedSample[2] = tem;
}

int convertStringToInt(String s) {
  char test[s.length() + 1];
  s.toCharArray(test, sizeof(test));
  return atoi(test);

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2); // pulse off

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); // pulse for 10 microseconds

  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH); // echo pin listens / receives

  delay(50); // good practice not to overload the serial port

}

Thank you so much
Benny

arduinoInOutForMaxWithUltrasonicSensor.ino (3.2 KB)

In advance!

It would help (me) if you would post not your combined code, but instead (or in addition as it will be ) both sketches you are trying to combine. Original you didn't mess with them working condition.

Along with a description (which you may have done already) of how the functionality of the one sketch is to be used in the other when combined. I'm in transit looking through the tiny window just now.

You may have bungled the combining or otherwise inadvertently changed or damaged the logic of one or both, so seeing what you started from is necessary.

TIA

a7

I also do work with an organisation called Drake Music which dose a similar thing with disabled people.

I am based in the North of England, but there is also a large group in London.

The basics about combining code without having to know too much about it is here
http://www.thebox.myzen.co.uk/Tutorial/Merging_Code.html

However as you are trying to send two lots of data to MAX over a single serial port you will have to split that back into separate streams of data in MAX itself.

I don't do much with MAX myself so I can't tell you exactly how to do this. So it might be worth asking in a MAX forum.

Hey @alto777 , thanks for checking out the code, OK so here are the two seperate pieces of Arduino code...

 SERIAL INPUT:
  - set pin state (p) og set pin value (v)
    - When setting a pin state you can write 0 (input),1 (output),2 (pwm)
  - set pin number
  - set value
  - Example: [p 3 2] & [v 3 128] == Pin 3 is set to be pwm and addressed with 50/50 duty cycle (medium "speed")
  (just send as char values from any program that can communicate with serial ports ex. Max/MSP)
    - You´ll need "[" and "]" to start and end requests.

  SERIAL OUTPUT:
  - pin number
  - value
  - Example: 7 0 == Pin 7 is set to receive a digital input (a carriage return is send to end request.)
  - The board will only output through serial if an Arduino port is set to input.

*/

unsigned long sendtime;

int portregister[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
String sample = "";
String explodedSample[3];

void setup() {
  sendtime = millis();
  Serial.begin(57600);
}

void loop() {
  while (Serial.available() > 0) {
    char c = (char)Serial.read();
    if (c == '[')
      sample = "";
    else if (c == ']') {
      explodeString(sample);
      if (explodedSample[0].equalsIgnoreCase("v")) {
        setPinValue(convertStringToInt(explodedSample[1]), convertStringToInt(explodedSample[2]));
      }
      else if (explodedSample[0].equalsIgnoreCase("p")) {
        setPinState(convertStringToInt(explodedSample[1]), convertStringToInt(explodedSample[2]));
      }
    }
    else
      sample += c;
  }

  if (millis() > sendtime + 5) {
    readSendInput();
    sendtime = millis();
  }

}

void readSendInput() {
  for (int i = 0; i < 18; i++) {
    if (portregister[i] == 0) {
      if (i < 12) {
        Serial.print(i + 2);
        Serial.print(" ");
        Serial.println(digitalRead(i + 2));
      }
      else {
        Serial.print(i + 2);
        Serial.print(" ");
        Serial.println(analogRead(i + 2));
      }
    }
  }
}

void setPinState(int pin, int pinState) {
  portregister[pin - 2] = pinState;
  if (pinState == 2)
    pinState = 1;
  pinMode(pin, pinState);
}

void setPinValue(int pin, int val) {
  int pinState = portregister[pin - 2];
  if (pinState == 1) {
    digitalWrite(pin, val);
  }
  else if (pinState == 2) {
    analogWrite(pin, val);
  }
}


/***********************************/
/*        HELPER FUNCTIONS         */
/***********************************/

void explodeString(String s) {
  String tem = "";
  int tempointer = 0;

  for (int i = 0; i < s.length(); i++) {
    if (s[i] == ' ') {
      explodedSample[tempointer++] = tem;
      tem = "";
    }
    else
      tem += s[i];
  }
  explodedSample[2] = tem;
}

int convertStringToInt(String s) {
  char test[s.length() + 1];
  s.toCharArray(test, sizeof(test));
  return atoi(test);
}

That was the one for all the buttons etc. Here is the one for the ultrasonic sensor that I borrowed from the Ask Audio website...

#define echoPin 3 // The number of the digital pin connected to the echo input
#define trigPin 4 // The number of the digital pin connected to the trigger output
#define echoPin 6 // The number of the digital pin connected to the echo input
#define trigPin 5 // The number of the digital pin connected to the trigger output
#define LEDPin 13 // This enables the LED feedback for testing

int maximumRange = 30; // The max distance observed from the sensor
int minimumRange = 0;
long duration, distance; //duration used to calculate distance

void setup() {
  Serial.begin(9600); //starts the serial communication via USB
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  pinMode(LEDPin, OUTPUT); //board LED for testing

}

void loop() {

  digitalWrite(trigPin, LOW);
  delayMicroseconds(2); // pulse off

  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10); // pulse for 10 microseconds

  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH); // echo pin listens / receives

  // from that data calculate distance in CentiMeters based on Speed of Sound
  distance = duration / 58.2;

  // error handling
  if (distance >= maximumRange || distance <= minimumRange) {
    Serial.println("-1"); //if nothing observed ouput -1
    digitalWrite(LEDPin, HIGH); // LED will be on
  } else {
    Serial.println(distance); // prints the distance in CM
    digitalWrite(LEDPin, LOW); // LED will be off if object detected
  }

  delay(50); // good practice not to overload the serial port

}

Thanks again! :slight_smile:
Benny

PS - I would just like to mention that I don't really require an LED in the circuit..

Hey @Grumpy_Mike thanks for getting back to me! Ah small world :slight_smile: We did some work with Drake years ago now and my colleague Lee visited Drake in Scotland as part of his MA a few years back :slight_smile: Brilliant organisation!!

Yeah I am pretty new to Max too, panicking now a little just because I am trying to take a crash course in 2 entirely different coding languages arrrgh...

Thanks for the link, I have a great Max patch from the same tutor I mentioned. I would attach it, however I am probs not allowed to do that on here?? I just need to figure out how to amend the Max patch once I have sorted the Arduino code. I feel a little more confident with Max just becuase it is a more graphical GUI.

I will head over to the MAX forum asap for some further guidance on that. Thanks again

Benny

No you would be free to do that here.

I have used PD rather than Max, to do things like a theremin using a rather unusual sensor, but still a distant sensor. This was using a Raspberry Pi version of PD with GPIO inputs of the PI built in. If you haven't come across PD, this is an open source program written by the same person who wrote the commercial MAX language, and is mainly the same sort of thing but with better graphics.
Here is a video of it:-

Check out some of my recent accessible instruments on my feed as well including my Trill sensor guitar that can be programmed up with chord changes so you only have to press one button to change to the correct chord.

Wow @Grumpy_Mike, your theremin and trill guitar are amazing! It would be so cool if you could make the trip down to us one day and bring some of your instruments for our attendees to try out! :slight_smile:

Hey @alto777 , so sorry to bother you again, but I don't suppose you had a chance to look at the code(s) I sent through before regarding adding an ultrasonic sensor to the mix? I recently spoke with an interactive designer who suggested using the more simplified ultrasonic sensor code and adding the buttons/pots to that instead of the other way around.

Many thanks for your consideration!! I am panicking slightly because my next assignment is due in 2 weeks, I am settled on this idea and feel its too late to turn back haha! :))

Kindest
Benny

Oh hi there!

I did look at your two sketches and thought it was a trivial matter that you were all on top of.

I do not agree with the advice to add buttons to the ultrasound sketch.

The ultrasound sketch is... super simple. It boils down to a context for well known code sequences to develop an echo value from a sensor.

I re-wrote that sketch, placing all the echo stuff in a function:

Play with it here in the wokwi siumulator.

I hacked the other sketch to allow the insertion of "special functions" to override and supplant the normal intake of an analog value. You'll have to read the code to see how I did this, and where you might go to use the value returned from a call to the echo function from the other sketch instead of my text message about how special I am.

Again, play with it here in the wokwi siumulator.

That's as far as I can go with you on this, it is now a matter of combining two sketches, which I certainly hope you have been looking into... google is your feind.

  arduino combine two sketches

The nice thing here is that there is almost no conflict between the two sketches, and as long as you don't use the pins that the ultrasonic sensor uses(2 and 3) when you run the program, you should be able to combine these without problem.

We here if you have problems. Please see if the wokwi simulator agrees with you, and use it to present your sketches going forward to save time and trouble for your helpers.

Post your code on the thread also.

HTH

a7

Check your personal messages.

Thanks you so much @alto777 for all of your help. Apolgies for the late reply, I have been snowed under with other work. I had no idea that the wokwi simulator even existed, that's such a useful resource!

I will take a good look at both of the sketches to see if I can figure out what is going on. I will then attemot to combine the two sketches so will let you know how I get on.

Wish me luck! :slight_smile:

Thanks again for your time and energy I really appreciate it.

Kindest
Benny

Consider it wished.* I'll think of all that snow you are getting when I'm at the beach, :wink:

wokwi is indeed a terrific resource, a huge time and money saver. I enjoy finding opportunities to spread the word on that.

*Although luck shouldn't enter into your chances of success here.

a7

Hey @alto777 and @Grumpy_Mike, I (or should I say we) have finally managed to get something half-decent happening. I have also had some assistance from the very talented Mr. Kyle Duffield and Mr. Jacob Smith. I am very grateful for people helping me out (a complete novice when it comes to maker electronics). It's been a real journey, I hope to develop this system further. The ultimate aim is to make a hands-free, wireless musical "object" that can be started up, programmed and operated by ANYONE from a non-musical background....the holy grail of "adaptive music technology" in my humble opinion.

Thanks again!

Kindest
Benny x

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