I2C Ansteuerung des Soundmoduls WTV020

TubeFiebig

Mitglied
30. Jan. 2012
34
0
6
Delmenhorst
Sprachen
Hallo zusammen,
ich möchte meinen Röhrenvorverstärker mit einer Sprachausgabe erweitern. Dazu habe ich mir nach " Zitronenfalter " eine Platine angefertigt.
Ein Attiny45 setzt die I2C - Signale vom ATmega32 passend für das Soundmodul um.
Lautstärke ändern und einen Sound auswählen geht. Ich habe Probleme den Status des Busy auszulesen.
Der nähste Sound darf erst abgespielt werden wenn der vorrige fertig ist.
Wer hätte da mal eine Idee dazu.

Das Schaltbild ist die Platine mit dem Attiny welche ich über I2C ansprechen möchte.
Mein Testprogramm:

'*******************************************************************************
$regfile = "m32def.dat"
$crystal = 8000000
$hwstack = 256
$swstack = 256
$framesize = 256

Ddrd = &B00000000
Portd = &B11111111

'----------- Konfigation CD-Display -------------------
Config Lcd = 16 * 2 'LCD Zeichen Anzahl Options
Config Lcdpin = Pin , Db4 = Portc.4 , Db5 = Portc.5 , Db6 = Portc.6 , Db7 = Portc.7 , E = Portc.3 , Rs = Portc.2
Cursor Off
Cursor Noblink
Cls
'-------------------------------------------------------------------------------

Config Sda = Portc.1 ' I2C Bus konfigurieren
Config Scl = Portc.0
Config I2cdelay = 5 ' je höher der Wert umso langsamer der Bus
Const Wtv020w = &H50
Const Wtv020r = &H51
I2cinit

Declare Sub Speakout(byval Song_nr As Word)
Declare Sub Wartewtv
Dim Busy As Byte

'###############################################################################
Test:
Locate 1 , 1 : Lcd " Sprachausgabe "

Do

If Pind.0 = 0 Then
Waitms 200
Locate 1 , 1 : Lcd " Spielt Sound 0 "
Call Speakout(00)
Call Wartewtv
Goto Test
End If

If Pind.1 = 0 Then
Waitms 200
Locate 1 , 1 : Lcd " Spielt Sound 1 "
Call Speakout(01)
Call Wartewtv
Goto Test
End If

Loop
'-------------------------------------------------------------------------------
' Lautstärke einstellen
I2cstart
I2cwbyte Wtv020w
I2cwbyte &HFF
I2cwbyte &HF7 ' &HF7 = volle Lautstärke
I2cstop
Waitms 300

'-------------------------------------------------------------------------------
' Spiel die Datei mit der Songnummer ab
Sub Speakout(byval Song_nr As Word)
I2cstart
I2cwbyte Wtv020w
I2cwbyte &H00
I2cwbyte Song_nr
I2cstop
Waitms 30
End Sub

'-------------------------------------------------------------------------------
' Wartet bis Datei abgespielt ist
Sub Wartewtv
Do
I2cstart
I2cwbyte Wtv020r
'I2crbyte &HFF , Nack
I2crbyte Busy , Ack
I2cstop
Waitms 30
Loop Until Busy = 0
Waitms 30
Locate 2 , 1 : Lcd Busy
End Sub

'-------------------------------------------------------------------------------
End 'end program


#####################################################################################################

I2C Steuerbefehle zum Attiny45
Code:
' #########################################################################
' #
' # WAV-Soundmodul Attiny25/45/85 mit I2C Steuerung
' #
' # (c) HFEDV 06/2012   eMail: hal90009@aon.at
' # V 1.0.0
' #
' # Ausschließlich für den privaten Gebrauch!
' # Jedwede gewerbliche Nutzung ist untersagt!
' #
' #########################################################################
' #
' # Die Befehle werden über die I2C-Schnittstelle im Zwei-Byte-Format
' # gesendet.
' #
' # Die I2C-Geräteadresse ist vorerst auf hex50 bzw. dez80 festgelegt
' # kann aber 16 verschiedene Adressen annehmen (siehe Befehl FFAx)
' #
' # Hier ein Beispiel zum abspielen der Melodie hex34
' # I2Cinit-I2Cstart(50)-I2Cwrite(00)-I2Cwrite(34)-I2Cstop
' #
' # Ein weiteres Beispiel um das Modul zurückzusetzen
' # I2Cinit-I2Cstart(50)-I2Cwrite(FF)-I2Cwrite(EE)-I2Cstop
' #
' # Zum Abfragen des Status wird ein Byte wie folgt gelesen
' # I2Cinit-I2Cstart(51)-S=I2Cread()-I2Cstop
' #
' # Kommandos (alle Befehle in HEX von 0000 bis FFFF)
' # 00 00 bis 07 FF : Spielt Sound 0 bis 2047,
' #                   wenn belegt, dann wird nicht unterbrochen
' #                   sondern der Befehl verworfen
' #
' # 08 00 bis 0F FF : Spielt Sound 0 bis 2047,
' #                   wenn belegt, dann wird sofort unterbrochen
' #                   und sofort der neue Sound abgespielt
' #
' # FF F0 bis FF F7 : Setzt Lautstärke zwischen 0 bis 7 (0=min, 7=max)
' #
' # FF FE           : Play/Pause
' #
' # FF FF           : Stop
' #
' # FF EE           : Reset Soundmodul
' #
' # FF 00           : Löscht das Error-Flag im Statusregister
' #
' # FF A0 bis FF AF : Setze I2C-Adresse von H50 bis H6E
' #                   Die Änderung wird erst nach neustart des Interfaces
' #                   aktiv.
' #                   Die Reset-Leitung wird nach erfolgter Änderung
' #                   für 250ms gesetzt (normal nur für 5ms, siehe Reset-Modul).
' #
' #                   Welche Adresse aktuell ist, kann mittels lesen des
' #                   Statusbytes ermittelt werden.
' #                   Bei ansprechen mit ungültiger Geräteadresse gibt das
' #                   Modul eben diese ungültige Adresse zurück
' #                   Bei Ansprecchen mit korrekter Adresse wird der Status
' #                   (siehe I2C-Lesen) zurückgegeben.
' #                   Es ist auch zwingend erforderlich, dass sich für diesen
' #                   Test nur das zu testende Modul am I2C-BNus befindet da
' #                   es anderenfalls zu Fehlinterpretationen kommen könnte!
' #
' # I2C-Lesen       : Gibt Status als Byte zurück.
' #                   Die einzelnen Bits 76543210 bedeuten dabei
' #                   Bit 7 = 1 = Error, falsches Kommando
' #                               Wird gelöscht mit Clear after Status
' #                   Bit 1 = 1 = Pause (FFFE) activ"
' #                   Bit 0 = 0 = Busy, 1=Ready"
' #
' #                   Wird das Modul mit falscher Adresse angesprochen, wird
' #                   als Status die falsche Adresse zurückgegeben.
' #
' #                   Die Leseadresse ist I2C-Konform immer ungerade bzw.
' #                   um den Wert 1 erhöht.
' #                   Wenn die Schreibadresse 50 ist die Leseadresse 51.
' #
' #########################################################################
' #
' # HINWEIS: Beim µC wird der RESET-Pin als I/O-Port verwendet!
' #          Daher ist eine ISP-Programmierung nicht möglich!
' #
' # Mögliche µCs sind jedenfalls die Tiny25/45/85
' #
' #########################################################################

Für eure Hilfe wäre ich sehr dankbar.
Viele Grüße,
Wolfgang


Anhang anzeigen Platine_WTV020.zip
Anhang anzeigen Soundmodultester.pdf
Soundmodultester.jpg
 
???
Ist das jetzt 'ne Ankündigung, oder kommen da noch Fragen?

Was mich wundert ist das I2C. Ich finde nur was mit (low-aktiven) Tastern, und ein digitales Kommunikationsschema, das am ehesten an SPI erinnert (16Bits).
Im Prinzip entspricht das CPHA=1, CPOL=1 (Reihenfolge der Bits unklar) - allerdings soll vor dem ersten Bit 2ms gewartet werden (also zwischen Clk \ = setup und Clk / = sample).
Nimmt man CPHA=0, CPOL=0, könnte man sich in Software selbst um diese kümmern (also die Leitung über den Pin erstmal Hi halten (als I/O-Ausgang), dann den Pin auf Gnd schalten, und nach knapp 2ms das SPI aktivieren, und nacheinander die beiden Bytes senden. Problem hier wäre aber, daß nach dem letzten Bit Clk low geht. Hier sollte es aber Hi bleiben. Ob das IC damit klarkommt, wenn man den Pin dann nach abschalten des SPI selbst Hi setzt, weiß ich nicht.
In beiden Fällen hätte man 'ne (mehr oder weniger) kurze Pause zwischen den beiden Bytes (hatte das irgendwann mal in'nem Beitrag hier ausgewertet, mit der HW-SPI).

Ansonsten kannst Du das natürlich auch in SW umsetzen. Bei den 200µs pro Bit würde ich dann 'n Timerinterrupt empfehlen. Bei 20MHz wären das immerhin 4000 Takte.

Frage am Rande: Du warst derjenige welche hier, der einem bei der Planung eines "guten" Stereo-Röhrenverstärkers unter die Arme greifen könnte?

Nachtrag: Da Du ja gleichzeitig geantwortet hast: Deine Links/Anhänge greifen irgendwie nichts. Für die Lösung Deines Problemes brauchen wir natürlich den Code des Tiny (und den konkreten Schaltplan).

Warum 2 Controller? reicht nicht einer?
 
Hallo LotadaC,
Ich mußte beim einstellen des Beitrages zwischendurch unterbrechen. Da ist dann einiges durcheinander gekommen.
Also ich habe nach dem Schaltplan von Zitronenfalter eine Platine hergestellt wo der Attiny45 die Ansteuerung des WTV020 Soundmoduls übernimmt. Diese Sound-Platine wird über den I2C-Bus angesprochen. Den I2C Befehlssatz steht in meinem Beitrag. Ich hänge mal den Code des Attiny hiermit dran.

Anhang anzeigen Soundmodul-I2C (Tiny45)-Interface.bas

Problem habe ich mit der Abfrage des Busy. Mein Programm soll in der Do .....Loop-Schleife warten ( bleiben ) bis der Sound zu Ende gespielt ist. Oder gibt es noch eine andere bessere Möglichkeit.
Bei meinen Steuerungs-Code für den Röhrenvorverstärker sind nur noch die beiden I2C Ports unbenutzt.

Grüße Wolfgang
----------------------------

PS:
Du fragst nach Hilfe für einen Röhrenverstärker Bau da kann ich dir helfen. Ich beschäfige mich seit 15 Jahren damit.
Meine neusten Verstärker werden jetzt von einem Atmega gesteuert und überwacht.
 
Steht eigentlich im Kopf des Programmes:
Zeile 25..26 schrieb:
' # Zum Abfragen des Status wird ein Byte wie folgt gelesen
' # I2Cinit-I2Cstart(51)-S=I2Cread()-I2Cstop
51 ist hierbei die I2C-Leseadresse des Tinies, S 'n vorher definiertes Byte, in das der Status gelesen werden soll
Zeile 63..75 schrieb:
' # I2C-Lesen : Gibt Status als Byte zur�ck.
' # Die einzelnen Bits 76543210 bedeuten dabei
' # Bit 7 = 1 = Error, falsches Kommando
' # Wird gel�scht mit Clear after Status
' # Bit 1 = 1 = Pause (FFFE) activ"
' # Bit 0 = 0 = Busy, 1=Ready"
' #
' # Wird das Modul mit falscher Adresse angesprochen, wird
' # als Status die falsche Adresse zur�ckgegeben.
' #
' # Die Leseadresse ist I2C-Konform immer ungerade bzw.
' # um den Wert 1 erh�ht.
' # Wenn die Schreibadresse 50 ist die Leseadresse 51.

Der Tiny verwendet sein USI als TWI (I2C), also mehr oder weniger in Hardware, und unter Verwendung der entsprechenden Interrupts.
Außerdem kannst Du die abzuspielende "Track"-Nummer entweder direkt übermitteln (dann wird ggf gewartet, bis der eventuell grad laufende Track beendet ist (oder Pause betätigt/empfangen (IRQ) wurde), und danach der zu spielende Track an den Soundchip übermittelt)
oder Du Addierst 2048 auf die Nummer, dann wird die original-Tracknummer ohne warten an den Soundchip gesendet. Aneblich soll dadurch der ggf laufende Track abgebrochen werden.
Also so interpretiere ich den Code.

Generell kannst Du natürlich mit dem Senden der Tracknummer auf !Busy warten (also das Statusbyte des Tinies auslesen) - vor oder nach dem Senden. Ggf mit'nem Timeout. Meiner Meinung nach wäre vorher besser.
Oder Du legst Dir 'n Puffer an, wo die zu sendenden Tracks etc. reingepackt werden. Irgendwo in der Hauptscheife fragst Du dann ab, ob der Puffer noch was enthält, wenn ja pollst Du das Busy-Flag des Statusbytes des Tinies, ist das frei, läßt Du die TRacknummer senden, und entferns sie aus dem Puffer. Dann würde das Programm nicht nur darauf warten, sondern könnte nebenbei noch andere Sachen machen.
Diese anderen Sachen müssen natürlich entsprechend programmiert sein.

Im Prinzip ist das sowas ähnliches(!) wie kooperatives Multitasking - die Haupschleife schaut quasi als Scheduler reihum bei den einzelnen Tasks vorbei, ob was zu tun ist.

Als nächster Level können dann IRQs dazwischenhauen, und ggf irgendwelche Statusinfos verändern, etc...

Was für'n Controller haste denn für den Verstärker eingesetzt, und was ist wo angeschlossen? (nur nebenbei)
2 Leitungen reichen natürlich nicht, ok.

P.S. @Röhrenverstärker: mir schwebt derzeit der Selbstbau eines entsprechenden Stereo-Röhrenverstärkers vor. Die dazugehörenden Boxen wären dann auch noch zu bauen. Aber alles noch sehr(!!) frühe Planungsphase. Primär soll das an den Fernseher angeschlossen werden (optisch, oder 2xLine). Des WAF wegen sollte das dann (Boxen) aus einem Stück hinter dem Fernseher platziert werden (also als Wand, und den Fernseher daran, die eigentlichen LS über dem Fernseher, die "Bässe" darunter raus. in der Mitte der "Wand" wäre dann genug Platz für den Verstärker etc.). Außerdem dann noch einen Radioempfang mit rein (digital?), mit Anbindung eines CD-Players hab ich mich noch nicht beschäftigt. Ein Heimnetzwerk mit streambaren Daten haben wir hier nicht (zumindest noch nicht) - insofern muß ich mich (und den AVR) also nicht mit derlei beschäftigen.
Realisierbar? (ok, gehört hier nicht rein - wenns damit irgendwann mal konkreter wird, mach ich natürlich 'n Thread auf... )
 
Hallo,
Mein Problem ist das ich das Auslesen des Statusbyte des Tinies auf der Soundplatine nicht hinbekomme.
Es wird immer 0 gelesen.

' Wartet bis Datei abgespielt ist
Sub Wartewtv
Do
I2cstart
I2cwbyte Wtv020r
'I2crbyte &HFF , Nack
I2crbyte Busy , Ack
I2cstop
Waitms 30
Loop Until Busy = 0
Waitms 30
Locate 2 , 1 : Lcd Busy
End Sub

Hat da jemand eine Idee.

Zum Röhrenvorverstärker hier die Belegung der Ports des Atmega16
'-------------------------------------------------------------------------------
'Name : ST_Vor_Atmega16_v_1.0 Servo.bas
'Copyright : (c) 2012 WF
'Purpose : Vorverstärker Controller
'Micro : Atmega16
'Version : v1.0
'Endwicklungsstand : 1.0
'4 x Input Audiorelais
'2 x Output Audiorelais
'2 x Netzrelais für Endstufeneinschaltung
'RC5 Remote Control & Motor Volume Potentiometer
'Mute ist activ über Remote Control, Ausgabe auf LCD
'Servomotor für AudioPoti
'Sprachausgabe über Zuatzboard
'-------------------------------------------------------------------------------
$regfile = "m16def.dat" ' Controller Type
$crystal = 8000000 ' used crystal frequency
$hwstack = 32
$swstack = 32
$framesize = 32
$eeprom

'---- Konfiguration Port A -----------------------------------------------------

Ddra = &B11111111 ' PA0...PA7 wird Output
Porta = 0 ' alle Ausgänge auf 0V schalten
'PortA.0 = LED 1 rot Blinken Output 1 Einschaltverzögerung
'PortA.1 = LED 1 grün Output 1 Relias eingeschaltet
'PortA.2 = LED 1 blau Output 1 Relias für Endstufe 1 einschalten
'PortA.3 = LED 2 rot Blinken Output 2 Einschaltverzögerung
'PortA.4 = LED 2 grün Output 2 Relias eingeschaltet
'PortA.5 = LED 2 blau Output 2 Relias für Endstufe 2 einschalten
'PortA.6 = frei
'PortA.7 = Servo Takt

'---- Konfiguration Port B -----------------------------------------------------

Ddrb = &B11111111 ' PB0...PB7 wird Output
Portb = 0 ' alle Ausgänge auf 0V schalten

'PortB.0 = Audiorelias " Aux "
'PortB.1 = Audiorelias " Tape "
'PortB.2 = Audiorelias " Tuner "
'PortB.3 = AudioRelias " CD "
'PortB.4 = frei
'PortB.5 = Lautsprecher für Sprachausgabe einschalten
'PortB.6 = Netz-Relais Haupttrafo einschalten
'PortB.7 = Netz-Relias Einschaltverzögerung Haupttrafo einschalten

'------------ Konfiguration Port C ---------------------------------------------

Config Scl = Portc.0 ' I2c-Bus vorbereitet für Sprachausgabe
Config Sda = Portc.1 ' I2C-Bus vorbereitet für Sprachausgabe
'PortC.2 = LCD RS
'PortC.3 = LCD E
'PortC.4 = LCD Db4
'PortC.5 = LCD Db5
'PortC.6 = LCD DB6
'PortC.7 = LCD DB7

'---- Belegung der Taster Eingänge Port D -------------------------------------

Ddrd = &B00000000 ' PD0...PD7 PortD wird Input
Portd = &B11111111 ' PD0...PD7 pull-up Resistor einschalten
'PortD.0 = Taster Motorpoti Up Lauter
'PortD.1 = Taster Motorpoti Down Leiser
'PortD.2 = Taster Eingangs Audio-Relais Umschaltung links
'PortD.3 = Taster Eingangs Audio-Relais Umschaltung Rechts
'PortD.4 = Endschalter Servomotor Endlage Poti noch frei
'PortD.5 = IR Empfangs Sensor
'PortD.6 = Taster Output1 Relias Ein
'PortD.7 = Taster Output2 Relias Ein

'------------------------------------------------------------------------------

Einen schönen Tag noch zusammen.
 
Dein oberer Code-Block ist etwas ... verwirrend:
  1. Statusmeldung des Tiny4x anfordern, und komplett(!) in eine Variable kopieren
  2. 30ms warten
  3. Warteschleife, bis die Variable 0 ist
  4. 30ms warten
  5. Ausgabe auf LCD
Wenn Du die Statusmeldung anforderst, ist die entweder null, oder nicht null. Dementsprechend ist auch die Kopie null oder nicht null. Da ändert auch beliebig langes warten nichts drann. Oder läßt Du das noch in irgendeiner ISR manipulieren?

Folglich mußDein Programm immer null ausgeben (wenn der Status beim auslesen des Status grad 0 war, war er nicht 0, hängt das Programm in der Endlosschleife fest).
Und: das Bysy ist nur ein Bit im übermittelten Statusbyte. Ist eines der anderen Bits nicht null (error, pause, eines der (noch?) nicht verwendeten), ist auch deine Veriable nicht null. Du mußt die anderen wegmaskieren;)
 
' Wartet bis Datei abgespielt ist
Sub Wartewtv
Do
I2cstart
I2cwbyte Wtv020r
'I2crbyte &HFF , Nack
I2crbyte Busy , Ack
I2cstop
Waitms 30
Loop Until Busy = 0
Waitms 30
Locate 2 , 1 : Lcd Busy
End Sub



Hallo TubeFiebig!

Bist du sicher, dass du zwischen dem Senden der Adresse und dem Lesen der Daten vorher kein Register ansprechen musst?
Außerdem müsste es ( I2crbyte Busy , Nack ) heißen.

Hast du vielleicht mal ein passendes Datenblatt (PDF oder Link zum PDF)?


Grüße,
Cassio :ciao:
 
Irgendwo weiter oben ist der Quellcode des korrespondierenden Tiny45 (Slave) verlinkt. Meiner Meinung nach paßt das mit dem Senden der Adresse.
Auf die Acks und NAcks hatte ich nicht geachtet - der Rest schien ja zu gehen, nur eben die Abfrage nicht.
Ich sehe, wie gesagt, den klassischen "Hochsprachen-Pollingfehler": was auszulesendes (einmal) 'ner Variable zuweisen, und dann die Variable pollen. Die Variable referenziert ja nicht auf die Methode zum Auslesen.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)