PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : NIBObee - Play Bach!



nibo
07.11.2011, 09:48
Hallo,

habe eine Melodie von J. S. Bach für den NIBObee umgesetzt. Die Melodie wird von den Motoren gesummt, die LEDs leuchten im Takt dazu.

Vielleicht errät jemand, was es für ein Stück ist? :)


/**
* @brief Play a melody from J. S. Bach.
* Push the left sensor to modify the speed.
* Push the right sensor to modify the sound volume.
*
* The sound quality depends on the underground, how many mechanical parts can vibrate
* on the robot, how the spheres are installed, the volume, etc..
*
* tip Hold the wheels with all fingers to feel the music :)
* This also may reduce rasping/scratchy sound.
*
*
* @author Oliver G.
* @date 2011-10-24
* @version 1.0
*/
#include <nibobee/iodefs.h>
#include <nibobee/led.h>
#include <nibobee/delay.h>
#include <nibobee/sens.h>
#include <nibobee/motpwm.h>
#include <math.h>


volatile uint8_t pulse; // helper for timing
uint16_t noteCnt; // current note of the melody
uint16_t beeperVolume;
uint8_t beeperActive;
uint16_t speed; // length of one note in ms (so actually 1/speed)


void playNote(uint8_t note);
void playNoteTime(uint8_t note, uint16_t time);
void playScales();
void initBeeper();
void listenSensorInput();


// Note names as used by european musicians. a1 = a' = 440 Hz
// (x)es names are missing, but you know that cis' = des' etc.
enum {
_C, _Cis, _D, _Dis, _E, _F, _Fis, _G, _Gis, _A, _Ais, _H,
_c, _cis, _d, _dis, _e, _f, _fis, _g, _gis, _a, _ais, _h,
c1, cis1, d1, dis1, e1, f1, fis1, g1, gis1, a1, ais1, h1,
c2, cis2, d2, dis2, e2, f2, fis2, g2, gis2, a2, ais2, h2,
c3, cis3, d3, dis3, e3, f3, fis3, g3, gis3, a3, ais3, h3, c4
};

// frequencies for _c to _h, the remaining notes will be computed
float freqTable[] = {
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94
};

// Some nice melody from J.S. Bach!
// we don't need information about the note length,
// cause we can recognize this melody with equal note lengths
uint8_t melody[] = {
c1, e1, g1, c2, e2, g1, c2, e2, c1, e1, g1, c2, e2, g1, c2, e2,
c1, d1, a1, d2, f2, a1, d2, f2, c1, d1, a1, d2, f2, a1, d2, f2,
_h, d1, g1, d2, f2, g1, d2, f2, _h, d1, g1, d2, f2, g1, d2, f2,
c1, e1, g1, c2, e2, g1, c2, e2, c1, e1, g1, c2, e2, g1, c2, e2,
c1, e1, a1, e2, a2, a1, e2, a2, c1, e1, a1, e2, a2, a1, e2, a2,
c1, d1, fis1, a1, d2, fis1, a1, d2, c1, d1, fis1, a1, d2, fis1, a1, d2,
_h, d1, g1, d2, g2, g1, d2, g2, _h, d1, g1, d2, g2, g1, d2, g2,
_h, c1, e1, g1, c2, e1, g1, c2, _h, c1, e1, g1, c2, e1, g1, c2,
_a, c1, e1, g1, c2, e1, g1, c2, _a, c1, e1, g1, c2, e1, g1, c2,
_d, _a, d1, fis1, c2, d1, fis1, c2, _d, _a, d1, fis1, c2, d1, fis1, c2,
_g, _h, d1, g1, h1, d1, g1, h1, _g, _h, d1, g1, h1, d1, g1, h1,
_g, _ais, e1, g1, cis2, e1, g1, cis2, _g, _ais, e1, g1, cis2, e1, g1, cis2,
_f, _a, d1, a1, d2, d1, a1, d2, _f, _a, d1, a1, d2, d1, a1, d2,
_f, _gis, d1, f1, h1, d1, f1, h1, _f, _gis, d1, f1, h1, d1, f1, h1,
_e, _g, c1, g1, c2, c1, g1, c2, _e, _g, c1, g1, c2, c1, g1, c2,
_e, _f, _a, c1, f1, _a, c1, f1, _e, _f, _a, c1, f1, _a, c1, f1,
_d, _f, _a, c1, f1, _a, c1, f1, _d, _f, _a, c1, f1, _a, c1, f1,
_G, _d, _g, _h, f1, _g, _h, f1, _G, _d, _g, _h, f1, _g, _h, f1,
_c, _e, _g, c1, e1, _g, c1, e1, _c, _e, _g, c1, e1, _g, c1, e1,
c1 // melody shortened here...
};


int main() {
motpwm_init();
led_init();
sens_init();
initBeeper(); // (i'm used to camel case naming...)

speed = 130;
beeperVolume = 500;

playScales();

uint8_t i = 3;
while (i-- > 0) {
// short pause
beeperActive = 0;
delay(500);
beeperActive = 1;

noteCnt = 0;
while (noteCnt < sizeof(melody)) {
playNote(melody[noteCnt]);
noteCnt++;
}
delay(4 * speed); // hold last note of the melody
speed -= 20; // play melody a bit faster next time
}

beeperActive = 0;
delay(100);
disable_interrupts();
return 0;
}


/**
* Listen for some user/sensor input.
*/
void listenSensorInput() {
if (sens_getLeft()) {
speed += 10 * sens_getLeft();
while (sens_getLeft());
}
if (sens_getRight()) {
beeperVolume += 100 * sens_getRight();
while (sens_getRight());
}
}


/**
* Play the given note and hold it for the time defined in global var: speed.
*/
void playNote(uint8_t note) {
playNoteTime(note, speed);
}


/**
* Play the given note for the given time (milliseconds).
*/
void playNoteTime(uint8_t note, uint16_t time) {

uint8_t octave = note / 12;

float frequency = freqTable[note%12] * (1<<octave);

// set prescaler and compare value which will trigger interrupt
if (octave == 0) {
TCCR0 = (1<<WGM01) | (1<<CS00) | (1<<CS02); // set prescaler to 1024
OCR0 = roundf( (F_CPU / 1024.0f) / frequency) -1;
} else if (octave <= 2) {
TCCR0 = (1<<WGM01) | (1<<CS02); // set prescaler to 256
OCR0 = roundf( (F_CPU / 256.0f) / frequency) -1;
} else {
TCCR0 = (1<<WGM01) | (1<<CS00) | (1<<CS01); // set prescaler to 64
OCR0 = roundf( (F_CPU / 64.0f) / frequency) -1;
}

delay(time);

/* Uncomment this code for a little pause between the notes
TCCR0 = 0;
motpwm_setLeft(0);
motpwm_setRight(0);
delay(time/3); */

listenSensorInput();
}


/**
* Play some standard scales for sound check.
*/
void playScales() {
// chromatic scale
for (int i = 0; i < 5 * 12; i++)
playNoteTime(i, 20);

// 4 octaves c major scale
uint8_t cMajorScale[] = {
_c, _d, _e, _f, _g, _a, _h,
c1, d1, e1, f1, g1, a1, h1,
c2, d2, e2, f2, g2, a2, h2,
c3, d3, e3, f3, g3, a3, h3, c4
};
for (int i = 0; i < sizeof(cMajorScale); i++)
playNoteTime(cMajorScale[i], 100);
}


/**
* Config timer 0 and set beeper active.
*/
void initBeeper() {
TCCR0 = (1<<WGM01); // set CTC modus
TCCR0 |= (1<<CS02); // set prescaler to 256

OCR0 = (F_CPU/256) / 440 -1; // (value overwritten later)
TIMSK |= (1<<OCIE0); // allow compare interrupt

beeperActive = 1;
enable_interrupts();
}


/**
* Compare interrupt handler
* Is called if TCNT0 = OCR0
*/
ISR (TIMER0_COMP_vect) {

if (beeperActive) {

// let the motor turn left and right quickly to create some noise
// the led_set() calls are just added to create some light effect sync. to the melody
// the noteCnt % 8 distinction is also just for an effect - so deep notes are played on left,
// higher notes on the right motor
if (pulse++ % 2 == 0) {
if (noteCnt % 8 <= 1 ) {
led_set(3, 0);
led_set(2, 0);
led_set(noteCnt % 2, 1);
led_set(!(noteCnt % 2) , 0);

motpwm_setLeft(beeperVolume);
motpwm_setRight(0);
} else {
led_set(noteCnt % 2 + 2, 1);
led_set(!(noteCnt % 2) + 2, 0);
led_set(0, 0);
led_set(1, 0);

motpwm_setRight(beeperVolume);
motpwm_setLeft(0);
}
} else {
if (noteCnt % 8 <= 1) {
motpwm_setLeft(-beeperVolume);
motpwm_setRight(0);
} else {
motpwm_setRight(-beeperVolume);
motpwm_setLeft(0);
}
}
} else {
motpwm_setLeft(0);
motpwm_setRight(0);
}
}


Für Ideen, Anregungen, Verbesserungsvorschläge zum Programm/Code habe ich jederzeit ein offenes Ohr.

Das Projekt ist auch hier mit Source und Binary online: http://roboter.cc/index.php?option=com_nicaiwci&view=project&projectid=294

Viel Spaß und schöne Grüße,
Oliver G.

thewulf00
07.11.2011, 14:32
*sing* Wir wolln ein VIDEO sehn! Wir wolln ein Video sehn, wir wolln, wir wolln ein Video sehn!

mschilde
20.12.2011, 22:05
Hallo,

seit zwei Wochen Besitzer eines NIBObee.
(Mit Erfolg aufgebaut, in Betrieb genommen, vieles getestet -- hat eigentlich immer funktioniert).
Heute mein Problem: das Programm aus dem Beitrag meldet beim kompilieren Fehler. (sehe Anlage).
Ist da was beim Veröffentlichen falsch gelaufen oder habe ich irgendwo was falsch gemacht.
Kann mann denn nicht auch einen Port als Ausgang definieren, an einen MiniLautsprecher hängen und dann mit entsprechenden Befehlen ansteuern.

Hoffe auf Tipps

mschilde

Taramtamtam
20.12.2011, 22:53
*sing* Wir wolln ein VIDEO sehn! Wir wolln ein Video sehn, wir wolln, wir wolln ein Video sehn!

Ja, ich auch... Früher gabs mal Floppymusik auf dem Amiga 500... Bitte ein Video !!!

Taramtamtam
20.12.2011, 22:59
Orchestersuite Nr. 1 - kommt jetzt das Video ???

geekalert
21.12.2011, 11:10
Bach's Präludium Nr. 1 C-Dur (BWV 846) ... mein Klavierunterricht ist zwar eine Ewigkeit her, aber die ersten paar Noten erkenne ich trotzdem wieder. So, was hab ich gewonnen? Ein Video vielleicht? ;)
Flo

Taramtamtam
21.12.2011, 11:49
Hab bei youtube (http://www.youtube.com/watch?v=uT0JOIPxyE8) das besagte Video gefunden (Amiga 500 Floppymusic)... Ich hatte zwar damals ein anderes auf meinem Amiga aber das hier ist auch nicht schlecht ;)

radbruch
23.12.2011, 16:58
Hallo

asuro und probot haben einen ähnlichen Antrieb und können das auch:

https://www.roboternetz.de/community/threads/28675-ASURO-DDS
https://www.roboternetz.de/community/threads/28675-ASURO-DDS?p=459189&viewfull=1#post459189

Gruß

mic

gateway
04.01.2014, 05:11
Hallo,

ich grabe eigentlich ungern 2 Jahre alte Threads aus, aber ich wollte andererseits auch keinen Neuen dafür öffnen.

Ich habe das playbach Programm für den ATMega1284p angepasst, der im Tuningkit von Nicai Systems enthalten ist.

Vielleicht nützt es ja jemandem ;)



/**
* @brief Play a melody from J. S. Bach.
* Push the left sensor to modify the speed.
* Push the right sensor to modify the sound volume.
*
* The sound quality depends on the underground, how many mechanical parts can vibrate
* on the robot, how the spheres are installed, the volume, etc..
*
* tip Hold the wheels with all fingers to feel the music :)
* This also may reduce rasping/scratchy sound.
*
* Thanks to Oliver G. for the Version for ATMega16. I only ported it to 1284p.
*
* @author Philipp Stiegler
* @date 2014-01-03
* @version 1.0-1284p
*/
#include <nibobee/iodefs.h>
#include <nibobee/led.h>
#include <nibobee/delay.h>
#include <nibobee/sens.h>
#include <nibobee/motpwm.h>
#include <math.h>




volatile uint8_t pulse; // helper for timing
uint16_t noteCnt; // current note of the melody
uint16_t beeperVolume;
uint8_t beeperActive;
uint16_t speed; // length of one note in ms (so actually 1/speed)


void playNote(uint8_t note);
void playNoteTime(uint8_t note, uint16_t time);
void playScales();
void initBeeper();
void listenSensorInput();


// Note names as used by european musicians. a1 = a' = 440 Hz
// (x)es names are missing, but you know that cis' = des' etc.
enum {
_C, _Cis, _D, _Dis, _E, _F, _Fis, _G, _Gis, _A, _Ais, _H,
_c, _cis, _d, _dis, _e, _f, _fis, _g, _gis, _a, _ais, _h,
c1, cis1, d1, dis1, e1, f1, fis1, g1, gis1, a1, ais1, h1,
c2, cis2, d2, dis2, e2, f2, fis2, g2, gis2, a2, ais2, h2,
c3, cis3, d3, dis3, e3, f3, fis3, g3, gis3, a3, ais3, h3, c4
};

// frequencies for _c to _h, the remaining notes will be computed
float freqTable[] = {
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185, 196, 207.65, 220, 233.08, 246.94
};

// Some nice melody from J.S. Bach!
// we don't need information about the note length,
// cause we can recognize this melody with equal note lengths
uint8_t melody[] = {
c1, e1, g1, c2, e2, g1, c2, e2, c1, e1, g1, c2, e2, g1, c2, e2,
c1, d1, a1, d2, f2, a1, d2, f2, c1, d1, a1, d2, f2, a1, d2, f2,
_h, d1, g1, d2, f2, g1, d2, f2, _h, d1, g1, d2, f2, g1, d2, f2,
c1, e1, g1, c2, e2, g1, c2, e2, c1, e1, g1, c2, e2, g1, c2, e2,
c1, e1, a1, e2, a2, a1, e2, a2, c1, e1, a1, e2, a2, a1, e2, a2,
c1, d1, fis1, a1, d2, fis1, a1, d2, c1, d1, fis1, a1, d2, fis1, a1, d2,
_h, d1, g1, d2, g2, g1, d2, g2, _h, d1, g1, d2, g2, g1, d2, g2,
_h, c1, e1, g1, c2, e1, g1, c2, _h, c1, e1, g1, c2, e1, g1, c2,
_a, c1, e1, g1, c2, e1, g1, c2, _a, c1, e1, g1, c2, e1, g1, c2,
_d, _a, d1, fis1, c2, d1, fis1, c2, _d, _a, d1, fis1, c2, d1, fis1, c2,
_g, _h, d1, g1, h1, d1, g1, h1, _g, _h, d1, g1, h1, d1, g1, h1,
_g, _ais, e1, g1, cis2, e1, g1, cis2, _g, _ais, e1, g1, cis2, e1, g1, cis2,
_f, _a, d1, a1, d2, d1, a1, d2, _f, _a, d1, a1, d2, d1, a1, d2,
_f, _gis, d1, f1, h1, d1, f1, h1, _f, _gis, d1, f1, h1, d1, f1, h1,
_e, _g, c1, g1, c2, c1, g1, c2, _e, _g, c1, g1, c2, c1, g1, c2,
_e, _f, _a, c1, f1, _a, c1, f1, _e, _f, _a, c1, f1, _a, c1, f1,
_d, _f, _a, c1, f1, _a, c1, f1, _d, _f, _a, c1, f1, _a, c1, f1,
_G, _d, _g, _h, f1, _g, _h, f1, _G, _d, _g, _h, f1, _g, _h, f1,
_c, _e, _g, c1, e1, _g, c1, e1, _c, _e, _g, c1, e1, _g, c1, e1,
c1 // melody shortened here...
};


int main() {
motpwm_init();
led_init();
sens_init();
initBeeper(); // (i'm used to camel case naming...)

speed = 130;
beeperVolume = 500;

playScales();

uint8_t i = 3;
while (i-- > 0) {
// short pause
beeperActive = 0;
delay(500);
beeperActive = 1;

noteCnt = 0;
while (noteCnt < sizeof(melody)) {
playNote(melody[noteCnt]);
noteCnt++;
}
delay(4 * speed); // hold last note of the melody
speed -= 20; // play melody a bit faster next time
}

beeperActive = 0;
delay(100);
disable_interrupts();
return 0;
}


/**
* Listen for some user/sensor input.
*/
void listenSensorInput() {
if (sens_getLeft()) {
speed -= 10 * sens_getLeft();
while (sens_getLeft());
}
if (sens_getRight()) {
beeperVolume += 100 * sens_getRight();
while (sens_getRight());
}
}


/**
* Play the given note and hold it for the time defined in global var: speed.
*/
void playNote(uint8_t note) {
playNoteTime(note, speed);
}


/**
* Play the given note for the given time (milliseconds).
*/
void playNoteTime(uint8_t note, uint16_t time) {

uint8_t octave = note / 12;

float frequency = freqTable[note%12] * (1<<octave);

// set prescaler and compare value which will trigger interrupt
if (octave == 0) {
TCCR0B |= (1<<CS00) | (1<<CS02); // set prescaler to 1024
TCCR0B &= ~((1<<CS01));
TCCR0A |= (1<<WGM01);
OCR0A = roundf( (16000000 / 1024.0f) / frequency) -1;
} else if (octave <= 2) {
TCCR0B |= (1<<CS02); // set prescaler to 256
TCCR0B &= ~((1<<CS00) | (1<<CS01));
TCCR0A |= (1<<WGM01);
OCR0A = roundf( (16000000 / 256.0f) / frequency) -1;
} else {
TCCR0B |= (1<<CS00) | (1<<CS01); // set prescaler to 64
TCCR0B &= ~((1<<CS02));
TCCR0A |= (1<<WGM01);
OCR0A = roundf( (16000000 / 64.0f) / frequency) -1;
}

delay(time);

/* Uncomment this code for a little pause between the notes
TCCR0 = 0;
motpwm_setLeft(0);
motpwm_setRight(0);
delay(time/3); */

listenSensorInput();
}


/**
* Play some standard scales for sound check.
*/
void playScales() {
// chromatic scale
for (int i = 0; i < 5 * 12; i++)
playNoteTime(i, 20);

// 4 octaves c major scale
uint8_t cMajorScale[] = {
_c, _d, _e, _f, _g, _a, _h,
c1, d1, e1, f1, g1, a1, h1,
c2, d2, e2, f2, g2, a2, h2,
c3, d3, e3, f3, g3, a3, h3, c4
};
for (int i = 0; i < sizeof(cMajorScale); i++)
playNoteTime(cMajorScale[i], 100);
}


/**
* Config timer 0 and set beeper active.
*/
void initBeeper() {
TCCR0A |= (1<<WGM01); // set CTC modus
TCCR0B |= (1<<CS02); // set prescaler to 256

OCR0A = (16000000/256) / 440 -1; // (value overwritten later)
TIMSK0 |= (1<<OCIE0B); // allow compare interrupt


beeperActive = 1;
enable_interrupts();
}


/**
* Compare interrupt handler
* Is called if TCNT0 = OCR0
*/
ISR (TIMER0_COMPB_vect) {


if (beeperActive) {

// let the motor turn left and right quickly to create some noise
// the led_set() calls are just added to create some light effect sync. to the melody
// the noteCnt % 8 distinction is also just for an effect - so deep notes are played on left,
// higher notes on the right motor
if (pulse++ % 2 == 0) {
if (noteCnt % 8 <= 1 ) {
led_set(3, 0);
led_set(2, 0);
led_set(noteCnt % 2, 1);
led_set(!(noteCnt % 2) , 0);

motpwm_setLeft(beeperVolume);
motpwm_setRight(0);
} else {
led_set(noteCnt % 2 + 2, 1);
led_set(!(noteCnt % 2) + 2, 0);
led_set(0, 0);
led_set(1, 0);

motpwm_setRight(beeperVolume);
motpwm_setLeft(0);
}
} else {
if (noteCnt % 8 <= 1) {
motpwm_setLeft(-beeperVolume);
motpwm_setRight(0);
} else {
motpwm_setRight(-beeperVolume);
motpwm_setLeft(0);
}
}
} else {
motpwm_setLeft(0);
motpwm_setRight(0);
}
}


Hier gibts nochmals die Sourcen und vorkompilierte Binaries...
http://www.roboter.cc/index.php?option=com_nicaiwci&view=project&Itemid=41&projectid=2324

Liebe Grüße
Philipp

EDIT:
Ein Video gibts hier:
http://www.youtube.com/watch?v=JPF5jKrtDwU