Compare commits
60 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da334c97a9 | ||
|
|
de34d6f62b | ||
|
|
cb1f9fcf9b | ||
|
|
0db1e4fcaa | ||
|
|
c21d363526 | ||
|
|
59184187c0 | ||
|
|
5243d6c845 | ||
|
|
fadc5cc783 | ||
|
|
c147175bb2 | ||
|
|
646cd74442 | ||
|
|
3dc691cb98 | ||
|
|
e33335f379 | ||
|
|
eb03f104e0 | ||
|
|
5d2e9096c3 | ||
|
|
95b762afce | ||
|
|
19191f371c | ||
|
|
0b60af4044 | ||
|
|
4e8ad1e132 | ||
|
|
c10d2e5b0c | ||
|
|
05fc0c94af | ||
|
|
d938b31e91 | ||
|
|
582ac0859b | ||
|
|
7b2f0c750d | ||
|
|
4fddbf3190 | ||
|
|
e2a3935f07 | ||
|
|
5f994fcf7f | ||
|
|
9c4ffb6e7b | ||
|
|
bae5b3d412 | ||
|
|
9260d066ba | ||
|
|
336b2b45ab | ||
|
|
a7408c519a | ||
|
|
7e41bac2ce | ||
|
|
6f349b75d8 | ||
|
|
b2a6228236 | ||
|
|
fe929b835e | ||
|
|
8bd5f2b35c | ||
|
|
c983a92107 | ||
|
|
f5246baf9c | ||
|
|
f0556802f5 | ||
|
|
dbb6a746be | ||
|
|
8b24803aa2 | ||
|
|
37f714e3d3 | ||
|
|
8600cbd3e0 | ||
|
|
62b7761e9a | ||
|
|
4a2f82f907 | ||
|
|
b0bce01fac | ||
|
|
0f8eb0f54d | ||
|
|
769578fcf7 | ||
|
|
9f2f760a47 | ||
|
|
fc8f353064 | ||
|
|
f6fcb48859 | ||
|
|
cd4fdfc907 | ||
|
|
b74972db16 | ||
|
|
5912dfdcd4 | ||
|
|
642b4973ca | ||
|
|
e1a7320aa6 | ||
|
|
93da08c0ff | ||
|
|
80ce4b33a7 | ||
|
|
00b1190817 | ||
|
|
4c9e2ee748 |
4
README
4
README
@ -1,4 +0,0 @@
|
||||
WORK IN PROGRESS...
|
||||
Motors & Music & Motions (M&M&M)
|
||||
dviid, bill verplank, jakob bak
|
||||
|
||||
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
||||
## Motors & Music & Motions
|
||||
David Gauthier, Bill Verplank, Jakob Bak
|
||||
|
||||
<img src="https://git.le-club-des-sans-sujets.org/gauthiier/M-M-M/raw/branch/master/board.jpeg" width="35%"/>
|
||||
|
||||
Research material for:
|
||||
|
||||
* Bak, J., Verplank, B., & Gauthier, D. (2015). Motors, Music and Motion. In TEI '15: Proceedings of the Ninth International Conference on Tangible, Embedded, and Embodied Interaction (pp. 367-374). Association for Computing Machinery (ACM). https://doi.org/10.1145/2677199.2680590
|
||||
|
||||
* Verplank, B., Gauthier, D., & Bak, J. (2013). TEI 2013 studio: motors and music. In TEI '13:
|
||||
Proceedings of the 7th International Conference on Tangible, Embedded and Embodied Interaction (pp. 431-434). Association for Computing Machinery (ACM). https://doi.org/10.1145/2460625.2460721
|
||||
|
||||
BIN
board.jpeg
Normal file
BIN
board.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
BIN
hardware/datasheets/A1301-2-Datasheet.pdf
Normal file
BIN
hardware/datasheets/A1301-2-Datasheet.pdf
Normal file
Binary file not shown.
Binary file not shown.
BIN
hardware/eagle/v1/mm.controller.v1.pdf
Normal file
BIN
hardware/eagle/v1/mm.controller.v1.pdf
Normal file
Binary file not shown.
@ -1,36 +0,0 @@
|
||||
//Center
|
||||
//uses a variable force (pwm duty)
|
||||
//If it feels like a mountain - pushing away from center, then
|
||||
//reverse the motor leads
|
||||
//or for a quick fix in the code: change if(f < 0) to if (f > 0)
|
||||
|
||||
#include <Motor.h>
|
||||
|
||||
int pos; // position from analogRead
|
||||
int force; // computed from pos and k
|
||||
int k = 2; // spring constant
|
||||
int duty; // pwm duty for Timer1 (range 0 - 1023) 10-bit resolution
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
MotorA.torque(100); //is this necessary?
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
pos = analogRead(A0);
|
||||
|
||||
force = k * (512 - pos);
|
||||
duty = abs(force);
|
||||
duty = min(1023, duty);
|
||||
|
||||
MotorA.torque(duty);
|
||||
|
||||
if(force < 0) MotorA.direction(FORWARD);
|
||||
else MotorA.direction(BACKWARD);
|
||||
|
||||
}
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
//Damp - measure velocity then f=Bv
|
||||
#import <Motor.h>
|
||||
int x; //position measured
|
||||
float v, f, t, xold; //velocity, force, time delta
|
||||
byte c; //for debug print every 256th loop
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
xold = analogRead(A0);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
x = analogRead(A0);
|
||||
v = x - xold; //lag v, too?
|
||||
xold += 0.1*(x-xold); //slide xold with lag
|
||||
|
||||
if(c++==0){
|
||||
//Serial.print(xold);
|
||||
//Serial.print(" ");
|
||||
Serial.println(100*v);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
//Damp 2 with running average position
|
||||
|
||||
#define n 10 //number in buffer
|
||||
int x; //position measured
|
||||
float xf; // running average on n samples
|
||||
int buff[n];
|
||||
int index = 0;
|
||||
float v, oldavg; // estimate of velocity
|
||||
byte c;
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
buff[index] = analogRead(A0);
|
||||
index++;
|
||||
if(index > n-1) index = 0;
|
||||
int acc = 0;
|
||||
for(int i=0; i<n; i++)acc+=buff[i];
|
||||
float avg = acc/n;
|
||||
v = avg - oldavg;
|
||||
oldavg = avg;
|
||||
if(c++==0)Serial.println(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,48 +0,0 @@
|
||||
|
||||
int firstSensor = 0; // first analog sensor
|
||||
int secondSensor = 0; // second analog sensor
|
||||
int thirdSensor = 0; // digital sensor
|
||||
int inByte = 0; // incoming serial byte
|
||||
|
||||
void setup()
|
||||
{
|
||||
// start serial port at 9600 bps and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
pinMode(2, INPUT); // digital sensor is on digital pin 2
|
||||
establishContact(); // send a byte to establish contact until receiver responds
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// if we get a valid byte, read analog ins:
|
||||
if (Serial.available() > 0) {
|
||||
// get incoming byte:
|
||||
inByte = Serial.read();
|
||||
// read first analog input:
|
||||
firstSensor = analogRead(A0);
|
||||
// read second analog input:
|
||||
secondSensor = analogRead(A1);
|
||||
// read switch, map it to 0 or 255L
|
||||
thirdSensor = map(digitalRead(2), 0, 1, 0, 255);
|
||||
// send sensor values:
|
||||
Serial.print(firstSensor);
|
||||
Serial.print(",");
|
||||
Serial.print(secondSensor);
|
||||
Serial.print(",");
|
||||
Serial.println(thirdSensor);
|
||||
}
|
||||
}
|
||||
|
||||
void establishContact() {
|
||||
while (Serial.available() <= 0) {
|
||||
Serial.println("0,0,0"); // send an initial string
|
||||
delay(300);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,783 +0,0 @@
|
||||
{
|
||||
"patcher" : {
|
||||
"fileversion" : 1,
|
||||
"appversion" : {
|
||||
"major" : 6,
|
||||
"minor" : 0,
|
||||
"revision" : 5
|
||||
}
|
||||
,
|
||||
"rect" : [ 25.0, 82.0, 1184.0, 641.0 ],
|
||||
"bglocked" : 0,
|
||||
"openinpresentation" : 0,
|
||||
"default_fontsize" : 12.0,
|
||||
"default_fontface" : 0,
|
||||
"default_fontname" : "Arial",
|
||||
"gridonopen" : 0,
|
||||
"gridsize" : [ 15.0, 15.0 ],
|
||||
"gridsnaponopen" : 0,
|
||||
"statusbarvisible" : 2,
|
||||
"toolbarvisible" : 1,
|
||||
"boxanimatetime" : 200,
|
||||
"imprint" : 0,
|
||||
"enablehscroll" : 1,
|
||||
"enablevscroll" : 1,
|
||||
"devicewidth" : 0.0,
|
||||
"description" : "",
|
||||
"digest" : "",
|
||||
"tags" : "",
|
||||
"boxes" : [ {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-36",
|
||||
"maxclass" : "flonum",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "float", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 360.0, 393.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-34",
|
||||
"maxclass" : "number",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 229.0, 421.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-32",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "int" ],
|
||||
"patching_rect" : [ 289.0, 421.0, 32.5, 20.0 ],
|
||||
"text" : "* 1"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-31",
|
||||
"maxclass" : "flonum",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "float", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 289.0, 452.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-29",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "int" ],
|
||||
"patching_rect" : [ 289.0, 387.0, 32.5, 20.0 ],
|
||||
"text" : "-"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-28",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 709.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "76"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-26",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 649.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "74"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-25",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 589.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "71"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-24",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 529.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "68"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-13",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 469.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "66"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-3",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 409.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "63"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-23",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 349.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "61"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-1",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 289.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "58"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-37",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 229.0, 345.0, 50.0, 18.0 ],
|
||||
"text" : "57"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-27",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 10,
|
||||
"outlettype" : [ "int", "bang", "bang", "bang", "bang", "bang", "bang", "bang", "bang", "bang" ],
|
||||
"patching_rect" : [ 206.25, 306.0, 519.5, 20.0 ],
|
||||
"text" : "t i b b b b b b b b b"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-22",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 5,
|
||||
"outlettype" : [ "int", "bang", "bang", "bang", "bang" ],
|
||||
"patching_rect" : [ 879.0, 313.0, 73.0, 20.0 ],
|
||||
"text" : "t i b b b b"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"id" : "obj-21",
|
||||
"maxclass" : "button",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "bang" ],
|
||||
"patching_rect" : [ 310.0, 6.0, 20.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-20",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 3,
|
||||
"outlettype" : [ "bang", "bang", "int" ],
|
||||
"patching_rect" : [ 325.0, 37.0, 56.0, 20.0 ],
|
||||
"text" : "uzi 1024"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-19",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 41.0, 370.0, 37.0, 18.0 ],
|
||||
"text" : "clear"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"id" : "obj-17",
|
||||
"maxclass" : "button",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "bang" ],
|
||||
"patching_rect" : [ 292.0, 58.0, 20.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"hint" : "x 82 y -44",
|
||||
"id" : "obj-15",
|
||||
"maxclass" : "itable",
|
||||
"name" : "",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 150.0, 488.0, 1000.0, 145.0 ],
|
||||
"range" : 128,
|
||||
"signed" : 1,
|
||||
"size" : 1024,
|
||||
"table_data" : [ 0, 80, 4, 4, -32, -34, -36, -40, -40, -42, -50, -50, -18, -18, -22, -20, -20, -20, -16, -20, -20, -18, -14, -14, -16, -18, -22, -20, -18, -20, -18, -18, -18, -16, -14, -12, -6, -2, -2, 0, 4, 6, 8, 10, 6, 6, 6, 8, 6, 8, 8, 8, 10, 8, 8, 8, 8, 6, 8, 6, 6, 8, 8, 6, 6, 8, 6, 8, 6, 6, 6, 8, 8, 6, 8, 6, 6, 6, 6, 6, 6, 8, 6, 8, 8, 8, 8, 6, 8, 6, 8, 10, 10, 10, 10, 12, 12, 12, 10, 6, 8, 10, 10, 10, 8, 10, 12, 14, 14, 10, 10, 10, 10, 10, 8, 6, 6, 10, 10, 10, 12, 12, 12, 14, 12, 10, 10, 10, 10, 8, 8, 8, 8, 10, 10, 10, 8, 10, 12, 10, 10, 6, 8, 6, 8, 8, 6, 6, 8, 8, 8, 10, 8, 6, 8, 8, 6, 8, 10, 8, 10, 10, 10, 10, 12, 12, 10, 10, 10, 10, 10, 10, 8, 10, 8, 10, 10, 12, 12, 12, 14, 10, 12, 10, 8, 6, 6, 8, 6, 6, 6, 6, 8, 8, 8, 6, 6, 6, 6, 6, 4, 6, 6, 6, 6, 8, 6, 6, 6, 4, 0, -2, -4, -8, -10, -14, -18, -20, -20, -20, -20, -24, -22, -32, -36, -38, -44, -46, -50, -48, -50, -40, -32, -36, -32, -34, -34, -32, -38, -36, -38, -32, -30, -32, -32, -32, -24, -26, -26, -26, -26, -22, -22, -22, -24, -22, -22, -20, -18, -14, -8, -6, -4, -2, 0, 0, 2, 2, 4, 4, 4, 4, 4, 4, 2, 2, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4, 6, 2, 4, 4, 6, 6, 6, 6, 4, 4, 2, 2, 0, 0, 0, 0, 2, 2, 2, 4, 6, 146, 140, 134, 126, 116, 104, 102, 100, -38, -30, -24, -16, -4, 10, 12, 12, 12, 12, 12, 14, 12, 18, 22, 24, 22, 18, 14, 8, 2, -12, -20, -24, -28, -28, -26, -26, -22, -18, -22, -22, -18, -18, -14, -10, -4, 0, 10, -2, -14, -28, -38, -48, -54, -56, -66, -54, -50, -36, -32, -28, -26, -28, -22, -22, -14, -12, -6, -2, -2, 6, 6, 10, 10, 12, 12, 12, 12, 8, 10, 10, 10, 8, 6, 6, 6, 4, 2, 0, 0, 2, 2, 4, 6, 10, 18, 22, 26, 34, 36, 40, 40, 38, 28, 20, 12, 2, 0, -6, -8, -10, -8, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 4, 6, 4, 4, 4, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -4, -4, -4, -4, -4, -6, -6, -4, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 6, 6, 6, 6, 6, 6, 6, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -4, -6, -4, -6, -8, -10, -12, -14, -16, -18, -26, -30, -34, -34, -34, -34, -34, -32, -24, -20, -18, -18, -18, -18, -14, -8, -6, 2, 8, 12, 26, 30, 40, 38, 40, 40, 40, 44, 34, 34, 26, 26, 24, 20, 20, 16, 16, 18, 18, 24, 26, 26, 34, 36, 46, 46, 44, 38, 36, 36, 26, 22, 10, 4, 0, -8, -12, -16, -26, -30, -34, -34, -30, -26, -30, -32, -26, -26, -26, -26, -28, -30, -26, -24, -22, -20, -20, -20, -20, -18, -20, -20, -22, -24, -22, -24, -28, -32, -28, -30, -30, -30, -30, -26, -20, -12, -8, 4, 16, 22, 26, 32, 38, 38, 36, 36, 30, 32, 32, 30, 34, 34, 34, 30, 32, 32, 40, 38, 30, 32, 36, 36, 40, 40, 30, 32, 34, 32, 28, 28, 20, 14, 12, 4, -4, -10, -20, -28, -38, -46, -48, -48, -46, -42, -38, -38, -34, -26, -26, -28, -32, -36, -38, -38, -38, -38, -42, -42, -36, -36, -32, -30, -26, -38, -32, -28, -36, -34, -32, -32, -30, -18, -18, -18, -12, -10, -12, -10, -10, -8, -6, -2, 2, 6, 10, 12, 16, 18, 20, 22, 24, 24, 26, 28, 28, 30, 32, 28, 28, 32, 30, 34, 32, 28, 24, 24, 20, 12, 10, 2, 0, 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, -2, -2, -2, -2, 0, 2, 4, 4, 6, 6, 6, 6, 6, 4, 4, 4, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-14",
|
||||
"maxclass" : "number",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 150.0, 337.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-12",
|
||||
"maxclass" : "number",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 451.0, 92.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"id" : "obj-11",
|
||||
"maxclass" : "toggle",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "int" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 451.0, -4.0, 20.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-9",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "bang" ],
|
||||
"patching_rect" : [ 451.0, 27.0, 51.0, 20.0 ],
|
||||
"text" : "metro 1"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-8",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 5,
|
||||
"numoutlets" : 4,
|
||||
"outlettype" : [ "int", "", "", "int" ],
|
||||
"patching_rect" : [ 451.0, 60.0, 101.0, 20.0 ],
|
||||
"text" : "counter 0 1 1024"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-7",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 0,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 310.0, 96.0, 100.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-6",
|
||||
"maxclass" : "number",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 150.0, 85.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"hint" : "x 79 y 127",
|
||||
"id" : "obj-4",
|
||||
"maxclass" : "itable",
|
||||
"name" : "",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 150.0, 153.0, 1000.0, 145.0 ],
|
||||
"range" : 128,
|
||||
"size" : 1024,
|
||||
"table_data" : [ 0, 56, 55, 54, 53, 51, 51, 50, 48, 48, 46, 45, 42, 41, 41, 40, 40, 38, 36, 36, 35, 34, 33, 31, 29, 28, 27, 26, 26, 25, 24, 23, 22, 22, 24, 25, 25, 25, 26, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 32, 32, 32, 33, 33, 33, 34, 34, 35, 36, 36, 36, 36, 37, 37, 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 46, 47, 47, 48, 50, 50, 51, 51, 52, 53, 53, 53, 53, 54, 56, 56, 57, 57, 58, 59, 60, 61, 61, 61, 62, 62, 63, 63, 63, 64, 66, 66, 67, 68, 69, 69, 70, 70, 71, 71, 72, 73, 73, 73, 74, 74, 76, 76, 77, 77, 78, 79, 79, 79, 79, 80, 80, 81, 82, 82, 82, 83, 83, 84, 85, 85, 85, 86, 86, 86, 87, 89, 89, 90, 90, 91, 91, 92, 93, 94, 94, 95, 95, 96, 96, 96, 98, 98, 99, 100, 101, 102, 102, 103, 103, 104, 104, 104, 104, 105, 106, 106, 106, 107, 107, 108, 108, 109, 109, 109, 109, 110, 110, 110, 111, 112, 112, 112, 113, 113, 113, 113, 113, 112, 111, 110, 109, 108, 106, 104, 103, 102, 101, 100, 97, 97, 90, 86, 84, 80, 78, 75, 73, 72, 70, 70, 66, 64, 61, 58, 57, 53, 52, 51, 50, 49, 45, 42, 41, 41, 39, 38, 37, 36, 34, 31, 30, 29, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 30, 30, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 34, 35, 105, 102, 99, 96, 91, 85, 85, 85, 86, 87, 87, 88, 89, 90, 91, 91, 92, 93, 93, 95, 95, 99, 102, 103, 103, 102, 100, 99, 96, 93, 92, 91, 89, 88, 87, 86, 85, 84, 81, 80, 80, 79, 80, 81, 83, 84, 86, 79, 73, 65, 61, 57, 56, 56, 53, 52, 48, 47, 45, 43, 43, 42, 42, 41, 41, 41, 42, 42, 42, 45, 45, 46, 46, 47, 48, 48, 48, 49, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 53, 54, 56, 60, 62, 64, 69, 70, 73, 74, 75, 74, 72, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 70, 70, 70, 70, 70, 71, 71, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 73, 72, 72, 72, 72, 72, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 72, 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 73, 73, 73, 73, 73, 73, 72, 71, 71, 70, 69, 68, 67, 66, 64, 62, 58, 55, 52, 51, 50, 49, 47, 46, 46, 45, 43, 42, 41, 40, 40, 42, 43, 46, 47, 48, 54, 55, 60, 61, 63, 66, 67, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 81, 82, 86, 88, 89, 94, 96, 102, 104, 104, 105, 106, 107, 107, 107, 107, 106, 104, 101, 100, 99, 94, 92, 90, 89, 89, 88, 85, 83, 81, 79, 77, 76, 75, 73, 72, 71, 70, 69, 67, 66, 65, 64, 62, 61, 59, 57, 56, 54, 51, 48, 48, 46, 44, 42, 41, 41, 41, 42, 44, 48, 52, 53, 54, 57, 60, 61, 62, 66, 67, 69, 70, 72, 77, 78, 79, 81, 83, 85, 90, 91, 92, 94, 97, 99, 103, 105, 105, 107, 109, 110, 111, 113, 113, 112, 111, 109, 107, 105, 101, 99, 94, 89, 87, 85, 84, 84, 82, 80, 77, 76, 74, 71, 68, 66, 63, 61, 58, 57, 53, 50, 50, 48, 47, 46, 45, 38, 37, 36, 32, 31, 31, 30, 30, 29, 28, 27, 26, 26, 25, 25, 25, 25, 25, 26, 27, 29, 30, 31, 33, 34, 35, 37, 39, 41, 43, 45, 47, 49, 51, 51, 53, 57, 58, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 64, 64, 64, 64, 64, 64, 64, 64, 64, 65, 66, 66, 67, 67, 67, 67, 67, 67, 68, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 69, 69, 69, 69, 70, 70, 70, 70, 70, 70, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 73 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-2",
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 63.0, 39.0, 150.0, 20.0 ],
|
||||
"text" : "Plot Velocity from Position"
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"lines" : [ {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-23", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-1", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-9", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-11", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-15", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-12", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-4", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-12", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-24", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-13", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-8", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-17", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-15", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-19", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-8", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-20", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-20", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-21", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-3", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-23", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-25", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-24", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-26", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-25", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-28", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-26", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-1", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 2 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-13", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 5 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-23", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 3 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-24", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 6 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-25", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 7 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-26", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 8 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-28", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 9 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-3", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 4 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-37", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 1 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-37", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-27", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-29", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-28", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-32", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-29", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-34", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-29", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-13", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-3", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-15", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-31", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-31", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-32", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-32", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-36", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-1", 1 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-37", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-29", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-37", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-14", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-4", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-27", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-4", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-4", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-6", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-12", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-8", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-8", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-9", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"dependency_cache" : [ ]
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
//Damp3 trying integration to get velocity
|
||||
// ala Kalman filtering?
|
||||
|
||||
int x; //position measured [0-1023]
|
||||
float af, vf //acceleration, velocity estimates
|
||||
float ff // force out
|
||||
float K = 1.0 //spring
|
||||
float B = 10.0 //damping (dominant)
|
||||
float M = 1.0 //mass
|
||||
|
||||
void setup(){
|
||||
Serial.begin(115200);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
x = analogRead(A0);
|
||||
ff = K*(xf-x) - B*vf; // the spring K
|
||||
af = ff/M;
|
||||
vf += af*T; //T is cycle time
|
||||
xf += vf*T;
|
||||
@ -1,24 +0,0 @@
|
||||
//Damp Euler
|
||||
|
||||
#define n 10 //number in buffer "window size"
|
||||
// finite difference with n samples between x(i)
|
||||
int x[n]; //last n samples of position
|
||||
int index = 0;
|
||||
float v; // estimate of velocity
|
||||
byte c;
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
for(int i=0; i<n; i++) x[i]=analogRead(A0);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
x[index] = analogRead(A0); //position measured
|
||||
v = (x[index] - x[index++%n])/n;
|
||||
if(index > n-1) index = 0;
|
||||
v = buff[index] - buff[(index-n)%n];
|
||||
if(c++==0)Serial.println(v);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1 +0,0 @@
|
||||
//DampMass
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,28 +0,0 @@
|
||||
int x, v, t; //position velocity time
|
||||
#define n 10
|
||||
int xtab[n]; //table of x
|
||||
int i; // index for table
|
||||
|
||||
void setup()
|
||||
{
|
||||
// start serial port at 9600 bps:
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// if we get a valid byte, read analog ins:
|
||||
if (Serial.available() > 0) {
|
||||
x = analogRead(A0)/4; //just for this test
|
||||
xtab[i] = x; //put it in array of x
|
||||
i = i + 1; //index to last x (9 times ago)
|
||||
if(i>9)i=0; //increment index
|
||||
v = x - xtab[i]; //difference x vs old x
|
||||
t = (t+1)%256;
|
||||
// send sensor values:
|
||||
Serial.write(x); // sends one byte [0-255]
|
||||
Serial.write(v+128);
|
||||
Serial.write(t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,576 +0,0 @@
|
||||
{
|
||||
"patcher" : {
|
||||
"fileversion" : 1,
|
||||
"appversion" : {
|
||||
"major" : 6,
|
||||
"minor" : 0,
|
||||
"revision" : 5
|
||||
}
|
||||
,
|
||||
"rect" : [ 50.0, 94.0, 693.0, 652.0 ],
|
||||
"bglocked" : 0,
|
||||
"openinpresentation" : 0,
|
||||
"default_fontsize" : 12.0,
|
||||
"default_fontface" : 0,
|
||||
"default_fontname" : "Arial",
|
||||
"gridonopen" : 0,
|
||||
"gridsize" : [ 15.0, 15.0 ],
|
||||
"gridsnaponopen" : 0,
|
||||
"statusbarvisible" : 2,
|
||||
"toolbarvisible" : 1,
|
||||
"boxanimatetime" : 200,
|
||||
"imprint" : 0,
|
||||
"enablehscroll" : 1,
|
||||
"enablevscroll" : 1,
|
||||
"devicewidth" : 0.0,
|
||||
"description" : "",
|
||||
"digest" : "",
|
||||
"tags" : "",
|
||||
"boxes" : [ {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-23",
|
||||
"maxclass" : "flonum",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "float", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 561.0, 378.0, 50.0, 20.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-20",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "float" ],
|
||||
"patching_rect" : [ 519.0, 429.0, 44.0, 20.0 ],
|
||||
"text" : "+ 500."
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-18",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "float" ],
|
||||
"patching_rect" : [ 418.0, 414.0, 42.0, 20.0 ],
|
||||
"text" : "* 100."
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-32",
|
||||
"linecount" : 10,
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 479.0, 6.0, 344.0, 145.0 ],
|
||||
"text" : "Graph\n\nThis patch takes a string, containing ASCII formatted number from 0 to 1023, with a carriage return and linefeed at the end. It converts the string to an integer and graphs it.\n\ncreated 2006\nby David A. Mellis\nmodified 14 Apr 2009\nby Scott Fitzgerald and Tom Igoe"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-30",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 3,
|
||||
"numoutlets" : 3,
|
||||
"outlettype" : [ "bang", "bang", "" ],
|
||||
"patching_rect" : [ 327.0, 80.0, 62.0, 20.0 ],
|
||||
"text" : "select 0 1"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-26",
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 412.0, 231.0, 206.0, 20.0 ],
|
||||
"text" : "click here to close the serial port"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-27",
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 412.0, 205.0, 206.0, 20.0 ],
|
||||
"text" : "click here to open the serial port"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-21",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 327.0, 231.0, 39.0, 18.0 ],
|
||||
"text" : "close"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-19",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 349.0, 205.0, 41.0, 18.0 ],
|
||||
"text" : "port a"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"bgcolor" : [ 0.231373, 0.713726, 1.0, 1.0 ],
|
||||
"candicane2" : [ 0.145098, 0.203922, 0.356863, 1.0 ],
|
||||
"candicane3" : [ 0.290196, 0.411765, 0.713726, 1.0 ],
|
||||
"candicane4" : [ 0.439216, 0.619608, 0.070588, 1.0 ],
|
||||
"candicane5" : [ 0.584314, 0.827451, 0.431373, 1.0 ],
|
||||
"candicane6" : [ 0.733333, 0.035294, 0.788235, 1.0 ],
|
||||
"candicane7" : [ 0.878431, 0.243137, 0.145098, 1.0 ],
|
||||
"candicane8" : [ 0.027451, 0.447059, 0.501961, 1.0 ],
|
||||
"contdata" : 1,
|
||||
"id" : "obj-1",
|
||||
"maxclass" : "multislider",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "", "" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 302.0, 450.0, 246.0, 167.0 ],
|
||||
"peakcolor" : [ 0.498039, 0.498039, 0.498039, 1.0 ],
|
||||
"setminmax" : [ 0.0, 1023.0 ],
|
||||
"setstyle" : 3,
|
||||
"settype" : 0,
|
||||
"slidercolor" : [ 0.066667, 0.058824, 0.776471, 1.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-2",
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 412.0, 179.0, 207.0, 20.0 ],
|
||||
"text" : "Click here to get a list of serial ports"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-3",
|
||||
"linecount" : 2,
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 153.0, 409.0, 138.0, 34.0 ],
|
||||
"text" : "Here's the number from Arduino's analog input"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-4",
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 379.0, 378.0, 147.0, 20.0 ],
|
||||
"text" : "Convert ASCII to symbol"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-5",
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 379.0, 355.0, 147.0, 20.0 ],
|
||||
"text" : "Convert integer to ASCII"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"bgcolor" : [ 0.866667, 0.866667, 0.866667, 1.0 ],
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"htextcolor" : [ 0.870588, 0.870588, 0.870588, 1.0 ],
|
||||
"id" : "obj-6",
|
||||
"maxclass" : "number",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "bang" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 302.0, 414.0, 37.0, 20.0 ],
|
||||
"triscale" : 0.9
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-7",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 302.0, 378.0, 74.0, 20.0 ],
|
||||
"text" : "fromsymbol"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"color" : [ 1.0, 0.890196, 0.090196, 1.0 ],
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-8",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 3,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "int" ],
|
||||
"patching_rect" : [ 302.0, 355.0, 46.0, 20.0 ],
|
||||
"text" : "itoa"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-9",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "", "" ],
|
||||
"patching_rect" : [ 302.0, 332.0, 64.0, 20.0 ],
|
||||
"text" : "zl group 4"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-10",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 3,
|
||||
"numoutlets" : 3,
|
||||
"outlettype" : [ "bang", "bang", "" ],
|
||||
"patching_rect" : [ 244.0, 281.0, 77.0, 20.0 ],
|
||||
"text" : "select 10 13"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"id" : "obj-11",
|
||||
"maxclass" : "toggle",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "int" ],
|
||||
"parameter_enable" : 0,
|
||||
"patching_rect" : [ 244.0, 43.0, 15.0, 15.0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-12",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "bang" ],
|
||||
"patching_rect" : [ 244.0, 80.0, 65.0, 20.0 ],
|
||||
"text" : "qmetro 10"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-13",
|
||||
"maxclass" : "message",
|
||||
"numinlets" : 2,
|
||||
"numoutlets" : 1,
|
||||
"outlettype" : [ "" ],
|
||||
"patching_rect" : [ 369.0, 179.0, 36.0, 18.0 ],
|
||||
"text" : "print"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-14",
|
||||
"maxclass" : "newobj",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 2,
|
||||
"outlettype" : [ "int", "" ],
|
||||
"patching_rect" : [ 244.0, 255.0, 84.0, 20.0 ],
|
||||
"text" : "serial a 9600"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-15",
|
||||
"linecount" : 2,
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 53.0, 72.0, 185.0, 34.0 ],
|
||||
"text" : "Read serial input buffer every 10 milliseconds"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-16",
|
||||
"linecount" : 3,
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 332.0, 269.0, 320.0, 48.0 ],
|
||||
"text" : "If you get newline (ASCII 10), send the list. If you get return (ASCII 13) do nothing. Any other value, add to the list"
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"box" : {
|
||||
"fontname" : "Arial",
|
||||
"fontsize" : 12.0,
|
||||
"id" : "obj-17",
|
||||
"linecount" : 2,
|
||||
"maxclass" : "comment",
|
||||
"numinlets" : 1,
|
||||
"numoutlets" : 0,
|
||||
"patching_rect" : [ 271.0, 32.0, 199.0, 34.0 ],
|
||||
"text" : "Click to open/close serial port and start/stop patch"
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"lines" : [ {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-9", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"midpoints" : [ 311.5, 320.0, 311.5, 320.0 ],
|
||||
"source" : [ "obj-10", 2 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-9", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"midpoints" : [ 253.5, 308.0, 311.5, 308.0 ],
|
||||
"source" : [ "obj-10", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-12", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-11", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-30", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"midpoints" : [ 253.0, 71.0, 336.5, 71.0 ],
|
||||
"source" : [ "obj-11", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-14", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-12", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-14", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"midpoints" : [ 378.5, 200.5, 253.5, 200.5 ],
|
||||
"source" : [ "obj-13", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-10", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-14", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-20", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-18", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-14", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"midpoints" : [ 358.5, 228.5, 253.5, 228.5 ],
|
||||
"source" : [ "obj-19", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-23", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-20", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-14", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"midpoints" : [ 336.5, 251.5, 253.5, 251.5 ],
|
||||
"source" : [ "obj-21", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-1", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-23", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-19", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-30", 1 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-21", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-30", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-1", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-6", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-18", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-7", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-7", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-8", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
, {
|
||||
"patchline" : {
|
||||
"destination" : [ "obj-8", 0 ],
|
||||
"disabled" : 0,
|
||||
"hidden" : 0,
|
||||
"source" : [ "obj-9", 0 ]
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"dependency_cache" : [ ]
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
#include <Motion.h>
|
||||
|
||||
/*
|
||||
|
||||
Two motion objects are available from the MMM Motions library
|
||||
(1) MotionA
|
||||
(2) MotionB
|
||||
|
||||
MOTION {
|
||||
MOTIONA ,
|
||||
MOTIONB1
|
||||
};
|
||||
|
||||
Each objects needs intialisation with a specific input
|
||||
from which ADC reading will be performed.
|
||||
|
||||
Users may choose and identify inputs aa INPUT[A0, ... ,A7].
|
||||
ex: MotionA.init(INPOUTA5);
|
||||
|
||||
INPUT {
|
||||
INPUTA0,
|
||||
INPUTA1,
|
||||
INPUTA2,
|
||||
INPUTA3,
|
||||
INPUTA4,
|
||||
INPUTA5,
|
||||
INPUTA6,
|
||||
INPUTA7
|
||||
}
|
||||
|
||||
All calculation of physics (position, velocity and acceleration)
|
||||
are computed internally usign interrupts and timers. To access
|
||||
such information, user may call getPosition(), getVelocity()
|
||||
and getAcceleration() respectively on a initialised Motion object.
|
||||
|
||||
int getPosition();
|
||||
float getVelocity();
|
||||
float getAcceleration();
|
||||
|
||||
*/
|
||||
|
||||
void setup() {
|
||||
MotionA.init(INPUTA0);
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.print("position: "); Serial.println(MotionA.getPosition());
|
||||
Serial.print("velocity: "); Serial.println(MotionA.getVelocity());
|
||||
Serial.print("accel: "); Serial.println(MotionA.getAcceleration());
|
||||
Serial.println("-------");
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
@ -1,80 +0,0 @@
|
||||
// "Pendulum" - spring-mass oscillator
|
||||
//
|
||||
|
||||
#include <TimerOne.h>
|
||||
#include <Motor.h>
|
||||
float tf = 0.002; //time constant was .002
|
||||
float kf = 0.2; // spring constant was .15
|
||||
float xf,vf,ff; // floating point versions of pendulum x and v and force
|
||||
int x, f; //int versions of position (from a/d) and force (to Pwm)
|
||||
int duty; // abs(f)
|
||||
byte c=0; //counts up until 0 then prints
|
||||
|
||||
float m = 0.3;
|
||||
float k = 0.01;
|
||||
|
||||
float damp = 0.09;
|
||||
|
||||
byte incomingByte;
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
//Timer1.initialize(64); //64 microsecond period
|
||||
MotorA.torque(100); //initializes Timer1, pinModes
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
x = analogRead(0); // position [0-1024]
|
||||
ff = kf*(x - xf); // spring
|
||||
f = max(ff,-1024);
|
||||
f = min(f,1024);
|
||||
// if(f>0)digitalWrite(DIRA,HIGH);
|
||||
// else digitalWrite(DIRA,LOW);
|
||||
duty = abs(f);
|
||||
// Timer1.pwm(9,duty);
|
||||
MotorA.torque(duty);
|
||||
if(f>0)MotorA.direction(FORWARD);
|
||||
else MotorA.direction(BACKWARD);
|
||||
|
||||
// update (integrate) floating versions of xf and vf
|
||||
//integrate twice tf is deltaT/mass;
|
||||
vf += ff*tf;
|
||||
xf += vf*tf;
|
||||
|
||||
if(c++==0) // when c gets to 255 it next == 0 and send data
|
||||
{
|
||||
Serial.print(x);
|
||||
Serial.print(" ");
|
||||
Serial.print(xf);
|
||||
Serial.print(" ");
|
||||
Serial.println(ff);
|
||||
}
|
||||
|
||||
if (c++ == 0)Serial.println(x); //
|
||||
if (Serial.available() > 0) {
|
||||
//Serial.print(v);
|
||||
//Serial.print(" ");
|
||||
//Serial.println(x);
|
||||
incomingByte = Serial.read();
|
||||
//Serial.write(incomingByte);
|
||||
if(incomingByte == '\''){
|
||||
m = m * 1.1;
|
||||
Serial.println(m);
|
||||
}
|
||||
if(incomingByte == ';'){
|
||||
m = m / 1.1;
|
||||
Serial.println(m);
|
||||
}
|
||||
if(incomingByte == '.'){
|
||||
k = k / 1.1;
|
||||
Serial.println(k);
|
||||
}
|
||||
if(incomingByte == '/'){
|
||||
k = k * 1.1;
|
||||
Serial.println(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
//#include <TimerOne.h>
|
||||
|
||||
#include <Motor.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
MotorA.torque(500);
|
||||
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
static int j = 1;
|
||||
static long cnt = 0;
|
||||
|
||||
if(cnt == 50000) {
|
||||
j = -1;
|
||||
MotorA.direction(FORWARD);
|
||||
} else if(cnt == 0) {
|
||||
j = 1;
|
||||
MotorA.direction(BACKWARD);
|
||||
}
|
||||
cnt += j;
|
||||
|
||||
}
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
#include <Midi.h>
|
||||
|
||||
// variables for this sketch
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
// We initialize the MIDI engine by calling Midi.init()
|
||||
Midi.init();
|
||||
|
||||
// Choosing the sine wave oscillator (optional since this is already the default).
|
||||
Music.setSaw();
|
||||
|
||||
// Detuning the three oscillators heavily to create more movement in the sound.
|
||||
Music.setDetune(0.01);
|
||||
|
||||
// Enabling envelope, otherwise the synth would just play constant tones.
|
||||
Music.enableEnvelope();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// The MIDI must be used with the external
|
||||
// "IAC2Serial.pde" Processing sketch.
|
||||
Midi.checkMidi();
|
||||
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
void setup() {
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
Music.setSquare();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
// variables for this sketch
|
||||
boolean noteIsOn = false;
|
||||
int note = 48;
|
||||
|
||||
long time = 0;
|
||||
long lastTime = 0;
|
||||
long beatTime = 1000;
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
// enabling the envelope lets us define an gain envelope for the synth
|
||||
// without having to specify it in our loop() or physics code.
|
||||
Music.enableEnvelope();
|
||||
Music.setAttack(0x0FFF);
|
||||
Music.setDecay(0x0004);
|
||||
Music.setSustain(0x00FF);
|
||||
Music.setRelease(0x0008);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// This short routine loops note over and over again
|
||||
time = millis();
|
||||
if(time - lastTime > beatTime) {
|
||||
if(!noteIsOn) {
|
||||
Music.noteOn(note);
|
||||
noteIsOn = true;
|
||||
} else {
|
||||
Music.noteOff();
|
||||
noteIsOn = false;
|
||||
}
|
||||
lastTime = time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
// variables for this sketch
|
||||
boolean noteIsOn = false;
|
||||
int n = 0;
|
||||
int dir = 1;
|
||||
int rootNote = 48;
|
||||
int note[] = {0,2,3,5,7,9,10,12,14};
|
||||
|
||||
long time = 0;
|
||||
long lastTime = 0;
|
||||
long beatTime = 100;
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
// enabling the envelope lets us define an gain envelope for the synth
|
||||
// without having to specify it in our loop() or physics code.
|
||||
Music.enableEnvelope();
|
||||
Music.setAttack(0x00FF);
|
||||
Music.setDecay(0x0008);
|
||||
Music.setSustain(0x00FF);
|
||||
Music.setRelease(0x0008);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// This short routine loops note over and over again
|
||||
time = millis();
|
||||
if(time - lastTime > beatTime) {
|
||||
if(!noteIsOn) {
|
||||
Music.noteOn(rootNote+note[n]);
|
||||
noteIsOn = true;
|
||||
n = n + dir;
|
||||
if(n > 7)
|
||||
{
|
||||
dir = -1;
|
||||
}
|
||||
else if(n < 1)
|
||||
{
|
||||
dir = 1;
|
||||
}
|
||||
} else {
|
||||
Music.noteOff();
|
||||
noteIsOn = false;
|
||||
}
|
||||
lastTime = time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
// variables for this sketch
|
||||
boolean noteIsOn = false;
|
||||
int n = 0;
|
||||
int dir = 1;
|
||||
int rootNote = 48;
|
||||
int note[] = {0,2,3,5,7,9,10,12,14};
|
||||
|
||||
long time = 0;
|
||||
long lastTime = 0;
|
||||
long beatTime = 100;
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
// enabling the envelope lets us define an gain envelope for the synth
|
||||
// without having to specify it in our loop() or physics code.
|
||||
Music.enableEnvelope();
|
||||
Music.setAttack(8);
|
||||
Music.setDecay(70);
|
||||
Music.setSustain(24);
|
||||
Music.setRelease(90);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// This short routine loops note over and over again
|
||||
time = millis();
|
||||
if(time - lastTime > beatTime) {
|
||||
if(!noteIsOn) {
|
||||
Music.noteOn(rootNote+note[n]);
|
||||
noteIsOn = true;
|
||||
n = n + dir;
|
||||
if(n > 7)
|
||||
{
|
||||
dir = -1;
|
||||
}
|
||||
else if(n < 1)
|
||||
{
|
||||
dir = 1;
|
||||
}
|
||||
} else {
|
||||
Music.noteOff();
|
||||
noteIsOn = false;
|
||||
}
|
||||
lastTime = time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
void setup() {
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
Music.setSquare();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
void serialEvent() {
|
||||
while (Serial.available()) {
|
||||
// get the new byte:
|
||||
|
||||
|
||||
|
||||
int inChar = (int)Serial.read();
|
||||
if (inChar == '\n') {
|
||||
stringComplete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,113 @@
|
||||
import controlP5.*;
|
||||
import processing.serial.*;
|
||||
|
||||
//Plots
|
||||
ScopePlot plotA;
|
||||
ScopePlot plotB;
|
||||
ScopePlotDouble plotC;
|
||||
|
||||
//Communication with MMM boards
|
||||
Protocol proto;
|
||||
|
||||
//Serial port
|
||||
Serial p;
|
||||
|
||||
//Controlers
|
||||
ControlP5 cp5;
|
||||
SliderCallback scb;
|
||||
|
||||
// (k)
|
||||
float kmin = 0.0f;
|
||||
float kmax = 7.0f;
|
||||
float k = 0.2f;
|
||||
Slider k_slider;
|
||||
|
||||
// (m)
|
||||
float mmin = 0.0f;
|
||||
float mmax = 7.0f;
|
||||
float m = 1.0f;
|
||||
Slider m_slider;
|
||||
|
||||
// (d)
|
||||
float dmin = 0.0f;
|
||||
float dmax = 7.0f;
|
||||
float d = 0.02f;
|
||||
Slider d_slider;
|
||||
|
||||
void setup() {
|
||||
|
||||
int b = 15;
|
||||
int h = 300;//(displayHeight / 4) - (3*b);
|
||||
int w = displayWidth / 2;
|
||||
|
||||
plotA = new ScopePlot("Force", w, h, b, b + b, 512, true);
|
||||
plotB = new ScopePlot("Velocity", w, h, b, h + 4*b, 512, true);
|
||||
plotC = new ScopePlotDouble("Position Estimate", w, h, b, 2*h + 6*b, 512, true);
|
||||
|
||||
p = new Serial(this, Serial.list()[0], 9600);
|
||||
proto = new Protocol(p);
|
||||
|
||||
// Controls
|
||||
cp5 = new ControlP5(this);
|
||||
scb = new SliderCallback();
|
||||
|
||||
int sw = w / 3;
|
||||
|
||||
k_slider = cp5.addSlider("k", kmin, kmax, b, b-5, sw - b, b-5);
|
||||
k_slider.setColorForeground(color(127,34,255));
|
||||
k_slider.setColorBackground(color(50,50,50));
|
||||
k_slider.addListener(scb);
|
||||
|
||||
m_slider = cp5.addSlider("m", mmin, mmax, 2*b + sw, b-5, sw - b, b-5);
|
||||
m_slider.setColorForeground(color(127,34,255));
|
||||
m_slider.setColorBackground(color(50,50,50));
|
||||
m_slider.addListener(scb);
|
||||
|
||||
d_slider = cp5.addSlider("d", dmin, dmax, 3*b + 2*sw, b-5, sw - b, b-5);
|
||||
d_slider.setColorForeground(color(127,34,255));
|
||||
d_slider.setColorBackground(color(50,50,50));
|
||||
d_slider.addListener(scb);
|
||||
|
||||
size(w + 60, displayHeight - (h + (3*b)));
|
||||
//size(w + 60, 800);
|
||||
//size(600, 800);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
plotA.draw();
|
||||
plotB.draw();
|
||||
plotC.draw();
|
||||
}
|
||||
|
||||
/*
|
||||
void mouseDragged()
|
||||
{
|
||||
plotA.mdata(mouseX, mouseY);
|
||||
plotB.mdata(mouseX, mouseY);
|
||||
plotC.mdata(mouseX, mouseY);
|
||||
}
|
||||
|
||||
void mouseClicked()
|
||||
{
|
||||
plotA.mdata(mouseX, mouseY);
|
||||
plotB.mdata(mouseX, mouseY);
|
||||
plotC.mdata(mouseX, mouseY);
|
||||
}
|
||||
*/
|
||||
|
||||
void serialEvent (Serial myPort) {
|
||||
proto.processData();
|
||||
plotA.data(proto.F);
|
||||
plotB.data(proto.V);
|
||||
plotC.data(proto.X - 512, proto.Xin - 512);
|
||||
}
|
||||
|
||||
class SliderCallback implements ControlListener {
|
||||
public void controlEvent(ControlEvent ev) {
|
||||
p.write(new String(ev.controller().name()+ev.controller().value()+";"));
|
||||
//println(ev.controller().name() + ": " + ev.controller().value());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
import processing.serial.*;
|
||||
|
||||
class Protocol {
|
||||
Serial port; // The serial port
|
||||
Protocol() {;}
|
||||
|
||||
int F, V, X, Xin;
|
||||
|
||||
Protocol(Serial p) {
|
||||
port = p;
|
||||
port.bufferUntil('\n');
|
||||
}
|
||||
|
||||
void processData() {
|
||||
String in = port.readStringUntil('\n');
|
||||
if(in != null){
|
||||
String[] t = splitTokens(in);
|
||||
F = int(t[0]);
|
||||
V = int(t[1]);
|
||||
X = int(t[2]);
|
||||
Xin = int(t[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,161 @@
|
||||
class ScopePlot {
|
||||
|
||||
int d = 4, s = 4;
|
||||
int indx, max, min;
|
||||
int w, h;
|
||||
int px, py;
|
||||
int by;
|
||||
int[] values;
|
||||
int[] pixelvalues;
|
||||
String title;
|
||||
|
||||
ScopePlot(String t, int w, int h, int x, int y, int maxval, boolean mid){
|
||||
this.title = t;
|
||||
this.w = w + d;
|
||||
this.h = h + d;
|
||||
this.indx = s;
|
||||
this.px = x - d;
|
||||
this.py = y + d;
|
||||
this.max = maxval;
|
||||
this.min = -maxval;
|
||||
noFill();
|
||||
textSize(12);
|
||||
values = new int[w / s];
|
||||
pixelvalues = new int[w / s];
|
||||
if(mid) by = h / 2;
|
||||
else by = this.h;
|
||||
}
|
||||
|
||||
void draw(){
|
||||
|
||||
pushMatrix();
|
||||
|
||||
translate(px, py);
|
||||
|
||||
stroke(255,255,255);
|
||||
line( -d, h, w + d + d, h);
|
||||
line( 0, -d, 0, h + d);
|
||||
line( -d, 0, w + d + d, 0);
|
||||
line( w + d, h + d, w + d , -d);
|
||||
|
||||
fill(255,255,255);
|
||||
textSize(10);
|
||||
text(title, d, -d+2);
|
||||
noFill();
|
||||
if(by != h) {
|
||||
line(-d, by, w + d, by);
|
||||
text(Integer.toString(this.max), w + d + d + d, 0);
|
||||
text(Integer.toString(this.min), w + d + d + d, h + d);
|
||||
} else {
|
||||
text(Integer.toString(this.max), w + d + d + d, 0);
|
||||
text(Integer.toString(values.length), w + d + d + d, h + d + d + d);
|
||||
}
|
||||
|
||||
int x = s;
|
||||
for(int i = 0; i < pixelvalues.length; i++) {
|
||||
stroke(127,34,255);
|
||||
line(x, by, x, by - pixelvalues[i]);
|
||||
stroke(255,34,127);
|
||||
if(i == indx - 1) {
|
||||
stroke(255);
|
||||
text(Integer.toString(values[i]), w + d + d + d, by - pixelvalues[i]);
|
||||
}
|
||||
ellipse(x, by - pixelvalues[i], 3, 3);
|
||||
x += s;
|
||||
}
|
||||
|
||||
|
||||
popMatrix();
|
||||
|
||||
}
|
||||
|
||||
void data(int d) {
|
||||
values[indx] = d;
|
||||
float i = (float) d / (float)this.max;
|
||||
if(by != h) pixelvalues[indx++] = (int)(i * h / 2);
|
||||
else pixelvalues[indx++] = (int)(i * h);
|
||||
indx %= (w / s) - 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ScopePlotDouble extends ScopePlot {
|
||||
|
||||
int[] values_second;
|
||||
int[] pixelvalues_second;
|
||||
|
||||
ScopePlotDouble(String t, int w, int h, int x, int y, int maxval, boolean mid){
|
||||
super(t, w, h, x, y, maxval, mid);
|
||||
values_second = new int[values.length];
|
||||
pixelvalues_second = new int[pixelvalues.length];
|
||||
}
|
||||
|
||||
void data(int d0, int d1) {
|
||||
values_second[indx] = d1;
|
||||
float i = (float) d1 / (float)this.max;
|
||||
if(by != h) pixelvalues_second[indx] = (int)(i * h / 2);
|
||||
else pixelvalues_second[indx] = (int)(i * h);
|
||||
super.data(d0);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
pushMatrix();
|
||||
|
||||
translate(px, py);
|
||||
|
||||
int x = s;
|
||||
for(int i = 0; i < pixelvalues_second.length; i++) {
|
||||
stroke(255,34,127);
|
||||
line(x, by, x, by - pixelvalues_second[i]);
|
||||
stroke(127,34,255);
|
||||
if(i == indx - 1) {
|
||||
stroke(255);
|
||||
text(Integer.toString(values_second[i]), w + d + d + d, by - pixelvalues_second[i]);
|
||||
}
|
||||
ellipse(x, by - pixelvalues_second[i], 3, 3);
|
||||
x += s;
|
||||
}
|
||||
|
||||
popMatrix();
|
||||
|
||||
super.draw();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ScopePlotInteract extends ScopePlot {
|
||||
|
||||
int[] cpoints;
|
||||
int[] cpointsvalues;
|
||||
|
||||
int mx, my;
|
||||
|
||||
ScopePlotInteract(String t, int w, int h, int x, int y, int maxval, boolean mid) {
|
||||
super(t, w, h, x, y, maxval, mid);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
mx = 0;
|
||||
super.draw();
|
||||
}
|
||||
|
||||
void mdata(int mousex, int mousey) {
|
||||
if(mousex < px + w && mousex > px && mousey > py && mousey < py + h) {
|
||||
mx = (mousex - px) / s;
|
||||
my = mousey;
|
||||
if(mx < pixelvalues.length)
|
||||
pixelvalues[mx] = (by + py) - my;
|
||||
// compute real values here
|
||||
}
|
||||
/*
|
||||
else if((mousex > px + w && mousex < px + w + d) || (mousex < px && mousex > px - d) ||
|
||||
(mousey < py && mousey > py - d) || (mousey > py + h && mousey < py + h + d)) {
|
||||
px += (mousex - mx);
|
||||
py += (my - mousey);
|
||||
}
|
||||
mx = mousex;
|
||||
my = mousey;
|
||||
*/
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
#include <Motion.h>
|
||||
#include <Motor.h>
|
||||
#include <Music.h>
|
||||
|
||||
char buf[16] = "";
|
||||
|
||||
char b = 'x';
|
||||
String inputString = "";
|
||||
boolean stringComplete = false;
|
||||
|
||||
float k, m, d;
|
||||
|
||||
int cnt = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// MOTOR
|
||||
MotorA.init();
|
||||
|
||||
// MUSIC
|
||||
Music.init();
|
||||
|
||||
// MOTION
|
||||
MotionA.init(INPUTA0);
|
||||
MotionA.k = 5.2f; // spring
|
||||
MotionA.m = 1.0f; // mass
|
||||
MotionA.d = 8.02f; // damping
|
||||
|
||||
// Serial
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
MotionA.update_mass_spring_damper();
|
||||
|
||||
MotorA.torque(MotionA.F);
|
||||
|
||||
int f = map(abs(MotionA.F), 0, 512, 64, 76);
|
||||
Music.noteOn(f);
|
||||
|
||||
cnt++;
|
||||
|
||||
if(cnt == 10) {
|
||||
sprintf(buf, "%d %d %d %d", (int)MotionA.F, (int)MotionA.V, (int)MotionA.X, (int)MotionA.Xin);
|
||||
Serial.println(buf);
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
if(stringComplete) {
|
||||
if(b == 'k') {
|
||||
MotionA.k = convertToFloat(inputString);
|
||||
} else if(b == 'm') {
|
||||
MotionA.m = convertToFloat(inputString);
|
||||
} else if(b == 'd') {
|
||||
MotionA.d = convertToFloat(inputString);
|
||||
}
|
||||
b = 'x';
|
||||
stringComplete = false;
|
||||
inputString = "";
|
||||
}
|
||||
}
|
||||
|
||||
void serialEvent() {
|
||||
while (Serial.available()) {
|
||||
char inChar = (char)Serial.read();
|
||||
if(inChar == 'k' || inChar == 'm' || inChar == 'd') {
|
||||
b = inChar;
|
||||
} else {
|
||||
if (inChar == ';') {
|
||||
stringComplete = true;
|
||||
} else
|
||||
inputString += inChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float convertToFloat(String str) {
|
||||
char buf[16] = "";
|
||||
str.toCharArray(buf, str.length() + 1);
|
||||
return atof(buf);
|
||||
}
|
||||
128
software/apps/Processing/Motor/ForceProfile/ForceProfile.pde
Normal file
128
software/apps/Processing/Motor/ForceProfile/ForceProfile.pde
Normal file
@ -0,0 +1,128 @@
|
||||
import controlP5.*;
|
||||
import processing.serial.*;
|
||||
|
||||
static char NEW = '!';
|
||||
static char OK = '*';
|
||||
static char PRINT = '&';
|
||||
|
||||
ForceProfilePlot fpp;
|
||||
Button send;
|
||||
Button print;
|
||||
|
||||
//Serial port
|
||||
Serial p;
|
||||
|
||||
void setup() {
|
||||
|
||||
int b = 15;
|
||||
//int h = (displayHeight / 3); (work in certain resolution)
|
||||
//int w = displayWidth / 2; (work in certain resolution)
|
||||
int w = 720;
|
||||
int h = 300;
|
||||
|
||||
println("w: " + w + " h: " + h);
|
||||
|
||||
fpp = new ForceProfilePlot("Force Profile - Perception Terrain", w, h, b, b, 80, true);
|
||||
|
||||
ControlP5 cp5 = new ControlP5(this);
|
||||
|
||||
send = cp5.addButton("send");
|
||||
send.setPosition(w - 20, 2*h + 2*b + 7);
|
||||
send.setSize(35, 15);
|
||||
send.setColorForeground(color(127,34,255));
|
||||
send.setColorBackground(color(50,50,50));
|
||||
|
||||
print = cp5.addButton("print");
|
||||
print.setPosition(w - 140, 2*h + 2*b + 7);
|
||||
print.setSize(35, 15);
|
||||
print.setColorForeground(color(127,34,255));
|
||||
print.setColorBackground(color(50,50,50));
|
||||
|
||||
size(w + 60, 2*h + 60);
|
||||
|
||||
p = new Serial(this, Serial.list()[0], 9600);
|
||||
|
||||
}
|
||||
|
||||
void draw() {
|
||||
background(0);
|
||||
fpp.draw();
|
||||
|
||||
if(p.available() > 0) {
|
||||
String in = p.readStringUntil('\n');
|
||||
if(in != null) {
|
||||
println(in);
|
||||
String[] t = splitTokens(in);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mouseDragged() {
|
||||
fpp.drag(mouseX, mouseY);
|
||||
}
|
||||
|
||||
void mouseClicked()
|
||||
{
|
||||
fpp.click(mouseX, mouseY);
|
||||
}
|
||||
|
||||
void mouseReleased() {
|
||||
fpp.release();
|
||||
}
|
||||
|
||||
public void send() {
|
||||
|
||||
send.setOff();
|
||||
|
||||
p.write(NEW);
|
||||
println("1");
|
||||
while(p.available() <= 0);
|
||||
println("2");
|
||||
char in = p.readChar();
|
||||
println("3");
|
||||
if(in == OK) {
|
||||
println("GO!");
|
||||
int s = 800 / fpp.forces.length;
|
||||
int len = s * (fpp.forces.length - 1);
|
||||
serial_send(len);
|
||||
float dx = 1023.0f / (fpp.forces.length - 1);
|
||||
float ddx = dx / s;
|
||||
for(int i = 0; i < fpp.forces.length-1; i++) {
|
||||
float k = fpp.forces[i];
|
||||
float m = (fpp.forces[i+1] - k) / dx;
|
||||
for(int j = 0; j < s; j++) {
|
||||
int d = (int)(k + m*j);
|
||||
serial_send(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
send.setOn();
|
||||
|
||||
}
|
||||
|
||||
public void print() {
|
||||
println("print");
|
||||
print.setOff();
|
||||
p.write(PRINT);
|
||||
while(p.available() <= 0); // block
|
||||
while(p.available() > 0) {
|
||||
String s = p.readStringUntil('#');
|
||||
if(s != null)
|
||||
println(s);
|
||||
}
|
||||
send.setOn();
|
||||
}
|
||||
|
||||
public boolean serial_send(int i) {
|
||||
p.clear();
|
||||
char msb = (char) (i / 256);
|
||||
char lsb = (char) (i & 0xff);
|
||||
p.write(lsb);
|
||||
p.write(msb);
|
||||
while(p.available() <= 0);
|
||||
char in = p.readChar();
|
||||
return (in == OK);
|
||||
}
|
||||
|
||||
144
software/apps/Processing/Motor/ForceProfile/ForceProfilePlot.pde
Normal file
144
software/apps/Processing/Motor/ForceProfile/ForceProfilePlot.pde
Normal file
@ -0,0 +1,144 @@
|
||||
class ForceProfilePlot {
|
||||
|
||||
int d = 4, s = 4;
|
||||
float steps = 4;
|
||||
int max, min;
|
||||
int w, h, by;
|
||||
int px, py;
|
||||
|
||||
int res = 800;
|
||||
|
||||
int[] forces;
|
||||
int[] forces_pixelvalues;
|
||||
|
||||
int mx, my;
|
||||
|
||||
String title;
|
||||
|
||||
TerrainPlot tr;
|
||||
|
||||
|
||||
ForceProfilePlot(String t, int w, int h, int x, int y, int nbr_ctrpoints, boolean terrain) {
|
||||
this.title = t;
|
||||
this.w = w + d;
|
||||
this.h = h + d;
|
||||
this.px = x - d;
|
||||
this.py = y + d;
|
||||
this.max = 512;
|
||||
this.min = -512;
|
||||
noFill();
|
||||
textSize(12);
|
||||
this.s = 800 / nbr_ctrpoints;
|
||||
this.steps = (float)(w + 2*d) / (nbr_ctrpoints - 1);
|
||||
this.by = h / 2;
|
||||
forces = new int[nbr_ctrpoints]; // zeros???
|
||||
forces_pixelvalues = new int[nbr_ctrpoints];
|
||||
if (terrain)
|
||||
tr = new TerrainPlot("Terrain", w, h, x, y + h + 2 * d, nbr_ctrpoints, steps);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
|
||||
pushMatrix();
|
||||
|
||||
translate(px, py);
|
||||
|
||||
stroke(255, 255, 255);
|
||||
line( -d, h, w + d + d, h);
|
||||
line( 0, -d, 0, h + d);
|
||||
line( -d, 0, w + d + d, 0);
|
||||
line( w + d, h + d, w + d, -d);
|
||||
|
||||
fill(255, 255, 255);
|
||||
textSize(10);
|
||||
text(title, d, -d+2);
|
||||
noFill();
|
||||
line(-d, by, w + d, by);
|
||||
text(Integer.toString(this.max), w + d + d + d, 0);
|
||||
text(Integer.toString(this.min), w + d + d + d, h + d);
|
||||
|
||||
float x = 0;
|
||||
for (int i = 0; i < forces_pixelvalues.length; i++) {
|
||||
|
||||
stroke(127, 34, 255);
|
||||
line(x, by, x, by - forces_pixelvalues[i]);
|
||||
|
||||
stroke(255, 34, 127);
|
||||
ellipse(x, by - forces_pixelvalues[i], 5, 5);
|
||||
|
||||
if (i != 0) {
|
||||
stroke(255, 255, 255);
|
||||
line(x, by - forces_pixelvalues[i], x - steps, by - forces_pixelvalues[i - 1]);
|
||||
}
|
||||
|
||||
if(steps > 20)
|
||||
text(Integer.toString(forces[i]), x, by - forces_pixelvalues[i] + (forces[i] < 0 ? 7 : -7));
|
||||
|
||||
x += steps;
|
||||
}
|
||||
|
||||
|
||||
if (mx > 0) {
|
||||
int e = round((float) mx / steps);
|
||||
stroke(255, 34, 127);
|
||||
line(e * steps, by - forces_pixelvalues[e], mx, my);
|
||||
}
|
||||
|
||||
|
||||
popMatrix();
|
||||
|
||||
if (tr != null) tr.draw();
|
||||
}
|
||||
|
||||
void forces_from_pixels() {
|
||||
for (int i = 0; i < forces_pixelvalues.length; i++) {
|
||||
forces[i] = (int)(((by - forces_pixelvalues[i]) / h * 2) * 512);
|
||||
}
|
||||
}
|
||||
|
||||
void pixels_from_forces() {
|
||||
for (int i = 0; i < forces.length; i++) {
|
||||
forces_pixelvalues[i] = (int)(((float) forces[i] / (float)this.max) * h / 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void drag(int mousex, int mousey) {
|
||||
if (hit(mousex, mousey))
|
||||
position_point(mousex, mousey);
|
||||
}
|
||||
|
||||
void click(int mousex, int mousey) {
|
||||
if (hit(mousex, mousey))
|
||||
position_point(mousex, mousey);
|
||||
}
|
||||
|
||||
void release() {
|
||||
mx = -1;
|
||||
my = -1;
|
||||
}
|
||||
|
||||
void position_point(int mousex, int mousey) {
|
||||
int i = round((float) (mousex - px - d) / steps);
|
||||
forces_pixelvalues[i] = h / 2 - (mousey - py - d);
|
||||
forces[i] = (int)((((float)forces_pixelvalues[i]) / h * 2) * 512);
|
||||
|
||||
my = mousey - py - d;
|
||||
mx = mousex - px - d;
|
||||
|
||||
if (tr != null) {
|
||||
tr.data(forces_pixelvalues);
|
||||
/*
|
||||
if (i > 0)
|
||||
tr.data(i - 1, forces_pixelvalues[i - 1], i, forces_pixelvalues[i]);
|
||||
if (i < forces_pixelvalues.length - 1)
|
||||
tr.data(i, forces_pixelvalues[i], i + 1, forces_pixelvalues[i + 1]);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
boolean hit(int mousex, int mousey) {
|
||||
return (mousex < px + w) && (mousex > px) && (mousey > py) && (mousey < py + h);
|
||||
}
|
||||
}
|
||||
|
||||
95
software/apps/Processing/Motor/ForceProfile/TerrainPlot.pde
Normal file
95
software/apps/Processing/Motor/ForceProfile/TerrainPlot.pde
Normal file
@ -0,0 +1,95 @@
|
||||
class TerrainPlot {
|
||||
|
||||
int d = 4;
|
||||
float max, min;
|
||||
int w, h;
|
||||
int px, py;
|
||||
|
||||
float steps_per_index; // this should not exceed step_index;
|
||||
float s, step_index;
|
||||
|
||||
String title;
|
||||
float pixelvalues[];
|
||||
|
||||
TerrainPlot(String t, int w, int h, int x, int y, int nbr_index, float step_index) {
|
||||
this.title = t;
|
||||
this.w = w + d;
|
||||
this.h = h + d;
|
||||
this.px = x - d;
|
||||
this.py = y + d;
|
||||
noFill();
|
||||
textSize(12);
|
||||
this.step_index = step_index;
|
||||
this.steps_per_index = (step_index / 3);
|
||||
this.s = 3;
|
||||
/*
|
||||
|
||||
if(step_index > steps_per_index) {
|
||||
this.s = ((float) step_index / steps_per_index);
|
||||
} else {
|
||||
this.s = step_index;
|
||||
this.steps_per_index = 1;
|
||||
}
|
||||
*/
|
||||
pixelvalues = new float[(int)((nbr_index - 1) * steps_per_index) + 1];
|
||||
}
|
||||
|
||||
void draw() {
|
||||
pushMatrix();
|
||||
|
||||
pushMatrix();
|
||||
|
||||
translate(px, py);
|
||||
|
||||
stroke(255, 255, 255);
|
||||
line( -d, h, w + d + d, h);
|
||||
line( 0, -d, 0, h + d);
|
||||
line( -d, 0, w + d + d, 0);
|
||||
line( w + d, h + d, w + d, -d);
|
||||
|
||||
fill(255, 255, 255);
|
||||
textSize(10);
|
||||
//text(title, d, -d+2);
|
||||
|
||||
popMatrix();
|
||||
|
||||
translate(px, py + h);
|
||||
|
||||
for(int i = 0; i < pixelvalues.length; i++) {
|
||||
float y = pixelvalues[i];
|
||||
if(abs(min) > h) {
|
||||
y = (y / abs(min)) * h;
|
||||
}
|
||||
line(i * s, 0, i * s, y);
|
||||
}
|
||||
|
||||
popMatrix();
|
||||
}
|
||||
|
||||
void data(int[] forces_points) {
|
||||
|
||||
float FF = 0;//forces[0]; // forces interpolated
|
||||
float top = 0; // terrain value (integral of forces)
|
||||
float inc; // interpolated slope ( F[i+1] - F[i] ) / s
|
||||
|
||||
max = 0; min = 0;
|
||||
for(int i = 0; i < forces_points.length - 1; i++) {
|
||||
inc = 0.005 * (forces_points[i+1] - forces_points[i]) ;
|
||||
for(int j = 0; j < steps_per_index; j++) {
|
||||
FF += inc;
|
||||
top = top + FF;
|
||||
pixelvalues[(int)(i * steps_per_index) + j] = top;
|
||||
if(top > max) max = top;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < pixelvalues.length; i++) {
|
||||
pixelvalues[i] = (int)(pixelvalues[i] - max);
|
||||
if(pixelvalues[i] < min) {
|
||||
min = pixelvalues[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
mode.id=processing.mode.java.JavaMode
|
||||
mode=Java
|
||||
@ -0,0 +1,427 @@
|
||||
String[] knobName = { "FREQ1",
|
||||
"SEMI1",
|
||||
"DETUNE1",
|
||||
"GAIN1",
|
||||
"WAVE1",
|
||||
"FM1",
|
||||
"FREQ2",
|
||||
"SEMI2",
|
||||
"DETUNE2",
|
||||
"GAIN2",
|
||||
"WAVE2",
|
||||
"FM2",
|
||||
"FREQ3",
|
||||
"SEMI3",
|
||||
"DETUNE3",
|
||||
"GAIN3",
|
||||
"WAVE3",
|
||||
"FM3",
|
||||
"ATTACK",
|
||||
"DECAY",
|
||||
"SUSTAIN",
|
||||
"RELEASE"
|
||||
};
|
||||
|
||||
String[] controllerName = { "freq1",
|
||||
"semi1",
|
||||
"detune1",
|
||||
"gain1",
|
||||
"wave1",
|
||||
"fm1",
|
||||
"freq2",
|
||||
"semi2",
|
||||
"detune2",
|
||||
"gain2",
|
||||
"wave2",
|
||||
"fm2",
|
||||
"freq3",
|
||||
"semi3",
|
||||
"detune3",
|
||||
"gain3",
|
||||
"wave3",
|
||||
"fm3",
|
||||
"attack",
|
||||
"decay",
|
||||
"sustain",
|
||||
"release"
|
||||
};
|
||||
|
||||
|
||||
|
||||
String[] waveform = { "SINE",
|
||||
"SQUARE",
|
||||
"PULSE",
|
||||
"TRIANGLE",
|
||||
"SAW",
|
||||
"FUZZ",
|
||||
"DIGI1",
|
||||
"DIGI2",
|
||||
"DIGI3",
|
||||
"DIGI4",
|
||||
"NOISE",
|
||||
"DIGI6",
|
||||
"TAN1",
|
||||
"TAN2",
|
||||
"TAN3",
|
||||
"TAN4"
|
||||
};
|
||||
|
||||
Knob freq1,semi1,detune1,gain1,wave1,fm1,freq2,semi2,detune2,gain2,wave2,fm2,freq3,semi3,detune3,gain3,wave3,fm3,attack,decay,sustain,release;
|
||||
Knob[] knobs = {freq1,semi1,detune1,gain1,wave1,fm1,freq2,semi2,detune2,gain2,wave2,fm2,freq3,semi3,detune3,gain3,wave3,fm3,attack,decay,sustain,release};
|
||||
|
||||
int[] knobMin = { 0,-24, 0, 0, 0, 0, 0,-24, 0, 0, 0, 0, 0,-24, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int[] knobMax = {127, 24,127,127, 15,127,127, 24,127,127, 15,127,127, 24,127,127, 15,127,127,127,127,127};
|
||||
int[] knobValue = { 40, 0, 64,127, 2, 0, 40, 7, 64,127, 3, 0, 40,-12, 64,127, 5, 0, 12, 96, 64, 72};
|
||||
int[] knobMidiCC= { 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 25, 30, 31, 32, 33, 34, 35,114,115,116,117};
|
||||
int numKnobs = knobValue.length;
|
||||
|
||||
|
||||
int posX = 20;
|
||||
int posY = 20;
|
||||
int posEnvSpacer = 40;
|
||||
int posW = 65;
|
||||
int posH = 70;
|
||||
int knobS = 40;
|
||||
|
||||
|
||||
void setupKnobs() {
|
||||
|
||||
controlP5 = new ControlP5(this);
|
||||
PFont p = createFont("Georgia",24);
|
||||
controlP5.setControlFont(p,12);
|
||||
controlP5.setColorLabel(color(255,128));
|
||||
/*
|
||||
Textlabel labelFreq = controlP5.addTextlabel("freqLabel","FREQ",posX+posW*0,posY-20);
|
||||
Textlabel labelSemi = controlP5.addTextlabel("semiLabel","SEMI",posX+posW*1,posY-20);
|
||||
Textlabel labelDetune = controlP5.addTextlabel("detuneLabel","DETUNE",posX+posW*2,posY-20);
|
||||
Textlabel labelGain = controlP5.addTextlabel("gainLabel","GAIN",posX+posW*3,posY-20);
|
||||
Textlabel labelWave = controlP5.addTextlabel("waveLabel","WAVE",posX+posW*4,posY-20);
|
||||
|
||||
Textlabel labelAttack = controlP5.addTextlabel("attackLabel","A",posX+16+posW*0,posY+posH*4-20);
|
||||
Textlabel labelDecay = controlP5.addTextlabel("decayLabel","D",posX+16+posW*1,posY+posH*4-20);
|
||||
Textlabel labelsustain = controlP5.addTextlabel("sustainLabel","S",posX+16+posW*2,posY+posH*4-20);
|
||||
Textlabel labelReleasek = controlP5.addTextlabel("releaseLabel","R",posX+16+posW*3,posY+posH*4-20);
|
||||
|
||||
Knob freq1 = controlP5.addKnob("freq1", 0,127,knobValue[0], posX+posW*0,posY+posH*0,knobS);
|
||||
Knob semi1 = controlP5.addKnob("semi1", -24,24,knobValue[1], posX+posW*1,posY+posH*0,knobS);
|
||||
Knob detune1 = controlP5.addKnob("detune1",0,127,knobValue[2], posX+posW*2,posY+posH*0,knobS);
|
||||
Knob gain1 = controlP5.addKnob("gain1", 0,127,knobValue[3], posX+posW*3,posY+posH*0,knobS);
|
||||
Knob wave1 = controlP5.addKnob("wave1", 0,15,knobValue[4], posX+posW*4,posY+posH*0,knobS);
|
||||
*/
|
||||
for(int i=0; i<18; i++) {
|
||||
knobs[i] = controlP5.addKnob(controllerName[i])
|
||||
.setRange(knobMin[i],knobMax[i])
|
||||
.setValue(knobValue[i])
|
||||
.setPosition(posX+posW*(i%6),posY+posH*int(i/6))
|
||||
.setRadius(knobS/2)
|
||||
.setDragDirection(Knob.VERTICAL)
|
||||
.setViewStyle(Knob.ELLIPSE)
|
||||
.setNumberOfTickMarks(knobMax[i]-knobMin[i])
|
||||
.snapToTickMarks(true)
|
||||
.showTickMarks(false);
|
||||
/*
|
||||
if(i%6==1) {
|
||||
knobs[i].setNumberOfTickMarks(49)
|
||||
.snapToTickMarks(true)
|
||||
.showTickMarks(false);
|
||||
}
|
||||
if(i%6==4) {
|
||||
knobs[i].setNumberOfTickMarks(16)
|
||||
.snapToTickMarks(true)
|
||||
.showTickMarks(false);
|
||||
}
|
||||
*/
|
||||
}
|
||||
for(int i=18; i<22; i++) {
|
||||
knobs[i] = controlP5.addKnob(controllerName[i])
|
||||
.setRange(knobMin[i],knobMax[i])
|
||||
.setValue(knobValue[i])
|
||||
.setPosition(posX+posW*(i%6),posY+posEnvSpacer+posH*int(i/6))
|
||||
.setRadius(knobS/2)
|
||||
.setDragDirection(Knob.VERTICAL)
|
||||
.setViewStyle(Knob.ELLIPSE);
|
||||
|
||||
}
|
||||
/*
|
||||
Knob freq2 = controlP5.addKnob("freq2", 0,127,knobValue[5], posX+posW*0,posY+posH*1,knobS);
|
||||
Knob semi2 = controlP5.addKnob("semi2", -24,24,knobValue[6], posX+posW*1,posY+posH*1,knobS);
|
||||
Knob detune2 = controlP5.addKnob("detune2",0,127,knobValue[7], posX+posW*2,posY+posH*1,knobS);
|
||||
Knob gain2 = controlP5.addKnob("gain2", 0,127,knobValue[8], posX+posW*3,posY+posH*1,knobS);
|
||||
Knob wave2 = controlP5.addKnob("wave2", 0,15,knobValue[9], posX+posW*4,posY+posH*1,knobS);
|
||||
|
||||
Knob freq3 = controlP5.addKnob("freq3", 0,127,knobValue[10], posX+posW*0,posY+posH*2,knobS);
|
||||
Knob semi3 = controlP5.addKnob("semi3", -24,24,knobValue[11], posX+posW*1,posY+posH*2,knobS);
|
||||
Knob detune3 = controlP5.addKnob("detune3",0,127,knobValue[12], posX+posW*2,posY+posH*2,knobS);
|
||||
Knob gain3 = controlP5.addKnob("gain3", 0,127,knobValue[13], posX+posW*3,posY+posH*2,knobS);
|
||||
Knob wave3 = controlP5.addKnob("wave3", 0,15,knobValue[14], posX+posW*4,posY+posH*2,knobS);
|
||||
|
||||
Knob attack = controlP5.addKnob("attack", 0,127,knobValue[15], posX+posW*0, posY+posH*4, knobS);
|
||||
Knob decay = controlP5.addKnob("decay", 0,127,knobValue[16], posX+posW*1, posY+posH*4, knobS);
|
||||
Knob sustain = controlP5.addKnob("sustain",0,127,knobValue[17], posX+posW*2, posY+posH*4, knobS);
|
||||
Knob release = controlP5.addKnob("release",0,127,knobValue[18], posX+posW*3, posY+posH*4, knobS);
|
||||
*/
|
||||
}
|
||||
|
||||
void writeKnobValues() {
|
||||
textAlign(CENTER);
|
||||
fill(255);
|
||||
text("FREQ",40,30);
|
||||
text("SEMI",100,30);
|
||||
text("DETUNE",160,30);
|
||||
text("GAIN",220,30);
|
||||
text("WAVE",280,30);
|
||||
|
||||
text("A",40,270);
|
||||
text("D",100,270);
|
||||
text("S",160,270);
|
||||
text("R",220,270);
|
||||
|
||||
|
||||
fill(128);
|
||||
text(knobValue[0],40,90);
|
||||
text(knobValue[1],100,90);
|
||||
text(knobValue[2],160,90);
|
||||
text(knobValue[3],220,90);
|
||||
text(waveform[knobValue[4]],280,90);
|
||||
text(knobValue[5],40,150);
|
||||
text(knobValue[6],100,150);
|
||||
text(knobValue[7],160,150);
|
||||
text(knobValue[8],220,150);
|
||||
text(waveform[knobValue[9]],280,150);
|
||||
text(knobValue[10],40,210);
|
||||
text(knobValue[11],100,210);
|
||||
text(knobValue[12],160,210);
|
||||
text(knobValue[13],220,210);
|
||||
text(waveform[knobValue[14]],280,210);
|
||||
text(knobValue[15],40,330);
|
||||
text(knobValue[16],100,330);
|
||||
text(knobValue[17],160,330);
|
||||
text(knobValue[18],220,330);
|
||||
}
|
||||
|
||||
void freq1(int val)
|
||||
{
|
||||
int knob = 0;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + (int)(pow(2,(knobValue[knob]-69)/12.0)*440) + " Hz");
|
||||
//(2^((p-69)/12))*440
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void semi1(int val)
|
||||
{
|
||||
int knob = 1;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
int semi =(knobValue[knob]+24)*2+16;
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)semi);
|
||||
}
|
||||
}
|
||||
|
||||
void detune1(int val)
|
||||
{
|
||||
int knob = 2;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + map(knobValue[knob],0,127,-100,100)*0.0005946);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void gain1(int val)
|
||||
{
|
||||
int knob = 3;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]/127.0);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void wave1(int val)
|
||||
{
|
||||
int knob = 4;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob] + " (" + waveform[knobValue[knob]] + ")");
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)(knobValue[knob]*8));
|
||||
}
|
||||
}
|
||||
|
||||
void fm1(int val)
|
||||
{
|
||||
int knob = 5;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void freq2(int val)
|
||||
{
|
||||
int knob = 6;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + (int)(pow(2,(knobValue[knob]-69)/12.0)*440) + " Hz");
|
||||
//(2^((p-69)/12))*440
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void semi2(int val)
|
||||
{
|
||||
int knob = 7;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
int semi =(knobValue[knob]+24)*2+16;
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)semi);
|
||||
}
|
||||
}
|
||||
|
||||
void detune2(int val)
|
||||
{
|
||||
int knob = 8;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + map(knobValue[knob],0,127,-100,100)*0.0005946);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void gain2(int val)
|
||||
{
|
||||
int knob = 9;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]/127.0);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void wave2(int val)
|
||||
{
|
||||
int knob = 10;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob] + " (" + waveform[knobValue[knob]] + ")");
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)(knobValue[knob]*8));
|
||||
}
|
||||
}
|
||||
|
||||
void fm2(int val)
|
||||
{
|
||||
int knob = 11;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void freq3(int val)
|
||||
{
|
||||
int knob = 12;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + (int)(pow(2,(knobValue[knob]-69)/12.0)*440) + " Hz");
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void semi3(int val)
|
||||
{
|
||||
int knob = 13;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
int semi =(knobValue[knob]+24)*2+16;
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)semi);
|
||||
}
|
||||
}
|
||||
|
||||
void detune3(int val)
|
||||
{
|
||||
int knob = 14;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + map(knobValue[knob],0,127,-100,100)*0.0005946);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void gain3(int val)
|
||||
{
|
||||
int knob = 15;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]/127.0);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void wave3(int val)
|
||||
{
|
||||
int knob = 16;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob] + " (" + waveform[knobValue[knob]] + ")");
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)(knobValue[knob]*8));
|
||||
}
|
||||
}
|
||||
|
||||
void fm3(int val)
|
||||
{
|
||||
int knob = 17;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void attack(int val)
|
||||
{
|
||||
int knob = 18;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void decay(int val)
|
||||
{
|
||||
int knob = 19;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void sustain(int val)
|
||||
{
|
||||
int knob = 20;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
void release(int val)
|
||||
{
|
||||
int knob = 21;
|
||||
if(knobValue[knob] != val) {
|
||||
knobValue[knob] = val;
|
||||
if(printChange) println(knobName[knob] + " is: " + knobValue[knob]);
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[knob], (byte)knobValue[knob]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,63 @@
|
||||
//import oscP5.*;
|
||||
//import netP5.*;
|
||||
import controlP5.*;
|
||||
import rwmidi.*; // watch out for this
|
||||
import processing.serial.*;
|
||||
|
||||
ControlP5 controlP5;
|
||||
MidiInput input;
|
||||
Serial port0;
|
||||
|
||||
boolean printChange = true;
|
||||
boolean serialBusy = false;
|
||||
|
||||
int backgroundColor = color(0,0,0);
|
||||
int knobColor = color(235,103,295);
|
||||
|
||||
long time = 0;
|
||||
long lastTime = 0;
|
||||
long timePassed;
|
||||
long timeAllowed = 10;
|
||||
|
||||
int delayTime = 40;
|
||||
|
||||
void setup() {
|
||||
|
||||
size(400,400);
|
||||
smooth();
|
||||
background(0);
|
||||
|
||||
setupKnobs();
|
||||
|
||||
//println("print MIDI input devices:");
|
||||
//println(RWMidi.getInputDeviceNames());
|
||||
input = RWMidi.getInputDevices()[0].createInput(this);
|
||||
|
||||
println(Serial.list());
|
||||
port0 = new Serial(this, Serial.list()[0], 9600);
|
||||
}
|
||||
|
||||
|
||||
void draw() {
|
||||
background(backgroundColor);
|
||||
//writeKnobValues();
|
||||
}
|
||||
|
||||
|
||||
void keyPressed() {
|
||||
if(key=='s' || key=='S') {
|
||||
saveKnobValues();
|
||||
}
|
||||
if(key=='l' || key=='L') {
|
||||
loadKnobValues();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void keyReleased() {
|
||||
if(key=='l' || key=='L') {
|
||||
sendMidiKnobs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
software/apps/Processing/Music/Music_Controls_4/knobValues.txt
Normal file
BIN
software/apps/Processing/Music/Music_Controls_4/knobValues.txt
Normal file
Binary file not shown.
70
software/apps/Processing/Music/Music_Controls_4/midi_handling.pde
Executable file
70
software/apps/Processing/Music/Music_Controls_4/midi_handling.pde
Executable file
@ -0,0 +1,70 @@
|
||||
void noteOnReceived(Note note) {
|
||||
|
||||
byte channel = byte(note.getChannel());
|
||||
byte pitch = byte(note.getPitch());
|
||||
byte velocity = byte(note.getVelocity());
|
||||
|
||||
sendNoteOn(channel, pitch, velocity);
|
||||
|
||||
}
|
||||
|
||||
void noteOffReceived(Note note) {
|
||||
|
||||
byte channel = byte(note.getChannel());
|
||||
byte pitch = byte(note.getPitch());
|
||||
byte velocity = byte(note.getVelocity());
|
||||
|
||||
sendNoteOff(channel, pitch, velocity);
|
||||
|
||||
}
|
||||
|
||||
void controllerChangeReceived(rwmidi.Controller controller) {
|
||||
|
||||
byte channel = byte(controller.getChannel());
|
||||
byte CC = byte(controller.getCC());
|
||||
byte value = byte(controller.getValue());
|
||||
|
||||
sendControlChange(channel, CC, value);
|
||||
}
|
||||
|
||||
|
||||
void sendNoteOn(byte channel, byte pitch, byte velocity) {
|
||||
|
||||
byte noteOn = byte(0x90 | channel);
|
||||
|
||||
serialBusy = true;
|
||||
port0.write(noteOn);
|
||||
port0.write(pitch);
|
||||
port0.write(velocity);
|
||||
//println('\n' + hex(noteOn) + " " + hex(pitch) + " " + hex(velocity));
|
||||
serialBusy = false;
|
||||
}
|
||||
|
||||
void sendNoteOff(byte channel, byte pitch, byte velocity) {
|
||||
|
||||
byte noteOff = byte(0x80 | channel);
|
||||
|
||||
serialBusy = true;
|
||||
port0.write(noteOff);
|
||||
port0.write(pitch);
|
||||
port0.write(velocity);
|
||||
//println('\n' + hex(noteOff) + " " + hex(pitch) + " " + hex(velocity));
|
||||
serialBusy = false;
|
||||
}
|
||||
|
||||
void sendControlChange(byte channel, byte CC, byte value) {
|
||||
time = millis();
|
||||
timePassed = time - lastTime;
|
||||
if(timePassed > timeAllowed) {
|
||||
lastTime = time;
|
||||
|
||||
byte controlChange = byte(0xB0 | channel);
|
||||
|
||||
serialBusy = true;
|
||||
port0.write(controlChange);
|
||||
port0.write(CC);
|
||||
port0.write(value);
|
||||
serialBusy = false;
|
||||
//println('\n' + hex(controlChange) + " " + hex(CC) + " " + hex(value));
|
||||
}
|
||||
}
|
||||
124
software/apps/Processing/Music/Music_Controls_4/saving_loading.pde
Executable file
124
software/apps/Processing/Music/Music_Controls_4/saving_loading.pde
Executable file
@ -0,0 +1,124 @@
|
||||
byte[] savedKnobValues = new byte[numKnobs];
|
||||
byte[] loadedKnobValues = new byte[numKnobs];
|
||||
|
||||
|
||||
void loadKnobValues() {
|
||||
|
||||
loadedKnobValues = loadBytes("knobValues.txt");
|
||||
|
||||
for(int i=0; i<numKnobs; i++) {
|
||||
knobValue[i] = loadedKnobValues[i];
|
||||
controlP5.controller(controllerName[i]).setValue(knobValue[i]);
|
||||
}
|
||||
println();
|
||||
println("Loaded Knob Values");
|
||||
|
||||
}
|
||||
|
||||
void saveKnobValues() {
|
||||
|
||||
for(int i=0;i<numKnobs;i++) {
|
||||
savedKnobValues[i] = (byte)knobValue[i];
|
||||
}
|
||||
saveBytes("knobValues.txt", savedKnobValues);
|
||||
println();
|
||||
println("Saved Knob Values");
|
||||
|
||||
}
|
||||
|
||||
void sendMidiKnobs() {
|
||||
|
||||
sendControlChange((byte)0, (byte)knobMidiCC[0],(byte)knobValue[0]);
|
||||
delay(delayTime);
|
||||
//semi1(knobValue[1]);
|
||||
int semi =(knobValue[1]+24)*2+16;
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[1], (byte)semi);
|
||||
|
||||
delay(delayTime);
|
||||
//detune1(knobValue[2]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[2], (byte)knobValue[2]);
|
||||
|
||||
delay(delayTime);
|
||||
//gain1(knobValue[3]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[3], (byte)knobValue[3]);
|
||||
|
||||
delay(delayTime);
|
||||
//wave1(knobValue[4]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[4], (byte)(knobValue[4]*8));
|
||||
|
||||
delay(delayTime);
|
||||
//fm1(knobValue[5]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[5], (byte)knobValue[5]);
|
||||
|
||||
delay(delayTime);
|
||||
//freq2(knobValue[6]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[6], (byte)knobValue[6]);
|
||||
|
||||
delay(delayTime);
|
||||
//semi2(knobValue[7]);
|
||||
semi = (knobValue[7]+24)*2+16;
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[7], (byte)semi);
|
||||
|
||||
delay(delayTime);
|
||||
//detune2(knobValue[8]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[8], (byte)knobValue[8]);
|
||||
|
||||
delay(delayTime);
|
||||
//gain2(knobValue[7]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[9], (byte)knobValue[9]);
|
||||
|
||||
delay(delayTime);
|
||||
//wave2(knobValue[10]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[10], (byte)(knobValue[10]*8));
|
||||
|
||||
delay(delayTime);
|
||||
//fm2(knobValue[11]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[11], (byte)knobValue[11]);
|
||||
|
||||
delay(delayTime);
|
||||
//freq3(knobValue[12]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[12], (byte)knobValue[12]);
|
||||
|
||||
delay(delayTime);
|
||||
//semi3(knobValue[13]);
|
||||
semi =(knobValue[13]+24)*2+16;
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[13], (byte)semi);
|
||||
|
||||
delay(delayTime);
|
||||
//detune3(knobValue[14]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[14], (byte)knobValue[14]);
|
||||
|
||||
delay(delayTime);
|
||||
//gain3(knobValue[15]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[15], (byte)knobValue[15]);
|
||||
|
||||
delay(delayTime);
|
||||
//wave3(knobValue[16]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[16], (byte)(knobValue[16]*8));
|
||||
|
||||
delay(delayTime);
|
||||
//fm3(knobValue[17]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[17], (byte)knobValue[17]);
|
||||
|
||||
delay(delayTime);
|
||||
//attack(knobValue[18]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[18], (byte)knobValue[18]);
|
||||
|
||||
delay(delayTime);
|
||||
//decay(knobValue[19]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[19], (byte)knobValue[19]);
|
||||
|
||||
delay(delayTime);
|
||||
//sustain(knobValue[20]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[20], (byte)knobValue[20]);
|
||||
|
||||
delay(delayTime);
|
||||
//release(knobValue[21]);
|
||||
if(!serialBusy) sendControlChange((byte)0, (byte)knobMidiCC[21], (byte)knobValue[21]);
|
||||
|
||||
println();
|
||||
println("Sent Knob Values over MIDI");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,248 +0,0 @@
|
||||
/*
|
||||
Midi.cpp - Music library
|
||||
Copyright (c) 2012 Copenhagen Institute of Interaction Design.
|
||||
All right reserved.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ author: Jakob Bak
|
||||
+ contact: j.bak@ciid.dk
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <hardwareSerial.h>
|
||||
//#include <MidiTables.h>
|
||||
#include <Music.h>
|
||||
#include <Midi.h>
|
||||
|
||||
prog_uint16_t hertzTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543};
|
||||
|
||||
MMidi Midi;
|
||||
|
||||
bool midiRead = false;
|
||||
|
||||
|
||||
void MMidi::init()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
midiBufferIndex = 0;
|
||||
midiChannel = 0;
|
||||
|
||||
}
|
||||
|
||||
void MMidi::checkMidi()
|
||||
{
|
||||
while(Serial.available() > 0) {
|
||||
|
||||
data = Serial.read();
|
||||
|
||||
if(data & 0x80 && (data & 0x0F) == midiChannel) { // bitmask with 10000000 to see if byte is over 127 (data&0x80)
|
||||
midiBufferIndex = 0; // and check if the midi channel corresponds to the midiChannel
|
||||
midiRead = true; // the device is set to listen to.
|
||||
} else if(data & 0x80) { // Else if the byte is over 127 (but not on the device's
|
||||
midiRead = false; // midiChannel, don't read this or any following bytes.
|
||||
}
|
||||
|
||||
if(midiRead) {
|
||||
midiBuffer[midiBufferIndex] = data;
|
||||
midiBufferIndex++;
|
||||
if (midiBufferIndex > 2) {
|
||||
midiHandler();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MMidi::midiHandler() {
|
||||
|
||||
uint8_t midiChannel = (midiBuffer[0] & 0x0F);
|
||||
|
||||
|
||||
switch(midiBuffer[0] & 0xF0) { // bit mask with &0xF0 ?
|
||||
case 0x80:
|
||||
noteOff (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F, // note value 0-127
|
||||
midiBuffer[2] & 0x7F); // note velocity 0-127
|
||||
break;
|
||||
|
||||
case 0x90:
|
||||
noteOn (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F, // note value 0-127
|
||||
midiBuffer[2] & 0x7F); // note velocity 0-127
|
||||
break;
|
||||
|
||||
case 0xA0:
|
||||
aftertouch (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F, // note value 0-127
|
||||
midiBuffer[2] & 0x7F);// note velocity 0-127
|
||||
break;
|
||||
|
||||
case 0xB0:
|
||||
controller (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F, // controller number 0-127
|
||||
midiBuffer[2] & 0x7F);// controller value 0-127
|
||||
break;
|
||||
|
||||
case 0xC0:
|
||||
programChange (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F); // program number 0-127
|
||||
break;
|
||||
|
||||
case 0xD0:
|
||||
channelPressure (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F); // pressure amount 0-127
|
||||
break;
|
||||
|
||||
case 0xE0:
|
||||
pitchWheel (midiBuffer[0] & 0x0F, // midi channel 0-16
|
||||
midiBuffer[1] & 0x7F, // higher bits 0-6
|
||||
midiBuffer[2] & 0x7F);// lower bits 7-13
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MMidi::noteOff(uint8_t channel, uint8_t note, uint8_t vel) {
|
||||
|
||||
if(notePlayed == note) {
|
||||
Music.setEnvStage(4);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MMidi::noteOn(uint8_t channel, uint8_t note, uint8_t vel) {
|
||||
|
||||
Music.setEnvStage(1);
|
||||
Music.setVelSustain(vel);
|
||||
Music.setVelPeak(vel);
|
||||
notePlayed = note;
|
||||
memcpy_P(&frequency, &hertzTable[notePlayed],2);
|
||||
Music.setFrequency1(frequency);
|
||||
Music.setFrequency2(frequency);
|
||||
Music.setFrequency3(frequency);
|
||||
}
|
||||
|
||||
|
||||
void MMidi::aftertouch(uint8_t channel, uint8_t note, uint8_t pressure) {
|
||||
// Write code here for Aftertouch
|
||||
}
|
||||
|
||||
|
||||
void MMidi::controller(uint8_t channel, uint8_t number, uint8_t value) {
|
||||
|
||||
switch(number) {
|
||||
case DETUNE:
|
||||
Music.setDetune(value/5120.0);
|
||||
break;
|
||||
case PORTAMENTO:
|
||||
//Music.setPortamento(value); // function to be defined, also argument
|
||||
break;
|
||||
case DETUNE1:
|
||||
Music.setDetune1(value/5120.0);
|
||||
break;
|
||||
case DETUNE2:
|
||||
Music.setDetune2(value/5120.0);
|
||||
break;
|
||||
case DETUNE3:
|
||||
Music.setDetune3(value/5120.0);
|
||||
break;
|
||||
case SEMITONE1:
|
||||
if(15 < value && value < 113) {
|
||||
int8_t val = (((value-16)/2)-24);
|
||||
Music.setSemitone1(val);
|
||||
} else if (value < 16) {
|
||||
Music.setSemitone1(-24);
|
||||
} else {
|
||||
Music.setSemitone1(24);
|
||||
}
|
||||
break;
|
||||
case SEMITONE2:
|
||||
if(15 < value && value < 113) {
|
||||
int8_t val = (((value-16)/2)-24);
|
||||
Music.setSemitone2(val);
|
||||
} else if (value < 16) {
|
||||
Music.setSemitone2(-24);
|
||||
} else {
|
||||
Music.setSemitone2(24);
|
||||
}
|
||||
break;
|
||||
case SEMITONE3:
|
||||
if(15 < value && value < 113) {
|
||||
int8_t val = (((value-16)/2)-24);
|
||||
Music.setSemitone3(val);
|
||||
} else if (value < 16) {
|
||||
Music.setSemitone3(-24);
|
||||
} else {
|
||||
Music.setSemitone3(24);
|
||||
}
|
||||
break;
|
||||
case GAIN1:
|
||||
Music.setGain1(uint16_t(value * 512));
|
||||
break;
|
||||
case GAIN2:
|
||||
Music.setGain2(uint16_t(value * 512));
|
||||
break;
|
||||
case GAIN3:
|
||||
Music.setGain3(uint16_t(value * 512));
|
||||
break;
|
||||
case WAVEFORM:
|
||||
Music.setWaveform(value / 8);
|
||||
break;
|
||||
case WAVEFORM1:
|
||||
Music.setWaveform1(value / 8);
|
||||
break;
|
||||
case WAVEFORM2:
|
||||
Music.setWaveform2(value / 8);
|
||||
break;
|
||||
case WAVEFORM3:
|
||||
Music.setWaveform3(value / 8);
|
||||
break;
|
||||
case ENV_ATTACK:
|
||||
Music.setAttack(value);
|
||||
break;
|
||||
case ENV_DECAY:
|
||||
Music.setDecay(value);
|
||||
break;
|
||||
case ENV_SUSTAIN:
|
||||
Music.setSustain(value);
|
||||
break;
|
||||
case ENV_RELEASE:
|
||||
Music.setRelease(value);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MMidi::programChange(uint8_t channel, uint8_t number) {
|
||||
// Write code here for Program Change
|
||||
}
|
||||
|
||||
|
||||
void MMidi::channelPressure(uint8_t channel, uint8_t pressure) {
|
||||
// Write code here for Channel Pressure
|
||||
}
|
||||
|
||||
|
||||
void MMidi::pitchWheel(uint8_t channel, uint8_t highBits, uint8_t lowBits) {
|
||||
// Write code here for Pitch Wheel
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
/*
|
||||
Midi.h - Music library
|
||||
Copyright (c) 2012 Copenhagen Institute of Interaction Design.
|
||||
All right reserved.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ author: Jakob Bak
|
||||
+ contact: j.bak@ciid.dk
|
||||
*/
|
||||
|
||||
// MIDI specific constants
|
||||
|
||||
#ifndef MIDI_CHANNEL
|
||||
#define MIDI_CHANNEL 1
|
||||
#endif
|
||||
|
||||
// SYSEX constants
|
||||
#define SYSEX_LIMIT 16
|
||||
#define CFO_MANUFACTURER_ID 44
|
||||
#define CFO_DEVICE_GROUP_ID 3
|
||||
#define SET_CHANNEL 0
|
||||
|
||||
|
||||
//synth parameters as MIDI controller numbers
|
||||
#define DETUNE 4
|
||||
#define WAVEFORM 5
|
||||
#define PORTAMENTO 6
|
||||
|
||||
#define FREQUENCY1 10
|
||||
#define SEMITONE1 11
|
||||
#define DETUNE1 12
|
||||
#define GAIN1 13
|
||||
#define WAVEFORM1 14
|
||||
|
||||
#define FREQUENCY2 20
|
||||
#define SEMITONE2 21
|
||||
#define DETUNE2 22
|
||||
#define GAIN2 23
|
||||
#define WAVEFORM2 24
|
||||
|
||||
#define FREQUENCY3 30
|
||||
#define SEMITONE3 31
|
||||
#define DETUNE3 32
|
||||
#define GAIN3 33
|
||||
#define WAVEFORM3 34
|
||||
|
||||
#define ENV_ATTACK 114
|
||||
#define ENV_DECAY 115
|
||||
#define ENV_SUSTAIN 116
|
||||
#define ENV_RELEASE 117
|
||||
|
||||
#define ENV2_ATTACK 124
|
||||
#define ENV2_DECAY 125
|
||||
#define ENV2_SUSTAIN 126
|
||||
#define ENV2_RELEASE 127
|
||||
|
||||
|
||||
// Synth parameters used in MIDI code
|
||||
#define ENV_MAX_GAIN (65536 * 4 - 1)
|
||||
|
||||
|
||||
class MMidi {
|
||||
public:
|
||||
void init();
|
||||
void checkMidi();
|
||||
|
||||
void midiHandler();
|
||||
void noteOff(uint8_t channel, uint8_t note, uint8_t vel);
|
||||
void noteOn(uint8_t channel, uint8_t note, uint8_t vel);
|
||||
void aftertouch(uint8_t channel, uint8_t note, uint8_t pressure);
|
||||
void controller(uint8_t channel, uint8_t number, uint8_t value);
|
||||
void programChange(uint8_t channel, uint8_t number);
|
||||
void channelPressure(uint8_t channel, uint8_t pressure);
|
||||
void pitchWheel(uint8_t channel, uint8_t highBits, uint8_t lowBits);
|
||||
|
||||
private:
|
||||
|
||||
// MIDI
|
||||
uint8_t data;
|
||||
uint8_t midiBuffer[SYSEX_LIMIT];
|
||||
uint8_t midiChannel;
|
||||
|
||||
int midiBufferIndex;
|
||||
uint16_t frequency;
|
||||
uint8_t notePlayed;
|
||||
};
|
||||
|
||||
extern MMidi Midi;
|
||||
@ -23,117 +23,50 @@
|
||||
|
||||
#include "Motion.h"
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define PB0 PORTB0
|
||||
|
||||
bool motion_reg_init = false;
|
||||
//bool motion_reg_init = false;
|
||||
|
||||
Motion MotionA(MOTIONA);
|
||||
Motion MotionB(MOTIONA);
|
||||
|
||||
uint8_t lb;
|
||||
uint8_t hb;
|
||||
int x, xx;
|
||||
float T = N * 0.004f; // 4ms (see TCNT1)
|
||||
float v;
|
||||
|
||||
float MAX_POS = 1023;
|
||||
float MAX_VEL = MAX_POS / T;
|
||||
float MAX_ACC = MAX_VEL / T;
|
||||
Motion MotionB(MOTIONB);
|
||||
|
||||
int MAX_POS = 1023;
|
||||
|
||||
Motion::Motion(MOTION m){
|
||||
_m = m;
|
||||
_i = false;
|
||||
_fcb = NULL;
|
||||
};
|
||||
}
|
||||
|
||||
void Motion::init(INPUT sensor)
|
||||
void Motion::init(SENSOR_INPUT sensor)
|
||||
{
|
||||
if(!motion_reg_init){
|
||||
TCNT1 = 1000; //4 ms (TCNT1)
|
||||
TIMSK1 = (1 << TOIE1);
|
||||
motion_reg_init = true;
|
||||
}
|
||||
_i = true;
|
||||
_s = sensor;
|
||||
}
|
||||
|
||||
int Motion::getPosition() {
|
||||
return _x;
|
||||
}
|
||||
|
||||
float Motion::getVelocity() {
|
||||
return _v;
|
||||
}
|
||||
|
||||
float Motion::getAcceleration() {
|
||||
return _a;
|
||||
}
|
||||
|
||||
void Motion::set_force_callback(force_callback fcb, PHY physics) {
|
||||
_fcb = fcb;
|
||||
_fcb_phy = physics;
|
||||
}
|
||||
|
||||
|
||||
// clocked at 4ms period
|
||||
ISR(TIMER1_OVF_vect) {
|
||||
TCNT1 = 1000;
|
||||
|
||||
|
||||
|
||||
if(MotionA._i) {
|
||||
ADMUX = MotionA._s & 0x07;
|
||||
ADCSRA |= (1 << ADSC);
|
||||
while (ADCSRA & (1 << ADSC));
|
||||
lb = ADCL;
|
||||
hb = ADCH;
|
||||
x = (hb << 8) | lb;
|
||||
MotionA._xv[MotionA._ix] = x;
|
||||
MotionA._ix++;
|
||||
MotionA._ix %= N;
|
||||
|
||||
xx = x - MotionA._x;
|
||||
if(abs(xx) < 2) {
|
||||
v = 0.0f;
|
||||
} else {
|
||||
v = xx / T;
|
||||
}
|
||||
|
||||
MotionA._a = (v - MotionA._v) / T;
|
||||
MotionA._v = v;
|
||||
MotionA._x = x;
|
||||
|
||||
}
|
||||
|
||||
if(MotionB._i) {
|
||||
ADMUX = MotionB._s & 0x07;
|
||||
ADCSRA |= (1 << ADSC);
|
||||
while (ADCSRA & (1 << ADSC));
|
||||
lb = ADCL;
|
||||
hb = ADCH;
|
||||
x = (hb << 8) | lb;
|
||||
MotionB._xv[MotionB._ix] = x;
|
||||
MotionB._ix++;
|
||||
MotionB._ix %= N;
|
||||
|
||||
|
||||
xx = x - MotionB._x;
|
||||
if(abs(xx) < 2) {
|
||||
v = 0;
|
||||
} else {
|
||||
v = xx / T;
|
||||
}
|
||||
|
||||
MotionB._a = (v - MotionB._v) / T;
|
||||
MotionB._v = v;
|
||||
MotionB._x = x;
|
||||
|
||||
}
|
||||
_s = sensor;
|
||||
|
||||
tick = millis();
|
||||
}
|
||||
|
||||
void Motion::update_position() {
|
||||
Xin = analogRead(_s); // may take some time
|
||||
}
|
||||
|
||||
void Motion::update_mass_spring_damper() {
|
||||
|
||||
// todo: filtering
|
||||
|
||||
long t = millis();
|
||||
float dt = (float)(t - tick) / 100.0f;
|
||||
|
||||
int xin = analogRead(_s); // may take some time, put: 512 - analogRead(_s);
|
||||
|
||||
Xin = xin;
|
||||
F = k * (xin - X) - (d * V);
|
||||
V += (F / m) * dt;
|
||||
X += V * dt;
|
||||
|
||||
tick = t;
|
||||
}
|
||||
|
||||
@ -32,7 +32,7 @@ enum MOTION {
|
||||
MOTIONB = 1
|
||||
};
|
||||
|
||||
enum INPUT {
|
||||
enum SENSOR_INPUT {
|
||||
INPUTA0 = 0x0000,
|
||||
INPUTA1 = 0x0001,
|
||||
INPUTA2 = 0x0010,
|
||||
@ -43,41 +43,32 @@ enum INPUT {
|
||||
INPUTA7 = 0x0111
|
||||
};
|
||||
|
||||
enum PHY {
|
||||
POSITION = 0,
|
||||
VELOCITY = 1,
|
||||
ACCELERATION = 2
|
||||
};
|
||||
|
||||
|
||||
class Motion {
|
||||
|
||||
public:
|
||||
Motion(MOTION m);
|
||||
|
||||
void init(INPUT sensor);
|
||||
|
||||
int getPosition();
|
||||
float getVelocity();
|
||||
float getAcceleration();
|
||||
|
||||
void set_force_callback(force_callback fcb, PHY physics);
|
||||
|
||||
void init(SENSOR_INPUT sensor);
|
||||
|
||||
void update_position();
|
||||
void update_mass_spring_damper();
|
||||
|
||||
// raw position vector
|
||||
int _xv[N];
|
||||
int _ix;
|
||||
|
||||
int _x;
|
||||
float _v;
|
||||
float _a;
|
||||
float X, V, F;
|
||||
float m, k, d;
|
||||
int Xin;
|
||||
|
||||
long tick;
|
||||
|
||||
MOTION _m;
|
||||
INPUT _s;
|
||||
SENSOR_INPUT _s;
|
||||
bool _i;
|
||||
|
||||
force_callback _fcb;
|
||||
PHY _fcb_phy;
|
||||
force_callback _fcb; // not used in current version
|
||||
};
|
||||
|
||||
extern Motion MotionA;
|
||||
|
||||
43
software/lib/MMM/Motor.cpp
Normal file → Executable file
43
software/lib/MMM/Motor.cpp
Normal file → Executable file
@ -23,6 +23,8 @@
|
||||
|
||||
#include "Motor.h"
|
||||
#include <avr/io.h>
|
||||
#include <stdlib.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#define RESOLUTION 65536
|
||||
|
||||
@ -45,29 +47,48 @@ void MMotor::init()
|
||||
{
|
||||
|
||||
if(!reg_init){
|
||||
|
||||
|
||||
//cli();
|
||||
//direction pins are outputs
|
||||
DDRD |= (1 << PD7);
|
||||
DDRB |= (1 << PB0);
|
||||
DDRD |= (1 << PD7);
|
||||
DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2);
|
||||
|
||||
DDRB |= (1 << PB1) | (1 << PB2);
|
||||
TCCR1A = (1 << COM1A1) | (1 << COM1B1);
|
||||
//TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM10);
|
||||
|
||||
// clear the bits
|
||||
TCCR1B &= ~((1 << CS10) | (1 << CS11) | (1 << CS12));
|
||||
//TCCR1B &= ~((1 << CS10) | (1 << CS11) | (1 << CS12));
|
||||
|
||||
TCCR1B = (1 << WGM13) | (1 << CS10);
|
||||
|
||||
ICR1 = 512;
|
||||
ICR1 = 512;
|
||||
//OCR1A = 512;
|
||||
|
||||
reg_init = true;
|
||||
//sei();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MMotor::torque(int value)
|
||||
{
|
||||
if(_m == MOTORA) OCR1A = value;
|
||||
else if(_m == MOTORB) OCR1B = value;
|
||||
{
|
||||
if(value < 0) {
|
||||
_d = BACKWARD;
|
||||
} else {
|
||||
_d = FORWARD;
|
||||
}
|
||||
value = abs(value);
|
||||
if(value > 512) value = 512;
|
||||
//else value = abs(512);
|
||||
if(_m == MOTORA) {
|
||||
OCR1A = value;
|
||||
direction(_d);
|
||||
}
|
||||
else if(_m == MOTORB) {
|
||||
OCR1B = value;
|
||||
direction(_d);
|
||||
}
|
||||
_t = value;
|
||||
}
|
||||
|
||||
@ -81,8 +102,8 @@ void MMotor::direction(DIRECTION d)
|
||||
_d = d;
|
||||
if(_m == MOTORA && _d == FORWARD) PORTD |= (1 << PD7);
|
||||
else if(_m == MOTORA && _d == BACKWARD) PORTD &= ~(1 << PD7);
|
||||
else if(_m == MOTORB && _d == BACKWARD) PORTB |= (1 << PB0);
|
||||
else if(_m == MOTORB && _d == FORWARD) PORTB &= ~(1 << PB0);
|
||||
else if(_m == MOTORB && _d == BACKWARD) PORTB &= ~(1 << PB0); // The direction of FORWARD and BACKWARD is
|
||||
else if(_m == MOTORB && _d == FORWARD) PORTB |= (1 << PB0); // switched for MOTORB due to hardware design
|
||||
}
|
||||
|
||||
void MMotor::stop()
|
||||
|
||||
3
software/lib/MMM/Motor.h
Normal file → Executable file
3
software/lib/MMM/Motor.h
Normal file → Executable file
@ -53,8 +53,7 @@ protected:
|
||||
|
||||
MOTOR _m;
|
||||
DIRECTION _d;
|
||||
int _t;
|
||||
long _p;
|
||||
int _t; // torque
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -1,623 +0,0 @@
|
||||
/*
|
||||
Music.cpp - Music library
|
||||
Copyright (c) 2012 Copenhagen Institute of Interaction Design.
|
||||
All right reserved.
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser Public License
|
||||
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
+ author: Jakob Bak
|
||||
+ contact: j.bak@ciid.dk
|
||||
*/
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#include <Wavetable.h>
|
||||
#include <Music.h>
|
||||
#include <hardwareSerial.h>
|
||||
|
||||
// Table of MIDI note values to frequency in Hertz
|
||||
prog_uint16_t hertsTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543};
|
||||
|
||||
prog_uint32_t envTimeTable[] PROGMEM = {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,33,34,35,36,37,38,39,41,42,43,45,46,48,49,51,53,55,57,59,61,63,65,67,70,73,75,78,81,85,88,92,96,100,104,109,114,119,125,131,138,146,154,163,172,183,195,209,225,242,261,284,310,341,379,425,482,556,654,792,998,1342,2030,4095};
|
||||
|
||||
float semitoneTable[] = {0.25,0.2648658,0.2806155,0.29730177,0.31498027,0.33370996,0.35355338,0.37457678,0.39685026,0.4204482,0.44544938,0.47193715,0.5,0.5297315,0.561231,0.59460354,0.62996054,0.6674199,0.70710677,0.74915355,0.7937005,0.8408964,0.8908987,0.9438743,1.0,1.0594631,1.122462,1.1892071,1.2599211,1.3348398,1.4142135,1.4983071,1.587401,1.6817929,1.7817974,1.8877486,2.0,2.1189263,2.244924,2.3784142,2.5198421,2.6696796,2.828427,2.9966142,3.174802,3.3635857,3.563595,3.7754972,4.0};
|
||||
|
||||
MMusic Music;
|
||||
|
||||
// Defining which pins the SPI interface is connected to.
|
||||
#define SPI_SCK 5
|
||||
#define SPI_MOSI 3
|
||||
|
||||
// timer 2 is audio interrupt timer
|
||||
ISR(TIMER2_COMPA_vect) {
|
||||
|
||||
OCR2A = 127;
|
||||
|
||||
Music.synthInterrupt();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// INITIALIZING FUNCTION
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
void MMusic::init()
|
||||
{
|
||||
// clear interrupts. to make sure the interrupt timer doesn't start until we've set it up.
|
||||
cli();
|
||||
|
||||
// set up syntheziser
|
||||
// this is the timer 2 audio rate timer, fires an interrupt at 15625 Hz sampling rate
|
||||
TIMSK2 = 1<<OCIE2A; // interrupt enable audio timer
|
||||
OCR2A = 127;
|
||||
TCCR2A = 2; // CTC mode, counts up to 127 then resets
|
||||
TCCR2B = 0<<CS22 | 1<<CS21 | 0<<CS20;
|
||||
|
||||
// OUTPUTS
|
||||
// sck + mosi + ss
|
||||
DDRB = (1 << DDB2) | (1 << DDB3) | (1 << DDB5);
|
||||
// dac_cs output
|
||||
DDRD = (1 << DDD6);
|
||||
|
||||
// set up SPI port
|
||||
SPCR = 0x50;
|
||||
SPSR = 0x01;
|
||||
|
||||
// DAC frame sync HIGH, so that the SPI port doesn't start wirting straight away
|
||||
PORTD |= (1<<6);
|
||||
|
||||
// waveform setup
|
||||
//setSine();
|
||||
setWaveform(0);
|
||||
|
||||
// frequency setup
|
||||
setFrequency(440);
|
||||
setSemitone1(0);
|
||||
setSemitone2(0);
|
||||
setSemitone3(0);
|
||||
setDetune(0);
|
||||
|
||||
// gain setup
|
||||
setGain(1.0f);
|
||||
setGain1(1.0f);
|
||||
setGain2(1.0f);
|
||||
setGain3(1.0f);
|
||||
|
||||
// envelope setup
|
||||
setEnvStage(0);
|
||||
disableEnvelope();
|
||||
env = 0;
|
||||
|
||||
setAttack(4);
|
||||
setDecay(90);
|
||||
setSustain(32);
|
||||
setRelease(64);
|
||||
setVelSustain(0);
|
||||
|
||||
sei(); // global interrupt enable
|
||||
|
||||
Serial.println("MUSIC INITIALIZED!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// FREQUENCY AND DETUNE FUNCTIONS
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
void MMusic::setFrequency(float freq)
|
||||
{
|
||||
period1 = uint16_t(((freq * semi1 * (1 + detune1 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
period2 = uint16_t(((freq * semi2 * (1 + detune2 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
period3 = uint16_t(((freq * semi3 * (1 + detune3 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
frequency = freq;
|
||||
frequency1 = freq;
|
||||
frequency2 = freq;
|
||||
frequency3 = freq;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setFrequency1(float freq)
|
||||
{
|
||||
frequency1 = freq;
|
||||
period1 = uint16_t(((frequency1 * semi1 * (1 + detune1 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setFrequency2(float freq)
|
||||
{
|
||||
frequency2 = freq;
|
||||
period2 = uint16_t(((frequency2 * semi2 * (1 + detune2 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setFrequency3(float freq)
|
||||
{
|
||||
frequency3 = freq;
|
||||
period3 = uint16_t(((frequency3 * semi3 * (1 + detune3 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setSemitone1(int8_t semi)
|
||||
{
|
||||
if(-25 < semi && semi < 25){
|
||||
semi1 = semitoneTable[semi+24];
|
||||
} else if (semi < -24) {
|
||||
semi1 = semitoneTable[0];
|
||||
} else {
|
||||
semi1 = semitoneTable[48];
|
||||
}
|
||||
period1 = uint16_t(((frequency1 * semi1 * (1 + detune1 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setSemitone2(int8_t semi)
|
||||
{
|
||||
if(-25 < semi && semi < 25){
|
||||
semi2 = semitoneTable[semi+24];
|
||||
} else if (semi < -24) {
|
||||
semi2 = semitoneTable[0];
|
||||
} else {
|
||||
semi2 = semitoneTable[48];
|
||||
}
|
||||
period2 = uint16_t(((frequency2 * semi2 * (1 + detune2 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setSemitone3(int8_t semi)
|
||||
{
|
||||
if(-25 < semi && semi < 25){
|
||||
semi3 = semitoneTable[semi+24];
|
||||
} else if (semi < -24) {
|
||||
semi3 = semitoneTable[0];
|
||||
} else {
|
||||
semi3 = semitoneTable[48];
|
||||
}
|
||||
period3 = uint16_t(((frequency3 * semi3 * (1 + detune3 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setDetune(float detune)
|
||||
{
|
||||
detune1 = 0.0;
|
||||
detune2 = detune;
|
||||
detune3 = -detune;
|
||||
period2 = uint16_t(((frequency2 * semi2 * (1 + detune2 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
period3 = uint16_t(((frequency3 * semi3 * (1 + detune3 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setDetune1(float detune)
|
||||
{
|
||||
detune1 = detune;
|
||||
period1 = uint16_t(((frequency1 * semi1 * (1 + detune1 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setDetune2(float detune)
|
||||
{
|
||||
detune2 = detune;
|
||||
period2 = uint16_t(((frequency2 * semi2 * (1 + detune2 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setDetune3(float detune)
|
||||
{
|
||||
detune3 = detune;
|
||||
period3 = uint16_t(((frequency3 * semi3 * (1 + detune3 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::pitchBend(float b)
|
||||
{
|
||||
bend = b;
|
||||
period1 = uint16_t(((frequency1 * semi1 * (1 + detune1 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
period2 = uint16_t(((frequency2 * semi2 * (1 + detune2 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
period3 = uint16_t(((frequency3 * semi3 * (1 + detune3 + bend)) * 65536.0) / SAMPLE_RATE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// WAVEFORM FUNCTIONS
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
void MMusic::setWaveform(uint16_t waveForm)
|
||||
{
|
||||
waveForm1 = waveForm * 256;
|
||||
waveForm2 = waveForm * 256;
|
||||
waveForm3 = waveForm * 256;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setWaveform1(uint16_t waveForm)
|
||||
{
|
||||
waveForm1 = waveForm * 256;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setWaveform2(uint16_t waveForm)
|
||||
{
|
||||
waveForm2 = waveForm * 256;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setWaveform3(uint16_t waveForm)
|
||||
{
|
||||
waveForm3 = waveForm * 256;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// GAIN FUNCTIONS
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
void MMusic::setGainFloat(float value)
|
||||
{
|
||||
gain = uint16_t(value * 65535);
|
||||
gain1 = gain;
|
||||
gain2 = gain;
|
||||
gain3 = gain;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain16bit(uint16_t value)
|
||||
{
|
||||
gain = value;
|
||||
gain1 = value;
|
||||
gain2 = value;
|
||||
gain3 = value;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain(float value)
|
||||
{
|
||||
gain = uint16_t(value * 65535);
|
||||
gain1 = gain;
|
||||
gain2 = gain;
|
||||
gain3 = gain;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain(uint16_t value)
|
||||
{
|
||||
gain = value;
|
||||
gain1 = value;
|
||||
gain2 = value;
|
||||
gain3 = value;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain1(float value)
|
||||
{
|
||||
gain1 = uint16_t(value * 65535);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain2(float value)
|
||||
{
|
||||
gain2 = uint16_t(value * 65535);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain3(float value)
|
||||
{
|
||||
gain3 = uint16_t(value * 65535);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain1(uint16_t value)
|
||||
{
|
||||
gain1 = value;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain2(uint16_t value)
|
||||
{
|
||||
gain2 = value;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setGain3(uint16_t value)
|
||||
{
|
||||
gain3 = value;
|
||||
}
|
||||
|
||||
|
||||
float MMusic::getGainFloat()
|
||||
{
|
||||
return float(gain);
|
||||
}
|
||||
|
||||
|
||||
uint16_t MMusic::getGain()
|
||||
{
|
||||
return gain;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// NOTE_ON/OFF FUNCTIONS
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
void MMusic::noteOn(uint8_t note, uint8_t vel)
|
||||
{
|
||||
envStage = 1;
|
||||
velSustain = vel;
|
||||
notePlayed = note;
|
||||
memcpy_P(&frequency16bit, &hertsTable[notePlayed],2);
|
||||
setFrequency1(frequency16bit);
|
||||
setFrequency2(frequency16bit);
|
||||
setFrequency3(frequency16bit);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::noteOn(uint8_t note)
|
||||
{
|
||||
envStage = 1;
|
||||
velSustain = 127;
|
||||
notePlayed = note;
|
||||
memcpy_P(&frequency16bit, &hertsTable[notePlayed],2);
|
||||
setFrequency1(frequency16bit);
|
||||
setFrequency2(frequency16bit);
|
||||
setFrequency3(frequency16bit);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::noteOff(uint8_t note)
|
||||
{
|
||||
if(notePlayed == note) {
|
||||
envStage = 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MMusic::noteOff()
|
||||
{
|
||||
envStage = 4;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// ENVELOPE FUNCTIONS
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
void MMusic::enableEnvelope()
|
||||
{
|
||||
envelopeOn = true;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::disableEnvelope()
|
||||
{
|
||||
envelopeOn = false;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setEnvStage(uint8_t stage)
|
||||
{
|
||||
envStage = stage;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setAttack16bit(uint16_t att)
|
||||
{
|
||||
attack = att;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setDecay16bit(uint16_t dec)
|
||||
{
|
||||
decay = dec;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setSustain16bit(uint16_t sus)
|
||||
{
|
||||
sustain = sus;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setRelease16bit(uint16_t rel)
|
||||
{
|
||||
release = rel;
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setAttack(uint8_t att)
|
||||
{
|
||||
if(att>127) att = 127;
|
||||
memcpy_P(&attack, &envTimeTable[127 - att],2);
|
||||
//attack = envTimeTable[127 - att];
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setDecay(uint8_t dec)
|
||||
{
|
||||
if(dec>127) dec = 127;
|
||||
memcpy_P(&decay, &envTimeTable[127 - dec],2);
|
||||
//decay = envTimeTable[127 - dec];
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setSustain(uint8_t sus)
|
||||
{
|
||||
sustain = ((sus * MAX_ENV_GAIN)/128);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setRelease(uint8_t rel)
|
||||
{
|
||||
if(rel>127) rel = 127;
|
||||
memcpy_P(&release, &envTimeTable[127 - rel],2);
|
||||
//release = envTimeTable[127 - rel];
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setVelSustain(uint8_t vel)
|
||||
{
|
||||
velSustain = vel * (sustain / 128);
|
||||
}
|
||||
|
||||
|
||||
void MMusic::setVelPeak(uint8_t vel)
|
||||
{
|
||||
velPeak = vel * (MAX_ENV_GAIN / 128);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////
|
||||
//
|
||||
// AUDIO INTERRUPT SERVICE ROUTINE
|
||||
//
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
void inline MMusic::synthInterrupt()
|
||||
{
|
||||
// Frame sync low for SPI (making it low here so that we can measure lenght of interrupt with scope)
|
||||
PORTD &= ~(1<<6);
|
||||
|
||||
// The accumulator (16bit) keeps track of the pitch by adding the
|
||||
// the amount of "index" points that the frequency has "travelled"
|
||||
// since the last sample was sent to the DAC, i.e. the current phase
|
||||
// of the waveform.
|
||||
accumulator1 = accumulator1 + period1;
|
||||
accumulator2 = accumulator2 + period2;
|
||||
accumulator3 = accumulator3 + period3;
|
||||
|
||||
// To use the accumulator position to find the right index in the
|
||||
// waveform look-up table, we truncate it to 8bit.
|
||||
index1 = accumulator1 >> 8;
|
||||
index2 = accumulator2 >> 8;
|
||||
index3 = accumulator3 >> 8;
|
||||
|
||||
oscil1 = 0;
|
||||
oscil2 = 0;
|
||||
oscil3 = 0;
|
||||
|
||||
memcpy_P(&oscil1, &waveTable[index1 + waveForm1],1);
|
||||
memcpy_P(&oscil2, &waveTable[index2 + waveForm2],1);
|
||||
memcpy_P(&oscil3, &waveTable[index3 + waveForm3],1);
|
||||
|
||||
|
||||
|
||||
// The DAC formatting routine below assumes the sample to be transmitted
|
||||
// is in the higher 12 bits of the 2 byte variable, so we shift the
|
||||
// sample up 6 bits each which adds up to 4 bits.
|
||||
// The individual gains for each oscillator is added.
|
||||
sample = (oscil1 * gain1);
|
||||
sample += (oscil2 * gain2);
|
||||
sample += (oscil3 * gain3);
|
||||
sample >>= 10;
|
||||
|
||||
|
||||
// AMPLIFICATION ENVELOPE
|
||||
// Amplification envelope is calculated here
|
||||
if(envelopeOn) {
|
||||
|
||||
// Attack
|
||||
if(envStage == 1) {
|
||||
env += attack;
|
||||
if(velPeak < env) {
|
||||
env = velPeak;
|
||||
envStage = 2;
|
||||
}
|
||||
}
|
||||
// Decay
|
||||
else if(envStage == 2) {
|
||||
env -= decay;
|
||||
if(env < velSustain || MAX_ENV_GAIN < env) {
|
||||
env = velSustain;
|
||||
envStage = 3;
|
||||
}
|
||||
}
|
||||
// Sustain
|
||||
else if (envStage == 3) {
|
||||
env = velSustain;
|
||||
}
|
||||
|
||||
// Release
|
||||
else if (envStage == 4) {
|
||||
env -= release;
|
||||
if(MAX_ENV_GAIN < env) {
|
||||
env = 0;
|
||||
envStage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// No gain
|
||||
else if (envStage == 0) {
|
||||
env = 0;
|
||||
accumulator1 = 0;
|
||||
accumulator2 = 0;
|
||||
accumulator3 = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
env = 65535;
|
||||
}
|
||||
|
||||
// Adding the amplification envelope (16bit) we bring it back to the 16bit frame again afterwards.
|
||||
sample = (env * sample) >> 16;
|
||||
|
||||
|
||||
// Formatting the samples to be transfered to the MCP4921 DAC
|
||||
dacSPI0 = sample >> 8;
|
||||
dacSPI0 >>= 4;
|
||||
dacSPI0 |= 0x30;
|
||||
dacSPI1 = sample >> 4;
|
||||
|
||||
SPCR |= (1 << MSTR);
|
||||
|
||||
// transmit value out the SPI port
|
||||
SPDR = dacSPI0;
|
||||
while (!(SPSR & (1<<SPIF))); // Maybe this can be optimised
|
||||
SPDR = dacSPI1;
|
||||
while (!(SPSR & (1<<SPIF))); // Maybe this can be optimised
|
||||
|
||||
// Frame sync high
|
||||
PORTD |= (1<<6);
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Music.h - Music library
|
||||
Wavetable.h - Music library
|
||||
Copyright (c) 2012 Copenhagen Institute of Interaction Design.
|
||||
All right reserved.
|
||||
|
||||
@ -21,10 +21,6 @@
|
||||
+ contact: j.bak@ciid.dk
|
||||
*/
|
||||
|
||||
//uint32_t envTimeTable[] = {1,2,5,8,11,14,18,22,27,31,36,41,46,52,58,64,70,76,82,89,96,103,110,117,125,132,140,148,156,164,172,181,189,198,207,216,225,234,243,252,262,272,281,291,301,311,322,332,343,353,364,374,385,396,407,419,430,441,453,464,476,488,500,512,524,536,548,560,573,585,598,610,623,636,649,662,675,688,702,715,729,742,756,769,783,797,811,825,839,853,868,882,896,911,925,940,955,970,985,1000,1015,1030,1045,1060,1075,1091,1106,1122,1137,1153,1169,1185,1201,1217,1233,1249,1265,1281,1298,1314,1331,1347,1364,1380,1397,1414,1431,1448,1465,1482,1499,1516,1533,1551,1568,1586,1603,1621,1638,1656,1674,1692,1710,1728,1746,1764,1782,1800,1818,1837,1855,1873,1892,1911,1929,1948,1967,1986,2004,2023,2042,2061,2081,2100,2119,2138,2158,2177,2197,2216,2236,2255,2275,2295,2315,2334,2354,2374,2394,2414,2435,2455,2475,2495,2516,2536,2557,2577,2598,2618,2639,2660,2681,2702,2723,2744,2765,2786,2807,2828,2849,2870,2892,2913,2935,2956,2978,2999,3021,3043,3064,3086,3108,3130,3152,3174,3196,3218,3240,3263,3285,3307,3330,3352,3375,3397,3420,3442,3465,3488,3510,3533,3556,3579,3602,3625,3648,3671,3694,3718,3741,3764,3787,3811,3834,3858,3881,3905,3929,3952,3976,4000,4024,4048,4072,4095};
|
||||
|
||||
//prog_uint16_t hertzTable[] PROGMEM = {8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,48,51,54,58,61,65,69,73,77,82,87,92,97,103,109,116,123,130,138,146,155,164,174,184,195,207,219,233,246,261,277,293,311,329,349,369,391,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318,1396,1479,1567,1661,1760,1864,1975,2093,2217,2349,2489,2637,2793,2959,3135,3322,3520,3729,3951,4186,4434,4698,4978,5274,5587,5919,6271,6644,7040,7458,7902,8372,8869,9397,9956,10548,11175,11839,12543};
|
||||
|
||||
// Look-up table for sine waveform in 12 bit resolution in
|
||||
// both amplitude and time.
|
||||
|
||||
|
||||
@ -0,0 +1 @@
|
||||
Put Motion Tutorial sketches in this folder
|
||||
@ -0,0 +1,32 @@
|
||||
//"Pulse" - small duration positive then negative force
|
||||
// parameters: F1, T1, D1, F2, T2, D2
|
||||
|
||||
#define BIT_DEPTH 12
|
||||
|
||||
#include <Motor.h>
|
||||
#include <Music.h>
|
||||
|
||||
void setup(){
|
||||
MotorA.init();
|
||||
Music.init();
|
||||
|
||||
Music.setWaveform(SINE);
|
||||
Music.enableEnvelope();
|
||||
Music.setAttack(10);
|
||||
Music.setDecay(10);
|
||||
Music.setRelease(10);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
MotorA.torque(200);
|
||||
Music.noteOn(map(analogRead(A3),0,1023,30,60));
|
||||
delay (20);
|
||||
Music.noteOff();MotorA.torque(0);
|
||||
delay (150);
|
||||
MotorA.torque(-200);
|
||||
Music.noteOn(map(analogRead(A3),0,1023,35,65));
|
||||
delay (40);
|
||||
Music.noteOff();MotorA.torque(0);
|
||||
MotorA.torque(0);
|
||||
delay (750);
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
// Center - both motors A and B
|
||||
// feels like "Double Toggle"!
|
||||
|
||||
#include <Motor.h>
|
||||
|
||||
int duty, count, fout;
|
||||
int xA, xB, foutA, foutB;
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
MotorA.init();
|
||||
MotorB.init();
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
xA = analogRead(A0);
|
||||
xB = analogRead(A3);
|
||||
foutA = 6*(xB-512); // this will peak at x=1024/6
|
||||
MotorA.torque(foutA); // 1/4 or 1/2 ?
|
||||
|
||||
foutB = 6*(xA-512); // this will peak at x=1024/6
|
||||
MotorB.torque(foutB); // 1/4 or 1/2 ?
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
// CenterAB - both motors
|
||||
// xA->Freqequency1, xB->Frequency2
|
||||
//CenterA at xB, CenterB at xA
|
||||
//feels like "Slave"
|
||||
|
||||
#include <Motor.h>
|
||||
#include <Music.h>
|
||||
#define BIT_DEPTH 8
|
||||
#define NUM_OSCILLATORS 2
|
||||
|
||||
int duty, count, fout;
|
||||
int xA, xB, foutA, foutB;
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
MotorA.init();
|
||||
MotorB.init();
|
||||
Music.init();
|
||||
Music.setWaveform1(0);//8bit default?
|
||||
Music.setWaveform2(0);
|
||||
Music.setGain1(1.0f);
|
||||
Music.setGain2(1.0f);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
xA = analogRead(A0);
|
||||
Music.setFrequency1(map (xA, 0, 1023, 40, 2000));
|
||||
|
||||
xB = analogRead(A3);
|
||||
Music.setFrequency2(map (xB, 0, 1023, 40, 2000));
|
||||
|
||||
foutA = -6*(xA-xB); // this will peak at x=1024/6
|
||||
MotorA.torque(foutA); // 1/4 or 1/2 ?
|
||||
|
||||
foutB = -6*(xB-xA); // this will peak at x=1024/6
|
||||
MotorB.torque(foutB); // 1/4 or 1/2 ?
|
||||
|
||||
Music.setGain(float(abs(xA-xB))/1024.0f);
|
||||
|
||||
}
|
||||
36
software/lib/MMM/examples/Motion/_4_Theremin/_4_Theremin.ino
Normal file
36
software/lib/MMM/examples/Motion/_4_Theremin/_4_Theremin.ino
Normal file
@ -0,0 +1,36 @@
|
||||
// Theremin
|
||||
// A: pitch, B: volume
|
||||
|
||||
#include <Music.h>
|
||||
int xA, xB; //10bit A/D gives 0-1023
|
||||
float p; //midi note number 0-127
|
||||
double frequency, volume;
|
||||
byte c; //print every 256 cycles
|
||||
|
||||
void setup(){
|
||||
Music.init();
|
||||
Serial.begin(9600);
|
||||
}
|
||||
void loop(){
|
||||
xA = analogRead(A3); // A position
|
||||
p = float(xA)/8; //pitch (midi)
|
||||
|
||||
p = 80.*(p/128.)+20.;
|
||||
// p = map(p, 0,127,20,100);
|
||||
//linear mapping of p
|
||||
//The map() function uses integer math so will
|
||||
//not generate fractions, when the math might
|
||||
//indicate that it should do so. Fractional
|
||||
//remainders are truncated, and are not rounded
|
||||
//or averaged.
|
||||
//
|
||||
frequency = pow(2,((p-69.)/12.))*440; //midi 69 -> 440hz
|
||||
Music.setFrequency(frequency);
|
||||
|
||||
xB = analogRead(A0);
|
||||
volume = -float(xB)/1024.; // B position
|
||||
volume = pow(10,volume);
|
||||
Music.setGain(volume);
|
||||
|
||||
}
|
||||
|
||||
48
software/lib/MMM/examples/Motion/_5_Pluck/_5_Pluck.ino
Normal file
48
software/lib/MMM/examples/Motion/_5_Pluck/_5_Pluck.ino
Normal file
@ -0,0 +1,48 @@
|
||||
//Pluck: one pluck at x=512
|
||||
|
||||
int x, fout, count;
|
||||
float f;
|
||||
float w = 50; //width of pluck
|
||||
float h = 500; //height of pluck
|
||||
float slope = h/w;
|
||||
boolean forward = true;
|
||||
|
||||
#include <Motor.h>
|
||||
|
||||
void setup(){
|
||||
MotorA.init();
|
||||
MotorB.init();
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop(){
|
||||
x = analogRead(A0) - 512;
|
||||
if (forward){
|
||||
if (x <= - w/2) f = 0;
|
||||
if (x > -w/2 && x< w/2) f = - slope*(x + w/2);
|
||||
if (x > w/2){
|
||||
f = 0;
|
||||
forward = false;
|
||||
Serial.println("pluck forward");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x > w/2) f = 0;
|
||||
if (x < w/2 && x > -w/2) f = - slope*(x - w/2);
|
||||
if (x < -w/2){
|
||||
f = 0;
|
||||
forward = true;
|
||||
Serial.println("pluck back");
|
||||
}
|
||||
}
|
||||
fout = int(f);
|
||||
MotorA.torque(fout);
|
||||
|
||||
if(count++>=0){
|
||||
count=-1000; // wait 1000 loops before print
|
||||
Serial.print(x,DEC);
|
||||
Serial.print(" ");
|
||||
Serial.println(fout,DEC);
|
||||
}
|
||||
}
|
||||
90
software/lib/MMM/examples/Motion/_6_Bumps/_6_Bumps.ino
Normal file
90
software/lib/MMM/examples/Motion/_6_Bumps/_6_Bumps.ino
Normal file
@ -0,0 +1,90 @@
|
||||
<<<<<<< HEAD:software/lib/MMM/examples/Motion/_6_Bumps/_6_Bumps.ino
|
||||
//Plucks - four bumps / three notes (400,500,600hz)
|
||||
#define NUM_OSCILLATORS 3
|
||||
=======
|
||||
//plucks - four bumps
|
||||
//three notes (400,500,600hz)
|
||||
//can't get Music.setGain1, etc to work only Music.setGain() starts all of them.
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 8
|
||||
>>>>>>> update notes to motion.cpp:software/apps/Modeling/Bumps4/Bumps4.ino
|
||||
#include <Music.h>
|
||||
#include <Motor.h>
|
||||
|
||||
int x, xold, xt, F; // input position x, output force F
|
||||
int K = 10; // slope constant
|
||||
byte count; //for print count-down
|
||||
|
||||
void setup(){
|
||||
Music.init();
|
||||
Music.setFrequency1(200);
|
||||
Music.setFrequency2(250);
|
||||
Music.setFrequency3(300);
|
||||
|
||||
MotorA.init();
|
||||
|
||||
Serial.begin(9600);
|
||||
x = analogRead(A0); // initialize x
|
||||
}
|
||||
|
||||
void loop(){
|
||||
|
||||
xold = x;
|
||||
x = analogRead(A0);
|
||||
|
||||
if (((xold <= 125) && (x > 125)) || ((xold >= 125) && (x < 125))){
|
||||
Music.setGain1(1.0f);
|
||||
<<<<<<< HEAD:software/lib/MMM/examples/Motion/_6_Bumps/_6_Bumps.ino
|
||||
}
|
||||
if (((xold <= 375) && (x > 375)) || ((xold >= 375) && (x < 375))){
|
||||
Music.setGain2(1.0f);
|
||||
}
|
||||
if (((xold <= 625) && (x > 625)) || ((xold >= 625) && (x < 625))){
|
||||
Music.setGain3(1.0f);
|
||||
}
|
||||
if (((xold <= 875) && (x > 875)) || ((xold >= 875) && (x < 875))){
|
||||
Music.setGain1(1.0f);
|
||||
=======
|
||||
Music.setFrequency1(200);
|
||||
}
|
||||
if (((xold <= 375) && (x > 375)) || ((xold >= 375) && (x < 375))){
|
||||
Music.setGain2(1.0f);
|
||||
Music.setFrequency2(250);
|
||||
}
|
||||
if (((xold <= 625) && (x > 625)) || ((xold >= 625) && (x < 625))){
|
||||
Music.setGain3(1.0f);
|
||||
Music.setFrequency3(300);
|
||||
}
|
||||
if (((xold <= 875) && (x > 875)) || ((xold >= 875) && (x < 875))){
|
||||
Music.setGain1(1.0f);
|
||||
Music.setFrequency1(400);
|
||||
>>>>>>> update notes to motion.cpp:software/apps/Modeling/Bumps4/Bumps4.ino
|
||||
}
|
||||
else{
|
||||
Music.setGain1(0.995f*Music.getGain1());
|
||||
Music.setGain2(0.995f*Music.getGain2());
|
||||
Music.setGain3(0.995f*Music.getGain3());
|
||||
}
|
||||
|
||||
|
||||
|
||||
xt = x % 250; //same force for each 250 ranage
|
||||
F = 0;
|
||||
if (xt > 60) F = - K * (xt - 60);
|
||||
if (xt > 80) F = - K * (100 - xt);
|
||||
if (xt > 120) F = K * (140 - xt);
|
||||
if (xt > 140) F = 0;
|
||||
MotorA.torque(F);
|
||||
|
||||
|
||||
// print every 256 cycles
|
||||
if(count++==0){
|
||||
Serial.print(x);
|
||||
Serial.print(" ");
|
||||
Serial.print(xt);
|
||||
Serial.print(" ");
|
||||
Serial.println(F);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,86 @@
|
||||
/*
|
||||
This sketch runs with Processing sketch Oscilloscope.pde
|
||||
*/
|
||||
|
||||
#include <Motion.h>
|
||||
#include <Motor.h>
|
||||
#include <Music.h>
|
||||
|
||||
char buf[16] = "";
|
||||
|
||||
char b = 'x';
|
||||
String inputString = "";
|
||||
boolean stringComplete = false;
|
||||
|
||||
float k, m, d;
|
||||
|
||||
int cnt = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// MOTOR
|
||||
MotorA.init();
|
||||
|
||||
// MUSIC
|
||||
Music.init();
|
||||
|
||||
// MOTION
|
||||
MotionA.init(INPUTA0);
|
||||
MotionA.k = 5.2f; // spring
|
||||
MotionA.m = 1.0f; // mass
|
||||
MotionA.d = 8.02f; // damping
|
||||
|
||||
// Serial
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
MotionA.update_mass_spring_damper();
|
||||
|
||||
MotorA.torque(MotionA.F);
|
||||
|
||||
int f = map(abs(MotionA.F), 0, 512, 64, 76);
|
||||
Music.noteOn(f);
|
||||
|
||||
cnt++;
|
||||
|
||||
if(cnt == 10) {
|
||||
sprintf(buf, "%d %d %d %d", (int)MotionA.F, (int)MotionA.V, (int)MotionA.X, (int)MotionA.Xin);
|
||||
Serial.println(buf);
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
if(stringComplete) {
|
||||
if(b == 'k') {
|
||||
MotionA.k = convertToFloat(inputString);
|
||||
} else if(b == 'm') {
|
||||
MotionA.m = convertToFloat(inputString);
|
||||
} else if(b == 'd') {
|
||||
MotionA.d = convertToFloat(inputString);
|
||||
}
|
||||
b = 'x';
|
||||
stringComplete = false;
|
||||
inputString = "";
|
||||
}
|
||||
}
|
||||
|
||||
void serialEvent() {
|
||||
while (Serial.available()) {
|
||||
char inChar = (char)Serial.read();
|
||||
if(inChar == 'k' || inChar == 'm' || inChar == 'd') {
|
||||
b = inChar;
|
||||
} else {
|
||||
if (inChar == ';') {
|
||||
stringComplete = true;
|
||||
} else
|
||||
inputString += inChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float convertToFloat(String str) {
|
||||
char buf[16] = "";
|
||||
str.toCharArray(buf, str.length() + 1);
|
||||
return atof(buf);
|
||||
}
|
||||
31
software/lib/MMM/examples/Motion/_8_FM/_8_FM.ino
Normal file
31
software/lib/MMM/examples/Motion/_8_FM/_8_FM.ino
Normal file
@ -0,0 +1,31 @@
|
||||
//FM synthes of a sort
|
||||
//hang on! it's unstable and wants to limit cycle
|
||||
|
||||
#define BIT_DEPTH 8 // gives us 16 Waveforms
|
||||
|
||||
#include <Music.h>
|
||||
|
||||
#include <Motor.h>
|
||||
|
||||
byte cnt;
|
||||
float xf, vf; //
|
||||
float k = 10.0; // increase FM frequency
|
||||
float b = 0.40; // increase
|
||||
float Tf = .030 ; //integration time
|
||||
|
||||
void setup(){
|
||||
Serial.begin(9600);
|
||||
Music.init();
|
||||
Music.setWaveform(0);
|
||||
Music.setGain(1.0f);
|
||||
MotorA.init();
|
||||
}
|
||||
|
||||
void loop(){
|
||||
xf += vf * Tf;
|
||||
vf += (k * (analogRead(A0) - xf) - b*vf) * Tf;
|
||||
Music.setFrequency(100+vf);
|
||||
Music.setGain(.001*abs(vf));
|
||||
MotorA.torque(-500+xf);
|
||||
//if(cnt++==0)Serial.println(.001*abs(vf));
|
||||
}
|
||||
1
software/lib/MMM/examples/Motor/Motor_tutorial_files.txt
Normal file
1
software/lib/MMM/examples/Motor/Motor_tutorial_files.txt
Normal file
@ -0,0 +1 @@
|
||||
Put Motor Tutorial sketches in this folder
|
||||
12
software/lib/MMM/examples/Motor/_1_FlipFlop/_1_FlipFlop.ino
Normal file
12
software/lib/MMM/examples/Motor/_1_FlipFlop/_1_FlipFlop.ino
Normal file
@ -0,0 +1,12 @@
|
||||
#include <Motor.h>
|
||||
|
||||
void setup() {
|
||||
MotorA.init();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
MotorA.torque(500);
|
||||
delay(2000);
|
||||
MotorA.torque(-500);
|
||||
delay(2000);
|
||||
}
|
||||
@ -0,0 +1,67 @@
|
||||
|
||||
#include <Motion.h>
|
||||
#include <Motor.h>
|
||||
|
||||
#define NEW '!'
|
||||
#define OK '*'
|
||||
#define PRINT '&'
|
||||
|
||||
int table[800];
|
||||
int len = 800;
|
||||
|
||||
char buf[32] = "";
|
||||
int cnt = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
MotorA.init();
|
||||
MotionA.init(INPUTA0);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
MotionA.update_position();
|
||||
int i = (int) (((float) MotionA.Xin / 1023.0) * len);
|
||||
int f = table[i];
|
||||
MotorA.torque(f);
|
||||
|
||||
// TODO - send position back to interface
|
||||
/*
|
||||
cnt++;
|
||||
if(cnt == 1000) {
|
||||
sprintf(buf, "%d %d %d", MotionA.Xin, i, f);
|
||||
Serial.println(buf);
|
||||
cnt = 0;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void serialEvent() {
|
||||
|
||||
if(Serial.available()) {
|
||||
char in = (char)Serial.read();
|
||||
if(in == NEW) {
|
||||
Serial.print(OK);
|
||||
len = serial_read();
|
||||
for(int i = 0; i < len; i++) {
|
||||
table[i] = serial_read();
|
||||
}
|
||||
} else if(in == PRINT) {
|
||||
Serial.println(len);
|
||||
for(int i = 0; i < len; i++) {
|
||||
Serial.print(table[i]);
|
||||
Serial.print(';');
|
||||
}
|
||||
Serial.print('#');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int serial_read() {
|
||||
while(Serial.available() < 2);
|
||||
int l = Serial.read();
|
||||
int h = Serial.read();
|
||||
Serial.write(OK);
|
||||
return (h * 256) + l;
|
||||
}
|
||||
1
software/lib/MMM/examples/Music/Music_tutorial_files.txt
Normal file
1
software/lib/MMM/examples/Music/Music_tutorial_files.txt
Normal file
@ -0,0 +1 @@
|
||||
Put Music Tutorial sketches in this folder
|
||||
@ -0,0 +1,126 @@
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// DON'T TRY TO RUN THIS SKETCH, IT IS FOR DOCUMENTATION PURPOSES ONLY //
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// These are the music functions that are available for you to use in you sketches.
|
||||
// You can see examples of how some of them are used (the most basic ones) in the
|
||||
// Apps folder that downloaded with the MM library.
|
||||
|
||||
// In the following you can see the variable type that the function takes as an argument (float, uint8_t or uint16_t)
|
||||
// The weirdly looking "uint16_t" and "uint8_t" is just unsigned 16 and 8 bit integers. So instead of having
|
||||
// both negative and positive values, they only have positive values from 0 - 255 (8bit) and 0 - 65535 (16bit).
|
||||
// If you copy a function from here to your arduino sketch, just change the word "float", "uint8_t", etc into the
|
||||
// variable name that you uses in your sketch.
|
||||
|
||||
// PRE-PROCESSING COMMANDS
|
||||
#define NUM_OSCILLATORS 3 // define the use of 1, 2 or 3 oscillators
|
||||
#define BIT_DEPTH 12 // define the bit depth resolution of 8 or 12 bit waveforms
|
||||
#define MIDI // tell the system you will be using the MIDI part of the sound engine
|
||||
#define MIDI_CHANNEL 1 // set the MIDI channel to listen to. Between 1 and 16
|
||||
#define FM // tell the library to use the FM synthesis mode
|
||||
|
||||
#include <Music.h>
|
||||
|
||||
// INITIALIZERS
|
||||
// Use this in the setup() function to start the synth engine.
|
||||
// It defaults to a sine tone at 110Hz, no envelope and no detune.
|
||||
Music.init();
|
||||
|
||||
// Use this in the setup() function to start the MIDI engine. It sets up the serial communication.
|
||||
Midi.init();
|
||||
|
||||
// MIDI FUNCTIONS
|
||||
Midi.checkMidi() // put this function in the loop() function in your
|
||||
// Arduino sketch to check for incoming MIDI activity
|
||||
|
||||
// FREQUENCY AND DETUNE FUNCTIONS
|
||||
// Use these functions to set the frequency and detune parameters of the synth.
|
||||
Music.setFrequency(float); // Set base frequencies of all oscillators at once. Does _not_ affect detune or semitone
|
||||
Music.setFrequency1(float); // Set base frequency of individual oscillators.
|
||||
Music.setFrequency2(float); // Sounds best between 20Hz and 4000Hz
|
||||
Music.setFrequency3(float); //
|
||||
Music.setDetune(float); // Set the detune offset of all oscillators at once. Oscillator 1 stays fixed at it's base frequency
|
||||
Music.setDetune1(float); // Set the detune of oscillator 1,2 and 3 individually
|
||||
Music.setDetune2(float); // Sounds best between 0.00 and 0.02
|
||||
Music.setDetune3(float); //
|
||||
Music.setSemitone1(int8_t); // Set the semitone offset of base frequency in musical halftones relative to base frequency
|
||||
Music.setSemitone2(int8_t); // Goes from -24 halftones to +24 halftones
|
||||
Music.setSemitone3(int8_t);
|
||||
Music.setFM2(uint8_t); // Set the amount of frequency modulation (FM) on oscillator2.
|
||||
|
||||
|
||||
// WAVEFORM FUNCTIONS
|
||||
// Switch between the different waveforms for the oscillators. ONLY FOR 8BIT MODE!
|
||||
Music.setWaveform(uint16_t); // This sets waveform of all oscillators at once.
|
||||
Music.setWaveform1(uint16_t); // Takes a number from 0-15
|
||||
Music.setWaveform2(uint16_t); // Or take one of the macro names (in capitals) below for waveform types.
|
||||
Music.setWaveform3(uint16_t);
|
||||
// WAVEFORM TYPES
|
||||
SINE
|
||||
SQUARE
|
||||
PULSE
|
||||
TRIANGLE
|
||||
SAW
|
||||
FUZZ
|
||||
DIGI1
|
||||
DIGI2
|
||||
DIGI3
|
||||
DIGI4
|
||||
NOISE
|
||||
DIGI6
|
||||
TAN1
|
||||
TAN2
|
||||
TAN3
|
||||
TAN4
|
||||
|
||||
// GAIN FUNCTIONS
|
||||
// Set the gain of the oscillators all at once or individually. Use floats between 0.0 and 1.0
|
||||
Music.setGain(float); // 0.0 - 1.0
|
||||
Music.setGain1(float); // 0.0 - 1.0
|
||||
Music.setGain2(float); // 0.0 - 1.0
|
||||
Music.setGain3(float); // 0.0 - 1.0
|
||||
// You can also ask the sound engine
|
||||
Music.getGain(); // outputs a float between 0.0 and 1.0
|
||||
Music.getGain1(); //
|
||||
Music.getGain2(); //
|
||||
Music.getGain3(); //
|
||||
|
||||
|
||||
// NOTE FUNCTIONS
|
||||
// These functions triggers a note to be played. The noteOff() functions turns the note off again.
|
||||
// They come both with note and velocity information (for noteOn). If you don't know what that is,
|
||||
// just use the ones with the least arguments.
|
||||
// To get a proper note sound call Music.enableEnvelopes() [see below] before calling the noteOn function.
|
||||
// You just have to do that once in the setup for example.
|
||||
Music.noteOn(uint8_t, uint8_t); // 0 - 127, first argument is the note number, the second is the velocity
|
||||
Music.noteOn(uint8_t); // 0 - 127, here it is only note number and velocity defaults to 127
|
||||
Music.noteOff(uint8_t); // 0 - 127, specify which note should be turned off (not necessary yet)
|
||||
Music.noteOff(); // turns off last played note
|
||||
// This function returns the frequency of a MIDI note number sent to it.
|
||||
Music.getNoteFrequency(uint8_t); // input 0 - 127, returns a frequency in unsigned 16bit integers
|
||||
|
||||
|
||||
// ENVELOPE FUNCTIONS
|
||||
// These functions enables and sets the parameters of the internal envelope which creates dynamics for the notes
|
||||
// being played. You can read about ADSR envelopes here: http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope
|
||||
// When using the envelope you can only hear sound when you are triggering the notes with the note functions. In order
|
||||
// to get dynamics without triggering the note object you must have the envelope turned off, for example using
|
||||
// the Music.disableEnvelope() function [already set by default in the init() function]. You can then control the
|
||||
// dynamics of the sound with the overall or individual setGain() functions.
|
||||
Music.enableEnvelope();
|
||||
Music.disableEnvelope();
|
||||
|
||||
// Alternately to using the noteOn/NoteOff functions you can set the envelope stage. Experiment with it :)
|
||||
Music.setEnvStage(uint8_t); // 0 - 4, where 0 is in "silent" stage, 1 is attack, 2 is decay, 3 is sustain and 4 is release stage.
|
||||
|
||||
// Setting the parameters for the envelope you send an 8bit number between 0 and 127 to the functions below. 0 is a very fast
|
||||
// rise or decay in sound, whereas 127 is very long. Sustain is the sound level where 0 is silent and 127 is full gain.
|
||||
// You must experiment with what suits your musical taste :)
|
||||
// These parameters can of course be adjusted during the physics code for interesting results, but be aware that when
|
||||
// using the sine wave oscillator (which is more processor intensive) the sound can hang or have glitches if you alter
|
||||
// these parameters too quickly or set them at extremes. Try it out.
|
||||
Music.setAttack(uint8_t); // 0 - 127
|
||||
Music.setDecay(uint8_t); // 0 - 127
|
||||
Music.setSustain(uint8_t); // 0 - 127
|
||||
Music.setRelease(uint8_t); // 0 - 127
|
||||
|
||||
25
software/lib/MMM/examples/Music/_1_minimal/_1_minimal.ino
Normal file
25
software/lib/MMM/examples/Music/_1_minimal/_1_minimal.ino
Normal file
@ -0,0 +1,25 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 osciallator
|
||||
// and 8bit respectively.
|
||||
|
||||
#define NUM_OSCILLATORS 1
|
||||
#define BIT_DEPTH 12
|
||||
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects wit "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
56
software/lib/MMM/examples/Music/_2_waveform/_2_waveform.ino
Normal file
56
software/lib/MMM/examples/Music/_2_waveform/_2_waveform.ino
Normal file
@ -0,0 +1,56 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 osciallator
|
||||
// and 8bit respectively.
|
||||
|
||||
#define NUM_OSCILLATORS 1
|
||||
#define BIT_DEPTH 8
|
||||
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects with "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
int delayTime = 2000;
|
||||
int cnt = 0;
|
||||
long timeNow;
|
||||
long lastTime = 0;
|
||||
|
||||
byte waveFormArray[] = { SINE,
|
||||
SQUARE,
|
||||
PULSE,
|
||||
TRIANGLE,
|
||||
SAW,
|
||||
FUZZ,
|
||||
DIGI1,
|
||||
DIGI2,
|
||||
DIGI3,
|
||||
DIGI4,
|
||||
NOISE,
|
||||
DIGI6,
|
||||
TAN1,
|
||||
TAN2,
|
||||
TAN3,
|
||||
TAN4
|
||||
};
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
Music.setFrequency(220);
|
||||
Music.setWaveform(SINE);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
timeNow = millis();
|
||||
if((timeNow-lastTime) > delayTime) {
|
||||
cnt = cnt + 1;
|
||||
if(cnt>15) cnt = 0;
|
||||
Music.setWaveform(waveFormArray[cnt]);
|
||||
lastTime = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 osciallator
|
||||
// and 8bit respectively.
|
||||
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 8
|
||||
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects with "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
int delayTime = 400;
|
||||
int cnt = 0;
|
||||
float baseFrequency = 110;
|
||||
long timeNow;
|
||||
long lastTime = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
Music.setFrequency(220);
|
||||
Music.setDetune(0.001); // ranges from 0.00 - 0.02 are usually good
|
||||
Music.setWaveform(SAW);
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
timeNow = millis();
|
||||
if((timeNow-lastTime) > delayTime) {
|
||||
cnt = cnt + 1;
|
||||
if(cnt>3) cnt = 0;
|
||||
Music.setFrequency1(baseFrequency*1*cnt);
|
||||
Music.setFrequency2(baseFrequency*1.3333*cnt);
|
||||
Music.setFrequency3(baseFrequency*1.5*cnt);
|
||||
lastTime = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
47
software/lib/MMM/examples/Music/_4_gain/_4_gain.ino
Normal file
47
software/lib/MMM/examples/Music/_4_gain/_4_gain.ino
Normal file
@ -0,0 +1,47 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 osciallator
|
||||
// and 8bit respectively.
|
||||
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 8
|
||||
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects with "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
int delayTime = 100;
|
||||
int cnt = 0;
|
||||
float baseFrequency = 110;
|
||||
long timeNow;
|
||||
long lastTime = 0;
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
Music.setFrequency(220);
|
||||
Music.setDetune(0.005); // ranges from 0.00 - 0.02 are usually good
|
||||
Music.setWaveform(PULSE);
|
||||
Music.setFrequency1(baseFrequency*1);
|
||||
Music.setFrequency2(baseFrequency*1.3333);
|
||||
Music.setFrequency3(baseFrequency*1.5);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
timeNow = millis();
|
||||
if((timeNow-lastTime) > delayTime) {
|
||||
cnt = cnt + 1;
|
||||
if(cnt>16) cnt = 0;
|
||||
float counter = float(cnt);
|
||||
Music.setGain1(1.0/cnt);
|
||||
Music.setGain2(1.0/cnt);
|
||||
Music.setGain3(1.0/cnt);
|
||||
lastTime = timeNow;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 osciallator
|
||||
// and 8bit respectively.
|
||||
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 8
|
||||
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects with "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
Music.setFrequency(110);
|
||||
Music.setDetune(0.005); // ranges from 0.00 - 0.02 are usually good
|
||||
Music.setWaveform(DIGI2);
|
||||
Music.setSemitone1(0);
|
||||
Music.setSemitone2(7);
|
||||
Music.setSemitone3(-12);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
||||
|
||||
@ -1,31 +1,33 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 osciallator
|
||||
// and 8bit respectively.
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 8
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
// You still need to call Music.init() and Midi.init() in the setup() function below.
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects with "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#include <Music.h>
|
||||
|
||||
// variables for this sketch
|
||||
boolean noteIsOn = false;
|
||||
int n = 0;
|
||||
int dir = 1;
|
||||
int rootNote = 26;
|
||||
int rootNote = 36;
|
||||
int note[] = {0,2,3,5,7,9,10,12,14};
|
||||
|
||||
long time = 0;
|
||||
long lastTime = 0;
|
||||
long beatTime = 100;
|
||||
|
||||
long timeDelay = 80;
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
|
||||
// Choosing the square wave oscillator instead of the sine wave.
|
||||
Music.setSquare();
|
||||
// Choosing the square wave oscillator.
|
||||
Music.setWaveform(DIGI3);
|
||||
|
||||
// Detuning the three oscillators slightly to create movement in the sound.
|
||||
Music.setDetune(0.008);
|
||||
@ -37,14 +39,14 @@ void setup() {
|
||||
Music.setDecay(90);
|
||||
Music.setSustain(48);
|
||||
Music.setRelease(64);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// This short routine loops note over and over again
|
||||
time = millis();
|
||||
if(time - lastTime > beatTime) {
|
||||
if(time - lastTime > timeDelay) {
|
||||
if(!noteIsOn) {
|
||||
Music.noteOn(rootNote+note[n]);
|
||||
noteIsOn = true;
|
||||
@ -1,6 +1,5 @@
|
||||
|
||||
// This needs to be in all sketches at the moment
|
||||
#include <stdint.h>
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 12
|
||||
|
||||
// The Music and Midi objects are automatically instantiated when the header file is included.
|
||||
// Make calls to the Music and Midi objects with "Music.function(args)" and "Midi.function(args)"
|
||||
@ -24,7 +23,7 @@ void setup() {
|
||||
Music.init();
|
||||
|
||||
// Choosing the sine wave oscillator (optional since this is already the default).
|
||||
Music.setSine();
|
||||
Music.setWaveform(0);
|
||||
|
||||
// Setting the initial frequency for all three oscillators.
|
||||
Music.setFrequency(c);
|
||||
36
software/lib/MMM/examples/Music/_8_midi/_8_midi.ino
Executable file
36
software/lib/MMM/examples/Music/_8_midi/_8_midi.ino
Executable file
@ -0,0 +1,36 @@
|
||||
// The Music object is automatically instantiated when the header file is
|
||||
// included. Make calls to the Music objects with "Music.function(args)".
|
||||
// You still need to call Music.init() in the setup() function below.
|
||||
#define NUM_OSCILLATORS 3
|
||||
#define BIT_DEPTH 8
|
||||
#define MIDI
|
||||
#define MIDI_CHANNEL 1
|
||||
#include <Music.h>
|
||||
|
||||
long timeNow = 0;
|
||||
long lastTime = 0;
|
||||
long delayTime = 400; //in milliseconds
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
Music.enableEnvelope();
|
||||
Midi.init();
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// In order to send MIDI to the sketch, use the Music_Controls_4.pde Processing sketch
|
||||
Midi.checkMidi();
|
||||
|
||||
// The below code is an example of triggering the noteOn function to play some sounds
|
||||
timeNow = millis();
|
||||
if((timeNow - lastTime) > delayTime) {
|
||||
Music.noteOn(64);
|
||||
lastTime = timeNow;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
// You can set the number of oscillators (1 to 3) and the bit depth of the
|
||||
// oscillators (8 or 12 bit). These settings must be defined before the
|
||||
// inclusion of the MMM library files. They default to 1 oscallator
|
||||
// and 8bit respectively.
|
||||
#define FM // tell the library to use FM synthesis
|
||||
#define NUM_OSCILLATORS 2
|
||||
#define BIT_DEPTH 12
|
||||
|
||||
#include <Music.h>
|
||||
|
||||
long time;
|
||||
long lastTime = 0;
|
||||
long eventTime = 10;
|
||||
int cnt = 0;
|
||||
int dir = 1;
|
||||
|
||||
void setup() {
|
||||
|
||||
// We initialise the sound engine by calling Music.init() which outputs a tone
|
||||
Music.init();
|
||||
Music.setFM2(0); // this value is already defaulted to 0 in Music.init()
|
||||
Music.setFrequency2(148.3); // This is the base frequency of the audible oscillator
|
||||
Music.setFrequency1(487.78); // This is the modulating frequency
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// This code increases the FM amount from 0 to 127 and back again in intervals defined by "eventTime"
|
||||
time = millis();
|
||||
if(time-lastTime > eventTime) {
|
||||
Music.setFM2(cnt);
|
||||
cnt += dir;
|
||||
if(cnt <= 0 || cnt >= 127) dir *= -1;
|
||||
lastTime = time;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
91
software/lib/MMM/keywords.txt
Normal file
91
software/lib/MMM/keywords.txt
Normal file
@ -0,0 +1,91 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For MMM Library
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Music KEYWORD1
|
||||
MotorA KEYWORD1
|
||||
MotorB KEYWORD1
|
||||
MotionA KEYWORD1
|
||||
MotionB KEYWORD1
|
||||
Midi KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
init KEYWORD2
|
||||
checkMidi KEYWORD2
|
||||
enableEnvelope KEYWORD2
|
||||
disableEnvelope KEYWORD2
|
||||
setEnvStage KEYWORD2
|
||||
setDetune KEYWORD2
|
||||
setDetune1 KEYWORD2
|
||||
setDetune2 KEYWORD2
|
||||
setDetune3 KEYWORD2
|
||||
setFrequency KEYWORD2
|
||||
setFrequency1 KEYWORD2
|
||||
setFrequency2 KEYWORD2
|
||||
setFrequency3 KEYWORD2
|
||||
setSemitone1 KEYWORD2
|
||||
setSemitone2 KEYWORD2
|
||||
setSemitone3 KEYWORD2
|
||||
setWaveform KEYWORD2
|
||||
setWaveform1 KEYWORD2
|
||||
setWaveform2 KEYWORD2
|
||||
setWaveform3 KEYWORD2
|
||||
setGain KEYWORD2
|
||||
setGain1 KEYWORD2
|
||||
setGain2 KEYWORD2
|
||||
setGain3 KEYWORD2
|
||||
getGain KEYWORD2
|
||||
getGain1 KEYWORD2
|
||||
getGain2 KEYWORD2
|
||||
getGain3 KEYWORD2
|
||||
noteOn KEYWORD2
|
||||
noteOff KEYWORD2
|
||||
getNoteFrequency KEYWORD2
|
||||
setAttack KEYWORD2
|
||||
setDecay KEYWORD2
|
||||
setSustain KEYWORD2
|
||||
setRelease KEYWORD2
|
||||
update_position KEYWORD2
|
||||
update_mass_spring_damper KEYWORD2
|
||||
torque KEYWORD2
|
||||
direction KEYWORD2
|
||||
stop KEYWORD2
|
||||
start KEYWORD2
|
||||
restart KEYWORD2
|
||||
setFM2 KEYWORD2
|
||||
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
NUM_OSCILLATORS LITERAL1
|
||||
BIT_DEPTH LITERAL1
|
||||
MIDI LITERAL1
|
||||
MIDI_CHANNEL LITERAL1
|
||||
FM LITERAL1
|
||||
CFO LITERAL1
|
||||
|
||||
SINE LITERAL1
|
||||
SQUARE LITERAL1
|
||||
PULSE LITERAL1
|
||||
TRIANGLE LITERAL1
|
||||
SAW LITERAL1
|
||||
FUZZ LITERAL1
|
||||
DIGI1 LITERAL1
|
||||
DIGI2 LITERAL1
|
||||
DIGI3 LITERAL1
|
||||
DIGI4 LITERAL1
|
||||
NOISE LITERAL1
|
||||
DIGI6 LITERAL1
|
||||
TAN1 LITERAL1
|
||||
TAN2 LITERAL1
|
||||
TAN3 LITERAL1
|
||||
TAN4 LITERAL1
|
||||
Loading…
x
Reference in New Issue
Block a user