• Die Forumsregeln und Nutzungsbedingungen findet ihr in der Navbar unter Impressum !
    Bitte unbedingt beachten!
    Wie überall im Leben gibt es Spielregeln, so auch hier!
    Die Datenschutzerklärung zum DSGVO findet ihr ebenfalls in der Navbar unter Datenschutzerklärung !
    Hinweis nach DSGVO :
    Es ist hier keinerlei Angabe erforderlich. Alle Angaben in diesem Bereich sind öffentlich sichtbar und werden freiwillig gemacht. Mit einem Eintrag in diesem Bereich erkenne ich dieses an, und bestätige die Datenschutzerklärung zur DSGVO für das Forum gelesen zu haben.

    Danke
  • Hallo Gast, beschränke dich hier bitte auf den Bereich der Elektronik. Die Fahrzeuge oder Gebäude, wo diese Elektronik eingebaut wird bitte in dem passenden Fachbereiich behandeln. Auch wenn Teile des Projektes dadurch im Forum doppelt vorhanden sind! Danke.

Arduino Steuerung eines MP3 Players per Fernsteuerung

gismow

Active member
Registriert
03.03.2012
Beiträge
2.203
Moin, moin...

Mein Black Devil soll ja nicht nur schwarz sein, er soll auch ordentlich Radau machen können. Da die WAV Player Funktionalität des Beier Moduls hier nicht ausreicht musste eine andere Lösung her.

Warum nicht ein Arduino Projekt starten, welches auf 2 Kanäle einer Fernsteuerung lauscht und so einen MP3 Player steuert. Also erst einmal suchen und gefunden habe ich einen kleinen MP3 Spieler für 4,50€ bei ebay. Da kann man durchaus mal ein Experiment starten.



Zuerst wurde der Spieler zerlegt und die Steuerknöpfe frei gelegt.



Damit ich ihn steuern kann müssen die einzelnen Kontakte verkabelt werden. Eine Funktion wird ausgelöst indem eine Brücke vom äußeren Ring auf den Knopf darin geschaltet wird.



Als nächstes folgte die Steuerplatine. Die Ansteuerung erfolgt indem über einen Arduino Pin ein Transistor geschaltet wird, welcher die Verbindung zwischen Ring und Knopf schließt. Die Verbindung wird für eine gewisse Zeit gehalten und danach wieder getrennt um eben einen Druck mit dem Finger zu simulieren.







Das Programm lauscht auf 2 Kanälen der Funke.

Kanal 1 : Lautstärke - Hier schaltet es den Transistor für lauter/leiser so lange wie der Schalter an der Funke nicht in der Mitte steht.
Kanal 2 : Songs - Wird der Schalter länger als 1 Sekunde nach oben geschaltet wir die Play/Pause Funktion ausgelöst. Kurze Bewegungen nach oben bzw. unten unter einer Sekunde lösen die Funktion nächster bzw. vorheriger Song aus.

Und hier noch ein kleines Video.

Um diese Inhalte anzuzeigen, benötigen wir die Zustimmung zum Setzen von Drittanbieter-Cookies.
Für weitere Informationen siehe die Seite Verwendung von Cookies.
 
Und hier der Quellcode für das Programm. Ich habe es erst einmal rudimentär zusammen geklopft, da gibt es sicherlich noch Möglichkeiten der Optimierung.

Code:
//#define	__SERIAL_OUTPUT__
/*	Modul zur Steuerung eines MP3 Players.
	Die Bedienung erfolgt ueber 5 Transistoren, welche die Kontakte der Tasten schliessen.

	Eingang
	- Lautstaerke
		Lang geschaltet nach oben	= Lautstaerke +
		Lang geschaltet nach unten	= Lautstaerke -
	- Liederwahl
		Lang geschaltet nach oben	= Wechsel zwischen Play/Pause
		Kurz geschaltet nach oben	= Vorheriger Song bzw. an den Anfang des Liedes
		Kurz geschaltet nach unten	= Naechster Song
		
*/

#define		ChannelStateUp				0
#define		ChannelStateCenter			1
#define		ChannelStateDown			2

#define		PinChannelVolume			2
#define		PinChannelSong				3

#define		PinTransistorVolumeUp		4
#define		PinTransistorVolumeDown		8
#define		PinTransistorNextSong		7
#define		PinTransistorPreviousSong	5
#define		PinTransistorPlayPause		6

#define		PinStatusVolume				12
#define		PinStatusSong				13

volatile	uint8_t		LastInterruptState				= PIND;

//	Variablen fuer die Verwaltung des Volume Interrupts
volatile	uint32_t	LastChannelVolumeSignalChange	= 0;
volatile	uint16_t	LastChannelVolumeValue			= 1500;

//	Variablen fuer die Verwaltung des Song Interrupts
volatile	uint8_t		LastChannelSongState			= ChannelStateCenter;
volatile	uint32_t	LastChannelSongStateTimeStamp	= millis();
volatile	uint32_t	LastChannelSongSignalChange		= 0;
volatile	uint16_t	LastChannelSongValue			= 1500;

#define		ChannelSongCommandNone		0
#define		ChannelSongCommandPlayPause	1
#define		ChannelSongCommandNextSong	2
#define		ChannelSongCommandPrevSong	3

volatile	uint8_t		ChannelSongCommand				= ChannelSongCommandNone;

void ChannelVolumeInterrupt()
{
	uint32_t    nMicros		= micros();
	uint16_t    nDifference  = (uint16_t)(nMicros - LastChannelVolumeSignalChange);

	if ((nDifference > 900) && (nDifference < 2300))
	{
		digitalWrite(PinTransistorVolumeUp, (nDifference > 1700) ? HIGH : LOW);
		digitalWrite(PinTransistorVolumeDown, (nDifference < 1300) ? HIGH : LOW);

		digitalWrite(PinStatusVolume, ((nDifference < 1700) && (nDifference > 1300)) ? HIGH : LOW);

		LastChannelVolumeValue  = nDifference;
	}
	LastChannelVolumeSignalChange	= nMicros;
}

void ChannelSongInterrupt()
{
	uint32_t    nMicros		= micros();
	uint16_t    nDifference  = (uint16_t)(nMicros - LastChannelSongSignalChange);

	if ((nDifference > 900) && (nDifference < 2300))
	{
		uint8_t	NewState	=	ChannelStateCenter;
		if ( nDifference > 1700)	NewState	= ChannelStateUp;
		else
			if ( nDifference < 1300)	NewState	= ChannelStateDown;


		if ( NewState != LastChannelSongState )
		{
			//	Es gab einen Wechsel im Status. Wenn wieder in Center zurueck gewechselt wurde muss es entsprechend ausgewertet werden.
			uint32_t	nMillis	= millis();

			if (NewState == ChannelStateCenter)
			{
				if ((nMillis - LastChannelSongStateTimeStamp) > 1000)
				{
					if (LastChannelSongState == ChannelStateUp)
						ChannelSongCommand	= ChannelSongCommandPlayPause;
				}
				else
				{
					if ((nMillis - LastChannelSongStateTimeStamp) > 100)
					{
						if (LastChannelSongState == ChannelStateUp)
							ChannelSongCommand	= ChannelSongCommandNextSong;
						if (LastChannelSongState == ChannelStateDown)
							ChannelSongCommand	= ChannelSongCommandPrevSong;
					}
				}
			}

			LastChannelSongState			= NewState;
			LastChannelSongStateTimeStamp	= nMillis;
		}
		LastChannelSongValue  = nDifference;
	}
	LastChannelSongSignalChange	= nMicros;
}

void setup()
{
#ifdef __SERIAL_OUTPUT__
	Serial.begin(115200);
	Serial.println(F("Start..."));
#endif

	pinMode(PinTransistorNextSong, OUTPUT);
	pinMode(PinTransistorPreviousSong, OUTPUT);
	pinMode(PinTransistorPlayPause, OUTPUT);
	pinMode(PinTransistorVolumeUp, OUTPUT);
	pinMode(PinTransistorVolumeDown, OUTPUT);

	pinMode(PinStatusSong, OUTPUT);
	pinMode(PinStatusVolume, OUTPUT);

	//	Es wird gewartet bis 10 saubere Signale aus dem gültigen Wertebereich gelesen wurden
	//	Erst dann ist davon auszugehen dass der Empfänger online ist und Daten sendet.
	uint8_t	ValidServoSignalsReceived	= 0;

	digitalWrite(PinStatusSong, HIGH);

	while( ValidServoSignalsReceived < 10 )
	{
		uint32_t	nPulse	= pulseIn( PinChannelSong, HIGH );
		if ( (nPulse >= 800) && (nPulse <= 2300))
			ValidServoSignalsReceived++;
		else
			ValidServoSignalsReceived	= 0;
	}
	digitalWrite(PinStatusSong, LOW);

#ifdef __SERIAL_OUTPUT__
	Serial.println(F("Servo values received..."));
#endif

	//	Nun haben wir regulaere Signale vom Empfaenger
	PCICR	|= (1 << PCIE2);
	PCMSK2	|= ((1<<PCINT18) | (1<<PCINT19));

	sei();
}

void SwitchTransistor( uint8_t PinTransistor, uint32_t Delay)
{
	digitalWrite(PinStatusSong, HIGH);
	digitalWrite(PinTransistor, HIGH);
	delay(Delay);
	digitalWrite(PinTransistor, LOW);
	digitalWrite(PinStatusSong, LOW);
}

void loop()
{
	cli();

	uint8_t	ReceivedCommand	= ChannelSongCommand;
	ChannelSongCommand		= ChannelSongCommandNone;

	sei();

	if (ReceivedCommand != ChannelSongCommandNone)
	{
		switch (ReceivedCommand)
		{
			case ChannelSongCommandPlayPause:
#ifdef __SERIAL_OUTPUT__
	Serial.println(F("Play / Pause"));
#endif
				SwitchTransistor(PinTransistorPlayPause, 1000);
				break;
			case ChannelSongCommandNextSong:
#ifdef __SERIAL_OUTPUT__
	Serial.println(F("Next song"));
#endif
				SwitchTransistor(PinTransistorNextSong, 250);
				break;
			case ChannelSongCommandPrevSong:
#ifdef __SERIAL_OUTPUT__
	Serial.println(F("Previous song"));
#endif
				SwitchTransistor(PinTransistorPreviousSong, 250);
				break;
		}
	}

#ifdef __SERIAL_OUTPUT__
	Serial.print(F("Song : ")); Serial.print(LastChannelSongValue);
	Serial.print(F(" - Volume : ")); Serial.println(LastChannelVolumeValue);
#endif

	delay(50);
}

ISR(PCINT2_vect)
{
	uint8_t	PinState	= PIND;
	uint8_t	PinChanges	= PinState ^ LastInterruptState;

	if (PinChanges & (1<<PCINT18))
		ChannelVolumeInterrupt();
	if (PinChanges & (1<<PCINT19))
		ChannelSongInterrupt();

	LastInterruptState	= PinState;
}
 
Hallo Peter

Na das is ja mal eine Idee, oder wie das Lied I have a Dream :ok!:ok!:ok!:ok!:ok!
 
Moin Peter,
super Sache! Und ein einfaches Prinzip!:ok Bin auf das Ergebnis im Truck gespannt!
 
Moin, moin...

Leider hat sich dieses Konstrukt als nicht sehr stabil erwiesen. Mal haben die Kontakte be Betätigung geschlossen, mal nicht. Irgendwann war ich es leid und habe mich auf die Suche nach einer anderen Lösung gemacht.

Beim Stöbern im Internet bin ich auf ein Shield von Adafruit gestoßen. Es spielt MP3 und OGG Files ab. Das ist doch genau das was ich suche.



Hier der Link zum Produkt Adafruit VS1053.

Dazu gibt es noch ein sehr ausführliches Tutorial.

Die Ansteuerung ist recht simpel. Falls jemand Interesse am Quelltext hat, bitte melden. Ich muss ihn erst noch ein bisschen aufräumen.

Die Platine ist nun eine etwas andere :)



Die Bedienung ist die gleiche, mit einer kleinen Änderung. Es gibt nun nur noch die Funktionen "Next" und "Play/Pause", "Prev" ist gestorben. Die Lautstärke wird über einen zweiten Kanal gesteuert.

Es funzt und wird die Tage Einzug im Black Devil halten :)
 
Moin Peter,

Eine Klasse Idee und eine gute Umsetzung. Sehr interessant auch für BOS-Fahrzeuge. Soundfiles von Einsatzfahrzeugen gibt es im Internet mehr als genug, und ein dazu passender Sketch für ein Blaulicht nach Gusto ist schnell geschrieben.

Die Blaulicht Fraktion wird Dir bestimmt dankbar für dieses Projekt sein. Module mit Sound und Blaulicht gibt es auf dem Markt nur wenige. Und diese sind obendrein teuer und haben kaum Auswahlmöglichkeiten für mehrere Sounds und Blaulichtkonfigurationen.

Last not least: Mikrocontroller verleihen dem Modellbau reichlich Möglichkeiten zur Umsetzung realitätsnaher Projekte.

Viel Erfolg beim Optimieren des Sketch.

Gruß
Armin de DO1XXY
 

Servonaut
Zurück
Oben Unten