Shop-Wechsel

Der Warenkorb wird nicht übernommen.

Zum Firmenkunden / Bildungseinrichtungs Shop

Arduino

Abspielgerät über Serielle Schnittstelle steuern

Beiträge zu diesem Thema: 6

ELV Komplettbausatz Audio Shield für Arduino, ASA1

Artikel-Nr.: 105922

zum Produkt
Abspielgerät über Serielle Schnittstelle steuern
Antwort als hilfreich markieren
0Positive Markierungen
Antwort als nicht hilfreich markieren
0Negative Markierungen
Melden Sie diesen Beitrag
14.01.2014, 17:31
Guten Tag,

das Board funktioniert bei mir perfekt. Da ich während des Abspielvorganges noch sehr viele andere Berechnungen für mein Projekt durchführen muss, wird das Shield auf einem separaten Arduino betrieben. Für die Ansteuerung nutz ich die Serielle Schnittstelle. Die Schnittstelle läuft mit 115200 Baud, sodass hier möglichst wenig Verzögerungen auftreten.

Falls noch jemand das Programm gebrauchen kann:

Seriell senden:

  • pxxx => p=play, xxx=entspricht dem Mp3-File auf der SD Karte
  • lxxyyyzzz => l=loop, xx=Wiederholungsrate, yyy=Mp3-File, zzz=delay zwischen den wiedergaben
  • s => stop playing
  • + => volume + 1
  • ++ => volume + 10
  • - => volume - 1
  • -- => volume - 10
  • vxxx => v=set volume, xxx = Lautstärke zwischen 0 und 100 %
  • c => check liefert r=ready zurück wenn nichts abgespielt wird oder p=playing falls gerade ein sound läuft


Die Funktionen p liefert den wert s für started zurück,
Sobald ein Song zuende ist wird das "e" gesendet.

Code auf einem zweiten Arduino:
Ein möglicher Aufruf kann nun wie folgt aussehen:

// variante 1
Serial.println("p001"); // das mp3 mit der Bezeichnung 001.mp3 wird gestartet

// variante 2
Serial.println("p761"); // das mp3 001 wird gestoppt und das neue gestartet

// variante 3
Serial.println("c"); // liefert den Wert "p" zurück, da gerade mp3 761 abgespielt wird

// variante 4
Serial.println("v90"); // volumen wird auf 90% gesetzt

// variante 5
Serial.println("s"); // die Wiedergabe wird gestoppt



Quellcode auf dem Arduino mit dem ASA1 Shield


#include <SD.h>
#include <SPI.h>
#include <AudioShield.h>


// Description
//=======================
// pxxx | play song xxx.mp3 | returns 's' for start
// lxxyyyzzz | loop a song xx => loops, yyy => song yyy.mp3, zzz => delay between songs
// s | stop playing | return 'e' for end
// + | volume + 1
// ++ | volume + 10
// - | volume - 1
// -- | volume - 10
// v000 | volume between 0 and 100
// c | returns r when nothing is playing (r=ready) or p for playing

&*****************************************************************************
* globale Variablen
******************************************************************************/
#define SERIAL_BUFFER_CNT 12

char g_mp3_filename = "xxx.mp3";
uint8_t g_mp3_volume = 50;
unsigned char g_mp3_buffer;
File g_mp3_SoundFile;

char g_mp3_mode = 0;
char g_mp3_mode_old = 0;

char g_serial_buffer_read;
char g_serial_buffer;
unsigned char g_serial_cnt = 0;

uint8_t g_error_code = 0;

uint8_t g_loop_cnt = 0;
uint16_t g_loop_delay = 0;


&*****************************************************************************
* function
******************************************************************************/
&
* convertVolume: Wandelt das Volumen in einen Bereich zwischen 0 und 100 % um
*/
void mp3_convertAndSetVolume(unsigned char volume)
{
//check limit
if(volume > 100) {
volume = 100;
}

if(volume > 0) {
//volumen berechnen
volume = 120-(int)((double)(120./100*volume));
//Verstärker einschalten
VS1011.UnsetMute();
VS1011.SetVolume(volume, volume);
} else {
VS1011.SetMute();
}
}

&*****************************************************************************
* setup
******************************************************************************/
void setup()
{
Serial.begin(115200);
SPI.setClockDivider(2);

pinMode(SD_POWER, OUTPUT);
SD_POWER_ON; //SD-Karte low-aktiv

//SD-Karte initialisieren
//SD_CS als parameter übergeben, da hier ChipSelect anders belegt
if( SD.begin( SD_CS ) == false ){ return; }
Serial.println("r");

//MP3-Decoder initialisieren
VS1011.begin();
}

&*****************************************************************************
* loop
******************************************************************************/
void loop()
{
// reset serial input counter
g_serial_cnt = 0;

// get serial input data
while(Serial.available()) {
if(g_serial_cnt >= (SERIAL_BUFFER_CNT)) {
break;
} else {
g_serial_buffer_read = Serial.read();
g_serial_cnt++;
}
delay(5);
}

// clean serial input data
if(g_serial_cnt > 0) {
for(uint8_t i=0; i<(SERIAL_BUFFER_CNT-1);i++) {
g_serial_buffer = 0;
}
for(uint8_t i=0; i<g_serial_cnt; i++) {
g_serial_buffer = g_serial_buffer_read;
}
g_mp3_mode_old = g_mp3_mode;
g_mp3_mode = g_serial_buffer;
}
Serial.flush();


//select programm data
switch(g_mp3_mode) {

// -
// - system schleifen -
// -

// init audio player
case 1:
//open file
if(g_mp3_SoundFile = SD.open(g_mp3_filename)) {
mp3_convertAndSetVolume(g_mp3_volume); // Set Volume
g_mp3_mode = 3; // goto: play file
Serial.println("s");
} else {
g_mp3_mode = 0; // goto: nothing found
}
break;

// stop audio player
case 2:
mp3_convertAndSetVolume(0);
VS1011.Send2048Zeros();
g_mp3_mode = 0;
break;

// play audio file
case 3:
if(g_mp3_SoundFile.available()) {
g_mp3_SoundFile.read( g_mp3_buffer, sizeof(g_mp3_buffer) );
VS1011.Send32( g_mp3_buffer );
} else {
if(g_loop_cnt > 0) {
delay(g_loop_delay);
g_loop_cnt--;
g_mp3_mode = 1;
} else {
g_mp3_mode = 2; // Song Ende => goto: stop
Serial.println("e");
}
}
break;
// -
// - user input -
// -
case 'c':
if(g_mp3_mode_old == 3) {
Serial.println("p");
} else {
Serial.println("r");
}
g_mp3_mode = g_mp3_mode_old;
break;

//p => play xxx song
case 'p':
g_mp3_filename = g_serial_buffer;
g_mp3_filename = g_serial_buffer;
g_mp3_filename = g_serial_buffer;

g_mp3_mode = 1;
break;

//l => play song in loop
case 'l':
g_mp3_filename = g_serial_buffer;
g_mp3_filename = g_serial_buffer;
g_mp3_filename = g_serial_buffer;

g_loop_cnt = (g_serial_buffer-48)*10+(g_serial_buffer-48);
g_loop_delay = (g_serial_buffer-48)*100+(g_serial_buffer-48)*10+(g_serial_buffer-48);

g_mp3_mode = 1;
break;

//s => stop song
case 's':
g_mp3_mode = 2;
break;

//- => volume --
case '-':
if(g_serial_cnt == 1 && g_mp3_volume > 0) {
g_mp3_volume--;
} else if(g_serial_cnt == 2 && g_mp3_volume > 10) {
g_mp3_volume-= 10;
} else {
g_mp3_volume = 0;
}
mp3_convertAndSetVolume(g_mp3_volume);
g_mp3_mode = 3;
break;

//+ => volume ++
case '+':
if(g_serial_cnt == 1 && g_mp3_volume < 100) {
g_mp3_volume++;
} else if(g_serial_cnt == 2 && g_mp3_volume < 90) {
g_mp3_volume+= 10;
} else {
g_mp3_volume = 100;
}
mp3_convertAndSetVolume(g_mp3_volume);
g_mp3_mode = 3;
break;

// set volume
case 'v':
if(g_serial_cnt == 2) {
g_mp3_volume = (g_serial_buffer-48);
} else if(g_serial_cnt == 3) {
g_mp3_volume = (g_serial_buffer-48)*10+(g_serial_buffer-48);
} else if(g_serial_cnt == 4) {
g_mp3_volume = 100;
}
mp3_convertAndSetVolume(g_mp3_volume);
g_mp3_mode = 3;
break;

//other inputs
default:
break;
}
}


Anscheinend funktionieren hier die Code Tags nicht richtig. Die Zeilen mit gehören nicht in dem Programm Quelltext.

Aw: Abspielgerät über Serielle Schnittstelle steuern
Antwort als hilfreich markieren
0Positive Markierungen
Antwort als nicht hilfreich markieren
0Negative Markierungen
Melden Sie diesen Beitrag
15.04.2014, 17:46
Hallo,

über den Seriellen Monitor der IDE funktioniert der Code sehr gut, danke! Aber könntest du mit noch verraten, wei du die zwei Arduinos verbunden hast?
Ich habe es so versucht:
RX -> TX
TX -> RX
GND -> GND

Leider funktionert das ganze nicht.
Aw: Abspielgerät über Serielle Schnittstelle steuern
Antwort als hilfreich markieren
0Positive Markierungen
Antwort als nicht hilfreich markieren
0Negative Markierungen
Melden Sie diesen Beitrag
15.04.2014, 18:41
Hi, so habe ich es angeschlossen.

Vielleicht liegt es hierran:
- Stimmt die Baudrate bei beiden Arduinos ?
- Werden irgendwelche Trennzeichen wie \n\r ausversehen mit geschickt ?
Aw: Abspielgerät über Serielle Schnittstelle steuern
Antwort als hilfreich markieren
0Positive Markierungen
Antwort als nicht hilfreich markieren
0Negative Markierungen
Melden Sie diesen Beitrag
15.04.2014, 19:38
Danke für die schnelle Antwort!

Baudraten stimmen und Trennzeichen werden auch nicht mitgeschickt.
An dem Board, auf dem das ASA1 aufesteckt ist, ist RX und TX ja durch das ASA1 belegt. Aber die werden doch einfach durchgeschleift, oder?

Hier einmal den Quellcode den ich zum Senden verwende, vielleicht ist hier ja der Fehler:

void setup()
{
Serial.begin(115200);
while (!Serial) {}
}

void loop()
{
Serial.print("v100");
Serial.print("p001");
while(1)
{
}
}
Aw: Abspielgerät über Serielle Schnittstelle steuern
Antwort als hilfreich markieren
0Positive Markierungen
Antwort als nicht hilfreich markieren
0Negative Markierungen
Melden Sie diesen Beitrag
15.04.2014, 21:20
Was passiert, wenn du println verwendest ?

Ich hab meinen Quellcode gerade nicht hier und kann im Moment nur "raten". Über Ostern könnte ich mehr sagen.
Aw: Abspielgerät über Serielle Schnittstelle steuern
Antwort als hilfreich markieren
0Positive Markierungen
Antwort als nicht hilfreich markieren
0Negative Markierungen
Melden Sie diesen Beitrag
18.04.2014, 11:38
So,
ich hab mir das nochmal durch den Kopf gehen lassen.

Solange du beide Arduinos per USB Spannung versorgst, bzw einen von beiden. Ist die Serielle Schnittstelle durch die USB Kommunikation blockiert. Sprich der RX und TX hängen auch parallel noch am USB Chip.

Versuch mal deinen Kompletten Versuchsaufbau mit einem externen Netzteil oder einer Batterie zu versorgen, so dass keine USB Spannung von einem PC vorhanden ist. Dann sollte dein Aufbau besser Funktionieren.

Alternativ könntest du die SoftSerial Lib verwenden, diese gibt es irgendwo im Arduino Forum / Playground. Damit sollte es auch funktionieren. (Eventuell muss die Baudrate herab gesetzt werden)