Compare commits

..

60 Commits

Author SHA1 Message Date
gauthiier
da334c97a9 ... 2023-09-08 08:14:13 +02:00
gauthiier
de34d6f62b ... 2023-09-08 08:12:38 +02:00
gauthiier
cb1f9fcf9b .. 2023-09-08 08:11:14 +02:00
Jakob Bak
0db1e4fcaa Processing sketch Music_Controls_4.pde now shows actual values in the Processing terminal 2013-09-27 15:08:12 +02:00
Jakob Bak
c21d363526 Made some fixes to the MIDI processing sketch and MIDI example 2013-09-26 20:02:44 +02:00
Jakob Bak
59184187c0 Added pdf of board layout 2013-09-26 19:57:16 +02:00
Jakob Bak
5243d6c845 Fixed? a problem with MIDI when running Processing sketch Music_Controls and playing notes from sequencer program (like Ableton Live) at the same time. 2013-06-06 16:39:18 +02:00
Jakob Bak
fadc5cc783 fixed _8_FM.ino Arduino sketch
A conflict in github added some lines of text to the sketch that would
prevent it from compiling
2013-05-22 09:36:47 +02:00
Bill Verplank
c147175bb2 getting FM 2013-05-21 09:16:47 -07:00
Jakob Bak
646cd74442 Added example sketch for FM synthesis 2013-05-21 15:31:08 +02:00
Jakob Bak
3dc691cb98 updated music library documentation sketch and keywords 2013-05-21 15:30:44 +02:00
Jakob Bak
e33335f379 updated library documentation Arduino "sketch" 2013-05-21 14:46:40 +02:00
Jakob Bak
eb03f104e0 small changes to FM part, added MIDI CC for FM2 2013-05-21 10:01:19 +02:00
Jakob Bak
5d2e9096c3 Added FM synthesis and corrected detune via MIDI 2013-05-21 09:40:06 +02:00
Jakob Bak
95b762afce Added Music Controls processing sketch to processing folder 2013-05-15 10:12:25 +02:00
Jakob Bak
19191f371c added reference for the Music library to examples folder 2013-05-15 09:44:45 +02:00
Jakob Bak
0b60af4044 Changes to Music.h and keywords.txt
added support for the miniCFO platform to work with the audio
2013-05-15 09:44:07 +02:00
Jakob Bak
4e8ad1e132 update notes to motion.cpp 2013-03-21 11:45:45 +01:00
Jakob Bak
c10d2e5b0c Updated _8_mid.ino 2013-03-21 11:42:45 +01:00
dviid
05fc0c94af Goldsmiths 2013-03-18 10:51:33 +00:00
dviid
d938b31e91 Fixed small screen issues 2013-03-15 15:09:12 +01:00
Jakob Bak
582ac0859b updated keywords 2013-02-10 10:42:14 +01:00
Jakob Bak
7b2f0c750d Added Music examples to Apps folder 2013-02-10 10:34:10 +01:00
Jakob Bak
4fddbf3190 Added more examples 2013-02-10 08:43:42 +01:00
Jakob Bak
e2a3935f07 added examples 2013-02-10 08:42:33 +01:00
Jakob Bak
5f994fcf7f Added examples 2013-02-10 08:40:08 +01:00
dviid
9c4ffb6e7b TEI Studio 2013-02-10 07:11:56 +01:00
Bill Verplank
bae5b3d412 Updated sketches for TEI workshop 2013-02-09 21:38:12 +01:00
dviid
9260d066ba Added ForceProfile 2013-02-09 21:18:32 +01:00
Bill Verplank
336b2b45ab Bill Examples
M&MStudioBV
2013-02-05 19:01:46 +01:00
dviid
a7408c519a Added Motion update_position 2013-02-05 10:58:52 +01:00
Bill Verplank
7e41bac2ce Pulse_Beat.ino
added to software/lib/MMM/examples/motor/
2013-02-05 10:37:08 +01:00
Bill Verplank
6f349b75d8 KEYWORD1
Moror
2013-02-05 10:33:47 +01:00
Jakob Bak
b2a6228236 Added placeholders for tutorial library 2013-02-05 10:32:22 +01:00
Jakob Bak
fe929b835e Updated Music.h and added MIDI functionality to it 2013-02-05 10:23:08 +01:00
Jakob Bak
8bd5f2b35c Changed default direction for MOTORB
Due to hardware design of MM board MOTORA and MOTORB had opposite
directions. Fixed by switching settings for MOTORB in
MMotor::direction(DIRECTION) function
2013-02-01 11:33:43 +01:00
Jakob Bak
c983a92107 Updates to Music.h, deleted Midi.h and Midi.cpp
We can now use these commands in the arduino sketch:
#define NUM_OSCILLATORS x     // where x is 1, 2 or 3
#define BIT_DEPTH x    // where x is 8 or 12

Deleted Midi library files as they where causing multiple definition
errors with the outdated Music.h file.
2013-01-30 21:25:34 +01:00
dviid
f5246baf9c Updated Music 2013-01-30 19:04:28 +01:00
dviid
f0556802f5 Fixed Motion 2013-01-30 18:58:19 +01:00
dviid
dbb6a746be Revert "Changes to Music.h and Music.cpp"
This reverts commit 8b24803aa2fd9792ec9507376fc52fd238742b00.
2013-01-30 18:51:07 +01:00
Jakob Bak
8b24803aa2 Changes to Music.h and Music.cpp 2013-01-30 18:45:25 +01:00
Jakob Bak
37f714e3d3 Slight fixes to motion and music library 2013-01-29 12:41:15 +01:00
Bill Verplank
8600cbd3e0 Bill's Music mess 2013-01-29 12:09:26 +01:00
dviid
62b7761e9a Added Oscilloscope code in apps 2013-01-28 12:05:23 +01:00
dviid
4a2f82f907 Updates: Motion + Motor
Integration with unsyncable branch
2013-01-28 11:58:58 +01:00
Bill Verplank
b0bce01fac Jakob changed some comments on bill's computer 2013-01-25 11:15:06 +01:00
Jakob Bak
0f8eb0f54d created new center example 2013-01-25 11:14:01 +01:00
Bill Verplank
769578fcf7 bill friday 2013-01-25 09:44:15 +01:00
Jakob Bak
9f2f760a47 Changes to Motion, Motor and Music Library
Motion library still needs to be fixed. Don't use yet.
2013-01-24 21:14:16 +01:00
Bill Verplank
fc8f353064 Bill's Protocol Pendulum Plot
Added force-out to pendulum
2013-01-24 16:52:11 +01:00
Bill Verplank
f6fcb48859 Bill - Pendulum and PendulumDamped 2013-01-24 16:06:22 +01:00
Bill Verplank
cd4fdfc907 Bills Pendulum Works! 2013-01-24 12:48:04 +01:00
Bill Verplank
b74972db16 Thursday Commit
including David's lib from yesterday
2013-01-24 12:11:56 +01:00
Jakob Bak
5912dfdcd4 Added some comment text for interrupt select and NUM_OSCILLATORS 2013-01-24 10:22:47 +01:00
Jakob Bak
642b4973ca Oscillator selects and examples
Made it possible to select type and number of oscillators to compile
(via preprocessor). Made Examples folder to library where  tutorials
will go in.
2013-01-23 19:29:16 +01:00
Bill Verplank
e1a7320aa6 wednesday commit 2013-01-23 17:09:16 +01:00
Bill Verplank
93da08c0ff cleaning up 2013-01-11 10:40:27 -08:00
Bill Verplank
80ce4b33a7 hmmmmm 2012-12-07 08:23:30 -08:00
Bill Verplank
00b1190817 edited GitHowTo
lines 4 and 20
2012-12-07 08:22:23 -08:00
Bill Verplank
4c9e2ee748 Getting Synched
First time after a lot of tries. -Bill
2012-12-07 08:18:28 -08:00
73 changed files with 3854 additions and 6079 deletions

4
README
View File

@ -1,4 +0,0 @@
WORK IN PROGRESS...
Motors & Music & Motions (M&M&M)
dviid, bill verplank, jakob bak

12
README.md Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Binary file not shown.

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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" : [ ]
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -1 +0,0 @@
//DampMass

File diff suppressed because it is too large Load Diff

View File

@ -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);
}
}

View File

@ -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" : [ ]
}
}

View File

@ -1,71 +0,0 @@
#include <Motion.h>
#include <Motor.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);
MotorA.init();
Serial.begin(9600);
MotionA.k = 0.2f;
MotionA.m = 0.3f;
MotionA.d = 0.02f;
}
void loop() {
if(MotionA.F < 0) MotorA.direction(FORWARD);
else MotorA.direction(BACKWARD);
float t = abs(MotionA.F);
MotorA.torque(t);
/*
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);
*/
}

View File

@ -1,63 +0,0 @@
// "Pendulum" - spring-mass oscillator
#include <Motion.h>
#include <Motor.h>
byte incomingByte;
void setup()
{
// init MotionA & MotorA
MotionA.init(INPUTA0);
MotorA.init();
// provide MotionA with initial physics constants
MotionA.k = 0.2f; // spring
MotionA.m = 0.3f; // mass
MotionA.d = 0.02f; // damping
Serial.begin(9600);
}
void loop(){
if(MotionA.F < 0) MotorA.direction(FORWARD);
else MotorA.direction(BACKWARD);
float t = abs(MotionA.F);
//if(t > 512) t = 512;
//MotorA.torque(t);
if (Serial.available() > 0) {
incomingByte = Serial.read();
if(incomingByte == '1'){
MotionA.m = MotionA.m * 1.1;
Serial.print("m: ");
Serial.println(MotionA.m);
}
else if(incomingByte == '!'){
MotionA.m = MotionA.m / 1.1;
Serial.print("m: ");
Serial.println(MotionA.m);
}
else if(incomingByte == '2'){
MotionA.k = MotionA.k * 1.1;
Serial.print("k: ");
Serial.println(MotionA.k);
}
else if(incomingByte == '@'){
MotionA.k = MotionA.k / 1.1;
Serial.print("k: ");
Serial.println(MotionA.k);
}
else if(incomingByte == '3'){
MotionA.d = MotionA.d * 1.1;
Serial.print("d: ");
Serial.println(MotionA.d);
}
else if(incomingByte == '#'){
MotionA.d = MotionA.d / 1.1;
Serial.print("d: ");
Serial.println(MotionA.d);
}
}
}

View File

@ -1,16 +0,0 @@
#include <Motor.h>
void setup()
{
MotorA.init();
MotorA.torque(255);
}
void loop()
{
MotorA.direction(FORWARD);
delay(1000);
MotorA.direction(BACKWARD);
delay(1000);
}

View File

@ -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();
}

View File

@ -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() {
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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());
}
}

View File

@ -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]);
}
}
}

View File

@ -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;
*/
}
}

View File

@ -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);
}

View 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);
}

View 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);
}
}

View 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];
}
}
}
}

View File

@ -0,0 +1,2 @@
mode.id=processing.mode.java.JavaMode
mode=Java

View File

@ -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]);
}
}

View File

@ -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();
}
}

View 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));
}
}

View 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");
}

View File

@ -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
}

View File

@ -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;

View File

@ -23,102 +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;
float T = N * 0.004f; // 4ms (see TCNT1)
int xin, dx;
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)
{
if(!motion_reg_init){
TCNT1 = 1000; //4 ms (TCNT1)
TIMSK1 = (1 << TOIE1);
motion_reg_init = true;
}
void Motion::init(SENSOR_INPUT sensor)
{
_i = true;
_s = sensor;
// initial values
d = 0;
k = 1;
m = 1;
tick = millis();
}
void Motion::set_force_callback(force_callback fcb, PHY physics) {
_fcb = fcb;
_fcb_phy = physics;
void Motion::update_position() {
Xin = analogRead(_s); // may take some time
}
void Motion::update_mass_spring_damper() {
// clocked at 4ms period
ISR(TIMER1_OVF_vect) {
TCNT1 = 1000;
// todo: filtering
if(MotionA._i) {
ADMUX = MotionA._s & 0x07;
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC));
lb = ADCL;
hb = ADCH;
long t = millis();
float dt = (float)(t - tick) / 100.0f;
xin = (hb << 8) | lb;
int xin = analogRead(_s); // may take some time, put: 512 - analogRead(_s);
MotionA.F = MotionA.k * (xin - MotionA.X) - (MotionA.d * MotionA.V);
MotionA.A = MotionA.F / MotionA.m;
MotionA.V += MotionA.A * T;
MotionA.X += MotionA.V * T;
Xin = xin;
F = k * (xin - X) - (d * V);
V += (F / m) * dt;
X += V * dt;
tick = t;
}
/*
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;
}
*/
}

View File

@ -32,7 +32,7 @@ enum MOTION {
MOTIONB = 1
};
enum INPUT {
enum SENSOR_INPUT {
INPUTA0 = 0x0000,
INPUTA1 = 0x0001,
INPUTA2 = 0x0010,
@ -43,36 +43,32 @@ enum INPUT {
INPUTA7 = 0x0111
};
enum PHY {
POSITION = 0,
VELOCITY = 1,
ACCELERATION = 2
};
class Motion {
public:
Motion(MOTION m);
void init(INPUT sensor);
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;
float X, V, A, F;
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;

34
software/lib/MMM/Motor.cpp Normal file → Executable file
View File

@ -23,6 +23,8 @@
#include "Motor.h"
#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#define RESOLUTION 65536
@ -46,20 +48,24 @@ void MMotor::init()
if(!reg_init){
//cli();
//direction pins are outputs
DDRD |= (1 << PD7);
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2);
DDRB |= (1 << PB0) | (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();
}
}
@ -67,8 +73,22 @@ void MMotor::init()
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;
}
@ -82,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
View File

@ -53,8 +53,7 @@ protected:
MOTOR _m;
DIRECTION _d;
int _t;
long _p;
int _t; // torque
};

View File

@ -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

View File

@ -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.

View File

@ -0,0 +1 @@
Put Motion Tutorial sketches in this folder

View File

@ -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);
}

View File

@ -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 ?
}

View File

@ -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);
}

View 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);
}

View 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);
}
}

View 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);
}
}

View File

@ -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);
}

View 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));
}

View File

@ -0,0 +1 @@
Put Motor Tutorial sketches in this folder

View File

@ -0,0 +1,12 @@
#include <Motor.h>
void setup() {
MotorA.init();
}
void loop() {
MotorA.torque(500);
delay(2000);
MotorA.torque(-500);
delay(2000);
}

View File

@ -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;
}

View File

@ -0,0 +1 @@
Put Music Tutorial sketches in this folder

View File

@ -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

View 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() {
}

View 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;
}
}

View File

@ -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;
}
}

View 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;
}
}

View File

@ -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() {
}

View File

@ -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);
@ -44,7 +46,7 @@ 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;

View File

@ -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);

View 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;
}
}

View File

@ -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;
}
}

View 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