
Dominik собрал детскую музыкальную RFID-шкатулку, которая играет мелодии, для выбора которых используются RFID-метки, встроенные в карточки с картинками.
демонстрационное видео — Contact-free jukebox:
Замечательный проект, в основе которого:
* контроллер Arduino,
* wave-Shield,
* считыватель RFID (ID-12 RFID reader),
* динамик,
* аккумулятор LiPoly ,
* зарядка USB LiPoly Charger.
Внутренности

Схема

Скетч
/*
jukebox
this is the firmware for the contact-free jukebox.
that can play audio tracks depending on rfid tags.
attached to the arduino is an adafruit waveshield
and an id-12 rfid reader.
created @ 8.1.12 by dominik grob (@ruedi)
more information: http://tmblr.co/ZKZ-twHiQ_OK
*/
#include <FatReader.h>
#include <SdReader.h>
#include <avr/pgmspace.h>
#include "WaveUtil.h"
#include "WaveHC.h"
#include <SoftwareSerial.h>
// audio settings
boolean PlayComplete = true;
long playnext_prevmillis = 0;
long playanother_time = 3000;
// sdcard settings
SdReader card;
FatVolume vol;
FatReader root;
FatReader f;
WaveHC wave;
// rfid settings
SoftwareSerial RFIDSerial(8, 6);
int RFIDResetPin = 7;
char RFIDtag[14];
int RFIDindex = 0;
boolean RFIDreading = false;
// define tag id and tracks
#define NUMTAGS 8
char audiotags[NUMTAGS][14] = {"0100C4B7B2C0",
"0100C4A04C29",
"0100C49F6339",
"0100C48689CA",
"0100C4868AC9",
"4800B48C4C3C",
"4800B4CD90A1",
"4800B4838BF4"};
// make sure soundfile names are not longer then 8 chars (without filetype)
char audiofiles[NUMTAGS][14] = {"elefant.wav",
"pinguin.wav",
"nikki.wav",
"wildsau.wav",
"esel.wav",
"papagei.wav",
"krokodil.wav",
"nacht.wav"};
void setup() {
Serial.begin(9600);
putstring_nl("debug");
putstring_nl("----------------");
putstring("Free RAM: ");
Serial.println(freeRam());
// set output pins for DAC control
// pins are defined in the library
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
// pin13 LED
pinMode(13, OUTPUT);
if (!card.init()) {
putstring_nl("Card init. failed!");
sdErrorCheck();
while(1);
}
// enable optimize read
card.partialBlockRead(true);
// fat partition?
uint8_t part;
for (part = 0; part < 5; part++) {
if (vol.init(card, part))
break;
}
if (part == 5) {
putstring_nl("No valid FAT partition!");
sdErrorCheck();
while(1);
}
// show infos
putstring("Using partition ");
Serial.print(part, DEC);
putstring(", type is FAT");
Serial.println(vol.fatType(),DEC);
if (!root.openRoot(vol)) {
putstring_nl("Can't open root dir!");
while(1);
}
putstring_nl("> sdcard ready");
// rfid setup
pinMode(RFIDResetPin, OUTPUT);
digitalWrite(RFIDResetPin, HIGH);
RFIDSerial.begin(9600);
putstring_nl("> rfid ready");
// play startup chime
delay(500); // avoid loudspeaker click noise
playcomplete("chime.wav");
}
void loop() {
RFIDindex = 0;
// rfid data?
while(RFIDSerial.available()) {
int readByte = RFIDSerial.read();
if(readByte == 2) RFIDreading = true;
if(readByte == 3) RFIDreading = false;
if(RFIDreading && readByte != 2 && readByte != 10 && readByte != 13){
RFIDtag[RFIDindex] = readByte;
RFIDindex++;
}
}
// check tag and play track if tag id found
checkTag(RFIDtag);
// prepare for next read
clearTag(RFIDtag);
resetReader();
}
void playcomplete(char *name) {
playfile(name);
while (wave.isplaying) {
// playing
}
}
void playfile(char *name) {
if (wave.isplaying) {
wave.stop();
}
if (!f.open(root, name)) {
putstring("Couldn't open file "); Serial.println(name); return;
}
if (!wave.create(f)) {
putstring_nl("Not a valid WAV"); return;
}
wave.play();
}
void resetReader() {
digitalWrite(RFIDResetPin, LOW);
digitalWrite(RFIDResetPin, HIGH);
delay(150);
}
void clearTag(char one[]) {
for(int i = 0; i < strlen(one); i++){
one[i] = 0;
}
}
void checkTag(char tag[]) {
if(strlen(tag) == 0) return;
boolean matching = true;
// compare tag id
for(int a = 0; a < NUMTAGS; a++) {
matching = true;
for(int c = 0; c < 12; c++) {
if(tag[c] != audiotags[a][c]) {
matching = false;
break;
}
}
// in case of a match play the track
if(matching) {
putstring("playing: "); Serial.println(audiofiles[a]);
delay(500); // avoid loudspeaker click noise
if(PlayComplete) {
digitalWrite(RFIDResetPin, LOW);
playcomplete(audiofiles[a]);
} else {
unsigned long playnext_currentmillis = millis();
// wait with playing another audio track
if(playnext_currentmillis - playnext_prevmillis > playanother_time) {
playfile(audiofiles[a]);
playnext_prevmillis = playnext_currentmillis;
}
}
break;
}
}
}
// ---------------------------
// debug functions
// ---------------------------
int freeRam(void) {
extern int __bss_end;
extern int *__brkval;
int free_memory;
if((int)__brkval == 0) {
free_memory = ((int)&free_memory) - ((int)&__bss_end);
}
else {
free_memory = ((int)&free_memory) - ((int)__brkval);
}
return free_memory;
}
void sdErrorCheck(void) {
if (!card.errorCode()) return;
putstring("\n\rSD I/O error: ");
Serial.print(card.errorCode(), HEX);
putstring(", ");
Serial.println(card.errorData(), HEX);
while(1);
}
проект на гитхабе:
https://github.com/robogrobo/Contact-free-jukebox
Ссылки
Contact-free jukebox
Arduino
Ардуино что это и зачем?
Arduino, термины, начало работы
КМБ для начинающих ардуинщиков
Состав стартера (точка входа для начинающих ардуинщиков)
