logo-mobile

ROHM

ROHM
Menu
  • Arduino –
  • Raspberry Pi –
  • Trending –
  • Others –
  • About –
  • Contact –

Arduino

Linking Arduino to another Application with OSC Communication Part 2 – Making a Rhythm Machine with Sonic Pi

Device Plus Editorial Team
Published by Device Plus Editorial Team at March 12, 2016
Categories
  • Arduino
Tags
Arduino OSC Communication

DSC_0175-1024x576

In our last article, we learned about the OSC communication basics with Arduino. Since OSC (Open Sound Control) was developed as a protocol for musical instruments, today we will try to create an instrument device.

While I was kind of lost about what kind of device to create, I thought that it would be a good idea to create an OSC keyboard for Arduino. After doing some research, I found about the sound programming app Sonic Pi, which was featured in “Audio programming with Sonic Pi!.” It runs on Raspberry Pi ,and it’s compatible with OSC. So, today let’s create a rhythm machine that works with Sonic Pi.

Today’s Electronics Recipe

Expected time to complete: 150 minutes

Parts needed:

  • Arduino UNO https://international.switch-science.com/catalog/789/
  • Ethernet shield 2 http://www.amazon.com/Ethernet-Development-ARDUINO-ETHERNET-SHIELD/dp/B011PCMMM0/ref=sr_1_5?ie=UTF8&qid=1458613216&sr=8-5&keywords=Ethernet+shield
  • Breadboard
  • Toggle switch (ON-OFF-ON) http://www.amazon.com/250V-Position-Micro-Toggle-Switch/dp/B014XJ7PZG
  • Volume resistor (50KΩ)
  • Resistor (220Ω~10KΩ)

System Overall Structure

We designed the basic flow as follow. The data will be sent from the Arduino controller circuit to the Processing server using OSC. Based on the controller input value, it will be converted into sound programs for Sonic Pi. Then, they will be sent to Sonic Pi, which will create and play sounds. It’s fine if you don’t understand all the details. Sonic Pi is written with a programming language called Ruby, and today, we will use Ruby for the OSC signals.

fig20151007_01

Figure 1 System flow

sonicpi

Figure 2 Sonic Pi, the sound programming environment

Check this article for more information about Sonic Pi. Sonic Pi not only runs on Raspberry Pi, it also runs on Windows and Mac OS X. We already have the Processing environment set up from the part 1, so let’s download the Mac OS X version. Once we figure out the overall system structure, we will start building the actual device.

Creating the Rhythm Machine Controller Circuit

First of all, we need to build a controller. Let’s make a cool one! The cases I’m usually using are all flat and big, and I just couldn’t find a good one. So, I kept looking.

DSC_0166-1024x576

Picture 1 Chopstick box

I found the perfect size box, which actually is a chopstick box. The depth seems good too.

DSC_0167-1024x576

Picture 2 Inside the box

There’s something about making a rhythm machine out of a box that has Kanji (Chinese characters) on it. Well, now that we found a good case, let’s start creating the circuit.

Controller Interface

Before we build the circuit, let’s align the parts and get an image of the interface we want. When we build the circuit there will be many limitations, so it may not always go as planned. It’s still better to decide on the specs beforehand like part arrangement or where adaptors/LAN cables will come out from (if they come out from numerous directions, it doesn’t fit well). Thinking about all kinds of ideas is the fun part.

DSC_0169-1024x576

Picture 3 Mounting the parts and thinking about the interface

Since we’re building a rhythm machine, we arranged the parts so that the sounds can be toggled on and off using a toggle switch and the 8-beat rhythm could be controlled. We are using Arduino Ethernet (Arduino and Ethernet shield combined) due to the depth of the case. We want to add the 7 segment LED as shown in Photo 3, but we don’t have enough Arduino pins, so let’s think about that later. Also, we used a transparent acrylic board for the lid. We will drill holes in the board for each part.

Circuit Framing

Once we decided on the arrangement, we will process the case and build the circuit.

DSC_0170-1024x576

Picture 4 Making the case based on the parts

DSC_0171-1024x576

Picture 5 Drilling holes in the acrylic board for the each part

DSC_0172-1024x576

Photo 6 Arranging the parts

Once we have most of the parts arranged in the case, let’s start building the circuit. There are many parts for this one, so we need to save space on the breadboard and save pins on Arduino. If we simply use 8 pins from Arduino for the 8 toggle switches, we won’t be able to add other parts in the future if we we want to make improvements, so let’s try to get creative with the circuits.

OSC_RYTHM_MACHINE-1024x519

Figure 3 Rhythm machine interface circuit

The circuit we are building today has 8 toggle switches spread out in groups of 4s to determine the power input status. When we created the speaker, we arranged switches with different resistor values to remember which switch was pushed. We will use the same method here. (The actual device has LEDs too, but for the sake of the circuits explanation, we will skip that part)

Previously, we didn’t evaluate when multiple switches were being pushed, but we need to for this one. So, let’s go a step further. We will prepare 1KΩ, 2KΩ, 4KΩ, 8KΩ for the resistor values, so that even when multiple buttons get pushed, Arduino can determine each one by the input value. In simpler terms, if the resistor value is 1KΩ, 2KΩ, 4KΩ, 8KΩ from the top, the total will be 1 when #1 is being pushed, or 3 when #1 and #2 are being pushed, or 5 when #1 and #3 are being pushed, and so on. This way, if the total value is different for all patterns, Arduino can determine which buttons are being pushed. As long as it follows this rule, you can use other resistors as well.

With this method, the amount of pins used by Arduino will decrease significantly. But it still takes up a lot of space on the breadboard. So if you want more, try using an IC called shift register, which limits input and output.

DSC_0175-1024x576

Picture 7 Mounting the circuit once you have arranged the parts

DSC_0174-1024x576

Picture 8 The interface is complete!

Once the interface is done, let’s move on to the program.

Implementing the OSC Program

We will be using the same program as before to connect Arduino to processing using OSC. In this case, the controller status is being monitored by analog A0~2, so we will send that value to processing.

OSC program from Arduino to Processing server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include
#include
#include
 
//for OSC
byte myMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte myIp[] = { 192, 168, 11, 177 };
int destPort = 12000;
byte destIp[] = { 192, 168, 11, 2};
OSCClient client;
OSCMessage global_mes;
//end for OSC
 
const int buttonPin0 = A0;
const int buttonPin1 = A1;
const int buttonPin2 = A2;
const int ledPin = 7;
int buttonState0 = 0;
int buttonState1 = 0;
int buttonState2 = 0;
 
void setup() {
Serial.begin(9600);
Ethernet.begin(myMac ,myIp);
 
pinMode(ledPin, OUTPUT);
pinMode(buttonPin0, INPUT_PULLUP); //Enable pull up resistor in input mode
pinMode(buttonPin1, INPUT_PULLUP); //Enable pull up resistor in input mode
pinMode(buttonPin2, INPUT_PULLUP); //Enable pull up resistor in input mode
}
 
void loop(){
// buttonState = digitalRead(buttonPin);
buttonState0 = analogRead(buttonPin0);
buttonState1 = analogRead(buttonPin1);
buttonState2 = analogRead(buttonPin2);
Serial.print(buttonState0);
Serial.print(":");
Serial.print(buttonState1);
Serial.print(":");
Serial.println(buttonState2);
 
sendOSC(0,buttonState0);
sendOSC(1,buttonState1);
sendOSC(2,buttonState2);
 
//Limit LED by value
if (buttonState0 == LOW) { // pin value is low if the button has been pushed
digitalWrite(ledPin, HIGH);
}
else {
digitalWrite(ledPin, LOW);
}
}
 
//Send OSC
void sendOSC(int pin,int val){
global_mes.setAddress(destIp,destPort);
if(pin == 0){
global_mes.beginMessage("/pin01");
}
else if(pin == 1){
global_mes.beginMessage("/pin02");
}
else if(pin == 2){
global_mes.beginMessage("/pin03");
}
//global_mes.addArgString(1.0);
//global_mes.addArgFloat(1.0);
global_mes.addArgFloat(val);
client.send(global_mes);
global_mes.flush();
delay(100);
}

Next, let’s look at the program on the Processing side. The flow on the Processing side will look like this.

  1. [Receive OSC] Receive input values from Arduino
  2. Create Sonic Pi code based on input values
  3. [Send OSC] Send code (/run-code) from Processing to Sonic Pi
  4. Play the code received by Sonic Pi

With this flow, it is possible to communicate between Arduino – Processing – Sonic Pi. Some may ask, “Can’t I just connect Arduino and Sonic Pi directly?” Actually, we tried that first, but it seems that Sonic Pi can only communicate with OSC in a  local host (network within the PC), so we had to throw in the Processing in between.

Program for the Processing server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import oscP5.*;
import netP5.*;
 
OscP5 oscP5;
NetAddress myRemoteLocation;
 
void setup() {
size(400,400);
frameRate(25);
/* start oscP5, listening for incoming messages at port 12000 */
oscP5 = new OscP5(this,12000);
 
myRemoteLocation = new NetAddress("127.0.0.1",4557);
}
 
String code;
float speed = 1.0;
int[] ch1 = {0,0,0,0};
int[] ch2 = {0,0,0,0};
 
void changeCode(){
code = "speed="+str(speed)+";live_loop :foo do;";
code +="sample :bd_haus,rate:1,amp:"+str(ch1[0]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch1[1]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch1[2]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch1[3]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch2[0]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch2[1]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch2[2]);
code += ";sleep speed;sample :bd_haus,rate:1,amp:"+str(ch2[3]);
code += ";sleep speed;end;";
println(code);
 
}
 
void draw() {
background(0);
}
void mousePressed() {
/* in the following different ways of creating osc messages are shown by example */
OscMessage myMessage = new OscMessage("/run-code");
changeCode();
myMessage.add(code);
/* send the message */
oscP5.send(myMessage, myRemoteLocation);
}
 
void keyPressed() {
OscMessage myMessage = new OscMessage("/run-code");
if(key == CODED) {
if(keyCode == UP) {
myMessage.add("use_synth :piano"); /* add an int to the osc message */
}else if (keyCode == DOWN) {
stopSonic Pi();
}else if (keyCode == LEFT) {
myMessage.add("use_synth :dull_bell"); /* add an int to the osc message */
}else if (keyCode == RIGHT) {
myMessage.add("use_synth :beep"); /* add an int to the osc message */
}
}
/* send the message */
oscP5.send(myMessage, myRemoteLocation);
}
 
void stopSonic Pi() {
/* in the following different ways of creating osc messages are shown by example */
OscMessage myMessage = new OscMessage("/stop-all-jobs");
myMessage.add("");
oscP5.send(myMessage, myRemoteLocation);
}
 
/* incoming osc message are forwarded to the oscEvent method. */
void oscEvent(OscMessage theOscMessage) {
/* print the address pattern and the typetag of the received OscMessage */
/* print("### received an osc message.");
print(" addrpattern: "+theOscMessage.addrPattern());
println(" typetag: "+theOscMessage.typetag());
theOscMessage.print();
*/
String ptn = theOscMessage.addrPattern();
int val;
// println("PATTERN:"+ptn);
if(ptn.equals("/pin01")){
val = int(theOscMessage.get(0).floatValue());
print("pin01-");
println(val);
if(val == 231){ int[] ch = {0,0,0,0};ch1 = ch;}
else if(val == 242){ int[] ch = {1,0,0,0};ch1 = ch;}
else if(val == 281){ int[] ch = {0,1,0,0};ch1 = ch;}
else if(val == 295){ int[] ch = {0,0,1,0};ch1 = ch;}
else if(val == 334){ int[] ch = {0,0,0,1};ch1 = ch;}
else if(val == 447){ int[] ch = {1,1,0,0};ch1 = ch;}
else if(val == 523){ int[] ch = {1,0,1,0};ch1 = ch;}
else if(val == 284){ int[] ch = {1,0,0,1};ch1 = ch;}
else if(val == 647){ int[] ch = {0,1,1,0};ch1 = ch;}
else if(val == 703){ int[] ch = {0,1,0,1};ch1 = ch;}
else if(val == 825){ int[] ch = {0,0,1,1};ch1 = ch;}
else if(val == 844){ int[] ch = {1,1,1,0};ch1 = ch;}
else if(val == 682){ int[] ch = {0,1,1,1};ch1 = ch;}
else if(val == 922){ int[] ch = {1,1,1,1};ch1 = ch;}
}
else if(ptn.equals("/pin02")){
val = int(theOscMessage.get(0).floatValue());
print("pin02-");
println(val);
if(val == 231){ int[] ch = {0,0,0,0};ch2 = ch;}
else if(val == 242){ int[] ch = {1,0,0,0};ch2 = ch;}
else if(val == 281){ int[] ch = {0,1,0,0};ch2 = ch;}
else if(val == 295){ int[] ch = {0,0,1,0};ch2 = ch;}
else if(val == 334){ int[] ch = {0,0,0,1};ch2 = ch;}
else if(val == 447){ int[] ch = {1,1,0,0};ch2 = ch;}
else if(val == 523){ int[] ch = {1,0,1,0};ch2 = ch;}
else if(val == 284){ int[] ch = {1,0,0,1};ch2 = ch;}
else if(val == 647){ int[] ch = {0,1,1,0};ch2 = ch;}
else if(val == 703){ int[] ch = {0,1,0,1};ch2 = ch;}
else if(val == 825){ int[] ch = {0,0,1,1};ch2 = ch;}
else if(val == 844){ int[] ch = {1,1,1,0};ch2 = ch;}
else if(val == 682){ int[] ch = {0,1,1,1};ch2 = ch;}
else if(val == 922){ int[] ch = {1,1,1,1};ch2 = ch;}
}
else if(ptn.equals("/pin03")){
float val2 = int(theOscMessage.get(0).floatValue());
print("pin03-");
print(val2);
print(":");
speed =(val2-340)/408; //0~100%
println(speed);
}
mousePressed();
}

The Rhythm Machine is Done

Once we’ve written the programs, run them, and we’re done! In this program, each toggle switch can turn on/off bass drum, and we assigned the rhythm speed for the volume resistor. By changing this program, you can use it as another instrument aside from a rhythm machine.

※ For more information about Sonic Pi programs or how to use them, check out Audio programming with Sonic Pi!

  • Turn the switch ON to trigger the bass drum sound
  • Turn all of it ON to play the sound continuously
  • The tempo changes with the volume knob

Try it out, it should work like this.

Summary

In the second part, we applied our knowledge about the OSC and created a musical instrument device. When creating your own device, you can choose where to place the knobs and buttons, and what each of them transmits. You can create controllers that control more than just sounds. You can program it to control videos simultaneously, or use ultrasonic wave sensors or a photo reflector to create a contactless Theremin-like controller. If you’re a musician, it may be interesting to create your own instrument and perform on stage.

Device Plus Editorial Team
Device Plus Editorial Team
Device Plus is for everyone who loves electronics and mechatronics.

Check us out on Social Media

  • Facebook
  • Twitter

Recommended Posts

  • Linking Arduino to Another Application Using OSC Communication Part 1Linking Arduino to Another Application Using OSC Communication Part 1
  • Arduino Long Range Communication Tutorial – LoRaLib LibraryArduino Long Range Communication Tutorial – LoRaLib Library
  • Using Arduino with Parts and Sensors – Speakers Part 2Using Arduino with Parts and Sensors – Speakers Part 2
  • Make a Stevenson Screen with Arduino Part 2 – Display Numerical Values on an Electronic Scoreboard (7 segment LED)Make a Stevenson Screen with Arduino Part 2 – Display Numerical Values on an Electronic Scoreboard (7 segment LED)
  • Raspberry Radio Part 2 – Using MPD and a smartphone app to turn your Pi into an easy to use radio!Raspberry Radio Part 2 – Using MPD and a smartphone app to turn your Pi into an easy to use radio!
  • How to control your computer using hand gesturesHow to control your computer using hand gestures
Receive update on new postsPrivacy Policy

Recommended Tutorials

  • How to integrate an RFID module with Raspberry Pi How to integrate an RFID module with Raspberry Pi
  • How to Use the NRF24l01+ Module with Arduino How to Use the NRF24l01+ Module with Arduino
  • How to Run Arduino Sketches on Raspberry Pi How to Run Arduino Sketches on Raspberry Pi
  • Setting Up Raspberry Pi as a Home Media Server Setting Up Raspberry Pi as a Home Media Server

Recommended Trends

  • SewBot Is Revolutionizing the Clothing Manufacturing Industry SewBot Is Revolutionizing the Clothing Manufacturing Industry
  • All About The Sumo Robot Competition And Technology All About The Sumo Robot Competition And Technology
  • 5 Interesting Tips to Calculating the Forward Kinematics of a Robot 5 Interesting Tips to Calculating the Forward Kinematics of a Robot
  • Go Inside the Drones That Are Changing Food Delivery Go Inside the Drones That Are Changing Food Delivery
Menu
  • Arduino –
    Arduino Beginner’s Guide
  • Raspberry Pi –
    Raspberry Pi Beginner's Guide
  • Trending –
    Updates on New Technologies
  • Others –
    Interviews / Events / Others

Check us out on Social Media

  • Facebook
  • Twitter
  • About
  • Company
  • Privacy Policy
  • Terms of Service
  • Contact
  • Japanese
  • 简体中文
  • 繁體中文
Don’t Forget to Follow Us!
© Copyright 2016-2023. Device Plus - Powered by ROHM
© 2023 Device Plus. All Rights Reserved. Muffin group

istanbul escort istanbul escort istanbul escort