un bel lavoretto realizzato grazie alla sapiente programmazione di Dario Gavezzone . (La rima imponeva).
Tutta l'elettronica è basata su di un ATtiny 85, qualcosa in merito lo trovate anche QUI!
Lo schema a fritzing è un disastro:
più comprensibile lo schema dei soli led recuperato direttamente dalla pagina di wikipedia qui sotto:
Lo schema a fritzing è un disastro:
più comprensibile lo schema dei soli led recuperato direttamente dalla pagina di wikipedia qui sotto:
lo sketch è questo:
#include <avr/pgmspace.h> //This is in the Arduino library
// inizio implementazione assert con output in compilazione
#define CONCAT_TOKENS( TokenA, TokenB ) TokenA ## TokenB
#define EXPAND_THEN_CONCAT( TokenA, TokenB ) CONCAT_TOKENS( TokenA, TokenB )
#define ASSERT( Expression ) enum{ EXPAND_THEN_CONCAT( ASSERT_line_, __LINE__ ) = 1 / !!( Expression ) }
#define ASSERTM( Expression, Message ) enum{ EXPAND_THEN_CONCAT( Message ## _ASSERT_line_, __LINE__ ) = 1 / !!( Expression ) }
// fine implementazione assert con output in compilazione
#define ISDIGIT(n) (n >= '0' && n <= '9')
#define OCTAVE_OFFSET 0
#define SPEAKER_PIN 4
#define BUTTON_PIN 3
const int notes[] = { 0,
262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, // 4
523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, // 5
1047, 1109, 1175, 1245, 1319, 1397, 1480, 1568, 1661, 1760, 1865, 1976, // 6
2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951, // 7
};
char *songs[] = {
"R:d=4,o=5,b=160:8g,a,8g,e,c6,a,2g.,8g.,16a,8g.,16a,g,c6,1b,8f,g,8f,d,b,a,2g.,8g.,16a,8g.,16a,g,d6,2c.6",
"J:d=4,o=5,b=112:8a,8a,a,8a,8a,a,8a,8c6,8f.,16g,2a,8a#,8a#,8a#.,16a#,8a#,8a,8a.,16a,8a,8g,8g,8a,g,c6",
"W:d=8,o=5,b=140:4d,4g,g,a,g,f#,4e,4c,4e,4a,a,b,a,g,4f#,4d,4f#,4b,b,c6,b,a,4g,4e,4d,4e,4a,4f#,2g",
};
const char pins[] = {0, 1, 2};
const char ledPins[5][2] = {
{0, 1},
{1, 0},
{1, 2},
{2, 1},
{2, 0},
};
byte giro = 0;
byte j = 0;
#define NUM_OF_SONGS 3
#define NUM_OF_PINS (sizeof(pins) / sizeof(char))
#define NUM_OF_LEDS 5
ASSERT(NUM_OF_LEDS <= (NUM_OF_PINS * (NUM_OF_PINS-1)));
void setup(void) {
pinMode(SPEAKER_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop(void) {
alloff();
if ( digitalRead(BUTTON_PIN) == LOW ) {
play_rtttl(songs[giro]);
giro = (giro < (NUM_OF_SONGS -1)) ? giro + 1 : 0;
}
}
void play_rtttl(char *p) { // http://www.interactiondesign.se/wiki/attiny
// Absolutely no error checking in here
byte default_dur = 4;
byte default_oct = 6;
int bpm = 63;
int num;
long wholenote;
long duration;
byte note;
byte scale;
// format: d=N,o=N,b=NNN:
// find the start (skip name, etc)
// legge il titolo
while(*p != ':') p++; // ignore name
p++; // skip ':'
// get default duration
if(*p == 'd') {
p++; p++; // skip "d="
num = 0;
while(ISDIGIT(*p)) {
num = (num * 10) + (*p++ - '0');
}
if(num > 0) default_dur = num;
p++; // skip comma
}
// get default octave
if(*p == 'o') {
p++; p++; // skip "o="
num = *p++ - '0';
if(num >= 3 && num <=7) default_oct = num;
p++; // skip comma
}
// get BPM
if(*p == 'b') {
p++; p++; // skip "b="
num = 0;
while(ISDIGIT(*p)) {
num = (num * 10) + (*p++ - '0');
}
bpm = num;
p++; // skip colon
}
// quante note da un quarto stanno in un minuto
wholenote = (60 * 1000L / bpm) * 4 ; // this is the time for whole note (in milliseconds)
// now begin note loop
while(*p) {
// first, get note duration, if available
num = 0;
while(ISDIGIT(*p)) {
num = (num * 10) + (*p++ - '0');
}
if (num) duration = wholenote / num;
else duration = wholenote / default_dur; // we will need to check if we are a dotted note after
// now get the note
note = 0;
switch(*p) {
case 'c':
note = 1;
break;
case 'd':
note = 3;
break;
case 'e':
note = 5;
break;
case 'f':
note = 6;
break;
case 'g':
note = 8;
break;
case 'a':
note = 10;
break;
case 'b':
note = 12;
break;
case 'p':
default:
note = 0;
}
p++;
// now, get optional '#' sharp
if(*p == '#') {
note++;
p++;
}
// now, get optional '.' dotted note
if(*p == '.') {
duration += duration/2;
p++;
}
// now, get scale
if(ISDIGIT(*p)) {
scale = *p - '0';
p++;
} else {
scale = default_oct;
}
scale += OCTAVE_OFFSET;
if(*p == ',')
p++; // skip comma for next note (or we may be at the end)
// now play the note
if(note) {
freqout(notes[(scale - 4) * 12 + note], duration);
} else {
delay(duration);
}
}
}
void freqout(int freq, int t) {
freqout(freq, t, SPEAKER_PIN);
}
void freqout(int freq, int t, byte speaker) { // http://www.arduino.cc/playground/Main/Freqout
turnon(random(0, NUM_OF_LEDS - 1));
// freq in hz, t in ms
const int hperiod = 500000 / freq - 7; // subtract 7 us to make up for digitalWrite overhead
const long cycles = ((long)freq * (long)t) / 1000; // calculate cycles
pinMode(SPEAKER_PIN, OUTPUT); // turn on output pin
for (long i = 0; i <= cycles; i++) { // play note for t ms - SOFTWARE PWM?
digitalWrite(SPEAKER_PIN, HIGH);
delayMicroseconds(hperiod);
digitalWrite(SPEAKER_PIN, LOW);
delayMicroseconds(hperiod - 1); // - 1 to make up for digitaWrite overhead
pinMode(SPEAKER_PIN, INPUT); // shut off pin to avoid noise from other operations
// alloff();
// j = (j < (NUM_OF_LEDS - 1)) ? j + 1 : 0;
}
void turnon(int led) { // http://www.instructables.com/id/CharliePlexed-LED-string-for-the-Arduino/
// This turns on a certian led from the list of leds
int pospin = ledPins[led][0];
int negpin = ledPins[led][1];
pinMode (pospin, OUTPUT);
digitalWrite (pospin, HIGH);
pinMode (negpin, OUTPUT);
digitalWrite (negpin, LOW);
}
void alloff() { // http://www.instructables.com/id/CharliePlexed-LED-string-for-the-Arduino/
// This turns all the LED's off
for(int i = 0; i < NUM_OF_PINS; i++)
pinMode (pins[i], INPUT);
}