Hexi_Acceleromagnetic_Synth: Michael Yarnell, Alec Pierce, 2017 The program turns an NXP Hexiwear, its development board, and a Click buzzer collectively into an 'acceleromagnetic' synthesizer. That is to say that the synthesizer is controlled primarily via the on-board accelerometer and magnetometer units.
Dependencies: FXOS8700 Hexi_KW40Z NeatGUI PWM_6_Tone_Library
Revision 0:bec3a12e79e7, committed 2017-04-18
- Comitter:
- MTYarnell
- Date:
- Tue Apr 18 16:06:38 2017 +0000
- Commit message:
- Final build without hardware changes.
Changed in this revision
diff -r 000000000000 -r bec3a12e79e7 FXOS8700.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/FXOS8700.lib Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/AswinSivakumar/code/FXOS8700/#98ea52282575
diff -r 000000000000 -r bec3a12e79e7 Hexi_KW40Z.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexi_KW40Z.lib Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/Hexiwear/code/Hexi_KW40Z/#f6f9b24aea57
diff -r 000000000000 -r bec3a12e79e7 NeatGUI.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NeatGUI.lib Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/neilt6/code/NeatGUI/#a8f72d4864e6
diff -r 000000000000 -r bec3a12e79e7 PWM_Tone_Library.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PWM_Tone_Library.lib Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/MTYarnell/code/PWM_6_Tone_Library/#1d3262096227
diff -r 000000000000 -r bec3a12e79e7 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,242 @@ +/* Hexi_Acceleromagnetic_Synth + 2017 Michael Yarnell, Alec Pierce + Class Project: ECE49500 SP17 (MEMS/NEMS/IoT/Wearables) + IUPUI - Purdue School of Engineering and Technology + + The following program turns an NXP Hexiwear, its development board, and a Click + buzzer collectively into an 'acceleromagnetic' synthesizer. That is to say + that the synthsizer is controlled primarily via the onboard accelerometer and + magnetometer units. + Once the appropriate initializations have been made, the program plays a short, + preprogrammed tune. If, at any time, the left or right screen buttons are + pressed, they each emit unique "drumbeat" note sequences. The accelerometer + and magnetometer are read. The accelerometer x and y (pitch and roll, + respectively) control note selection. The magnetometer value RMS is + calculated, and if the magnetic field RMS is greater than 250uT, the + instrument will emit corresponding notes. + + Adapted from examples: + "Hexi_Magneto-v2_Example" + https://developer.mbed.org/teams/Hexiwear/code/Hexi_Magneto-v2_Example/ + "Hexi_Accelero-v2_Example" + https://developer.mbed.org/teams/Hexiwear/code/Hexi_Accelero-v2_Example/ + "Hexi_Click_Buzzer-v2_Example" + https://developer.mbed.org/teams/Hexiwear/code/Hexi_Click_Buzzer-v2_Example/ + "Hexi_Bubble_Game" + https://developer.mbed.org/teams/Hexiwear/code/Hexi_Bubble_Game/ +*/ + +// TYPEDEFS +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed long long int int64_t; +typedef unsigned long long int uint64_t; + +// LIBRARIES +// Note that pwm_6_tone.h has been modified from the default library header. +#include "mbed.h" +#include <pwm_6_tone.h> +#include "Hexi_KW40Z.h" +#include "FXOS8700.h" +#include "string.h" + +// PIN CONNECTIONS +// Define the Buzzer Pinout (PWM Out) +PwmOut Buzzer(PTA10); +// Instantiate the Hexi KW40Z Driver (UART TX, UART RX) +KW40Z kw40z_device(PTE24, PTE25); +// Accelerometer and Magnetometer instantiation +FXOS8700 mag(PTC11, PTC10); +FXOS8700 accel(PTC11, PTC10); +// Initialize Face LED +DigitalOut led1(LED_GREEN); +// Initialize Serial port +//Serial pc(USBTX, USBRX); // Include to debug modified sensor values + // or enter a practice mode. + +// VARIABLES +float accel_data[3]; // Storage for the data from the sensor +float mag_data[3]; // Storage for the data from the sensor +float mag_rms=0.0; // RMS value to be computed from sensor input + + // From Bubble +int xposg = 0; // The roll position of the unit +int yposg = 0; // The pitch position of the unit + + // New Variables + // Note is a floating-point value that bears a number to send to the + // Tune function. +float Note = 0.0; + // This table holds the values determined to play the appropriate notes + // as reverse-engineered from the values in + // "Hexi_Click_Buzzer-v2_Example" to widen range to nearly six octaves. +float C_1 = 1000000/Do1, Cs_1 = 1000000/Do1s, D_1 = 1000000/Re1, Ds_1 = 1000000/Re1s, + E_1 = 1000000/Mi1, F_1 = 1000000/Fa1, Fs_1 = 1000000/Fa1s, G_1 = 1000000/So1, + Gs_1 = 1000000/So1s, A_1 = 1000000/La1, As_1 = 1000000/La1s, B_1 = 1000000/Ti1, + + C_2 = 1000000/Do2, Cs_2 = 1000000/Do2s, D_2 = 1000000/Re2, Ds_2 = 1000000/Re2s, + E_2 = 1000000/Mi2, F_2 = 1000000/Fa2, Fs_2 = 1000000/Fa2s, G_2 = 1000000/So2, + Gs_2 = 1000000/So2s, A_2 = 1000000/La2, As_2 = 1000000/La2s, B_2 = 1000000/Ti2, + + C_3 = 1000000/Do3, Cs_3 = 1000000/Do3s, D_3 = 1000000/Re3, Ds_3 = 1000000/Re3s, + E_3 = 1000000/Mi3, F_3 = 1000000/Fa3, Fs_3 = 1000000/Fa3s, G_3 = 1000000/So3, + Gs_3 = 1000000/So3s, A_3 = 1000000/La3, As_3 = 1000000/La3s, B_3 = 1000000/Ti3, + + C_4 = 1000000/Do4, Cs_4 = 1000000/Do4s, D_4 = 1000000/Re4, Ds_4 = 1000000/Re4s, + E_4 = 1000000/Mi4, F_4 = 1000000/Fa4, Fs_4 = 1000000/Fa4s, G_4 = 1000000/So4, + Gs_4 = 1000000/So4s, A_4 = 1000000/La4, As_4 = 1000000/La4s, B_4 = 1000000/Ti4, + + C_5 = 1000000/Do5, Cs_5 = 1000000/Do5s, D_5 = 1000000/Re5, Ds_5 = 1000000/Re5s, + E_5 = 1000000/Mi5, F_5 = 1000000/Fa5, Fs_5 = 1000000/Fa5s, G_5 = 1000000/So5, + Gs_5 = 1000000/So5s, A_5 = 1000000/La5, As_5 = 1000000/La5s, B_5 = 1000000/Ti5, + + C_6 = 1000000/Do6, Cs_6 = 1000000/Do6s, D_6 = 1000000/Re6, Ds_6 = 1000000/Re6s, + E_6 = 1000000/Mi6, F_6 = 1000000/Fa6, Fs_6 = 1000000/Fa6s, G_6 = 1000000/So6, + Gs_6 = 1000000/So6s, A_6 = 1000000/La6, As_6 = 1000000/La6s, B_6 = 1000000/Ti6; + +//FUNCTIONS +void ButtonLeft(void) +{ +// "Beat" 1 + Tune(Buzzer, C_5, 1); Tune(Buzzer, E_2, 1); + Tune(Buzzer, C_5, 1); Tune(Buzzer, E_1, 1); +} + +void ButtonRight(void) +{ +// "Beat" 2 + Tune(Buzzer, C_3, 1); Tune(Buzzer, E_2, 1); + Tune(Buzzer, C_1, 1); Tune(Buzzer, E_1, 1); +} + +int main() +{ +// Instantiate Buttons + kw40z_device.attach_buttonLeft(&ButtonLeft); + kw40z_device.attach_buttonRight(&ButtonRight); + +// Configure Accelerometer, Magnetometer FXOS8700 + accel.accel_config(); + mag.mag_config(); + +// Startup tune tones + Tune(Buzzer, D_6, 2); wait_ms(5); Tune(Buzzer, D_4, 2); wait_ms(5); + Tune(Buzzer, C_5, 2); wait_ms(5); Tune(Buzzer, D_4, 4); wait_ms(5); + Tune(Buzzer, D_2, 4); wait_ms(5); Tune(Buzzer, Cs_1, 2); wait_ms(10); + Tune(Buzzer, C_1, 16); wait_ms(10); Tune(Buzzer, C_2, 8); wait_ms(25); + Tune(Buzzer, C_3, 4); wait_ms(60); Tune(Buzzer, C_4, 2); wait_ms(40); + Tune(Buzzer, C_5, 4); wait_ms(100); + +// This loop, modified from from the Bubble game example, locates the +// x/y accelerometer information (within boundaries) to determine +// the position of the user and thus the note to play. + while(1) { + +// Get accelerometer data + accel.acquire_accel_data_g(accel_data); + xposg=(accel_data[1] * (-20.0)); + if (xposg > 30) xposg = 30; // Notes: 12 per octave + if (xposg < -30) xposg = -30; + yposg=(accel_data[0] * (40.0)); + if (yposg > 30) yposg = 30; // Octaves: 6 available + if (yposg < -30) yposg = -30; + +// Find Note +// Program first attempts to find Octave from accelerometer y values. +// Then it further determines the and assigns the value of the note +// from the x value. + + if (yposg > 29) { // Octave 1 + if (xposg > 20) Note = C_1; // C + if (xposg > 16) Note = Cs_1; // Cs + if (xposg > 12) Note = D_1; // D + if (xposg > 8) Note = Ds_1; // Ds + if (xposg > 4) Note = E_1; // E + if (xposg >= 0) Note = F_1; // F + if (xposg > -4) Note = Fs_1; // Fs + if (xposg > -8) Note = G_1; // G + if (xposg > -12) Note = Gs_1; // Gs + if (xposg > -16) Note = A_1; // A + if (xposg > -20) Note = As_1; // As + else Note = B_1; // B + } else if (yposg > 15) { // Octave 2 + if (xposg > 20) Note = C_2; // C + if (xposg > 16) Note = Cs_2; // Cs + if (xposg > 12) Note = D_2; // D + if (xposg > 8) Note = Ds_2; // Ds + if (xposg > 4) Note = E_2; // E + if (xposg >= 0) Note = F_2; // F + if (xposg > -4) Note = Fs_2; // Fs + if (xposg > -8) Note = G_2; // G + if (xposg > -12) Note = Gs_2; // Gs + if (xposg > -16) Note = A_2; // A + if (xposg > -20) Note = As_2; // As + else Note = B_2; // B + } else if (yposg >= 0) { // Octave 3 + if (xposg > 20) Note = C_3; // C + if (xposg > 16) Note = Cs_3; // Cs + if (xposg > 12) Note = D_3; // D + if (xposg > 8) Note = Ds_3; // Ds + if (xposg > 4) Note = E_3; // E + if (xposg >= 0) Note = F_3; // F + if (xposg > -4) Note = Fs_3; // Fs + if (xposg > -8) Note = G_3; // G + if (xposg > -12) Note = Gs_3; // Gs + if (xposg > -16) Note = A_3; // A + if (xposg > -20) Note = As_3; // As + else Note = B_3; // B + } else if (yposg > -15) { // Octave 4 + if (xposg > 20) Note = C_4; // C + if (xposg > 16) Note = Cs_4; // Cs + if (xposg > 12) Note = D_4; // D + if (xposg > 8) Note = Ds_4; // Ds + if (xposg > 4) Note = E_4; // E + if (xposg >= 0) Note = F_4; // F + if (xposg > -4) Note = Fs_4; // Fs + if (xposg > -8) Note = G_4; // G + if (xposg > -12) Note = Gs_4; // Gs + if (xposg > -16) Note = A_4; // A + if (xposg > -20) Note = As_4; // As + else Note = B_4; // B + } else if (yposg > -29) { // Octave 5 + if (xposg > 20) Note = C_5; // C + if (xposg > 16) Note = Cs_5; // Cs + if (xposg > 12) Note = D_5; // D + if (xposg > 8) Note = Ds_5; // Ds + if (xposg > 4) Note = E_5; // E + if (xposg >= 0) Note = F_5; // F + if (xposg > -4) Note = Fs_5; // Fs + if (xposg > -8) Note = G_5; // G + if (xposg > -12) Note = Gs_5; // Gs + if (xposg > -16) Note = A_5; // A + if (xposg > -20) Note = As_5; // As + else Note = B_5; // B + } else { // Octave 6 + if (xposg > 20) Note = C_6; // C + if (xposg > 16) Note = Cs_6; // Cs + if (xposg > 12) Note = D_6; // D + if (xposg > 8) Note = Ds_6; // Ds + if (xposg > 4) Note = E_6; // E + if (xposg >= 0) Note = F_6; // F + if (xposg > -4) Note = Fs_6; // Fs + if (xposg > -8) Note = G_6; // G + if (xposg > -12) Note = Gs_6; // Gs + if (xposg > -16) Note = A_6; // A + if (xposg > -20) Note = As_6; // As + else Note = B_6; // B + } + +// Get magnetometer data + mag.acquire_mag_data_uT(mag_data); +// Find RMS values of this 3-axis reading + mag_rms = sqrt(((mag_data[0] * mag_data[0]) + (mag_data[1] * mag_data[1]) + (mag_data[2] * mag_data[2])) / 3); + + //printf("\tX: %i \tY: %i \tMAGRMS: %i", xposg, yposg, mag_rms); + // Above line displays modified sensor results, useful for practice or + // debugging. + +// If the magnetic field is strong enough, play a note. + if (mag_rms > 150) { + Tune(Buzzer, Note, 2); }// Timing is out of 16ths + } +} \ No newline at end of file
diff -r 000000000000 -r bec3a12e79e7 mbed-os.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#a6f3fd1a60d5df59246d7caf3f108c4d34e1808e
diff -r 000000000000 -r bec3a12e79e7 pwm_6_tone.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pwm_6_tone.h Tue Apr 18 16:06:38 2017 +0000 @@ -0,0 +1,97 @@ +/* Modified as part of "Hexi_Acceleromagnetic_Synth" + 2017 Michael Yarnell, Alec Pierce + Class Project: ECE49500 SP17 (MEMS/NEMS/IoT/Wearables) + IUPUI - Purdue School of Engineering and Technology + + Octaves 1, 2, and 6 were added after calculation based on 3, 4, and 5. + +** Includes ------------------------------------------------------------------*/ +#include "mbed.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define Do1 33 //C octave1 +#define Do1s 35 //C# +#define Re1 37 //D +#define Re1s 39 //D# +#define Mi1 41 //E +#define Fa1 44 //F +#define Fa1s 46 //F# +#define So1 49 //G +#define So1s 52 //G# +#define La1 55 //A +#define La1s 58 //A# +#define Ti1 62 //B + +#define Do2 66 //C octave2 +#define Do2s 69 //C# +#define Re2 74 //D +#define Re2s 78 //D# +#define Mi2 83 //E +#define Fa2 87 //F +#define Fa2s 93 //F# +#define So2 98 //G +#define So2s 104 //G# +#define La2 110 //A +#define La2s 117 //A# +#define Ti2 124 //B + +#define Do3 131 //C octave3 +#define Do3s 139 //C# +#define Re3 147 //D +#define Re3s 156//D# +#define Mi3 165 //E +#define Fa3 175 //F +#define Fa3s 185 //F# +#define So3 196 //G +#define So3s 208 //G# +#define La3 220 //A +#define La3s 233 //A# +#define Ti3 247 //B + +#define Do4 262 //C octave4 +#define Do4s 277 //C# +#define Re4 294 //D +#define Re4s 311//D# +#define Mi4 330 //E +#define Fa4 349 //F +#define Fa4s 370 //F# +#define So4 392 //G +#define So4s 415 //G# +#define La4 440 //A +#define La4s 466 //A# +#define Ti4 494 //B + +#define Do5 523 //C octave5 +#define Do5s 554 //C# +#define Re5 587 //D +#define Re5s 622//D# +#define Mi5 659 //E +#define Fa5 699 //F +#define Fa5s 740 //F# +#define So5 784 //G +#define So5s 831 //G# +#define La5 880 //A +#define La5s 932 //A# +#define Ti5 988 //B + +#define Do6 1045 //C octave6 +#define Do6s 1107 //C# +#define Re6 1173 //D +#define Re6s 1243 //D# +#define Mi6 1317 //E +#define Fa6 1395 //F +#define Fa6s 1478 //F# +#define So6 1566 //G +#define So6s 1659 //G# +#define La6 1757 //A +#define La6s 1861 //A# +#define Ti6 1972 //B + +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +void Tune(PwmOut name, int period, int beat); +void Auto_tunes(PwmOut name, int period, int beat); +void Stop_tunes(PwmOut name); + +/* Private functions ---------------------------------------------------------*/