Pringles Can Drums w/ Arduino

I made a couple Midi controllers out of some Pringles Cans and piezo sensors then hooked them up to Sonic Pi with an Arduino MKRZero and played some drumbeats

I recently got the MKRZero and it is super easy to set up in Sonic Pi. It reads as a Midi device in Sonic Pi right when you hook it up without any additional software.
Screen Shot 2020-08-29 at 11.03.27 PM

The code to send Midi messages was available online and is pretty straight forward and easy to modify.
Here is the code from the Pringles Project

#include "MIDIUSB.h"

byte note = 0;            // The MIDI note value to be played
const int ledPin2 = 13;
const int ledPin1 = 12;
const int knockSensor1 = A1;
const int knockSensor2 = A2;
const int threshold = 100; 

int sensorReading1 = 0;  
int sensorReading2 = 0;  
 
void setup() {
  Serial.begin(9600);
  pinMode(ledPin1, OUTPUT);
   pinMode(ledPin2, OUTPUT);
}
 
void loop() {
  
   sensorReading1 = analogRead(knockSensor1);
   sensorReading2 = analogRead(knockSensor2);
   
     if (sensorReading1 >= threshold) {
    //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
   Serial.println(sensorReading1);
    noteOn(0x90, 60, 0x45); 
    digitalWrite(ledPin1, HIGH);
    delay(50);
    //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
    digitalWrite(ledPin1, LOW);
    noteOn(0x90, 60, 0x00); delay(50);
     } 
     if (sensorReading2 >= threshold) {
    //Note on channel 1 (0x90), some note value (note), middle velocity (0x45):
   Serial.println(sensorReading2);
    noteOn(0x90, 48, 0x45); 
    digitalWrite(ledPin2, HIGH);
    delay(50);
    digitalWrite(ledPin2, LOW);
    //Note on channel 1 (0x90), some note value (note), silent velocity (0x00):
    noteOn(0x90, 48, 0x00); delay(50);
     }
 } 
 
 void noteOn(byte cmd, byte data1, byte data2) {
  
  midiEventPacket_t midiMsg = {cmd >> 4, cmd, data1, data2};
  MidiUSB.sendMIDI(midiMsg);
 
}

Here’s the Sonic Pi Code:

live_loop :midi_box do
  use_real_time
  note, velocity = sync "/midi*/note_on"
  puts note, velocity
  set :b, note
  if note == 48
    sample :bd_haus
  end
  if note == 60
    sample :sn_zome
  end  
end

It can also receive Midi messages from Sonic Pi. Here’s a quick project I made that lights up different LEDs depending on which note is playing.

If anyone is interested, I’ll post the code for this one too.

9 Likes

Hi, I really like your project. Honestly, I am also making a drums project that involves midi, piezo(Arduino UNO), and sonic pi. I want to make midi drums just like the Pringles can drums displayed in your first video. I want to hit the piezo and let Arduino code to transfer midi note to sonic pi, I use a usb-to-midi cable to connect the midi 5 pin female din that is installed in the breadboard to sonic pi. However, unfortunately, my sonic pi can not receive any midi signal, the problem has confused me for many months.
After seeing your sharing of this Pringles can drums project, I seem to find the hope, I want to make the same Pringles can drums project. However, Because currently I use Arduino UNO as my evaluation board, I don’t how to use Arduino MKRZero to fulfill this project. Could you share more information about this project? For example, the detail that how to connect the jumper wires to Arduino MKRZero and breadboard?
Please help me to fulfill your project, and if you are interested in my project, I will share more details about my project and the problem I currently encounter.
Please help me~
Sorry for my poor English.

Hi @ChunckLin,

You need to tell us what version of Sonic Pi you are running, and on what hardware.

For example, the version of Sonic Pi that runs on the Rasberry Pi has faults with Midi and OSC.

The more info you can give us, the more we can help you.

Eli…

Hello, Eli:
The version of my Sonic Pi is v3.2.2, and I run it on my win10 laptop computer.
I don’t use any Rasberry Pi, I only use Arduino Uno, piezo(a kind of sensor),and an usb-to-midi cable to connect the midi 5 pin female din that is installed in the breadboard to sonic pi to my laptop.


The picture above shows the combination of Arduino Uno, piezos, and breadboard.

The picture above shows the combination of Arduino Uno, piezos, breadboard, and usb-to-midi cable.

I have posted the details of the problem of my project in this forum, please go to look it, thanks a lot.
My post

Hi @ChunckLin,

Glad this project gave you some hope.
I saw the details from your other post. I can make a few suggestions, but please keep in mind, I am similar to you in that I figured out how to do this by doing a lot of internet searching and watching videos, so I may not be able to give you all the technical advice you need.

In terms of using the MKRZero board, it works just like setting up the piezos on a regular UNO and breadboard. The nice thing about the MKRZero is that it is automatically recognized as a MIDI device in Sonic Pi when it is plugged into the computer with the USB without needing to use any additional MIDI cables or hook ups. In the arduino code, you just include the noteOn function inside the conditional statement that executes when the piezo sensor reading goes above the threshold.
Be aware that the second argument in the noteOn function is the one that sets what note will play.
Example: noteOn(0x90, 48, 0x45); - The second argument is 48, so it plays the MIDI note 48.
In the Sonic Pi code, I just make a conditional statement that says if the incoming note from the MIDI device is 48, play a drum sample.

In your case, the issue you are having may have something to do with using the 5 pin MIDI output and MIDI to USB cable. I have tried playing around with making a MIDI output with a 5 pin female MIDI connector but have never had success (maybe you could help me with that :grinning:) There is a way that you can send MIDI messages from an arduino UNO without using any MIDI hardware. it just involves downloading a third party midi serial bridge program that allows the serial output of the arduino to be converted to MIDI messages that can be picked up from Sonic Pi. It is called “Hairless Midi” : http://projectgus.github.io/hairless-midiserial/
I have had success doing that as well which I documented in a post here
It involves using potentiometers, not piezos, but I would imagine it would transfer easily enough.

I noticed some people recommending you update to Sonic PI 3.3, but just so you know, none of these projects I did were on 3.3 and I actually haven’t tried them with the updated version yet.

I hope that helps you. Let me know if you have anymore questions.

Hi, @mrbombmusic ,
I am so glad and appreciate that you responded me so fast, I try some solutions that you suggested, but I still have some problems.
The first solution I tried was including #include “MIDIUSB.h” in my arduino code, and then using noteON function just like the code you posted, however, Arduino send an error message “#error MIDIUSB can only be used with an USB MCU.” After googling what this means, I found #include “MIDIUSB.h” needs a USB MCU like on the Arduino: Leonardo, (Pro) Micro, Zero, MKR1000 or Due. Because this reason, I decide to discard this method, and keep my Arduino code unchanged( the version I originally posted to ask question).

Ok, the second solution I tried was using “Hairless Midi” and didn’t use 5 pin female MIDI connector. Troublesomely, I have difficulty setting up the “Hairless Midi”. My “Serial port” has only “Arduino UNO (COM3)” can be used( COM3 was the port where my UNO connected), if I didn’t connect my UNO, there isn’t any port I could select(“Not Connected”).
The picture below shows the situation I described above.
hairless

The seventh depiction in “Getting Started” in Hairless Midi website says that “on Windows, set both sides to connect to the same loopMIDI virtual MIDI port.” So I set the same port on “Midi Out” and “Midi In” (the “my_midi” is the port I produced by loopMIDI).

In conclusion, under the condition that keeping the Arduino and Sonic Pi codes unchanged, without using 5 pin female MIDI connector, and setting the Hairless Midi just like the picture above. My Sonic Pi still can not receive the correct MIDI signal.
The picture below shows the current situation.

Additionally, my Sonic Pi received the wrong MIDI signal when I selected the Serial port from “Not Connected” to “Arduino UNO (COM3)”.
The picture below shows the wrong signal that Sonic Pi received.
signal

signal2

signal3
I don’t know why Sonic Pi received so weird wrong message when I set the Serial port from “Not Connected” to “Arduino UNO (COM3)”.

I have a thought that if because my laptop doesn’t install any FTDI USB Serial Port Driver(as the message showed in Debug MIDI messages in Hairless MIDI in the first picture), I can not select other serial ports except “Arduino UNO (COM3)”.
Because if I first select “Arduino UNO (COM3)” as my serial port, and then burn(run) Arduino, it will show the error message that “COM3 can not be opened.” I think this is a weird situation. If I reverse the order, I burn Arduino first and then select “Arduino UNO (COM3)” as my serial port , it will be able to run, but the result is still not I hope. The situation is still I described above. Therefore, I want to select other serial ports, but I don’t have any other options now.

I still have much trouble, please help me ><.
Thanks a lot.

By the way, the version of my Sonic Pi is still v3.2.2.

@ChunckLin I went back to check about the code and some info I had about using Hairless Midi as I haven’t used it since I started using the MKRZero board. A few things that I found:

  1. I believe the “#include MIDIUSB.h” from my code is specific for the MKRZero board that I used it for and will not work with an UNO board. You should stick with “#include <MIDI.h>” that you had in your original code.
  2. For MIDI serial communication with Hairless MIDI, the baud rate should be be 115200, not 9600.
  3. You cannot have any messages being sent to the serial monitor as the MIDI info that is being sent is on the same route and it will cause some interference. I also seem to recall that you should not have the serial monitor open when running Hairless MIDI for the same reason.
  4. There needs to be some specific code that is used to send MIDI messages when using Hairless MIDI. It is not just a catch all that will work with any type of code written for the Arduino.

I am including a small project of Arduino code that works with Hairless MIDI. It is just for sending a MIDI note by pressing a button adapted from the basic button push arduino code.
There is also some code for a debounce when pressing the button.
The parts of the code you should be concerned with are the MIDI.begin and Serial.begin(115200) in the setup function and the MIDI.sendNoteOn function in the loop function. The 3 arguments for the sendNoteOn function are the midi note, velocity and midi channel. Instead of having a noteOff function, the sendNoteOn function is repeated with the velocity set to 0.

#include <MIDI.h>


MIDI_CREATE_DEFAULT_INSTANCE();

const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  3;      // the number of the LED pin

int ledState = LOW; // variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
int buttonPState = LOW;

unsigned long lastDebTime = 0;
unsigned long debTime = 50;

void setup() {
  MIDI.begin();
  Serial.begin(115200);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}

void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

if((millis() - lastDebTime) > debTime) {
  if(buttonPState != buttonState) {
 lastDebTime = millis();
if(buttonState == HIGH) {
  ledState = HIGH;
  MIDI.sendNoteOn(60, 127, 1);
} else {
MIDI.sendNoteOn(60, 0, 1);
ledState = LOW;
}
  }
  buttonPState = buttonState;
}
digitalWrite(ledPin, ledState);
}

I would suggest to try that out just to see if it works for you. You could also just try a very simplified version of the code on your arduino without any hardware to see if it works.
I have not tried this code myself but I imagine it would be a good way to test if this type of code works with Hairless MIDI.

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

void setup() {
  MIDI.begin();
  Serial.begin(115200);
}

void loop() {
MIDI.sendNoteOn(60, 127, 1);
delay(1000);
MIDI.sendNoteOn(60, 0, 1);
delay(1000);
}

Just so you know, I learned all of this information from an online Udemy course I took called “Making Music with Arduino” It has since been removed from Udemy and is only available on the course creator’s website: https://www.musiconerd.com/making-music-with-arduino
Unfortunately it looks quite expensive ($122 usd) I had gotten a deal when I took it on Udemy. I never would have paid that much for the course. And quite frankly, if you are willing to spend any money to make this project work, I would recommend just getting the MKRZero board as it would be much cheaper and something you could get a lot of use out of.

I hope that helps. Let me know how it goes.

Hello, @mrbombmusic,
I added MIDI_CREATE_DEFAULT_INSTANCE();, MIDI.sendNoteOn(60, 127, 1); , and modified the paremeter in Serial.begin(); from 9600 to 115200, luckly, it is successful to transfer midi signal to my Sonic Pi. My Sonic Pi can receive the correct midi signal and then produce the drum sounds. However, I still have some problems that I encounter.

The first problem is that my sensors will affect each other when I hit them. I set one of my sensors to represent snare, and another is set to represent bass, and then suppose I hit the snare one, it sometimes will produce not only snare sound but also bass sound, I hit the bass one, it sometimes will also produce not only bass sound but also snare sound. The sounds will not be generated at the same time, there is an order, suppose I hit the snare, it will produce snare sound first and then produce bass sound. I don’t know the reason, is it maybe because my sensors are too close to each other or the threshold I set is too low? ( But sometimes I try to use a stronger strength and a weaker strength to hit the piezo, surprisingly, the weaker one can produce sound, but the stronger one can not produce sound, I don’t know why this weird situation happens base on the same threshold. ) I find this problem is called “crosstalk” in a comment of a yt video. There is a man named " Oscar Abraham" in comment zone discussed the “crosstalk” problem, he suggested some methods to solve, however, frankly, I can’t understand.
The link of the video is below:
video
I want to know how to let them not affect each other just like the drums displayed in your first video.

The second problem is latency, when I hit my sensors, they sometimes can not respond( produce sound) immediately. The sound will delay for a little time( Although the delayed time is smaller than 1 second, I still can feel the delaying.) It is not real time enough to produce sound.
I also want to let my sensors be able to respond immediately just like the drums displayed in your first video.

The code below is my current Arduino code:

#include <MIDI.h>

MIDI_CREATE_DEFAULT_INSTANCE();

byte note = 0;            // The MIDI note value to be played
const int knockSensor1 = A0;
const int knockSensor2 = A1;
const int threshold1 = 40;
const int threshold2 = 20;

int sensorReading1 = 0;  
int sensorReading2 = 0;  
 
void setup() {
  Serial.begin(115200);
}
 
void loop() {
  
   sensorReading1 = analogRead(knockSensor1);
   sensorReading2 = analogRead(knockSensor2);
   
     if (sensorReading1 >= threshold1) {
        MIDI.sendNoteOn(65, 90, 1); 
        delay(1000);
      
     } 
     if (sensorReading2 >= threshold2) {
        MIDI.sendNoteOn(64, 90, 1); 
        delay(1000);
     }
 }

Please help me complete the midi drums whose the sensors will not affect each other and can respond immediately.
Oh, by the way, could you tell me what the scale of your piezos is? For example, size, frequency, and so on.
Thanks a lot ~

One thing I see in your code is that you do not have any command that would be the equivalent of a MIDI_NOTE_OFF message. Im not sure if that is the reason you are having this problem, but it is worth a try.

It would look something like this

   if (sensorReading1 >= threshold1) {
        MIDI.sendNoteOn(65, 90, 1); 
        delay(1000);
        MIDI.sendNoteOn(65, 0, 1);  // This is the MIDI note off command. The 2nd argument is the velocity of the note
        delay(1000);
     }

Im not familiar with the concept of crosstalk. I would be happy to check out that part the video, but the video you posted is over an hour long, so you are going to need to provide me with the time of the video where that part is discussed.

As for the latency, I cannot really say I have any idea what is causing that. My only thought would be it may have to do with your computer. Or perhaps there is some delay in the serial communication going from the Arduino through Hairless MIDI and then to Sonic Pi. The project I did doesn’t use the Hairless MIDI so that step is removed from the serial communication which may affect the latency. If you are really determined to get this project to work, I would still recommend looking into getting the MKRZero board.

Here is a link to the piezo sensors that I use: $1.79 - 27mm Piezo Element (Vibration / Knock Sensor) - Tinkersphere

Hope that helps.