Hallo Welt
kennt jemand ein Projekt:
Drei Wave Dateien (oder auch mehr) auf SD, drei Knöppe, ein AVR, ein LSP
und auf Knopfdruck sollen die Dateien abgespielt werden. Bespielen der
SD mit WAV-Dateien von Windows aus. Wobei mir das Abspielen mit
Wave-Dateien schon gelungen ist, allerdings standen da die Dateien im
internen Flash vom MEGA 32. Hatte da die ersten 44 Byts gekappt und
direkt mit in den Speicher geflasht. Mein Problem ist vielmehr das
Handling mit der Speicherkarte. Wie komme ich an die Daten der SD-Karte
ran. Denke mal die müssen irgendwie kurzfristig zwischen gespeichert
werden. Würde diesbezüglich hier gerne öffentlich ein kleines Projekt
mit eurer Hilfe starten. Wenn jemand ideen hat, kann er sie ja bitte
posten. Wie gesagt das Problem ist die Speicherkarte.
Vielen Dank und Gruß aus Berlin
Ingo
Hallo Ingo,
wenn ich Dich richtig verstanden habe suchst Du Unterstützung beim SD
Kartenzugriff.
Projekte die sich mir SD Karten beschäftigen gibt es zu hauf. Bei Ulrich
Radig z.B. http://www.ulrichradig.de/ -> AVR -> MMC-SD. Dort findest Du
neben der Beschaltung auch einen Beispielcode mit Lib.
Ich hoffe das hilft Dir weiter.
Gruß
Florian
Werde mich mal mir dieser Aufgabenstellung annehmen und erstma Ullis
Schaltungsbeispiel aufbauen.
BTW: ist es eigentlich auch möglich eine SD über BASCOM anzusprechen ?
Gruß aus Berlin (ohhhh Somme scheint heute)
Ingo
Mario Grafe schrieb:> Genau das was du brauchst: http://elm-chan.org/works/sd8p/report.html
Hallo Mario,
hatte ich schon entdeckt, bloß ich brauche drei - vier Sounds die ich
per Tastendruck auslösen möchte.
Wo finde ich den Slot für die SD-Karte (Reichelt). Weiß die genaue
Bezeichnung nicht.
anderes Ding..
wird ein Mega 8 in Verbindung mit einer 1GB SD-Karte ausreichen für mein
Vorhaben ?
Als Hardware ankopplung denke ich an die Lösung von Ullich Radig.
Ingo Laabs schrieb:> TEUUUUUUER brrrrr
schau bei ebay, da gibts die für <1€ in Hongkong
Oder such dir bei ebay eine micro-SDkarte mit adapter auf mini oder SD
und löte den Adapter fest auf die Platine.
@Ingo:
Die Kartenslots bei Reichelt sind wirklich heftig; aber wenn Du schon
Ulrichs Lösung in Betracht ziehst, kannst ja auch mal ein seinen Shop
schauen; da gibts die Kartenslote für 1,99 Euro ;-)
Und schon gehn die Probleme los....ist doch irgendwie doof, jetzt
befinden sich die Pins für die SPI am Mega 8 genau da, wo auch die PWM
erzeugt werden soll. Anderen uP oder kann ich das SPI auch an anderen
Pins betreiben ?
Klaus schrieb:> Hey Ingo, du kannst in 15 Minuten ne SPI Schnittstelle per Software an> beliebige I/O-Pins basteln.
Hi Klaus,
na dann ist ja OK. Nein, zur Zeit mache ich mir Gedanken (und
Schaltplan) über die Hardware und hatte dabei nur festgestellt, dass da
ja die selben Ports benutzt werden. Aber wenn ich das umgehen kann, ist
ja OK.
Also kein Hardware SPI. Wobei ich immer noch nicht weiß, ob der MEGA 8
dazu geeignet ist.
Ingo Laabs:
>Dachte jetzt eigentlich Bascom ist für solch Projekte nicht schnell>genug.
Doch, da geht auch noch mehr. 8Bit/44khz mono sollte drinn sein, wenn
man den Code ein wenig optimiert.
Die Qualität ist im moment leider nicht so doll, aber ich weiß nicht
worann es liegt.
Ich habe leider kein Oszi um da weiter nachzuforschen...
Ich verwende für die SD-Karte die avr-dos-lib in Bascom, die ist echt
irre.
SD-Karten, CF-Karten und IDE-HDDs gehen mit dem Player, man müsste nur
die Treiber tauschen (andere einbinden).
Wo bekomme ich das AVR-DOS bzw wie binde ich es denn in mein BASCON ein.
Habe mir mal das Bsp. geladen, bekomme da jedoch jede menge
Fehlermeldungen.
Gruß Ingo
Hi,
hast du die Demo von Bascom oder die Vollversion?
Mit der Demoversion kannst du AVR-Dos nicht benutzen, da der Code
deutlich über 4kB groß wird.
Eigentlich ist AVR-Dos schon in BASCOM integriert.
Als beispiel solltest du dir die Datei
/BASCOM-AVR/SAMPLES/AVRDOS/Test_DOS_drive.bas benutzen.
du musst die Zeile include "config_HardDisk_M128.bas" auf deine Hardware
anpassen.
z.B. auf include "config_mmc.bas".
Danach musst du dir config_mmc.bas öffenen und auf deine Hardware
anpassen
Die config_AVR-Dos.bas solltest du erstmal unberührt lassen.
MfG Torben
Setze mich jetzt mit dem Code von Ulrich Radig auseinander und bekomme
hier jetzt folgende Meldung :
rm -rf usart.o fat.o main.o mmc.o SD_CARD.elf dep/* SD_CARD.hex
SD_CARD.eep SD_CARD.lss SD_CARD.map
Build succeeded with 0 Warnings...
make: *** No rule to make target `../../Eigene', needed by `usart.o'.
Stop.
Build failed with 1 errors and 0 warnings...
wat dat ??
Gruß
Ingo
>make: *** No rule to make target `../../Eigene', needed by `usart.o'.>Stop.>Build failed with 1 errors and 0 warnings...>wat dat ??
Leerzeichen im Pfad? Leg deine Dateien mal woanders hin.
holger schrieb:>>make: *** No rule to make target `../../Eigene', needed by `usart.o'.>>Stop.>>Build failed with 1 errors and 0 warnings...>>>wat dat ??>> Leerzeichen im Pfad? Leg deine Dateien mal woanders hin.
kein Leerzeichen da :-(
Ingo Laabs schrieb:> No rule to make target `../../Eigene', needed by `usart.o'.
Das 'Eigene' dort stammt doch bestimmt von 'Eigene Dateien', oder nicht?
Klaus schrieb:> Ingo Laabs schrieb:>> No rule to make target `../../Eigene', needed by `usart.o'.>> Das 'Eigene' dort stammt doch bestimmt von 'Eigene Dateien', oder nicht?
jeeepppp
danke,danke...kniefall
lt. Ulrich Radigs Programm würde ich auf folgende Beschaltung kommen
AVR_ATmega32
SPI_DI (MISO) PB6 an Data Output der SD-Karte (PIN 7)
SPI_DO (MOSI) PB5 an Data Input der SD-Karte (PIN 2)
SPI_Clock (SCK) PB7 an Clock der SD-Karte (PIN5)
MMC_Chip_Select (OC0) PB3 an Chip Select der SD-Karte (PIN 1)
SPI_SS PB4
GND an SD-Karte (PIN6/3)
VCC an SD-Karte (PIN4)
Stimmt ?
lt. Ulrich Radigs Programm würde ich auf folgende Beschaltung kommen
AVR_ATmega32
SPI_DI (MISO) PB6 an Data Output der SD-Karte (PIN 7)
SPI_DO (MOSI) PB5 an Data Input der SD-Karte (PIN 2)
SPI_Clock (SCK) PB7 an Clock der SD-Karte (PIN5)
MMC_Chip_Select (OC0) PB3 an Chip Select der SD-Karte (PIN 1)
SPI_SS PB4
GND an SD-Karte (PIN6/3)
VCC an SD-Karte (PIN4)
Stimmt ?
Ingo Laabs schrieb:> Warum verwendet Ulrich Radig PB3 anstatt den SS Pin für den CS der Karte
Der SS Pin ist nur wichtig, wenn du den AVR im SPI-Slave-Mode
verwendest. Im Master-Mode hat der keine besondere Bedeutung und du
kannst jeden beliebigen IO-Pin an CS anschließen.
Habe jetzt versucht die Datei NESSAJA.WAV auszugeben, will aber nicht so
recht.
Habe die main-Datei von Ulrich wie unten aufgeführt ( habe nur den
geänderten Teil hier reingestellt da sie ja bekannt sein sollte)
geändert..aber nach nessaja klingt es nicht.
Die Delays habe ich nur zu Testzwecken eingefügt. Meine Datei hat das
Format 8Bit/mono/PCM/22Khz
Kann mal einer auf den Code schauen wo da der Fehler liegt ?
Danke und Gruß aus Berlin
Ingo
//Lade Cluster für das index.htm File in den Speicher
Clustervar = 0;//suche im Root Verzeichnis
if (fat_search_file((unsigned char
*)"NESSAJA.WAV",&Clustervar,&Size,&Dir_Attrib,Buffer) == 1)
{
usart_write("\nFile Found!!\r\n");
// init PWM
DDRD = (1 << PD5 );
TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (0<<WGM11) | (1<<WGM10) ;
TCCR1B = (0<<CS12) | (0<<CS11) | (1<<CS10);
//Lese File und gibt es aus
for (int b = 0;b<52;b++)
{
fat_read_file (Clustervar,Buffer,b);
for (int a = 0;a<512;a++)
{
OCR1A = Buffer[a];
_delay_us(100); // nur zum test !!
}
}
}
usart_write("FERTIG!!\r\n");
Klaus schrieb:> Der SS Pin ist nur wichtig, wenn du den AVR im SPI-Slave-Mode> verwendest. Im Master-Mode hat der keine besondere Bedeutung und du> kannst jeden beliebigen IO-Pin an CS anschließen.
da der Pin sowiso als Ausgang konfiguriert werden muss, kann man doch
direkt den nehmen.
Konnte das Problem beheben . Der Fehler lag hier:
for (int b = 0;b<52;b++)
Die Variable b muss den Wert der Dateigroße / 512 enthalten. Dann
funktioniert es.
Soweit funktioniert die Sprachausgabe jetzt. Habe nun ein wenig Probleme
mit der Samplingfrequenz, weil ich nicht weiß wie lange der Zugriff auf
die Karte dauert. Ansonsten klingt es schon ganz gut. Sobald ich das
Projekt fertig habe, werde ich es hier posten.
Einen 4:0 Gruß aus Berlin
Ingo
Ingo Laabs schrieb:> Kann ich mir dieses ganze Pegelgewandle eigentlich nicht dadurch> ersparen indem ich den Mega32 gleich mit an 3,3 Volt betreibe ?
Ja, ist möglich. Bedenke aber, dass du dann nicht mehr die vollen 16Mhz
nutzen kannst.
Mit der hier aufgeführten Konstellation bin ich jetzt zum Erfolg
gekommen.
Verwenden tu ich eine 1GB SD-Karte. Zur Zeit takte ich mit 12 MHz (nicht
im Schalplan eingezeichnet).
Dateiformat der WAV 8 Bit,mono,22 KHz
Wobei ich die Dateien von Ulrich R, verwendet habe. Die Main.c habe ich
natürlich ändern müssen.( Es sind noch viele Sachen in dem Code die
nicht gebraucht werden wie z.B der USART). Es müssen aber auch noch
Dinge geändert werden wie zum Beispiel sollte sich die Dateilänge
errechnen lassen die ich bisher noch von Hand eintrage, und die ersten
44 Byts von der WAV müssen noch gekappt werden (Beim Abspielen knackt es
Anfang ein bissel). Ob die Verzögerung von 45 uS beim Abspielen da so in
der Form sinnvoll ist weiß ich noch nicht. Aber sonst Spricht das Ding.
Am Ausgang muss wohl noch ein Filter (Butterworth ?) gesetzt werden.
Super ! Ich habs gerade auf dem Steckbrett zum testen aufgebaut. Vorerst
mit internem Takt.
Das ist genau das was ich für mein nächstes Projekt gesucht habe. Danke
an alle beteiligten.
Für höhere Geschwindigkeiten würde ich aber den Innenwiderstand des
Spannungsteilers mindestens halbieren. Bzw. Serienwiderstand max. 1kOhm.
Ansonsten haste Probleme mit den kapazitiven Eingängen. Also zumindest
so über den Daumen jetzt mal gepeilt.
Matthias Reichelt schrieb:> Super ! Ich habs gerade auf dem Steckbrett zum testen aufgebaut. Vorerst> mit internem Takt.> Das ist genau das was ich für mein nächstes Projekt gesucht habe. Danke> an alle beteiligten.
Hallo Matthias,
habe hier einen Filter gefunden
http://www.elv-downloads.de/service/manuals/75344_Mini_Sound_Modul_km_web_um.pdf
ganz unten abgebildet.
Bin leider noch nicht dazu gekommen ihn nach zubauen (Fussball ist
angesagt.)Denke aber der sollte so in der Form funktionieren, da das
Soundmodul ebenfalls mit 8 Bit,22KHz arbeitet.
Wenn du Erfahrungen damit gemacht hast, kannst du sie ja posten oder
warten bis wieder Fussball frei ist. Denke mal als OP kannst du auch
einen LM324 verwenden
Gruß aus Berlin
Ingo
(Daumen drücken heute)
Hallo Ingo,
Ich habe den Filter jetzt fertig und ein bischen damit getestet. Auf dem
Oszi schaut es ziemlich gut aus aber die Sprache ist noch nicht viel
besser wenn ich es über den Verstärker wiedergebe.
Das leichte Brummen ist nun weg aber es klingt noch immer nicht optimal.
Der Gewinn ist so gering, daß ich mir den Bau des Filters sparen könnte
denn der "Roboterstimmeneffekt" ist vor und hinter dem Filter gleich.
Ich glaube das Problem liegt schon beim PWM signal.
Ich verwende 8Mhz Takt extern und Wav files mit 22khz und 8 Bit mono.
Die Sprache ist etwas langsamer als orginal :-)
>Ich verwende 8Mhz Takt extern und Wav files mit 22khz und 8 Bit mono.>Die Sprache ist etwas langsamer als orginal :-)
Dann geh auf 16MHz und benutz einen Double Buffer.
Matthias Reichelt schrieb:> ch verwende 8Mhz Takt extern und Wav files mit 22khz und 8 Bit mono.> Die Sprache ist etwas langsamer als orginal :-)
Also mein Ding läuft mit 12 Mhz und liefert schon ohne Filter akzeptable
ergebnisse. Solltest wiklich mal versuchen den Quarz zu ändern.
Ich taste mich langsam heran. Einen 10Mhz Quarz habe ich noch gefunden.
Es ist nun besser und keine Frage, es ist absolut akzeptabel als
Sprachausgabe.
Das Filter ( momentan noch am Steckbrett ) werde ich wohl nicht
aufbauen. Es bringt relativ wenig und ohne ist es schon gut genug. Es
soll alles in ein gleines Gehäuse passen ( Pollin Blitzgong ) und da
muss ich mit dem Platz haushalten.
Danke nochmal
Funktioniert jetzt super. Mit 12Mhz Quarz. Evtl. spiele ich trotzdem
noch ein bischen mit dem Buffer.
Ich habe einen kleinen NF Verstärker mit LM386 und den Ultraschall
Abstandswarner vom C hinzugefügt. Das RFM12 fehlt noch und dann spare
ich mir die nicht vorhandene Haustürglocke :-)
Übrigens, ich schalte die Versorgungsspannung von Verstärker mit einem
kleinen Relais weg, wenn nichts ausgegeben wird.
Grüße
Matthias
Matthias Reichelt schrieb:> Funktioniert jetzt super. Mit 12Mhz Quarz. Evtl. spiele ich trotzdem> noch ein bischen mit dem Buffer.>> Ich habe einen kleinen NF Verstärker mit LM386 und den Ultraschall> Abstandswarner vom C hinzugefügt. Das RFM12 fehlt noch und dann spare> ich mir die nicht vorhandene Haustürglocke :-)>> Übrigens, ich schalte die Versorgungsspannung von Verstärker mit einem> kleinen Relais weg, wenn nichts ausgegeben wird.>> Grüße> Matthias
Na iat doch super wenn alles geklappt hat. Wenn du den Buffer geändert
hast,
kannst Du den Code mal posten. Bei mir hat der Filter doch einiges
gebracht.
Aber jetzt geht es erstmal in die heiße Fussballphase und hier in Berlin
ist wiklich die Hölle los.
Freue mich aber über jeden Beitrag der das Projekt weiter bringt.
Möchte jetzt zur Anbindung der SD an den Controller auf das
Widerstandsgedöhns verzichten. Soll ja jetzt nicht die Kavalierslösung
sein mit den Widerständen.
Von daher mal die Bitte an euch: Welcher Pegelwandler/Treiber scheint da
am sinnvollsten zu sein. (Schaltplan findet ihr ja etwas weiter oben)
danke
Gruß Ingo
Nachdem die WM und die Hitze doch nun beendet ist, habe ich mich wieder
meinem Projekt gewidmet.
Soweit funktioniert ja alles.
Doch habe ich in der Ausgabe der Sounddateien einen Vibrator ähnlichen
Effekt. Habe es jetzt schon mit
diversen Samplingfrequenzen probiert. Der Effekt wird jedoch intensiver
je höher ich die Samplingfrequenz
Setze. Es macht den Eindruck als wenn die Sounddatei moduliert wird.
Hatte hier jemand schon mal mit ähnlichen Problemen zu kämpfen ?
Ein entsprechender Filter bringt keine Abhilfe.
>Doch habe ich in der Ausgabe der Sounddateien einen Vibrator ähnlichen>Effekt. Habe es jetzt schon mit>diversen Samplingfrequenzen probiert. Der Effekt wird jedoch intensiver>je höher ich die Samplingfrequenz Setze.
Dann ist dein Puffer schneller abgespielt als du Daten von der SD lesen
kannst. Nimm zwei Puffer. Einer wird abgespielt und der andere von der
SD
gefüllt. Dann immer schön die Puffer umschalten.
Gut!
Ich fülle hier meinen buffer und gebe ihn an OCR1A aus.
Wie kann ich denn heir während der Ausgabe den zweiten buffer füllen ?
Komme damit irgendwie nicht klar.
//Lese File und gibt es aus
for (int b = 0;b<52;b++)
{
fat_read_file (Clustervar,Buffer,b);
for (int a = 0;a<512;a++)
{
OCR1A = Buffer[a];
_delay_us(42); // nur zum test !!
}
}
> for (int a = 0;a<512;a++)> {> OCR1A = Buffer[a];> _delay_us(42); // nur zum test !!>> }> }> keiner ne Idee. Komme wirklich nicht weiter..jammer !!
sobald du ein _delay_us im System hast, ist jegliche Frage nach anderen
Sytsematiken sinnlos geworden.
Der _delay muss weg!
Eine Timer ISR, die Bytes ausgibt, muss her!
Ingo Laabs schrieb:> ja aber muss ich da nicht letztendlich auch eine Verzögerung einsetzen> um auf die Samplingrate zu kommen ??
KLar.
Aber anders.
Was du zur Zeit machst, ist aktives Warten, bis das nächste Byte
rausmuss.
Was du aber tun solltest, ist ganz normal weiterarbeiten ohne dich um
die Ausgabe zu kümmern und wenn es Zeit ist, das nächste Byte
auszugeben, benachrichtigt dich deine Stoppuhr. Du gibst das Byte aus
und kehrst wieder zurück an deine eigentliche Arbeit. Bis die Uhr das
nächste mal klingelt.
Genau das macht man in einem AVR mit einem Timer und seiner zugehörigen
ISR. Der Timer gibt die Stoppuhr vor und die ISR ist der Code der dann
in regelmässigen Abständen ausgeführt wird. Und die Samplingrate stellst
du ein, indem du die Zeit bis zur nächsten Unterbrechung (=ISR Aufruf)
am Timer einstellst. Der CTC Modus wird da hilfreich sein.
Karl heinz Buchegger schrieb:>>> Genau das macht man in einem AVR mit einem Timer und seiner zugehörigen> ISR. Der Timer gibt die Stoppuhr vor und die ISR ist der Code der dann> in regelmässigen Abständen ausgeführt wird. Und die Samplingrate stellst> du ein, indem du die Zeit bis zur nächsten Unterbrechung (=ISR Aufruf)> am Timer einstellst. Der CTC Modus wird da hilfreich sein.
d.h.
ich programmiere meinen Timer in soweit, dass er mir alle 45 uS einen
Interrupt auslöst der mir in der Interruptroutine mein Byte ausgibt:
//TIMER1 setzen
TIMSK |= (1 << TOIE1);
//VORTEILER auf 64
TCCR1B = (1<<CS10 | 1<<CS11);
//Zähler setzen
TCNT1 = 65535 - (20000000/64/22050);
//Interrupts zulassen
sei();
//Timer1 Interrupt
ISR (TIMER1_OVF_vect)
{
//hier dann irgendwie das Byte ausgeben
}
habe einen 20 MHz Quarz eingesetzt und Samplingrate 22,05 MHz, komme
dann auf 44,8 us (45 us sollten es sein)
Hi
>keine Reaktion ??
Was soll denn das sein:
>TCNT1 = 65535 - (20000000/64/22050); ?
Karl-Heinz schrieb:
>> am Timer einstellst. Der CTC Modus wird da hilfreich sein.
Warum benutz du den CTC-Mode nicht. Mit deiner Initialisierung bekommst
du etwa alle 210ms einen Interrupt.
MfG Spess
Hi
>20 Mhz Takt 64 Prescaler Samplinfrequenz (22,05 Mhz)>sind doch dann der Zählerstand den ich vorladen muss oder ?
Bei CTC brauchst du nichts vorladen.
TCCR1B = 1<<WGM12|1<<CS10 //CTC, Vorteiler 1
OCR1A = 899 //Macht genau 45µs
TIMSK = 1<<OCIE1A //OC1A Interrupt
Fertig.
Eigentlich würde auch ein 8-Bit-Timer reichen.
MfG Spess
spess53 schrieb:> Hi>>>OCR1A benutze ich als PWM Ausgang>> Dann kannst du TCNT1 auch nicht manipulieren. Hast du noch einen anderen> Timer frei?>> MfG Spess
eigetlich alle bis auf den besagten
Ähm mal ne Anmerkung:
Mit 22MHz Samplingrate geht das nicht, du müsstest ja alle ~50 ns nen
neuen Wert zum Lautsprecher rausgeben.
Wahrscheinlich meinst du 22kHz :-)
Hi
>Timer1 kann auch über das ICR im CTC betrieben werden. Zumindest bei>vielen AVRs.
Aber er benutzt doch Timer1 anscheinend schon für die PWM. Wobei jetzt
die Frage ist: Welche PWM-Frequenz? Wenn er alle 45µs das OC-Register
nachladen will, sollte die PWM-Frequenz schon um einiges höher, als die
Samplingfrequenz sein. Eigentlich macht da ein 16-Bit-Timer wenig Sinn.
MfG Spess
Floh schrieb:> Ähm mal ne Anmerkung:> Mit 22MHz Samplingrate geht das nicht, du müsstest ja alle ~50 ns nen> neuen Wert zum Lautsprecher rausgeben.> Wahrscheinlich meinst du 22kHz :-)
röchtög...tippfehler 22,05 Khz
8 Bit, mono, 22,05 Khz...siehe Beitrag oben..es funktioniert ja schon,
aber leider mit Vibratoreffekt. Denke mal dass das an den
Bufferzugriffen der SD Karte liegt. Schau die mal bitte den Beitrag
komplett an, Vllt. hast du ja eine andere Idee dazu..ware echt dankbar..
wie ermittel mich die PWM Frequenz, kann dir wirklich nur sagen dass das
Ding mit 20 Mhz läuft, und ich 8 Bit PWM mono mit 22,05 Khz verwende was
auch schon brauchbare Ergebnisse bringt.
Oben findest du auch den Schaltplan mit dem geänderten Programm. Für die
Zugriffe auf die SD-Karte verwende ich die (hoffe ich )bekannten
Routinen von U.Radig.
Gruß Ingo
Hi
Dann läuft deine PWM mit ca. 78kHz. Das hat aber zu Folge, da du mit
22,5Hz nachlädst, einige Sound-Werte 4x andere nur 3x 'abgespielt'
werden. Möglicherweise kommt dein 'Vibrato'-Effekt daher. Persönlich
würde ich PWM und Nachladen synchronisieren.
MfG Spess
Hi
>Wie kommst du auf die 78 Khz. Wäre für mich mal interessant wie sich der>Wert errechnet.
Datenblatt S.101. Du hast 20MHz, Vorteiler 1 und Top=255.
-> Fpwm= 20MHz/(1+255) = 78,125kHz
>hmmm...wie gehe ich da bei..kleinen Tipp an Board ?
Wenn du den Timermode 14 benutzt, kannst du die PWM-Frequenz mit ICR1
einstellen. Mit einem ICR1-Wert von 299 bekommst du eine PWM-Frequenz
von 66,67kHz. Damit dauert eine PWM-Periode 15µs. Das ist 1/3 deiner
Sample-Periode. Wenn du also bei jedem dritten OCR1A-Interrupt das
Register nachlädst, kommst du auf genau 45µs.
Einen Nachteil hat die Sache allerdings: Mit deinen 8-Bit-Sound-Daten
läuft die PWM mit maximal 85%. Das bringt eine etwas geringere
Lautstärke. Lässt sich aber bestimmt ausgleichen.
MfG Spess
Hi
>das ich OCR1A für die PWM benutze als ausgang benutze
Was hat denn der OCR1A-Interrupt mit dem OCR1A-Pin zu tun? Die PWM läuft
autonom. Der Interrupt ändert nichts an der Funktionalität der PWM.
MfG Spess
@Ingo
--nur mal so ins Blaue:
Du gibst doch sicher die Wav über einen Lautsprecher an einem
Leistungsverstärker aus?!
Ich hatte schon die seltsamsten ungewollten Modulationseffekte, weil der
Stützkondensator der Spannungsversorgung zu niedrig war!
Wieso zum Geier nutzt Du nicht den Overflow-Interrupt Deiner PWM zum
Nachladen der Daten? Parallel zur ohnehin laufenden PWM wird bei
TimerTOP das Overflow-Flag gesetzt, die Samplerate ist dabei abhängig
vom Wert im ICR_Register, wie schon erwähnt im Timer-Mode 14. Da das
OCR-Register gepuffert ist, wird bei der nächsten Runde der
aktualisierte Wert in die PWM übernommen. Somit brauchst Du nur alle
22kHz 1x das Capture-Register neu zu beschreiben.
Das nachladen der Daten scheint ja zu funktionieren. Wie gesagt das Ding
funktioniert ja schon, nur leider mit einem Vibratoreffekt der schneller
wird je höher ich die Samplingrate setze und ich keinen blassen schimmer
habe woran es liegt. Es geht mir nicht darum die Daten auszugeben. Das
funktioniert ja.
Ingo Laabs schrieb:> Es geht mir nicht darum die Daten auszugeben. Das> funktioniert ja.
Wenn die Daten nicht exakt synchron zur Samplerate gegeben werden, dann
entstehen Schwebungen. Es macht auch keinen ernsthaften Sinn, die PWM
mit 65kHz laufen zu lassen, wenn man nur mit 22kHz ausgibt. Wenn Du aber
so hoch takten willst, um zum Beispiel kleinere externe
Filterkomponenten zu verwenden, kannst Du natürlich auch einen
Interruptzähler einbauen und nur bei jedem 3. Interrupt Daten nachladen.
Das entlastet die CPU. Wichtig ist nur, daß der Timer, der die PWM
generiert, auch für den Datentransfer zum OCR-Register benutzt wird.
Hi
>Wenn die Daten nicht exakt synchron zur Samplerate gegeben werden, dann>entstehen Schwebungen....
Das hatte ich ihm schon weiter oben vorgeschlagen. Allerdings würde ich
zum Nachladen den OC-Interrupt nehmen. Dann wird das OC-Register beim
nächsten Top aktualisiert.
MfG Spess
spess53 schrieb:> Das hatte ich ihm schon weiter oben vorgeschlagen. Allerdings würde ich> zum Nachladen den OC-Interrupt nehmen. Dann wird das OC-Register beim> nächsten Top aktualisiert.
Wenn man den Overflow-Interrupt nimmt, wird das OCR zwar einen Zyklus
später ausgegeben, aber dafür jitterfrei. Beim Output-Compare Interrupt
kann es passieren, daß bei einem oberen Tastverhältnis der Update des
Registers zu spät kommt und die Übernahme dann doch erst im nächsten
Zyklus stattfindet. Außerdem kommt der OC-Interrupt zu nicht definierten
Zeiten, abhängig vom Sample-Inhalt. Das ist für das darunter laufende
Programm eher nachteilig. Der Overflow-Interrupt kommt immer zur
Samplerate oder einem Vielfachen davon, punktgenau.
spess53 schrieb:> Hi>>>Wie kommst du auf die 78 Khz. Wäre für mich mal interessant wie sich der>>Wert errechnet.>> Datenblatt S.101. Du hast 20MHz, Vorteiler 1 und Top=255.>> -> Fpwm= 20MHz/(1+255) = 78,125kHz
Fehlt da nicht noch ein "geteilt durch 2"?
Hi
>Fehlt da nicht noch ein "geteilt durch 2"?
Wenn er Phase/Frequence Correct hat Ja. Hab ich wohl übersehen. Dann
wundert mich sein Vibrato eigentlich nicht mehr. Ich werde das morgen
mal schnell selbst testen.
MFg Spess
spess53 schrieb:> Hi>>>Fehlt da nicht noch ein "geteilt durch 2"?>> Wenn er Phase/Frequence Correct hat Ja.
Habe das eigentlich verwechselt mit dem Output Compare.
Aber er hat tatsächlich den Phase correct mode (WGM10 gesetzt).
> Hab ich wohl übersehen. Dann> wundert mich sein Vibrato eigentlich nicht mehr. Ich werde das morgen> mal schnell selbst testen.
Jupp, eine Synchronisation ist absolut erforderlich. Am besten (wie
schon erwähnt) das Einlesen zum PWM Takt synchronisieren.
>Das nachladen der Daten scheint ja zu funktionieren. Wie gesagt das Ding>funktioniert ja schon, nur leider mit einem Vibratoreffekt der schneller>wird je höher ich die Samplingrate setze und ich keinen blassen schimmer>habe woran es liegt.
Wie sieht denn dein Programm aus? Das lesen der Daten
von der SD braucht Zeit. Das bedeutet eine Pause in
der Ausgabe. Vibratoreffekt. Wie kann man das lösen?
Zwei Puffer verwenden. Puffer1 wird für die Ausgabe benutzt,
Puffer2 zum lesen von der SD Karte. Diese beiden Puffer
werden bei Bedarf umgeschaltet. Sprich: Wenn die Ausgabe von
Puffer1 beendet ist muss Puffer2 die neuen Daten zur Ausgabe
bereits enthalten. Puffer1 und Puffer2 wechseln dann die Funktion.
Das bedeutet aber auch das schon während der Ausgabe von Puffer1
der Puffer2 mit Daten von der SD Karte gefüllt wird. Also schön
verschachteln diese beiden Aktionen.
Hi
Ich hatte gestern versprochen das mal zu Testen. Bei den ersten beiden
Oszilliogramme wird der OC-Wert synchron zur PWM nach geladen
(OC-Interrupt bzw. Overflow-Interrupt). Das dritte Bild zeigt die
Auswirkung von asynchronen Nachladen. Die sichtbaren Unregelmässigkeiten
sind deutlich als 'zweiter' Ton zu hören.
MfG Spess
spess53 schrieb:> Hi>> Ich hatte gestern versprochen das mal zu Testen. Bei den ersten beiden> Oszilliogramme wird der OC-Wert synchron zur PWM nach geladen> (OC-Interrupt bzw. Overflow-Interrupt). Das dritte Bild zeigt die> Auswirkung von asynchronen Nachladen. Die sichtbaren Unregelmässigkeiten> sind deutlich als 'zweiter' Ton zu hören.>> MfG Spess
Könntest du mir dein Testprogramm mal zur Verfügung stellen.
Wäre echt nett von dir.
Gruß aus Berlin
Ingo
Hi
>Könntest du mir dein Testprogramm mal zur Verfügung stellen.>Wäre echt nett von dir.
Ist aber Assembler. Und auch nichtwirklich für andere geschrieben. Immer
noch interessiert?
MfG Spess
Irgendwie will der Groschen bei mir noch nicht fallen. Also mein
Vibratoreffekt kommt wohl daher,dass ich zwischen den Bufferzugriffen
auf die SD-Karte (also alle 512 Bytes) eine Lücke habe. Ich denke mal
das dass die Zeit ist die das Programm benötigt um sich die neuen Daten
in den Zwischenspeicher ( Buffer zu laden). Gut, jetzt kann ich mit dem
Timer alle 45 uS einen Interrupt auslösen der mir das Bytet aus dem
gefüllten Buffer in das OCR-Register schreibt. Soweit ist ja alles OK.
Aber irgendwann habe ich ja das letzte Byte aus dem Buffer ausgelesen
und muss mir die nächsten Daten aus der Karte in den Buffer schreiben.
Dort werde ich doch wieder das gleiche Problem haben, dass dieser
Vorgang zu lange dauert und meine Lücke wieder entsteht.
Ingo Laabs schrieb:> Dort werde ich doch wieder das gleiche Problem haben, dass dieser> Vorgang zu lange dauert und meine Lücke wieder entsteht.
Eines ist klar.
Wenn das Lesen von 512 Bytes von der SD-Karte länger dauert, als die
getaktete Ausgabe von 512 Bytes, dann hast du ein prinzipielles Problem.
Da kann dir kein Mensch dabei helfen.
Wenn in eine Badewanne durch den Ablauf mehr Wasser abrinnt als
gleichzeitig durch den Zulauf zulaufen kann, dann wird sich in der Wanne
niemals ein Schaumbad ergebem. So sicher wie das Amen im Gebet.
Allerdings:
> dass ich zwischen den Bufferzugriffen auf die SD-Karte> (also alle 512 Bytes) eine Lücke habe
Was soll das heißen 'du hast eine Lücke'?
Das Lesen von der SD Karte muss passieren, während gleichzeitig über den
Timer Interrupt der vorhergehende (bereits vollständig gelesene) Buffer
ausgegeben wird. Und logischerweise wäre es gut, wenn das Lesen von 512
Bytes abgeschlossen ist, ehe der vorhergehende Buffer komplett
rausgetaktet wurde. Ist die SD Routine fertig, so wird gewartet, bis die
Timerinterrupt Routine den vorhergehenden Buffer abgearbeitet hat und
sich den eben erst gelesenen vornimmt. Erst dann kann die SD Routine
wieder loslegen und den dann freien Buffer wieder mit Daten befüllen.
Von daher ist zu erwarten, dass es eine zeitliche Lücke des Nichtstuns
zwischen 2 SD-Karten Lesevorgängen geben muss. Erst wenn diese Lücke
gegen 0 schrumpft bekommt man ein Problem.
Wenn du es genau wissen willst, dann hör auf im Trüben zu fischen und
miss die Zeit, die deine Leseroutine braucht um 512 Bytes zu lesen.
Rechne dir aus, wie lange es dauert bis diese 512 Bytes ausgegeben
werden.
Zu der Zeit für den Lesevorgang nimmst du noch ein paar Prozent dazu
(vielleicht 10%) für allgemeinen Verwaltungskram rundherum und dann
siehst in Zahlenform ob es sich ausgeht oder nicht oder ob das knapp
wird.
Karl heinz Buchegger schrieb:> Das Lesen von der SD Karte muss passieren, während gleichzeitig über den> Timer Interrupt der vorhergehende (bereits vollständig gelesene) Buffer> ausgegeben wird. Und logischerweise wäre es gut, wenn das Lesen von 512> Bytes abgeschlossen ist, ehe der vorhergehende Buffer komplett> rausgetaktet wurde. Ist die SD Routine fertig, so wird gewartet, bis die> Timerinterrupt Routine den vorhergehenden Buffer abgearbeitet hat und> sich den eben erst gelesenen vornimmt. Erst dann kann die SD Routine> wieder loslegen und den dann freien Buffer wieder mit Daten befüllen.
und genau da habe ich das Problem, dass ich nicht genau weiss, wie das
zu gehen hat. Ich gebe einen buffer aus und soll den nächsten lesen.
Die Lücke habe ich mal vereinfacht dargestellt. Wobwei die Lücke immer
der Moment ist, an dem sich der nächste Buffer vorgenommen wird.
Und gehen muss es ja irgendwie, da ich schon Projekte gesehen habe, die
genau das mit ner SD-Karte machen.
Ingo Laabs schrieb:> Karl heinz Buchegger schrieb:>> Das Lesen von der SD Karte muss passieren, während gleichzeitig über den>> Timer Interrupt der vorhergehende (bereits vollständig gelesene) Buffer>> ausgegeben wird. Und logischerweise wäre es gut, wenn das Lesen von 512>> Bytes abgeschlossen ist, ehe der vorhergehende Buffer komplett>> rausgetaktet wurde. Ist die SD Routine fertig, so wird gewartet, bis die>> Timerinterrupt Routine den vorhergehenden Buffer abgearbeitet hat und>> sich den eben erst gelesenen vornimmt. Erst dann kann die SD Routine>> wieder loslegen und den dann freien Buffer wieder mit Daten befüllen.>> und genau da habe ich das Problem, dass ich nicht genau weiss, wie das> zu gehen hat. Ich gebe einen buffer aus und soll den nächsten lesen.
Wo liegt da das Problem?
2 Aktionen die nebeneinander herlaufen.
Die eine wird regelmässig im Interrupt gemacht, die andere in der
Hauptschleife.
> der Moment ist, an dem sich der nächste Buffer vorgenommen wird.
Du darfst nicht warten, bis dein Interrupt den Ausgabepuffer
abgearbeitet hat! Du müsst mit dem Lesen beginnen während die
Interrupt Routine einen Buffer ausgibt!
Wenn ich mir deine Performance hier so ansehe, dann denke ich, dass
dieses Projekt noch 5 Nummern zu groß für dich ist.
Karl heinz Buchegger schrieb:> Wo liegt da das Problem?>> 2 Aktionen die nebeneinander herlaufen.> Die eine wird regelmässig im Interrupt gemacht, die andere in der> Hauptschleife.
Ungefähr so
1
// 2 Buffer die wechselweise zum Einlesen bzw. Abspielen benutzt werden
2
// wird aus dem einen abgespielt, dann wird in den anderen von der SD eingelesen
3
// und umgekehrt.
4
//
5
uint8_tBufferA[512];
6
uint8_tBufferB[512];
7
8
uint8_t*playBuffer=BufferA;// die ISR gibt immer aus playBuffer aus
9
uint8_t*readBuffer=BufferB;// von der SD Karte wird immer in readBuffer eingelesen
Karl heinz Buchegger schrieb:> 2 Aktionen die nebeneinander herlaufen.> Die eine wird regelmässig im Interrupt gemacht, die andere in der> Hauptschleife.
sie laufen ja nicht nebenher, eine Aktion wird ja immer Unterbrochen.
>Wenn ich mir deine Performance hier so ansehe, dann denke ich, dass>dieses Projekt noch 5 Nummern zu groß für dich ist.
Dann muß mann halt zusehen, dass man sich auf Nummer 1 runterarbeitet
und das möchte ich unter anderem mit diesem Projekt erreiche. Wenn ich
es jetzt wieder in die Ecke lege, bringt mich das nicht weiter und das
möchte ich eigentlich vermeiden.
Code werde ich mir mal durcharbeiten um ihn zu verstehen.
Ingo Laabs schrieb:> Karl heinz Buchegger schrieb:>> 2 Aktionen die nebeneinander herlaufen.>> Die eine wird regelmässig im Interrupt gemacht, die andere in der>> Hauptschleife.>>> sie laufen ja nicht nebenher
Sie müssen aber!
(Siehe das Codefragment 1 Posting höher)
> Dann muß mann halt zusehen, dass man sich auf Nummer 1 runterarbeitet> und das möchte ich unter anderem mit diesem Projekt erreiche.
Man fängt aber üblicherweise nicht als Kleinkind an, für den New York
Marathon zu trainieren, sondern man macht erst mal seine ersten
Schritte, lernt gehen, lernt laufen, läuft in der Regionalliga und
irgendwann ist man dann soweit für eine große Veranstaltung.
> Wenn ich> es jetzt wieder in die Ecke lege, bringt mich das nicht weiter und das> möchte ich eigentlich vermeiden.
Es bringt dich auch so nicht weiter, weil du die dahinterliegenden
Techniken noch nicht entdeckt hast. Und nein: 2 Dinge mehr oder weniger
gleichzeitig zu tun, ist keine Raketentechnik. Das ist absolut simpel,
wenn die eine sowieso schon im Interrupt abgearbeitet wird.
Der einzige "Trick" im geposteten Fragment besteht darin, 2 Pointer zu
benutzen, die auf die eigentlichen Buffer zeigen. Das müsste man nicht
so machen, wenn man die Aufgabenstellung das erste mal macht, machen die
meisten Neulinge erst mal eine Variable die anzeigt welcher Buffer was
macht und spicken dann den Code mit if-s. Mit den Hilfspointern ist das
deutlich einfacher. Aber abgesehen von diesem Detail ist die Benutzung
von 2 Buffern, die wechselweise zum Abspielen/Einlesen benutzt werden
ziemlich naheliegend.
Schade, dass hier immer wieder auf dieser Ebene Diskutiert werden muss.
Das bringt und nicht weiter.
Übrigens: Habe auch mit aufwendigeren Dingen begonnen und später auch
sehr einfache Dinge umgesetzt, die ich im Haus noch so benötigt habe. So
war es für mich zwar schwer aber reizvoller und es hat gut funktioniert.
Wenn ich mir ansehe, dass die Aufgabenstellung "SD-Karte auslesen und
mittels PWM abspielen" mitlerweile ins vierte Monat geht, dann ist das
nicht gerade ein überzeugender Beweis für die These "Es ist ok, mit
Dingen anzufangen, die noch 5 Schuhnummern zu groß sind"
Karl heinz Buchegger schrieb:> Wenn ich mir ansehe, dass die Aufgabenstellung "SD-Karte auslesen und> mittels PWM abspielen" mitlerweile ins vierte Monat geht, dann ist das> nicht gerade ein überzeugender Beweis für die These "Es ist ok, mit> Dingen anzufangen, die noch 5 Schuhnummern zu groß sind"
offtopic:
Vllt. hat man ja auch nicht immer die Zeit um sich darum zu kümmern. Es
existiert ja auch noch eine Familie. Ich kann mich mit Sicherheit 2
Wochen in ein mein Kämmerchen sperren, aber der Preis, den ich dann
gegenüber meiner Familie dafür zahle wäre ein bissel hoch, gell.
Von daher bin für jede Hilfe dankbar. Ich bin was das bertrifft mit
Sicherheit kein Profi und werde es wohl auch mit Sicherheit auch nicht
werden. Das hält mich aber nicht ab, Dinge umzusetzen, auch wenn es
aufgrund meines nicht Profidaseins ein wenig länger dauert. Von daher
bin ich jedem Profi hier, der sich das hart erarbeitet hat, dankbar.
OK. Einmal noch. Dann halt ich mich wieder raus
Ingo Laabs schrieb:> Vllt. hat man ja auch nicht immer die Zeit um sich darum zu kümmern.
Immer Zeit?
Tschuldigung. Wenn ich das da oben in 5 Minuten aus dem Ärmel schütteln
kann, dann erwarte ich von jemanden, der das noch nie gemacht hat, aber
die Grundlagen dazu hat, dass er das in deutlich unter einem Nachmittag
hinbringt. Da sind wir von 4 Monaten weit entfernt.
Die Nachmittage die ich dazu nutze, 2 Kindern die Hausaufgaben
beizubringen.
Gott sei dank programmieren die nicht in der Schule, sonst würde ich auf
dem schlauch stehen.
Es ist doch so Karl-Heinz, du darfs auch nicht vergssen, dass du, so wie
ich das hier mitkriege der absolute Profi bist und ich nur ein kleiner
ich-habe-mal-lust-programmierer der den Kindern was lustiges bauen
möchte was kein anderer hat.
Nun aber beim Thema bleiben, sonst wird das Thema hier noch geschlossen
(nicht von mir glaube ich).
10 Playlisten a 255 Tracks alternativ. Wenn der Controller ein AVR ist,
wonach es aussieht, kann man die Firmware ja auch patchen oder als
Open-Source-Projekt neu gestalten. Gibt ja genug Geeks hier :-).
Werde mal versuchen den von Karl-Heinz vorgeschlagenen Buffertausch zu
realisieren.
Habe aber parallel dazu noch mal folgende Überlegung im Kopf. Da das
Problem ja immer dann auftritt wenn der neuer Buffer von der Karte
gelesen wird, kann ich dann eigentlich nicht auch wenn das letzte Byte
gelesen wurde den delay entsprechend des Bufferzugriffs auf die Karte
kürzen.
1
while(1)
2
{
3
// taste 3
4
if(!(PINA&(1<<PINA3)))// ist 0 ?
5
//Lade Cluster für das index.htm File in den Speicher
Habe die Idee von Karl-Heinz jetzt mal umgesetzt.
Tausche jetzt die Buffer aus. Es ist aber immer noch das Problem
geblieben, dass folgender Zugriff auf die Karte
fat_read_file (Clustervar,Buffer,b);
einfach zu lange dauert und ich immer noch Lücken in der Ausgabe habe.
Hallo Ingo,
ich habe mich noch einmal an die Interrupt Lösung gemacht und die
Sprache hört sich nun besser an. Probiers mal aus.
Ich habe allerdings auf 12Mhz Quarz und ein 8khz wave File umgestellt.
Zugegeben, ich habe den Code einfach "hingebogen" bis es passt aber mir
gings mal um die Verbesserung der Sprachqualität.
Die Interrupts müssten nochmal nachgerechnet werden um die exakte
Geschwindigkeit hinzugekommen.
Viel Spaß
Grüße
Matthias
Hier nochmal das ganze mit:
Erkennung der Dateilänge. (Beendet Audioausgabe am Dateiende)
PortC0 schaltet Relais für den Verstärker (Stromversorgung ein und aus)
Pullups an den Eingängen wieder drin. ( Hatte ich versehentlich
auskommentiert).
Implementiert ist momentan jedoch nur die Datei ABAUF.WAV. Kann man aber
beliebig auf andere Dateien erweitern.
Ist es sicher. Ich freue mich auf die ersten Berichte.
Selbstgemacht und "lowest cost" wenn geht macht mir jedoch mehr Spaß.
Übrigens: Meine letzte Bestellung aus der E.. Apotheke hat 3,5 Monate
auf sich warten lassen. :-) War dann ganz überrascht über das Paket. Ist
nicht so mein Shop.
Matthias Reichelt schrieb:> Hallo Ingo,>> ich habe mich noch einmal an die Interrupt Lösung gemacht und die> Sprache hört sich nun besser an. Probiers mal aus.> Ich habe allerdings auf 12Mhz Quarz und ein 8khz wave File umgestellt.>> Zugegeben, ich habe den Code einfach "hingebogen" bis es passt aber mir> gings mal um die Verbesserung der Sprachqualität.>> Die Interrupts müssten nochmal nachgerechnet werden um die exakte> Geschwindigkeit hinzugekommen.>> Viel Spaß> Grüße> Matthias
WOW..Super,
muss jetzt mal schauen wo ich in meinem Programmteil zum Buffertausch
den Bockmist geschossen habe.
Hier ein Programm um die Timer zu berechnen.
http://www.avrcalc.com/
Gruß aus Berlin
Ingo
Hab das 8khz file auch mal auf einen ordentlichen Verstärker gegeben.
Das Knattern ist definiv weg.
Lass hören, wenn Du das mit dem 22khz file noch hinbekommst. Ich habe
die 8khz gewählt um Zeit beim Lesen der Karte zu gewinnen. Evtl. höheren
Takt verwenden.
Ich versuche erstmal nichts weiter in der Richtung sondern kümmere mich
um den Anschluß des RFM Moduls damit ich remote samples abspielen lassen
kann.
Grüße aus Wien
Matthias
Ups, sehe gerade, dass ich beim ersten Buffertausch noch keine Daten
geladen habe. Wahrscheinlich kommt daher der eine Knackser zu Beginn des
Abspielens.
Werde heute Abend es mit den 22050 Hz probieren. Konte gestern Abend nur
mal kurz probieren. Bin jetzt auf Arbeit. Evtl wäre für den Interrupt
der CTC Mode angebracht. Erspart das nachladen des Timers.
>Habe letzt 20MHz genommen un bekomme bei 16KHz brauchbare Ergebnisse.>Bissel Rattert es noch..aber brauchbar.
Also ich schaff mit 16MHz eine 22kHz Ausgabe ohne rattern.
Irgendwas machst du falsch;)
holger schrieb:>>Habe letzt 20MHz genommen un bekomme bei 16KHz brauchbare Ergebnisse.>>Bissel Rattert es noch..aber brauchbar.>> Also ich schaff mit 16MHz eine 22kHz Ausgabe ohne rattern.> Irgendwas machst du falsch;)
kannste mal code posten?
den hier habe ich bei 20 MHz und 22050 KHz sampling
1
#include<stdio.h>
2
#include<string.h>
3
#include<avr/io.h>
4
#include<avr/eeprom.h>
5
6
#include"mmc.h"
7
#include"fat.h"
8
#include"usart.h"
9
#include<util/delay.h>
10
#include<avr/interrupt.h>
11
12
volatileinta;
13
intb;
14
intdl2;
15
unsignedcharBuffer[512];
16
unsignedcharplayBuffer[512];
17
uint8_tbufferChanged;
18
19
20
21
22
23
ISR(TIMER2_OVF_vect)
24
{
25
26
TCNT2=0x8F;
27
28
if(a<512)
29
{
30
OCR1A=playBuffer[a];a++;
31
}
32
if(a==512)
33
{
34
}
35
36
}
37
38
//Hauptprogramm
39
intmain(void)
40
{
41
//SYSCLK defined in usart.h
42
//Initzialisierung der seriellen Schnittstelle
43
44
45
TCCR2|=(1<<CS21)|(0<<CS20)|(0<<CS22);// Start timer at Fcpu/08
46
//Enable Overflow Interrupt Enable
47
TIMSK|=(1<<TOIE2);
48
49
50
51
dl2=0;
52
53
54
//Initialisierung der MMC/SD-Karte
55
usart_write("System Ready!\r\n");
56
while(mmc_init()!=0)//ist der Rückgabewert ungleich NULL ist ein Fehler aufgetreten
57
{
58
usart_write("** Keine MMC/SD Karte gefunden!! **\n");
>kannste mal code posten?
Klar. Hier mal die main.c. Das komplette Projekt
poste ich später mal oder packs gleich in die Codesammlung.
Ich bin da noch ein bisschen am basteln;)
>hmmm..das is ja jetzt was völlig anderes als das was wir hier>haben..dachte jetzt du hast es mit dem vorhandenen code gemacht
Naja, nicht jeder nutzt Ulrichs Code;)
So, hier mal eine vorläufige Version zum schnuppern als AVR-Studio
Projekt.
Soundausgabe erfolgt an OC2/PD7 per PWM.
Standard SPI Anschluss der SD-Karte an MISO,MOSI, SCK.
CS der SD am SS Pin. ATMega32 getaktet mit 16MHz.
Bei Problemen schlagen sie ihren Arzt oder...;)
Gut, ich denke ich habe alles zusammen was ich brauche.
Vielen Dank für die Initiative und an die Beteiligten.
Danke auch an Holger für den Code. Werde mir Deine Lösung noch anschauen
und testen, wenn ich einen Quarz nachbesorgt habe.
>Danke auch an Holger für den Code. Werde mir Deine Lösung noch anschauen>und testen, wenn ich einen Quarz nachbesorgt habe.
Funktioniert auch bei 8MHz noch gut. Bei 4MHz raschelt es dann
doch ein wenig mit 22kHz Samplerate;)
Ingo Laabs schrieb:> Habe letzt 20MHz genommen un bekomme bei 16KHz brauchbare Ergebnisse.> Bissel Rattert es noch..aber brauchbar.
Ich hab grad noch mal ein bisschen experimentiert. 16khz laufen bei mir
mit 12Mhz problemlos. ( Version Ingo ) Kein Rattern zu hören.
Übrigens. Hab nette Ergänzungen gefunden:
Pollin Deckenlautsprecher 640 379
und Wavefiles von Balabolka. ( Text-to-Wave converter )
Hallo,
noch eine Anmerkung zur PCM Ausgabe per atTiny861.
ChaN beschreibt in seinem Artikel vom 11.09. einen "255-Voice PCM Sound
Generator".
http://elm-chan.org/works/sd20p/report.html
Da ich auch eine Sprachausgabe benötige, habe ich die Idee aufgegriffen
auf mit einem atTiny861V-10 auf einem Steckbrett die Software getestet.
original Schaltplan: http://elm-chan.org/works/sd20p/sdsg.png
Den Schaltplan habe ich etwas erweitert:
a) PB7 Reset - PullUp mit 10k an +5V
b) mit MMCSDSCH.JPG habe ich eine 4GB SDHC Karte per Floppystecker mit
dem atTiny861V-10 verbunden.
c) ein kleiner a Kopfhörverstärker LM386 gain=20 treibt einen 8 Ohm
Lautsprecher.
d) ein 3,3V Spannungsregler mit PO30RV11 Regler für die SD-Karte.
Leider habe ich noch Abbrüche beim abspielen der WAV Dateien, sie laufen
zwischen 1-20 sek, dann zeigt die Software einen Fehler beim Zugriff auf
das Dateisystem an.
Ich denke es liegt an der SDHC Karte Verkabelung - zu lange <=5cm.
Hallo,
Lösung für den "255-Voice PCM Sound Generator":
http://elm-chan.org/works/sd20p/report.html
Nun habe ich die SD-Karte und den atTiny861 direkt an die 3,3V des
Spannungsregler PO30RV11 angeschlossen.
- der atTiny861 ist direkt mit der SD-Karte verbunden, also keine
Spannungsteiler Widerstände mehr !
- ein 10k PullUp (3,3V) Widerstand ist noch an die CS-Leitung (PB0) der
SD-Karte angeschlossen.
- die +5V aus dem USB-Port speisen nun nur noch den LM386 direkt.
Und siehe da, es geht alles - 1A Projekt !
.
Hallo Matthias !
Matthias Reichelt schrieb:> Wo bekommt man den atTiny861 am einfachsten ?
ich habe meine drei Stück über das I-Net bei
- http://www.kessler-electronic.de/
bestellt.
Die Firma ist auch in der Bucht zu finden: kessler-electronic
Das geht immer innerhalb von 1-2 Tagen, wenn man per paypal bezahlt.
.
Eigentlich schade.
Zitat:
Für Lieferungen ins europäische Ausland erfolgt nur per Vorauskasse. Es
gilt ein Mindestbestellwert von 100,- . Die Versandkosten betragen hier
14,95 pro Paket mit maximal 30 kg Gewicht
Vielleicht komme ich mal die Verlegenheit 30kg Tinys zu bestellen. :-)
Trotzdem Danke für den Tip.
Hallo Uwe,
das ist wirklich sehr nett. Ich glaube ich werde bei Gelegenheit über
meinen "Kontaktmann" in Deutschland bestellen und dann weiterschicken
lassen, da evtl. noch einiges hinzu kommt.
Es ärgert mich nur immer wenn ich solche Phantasiepreise für
Versandkosten sehe. Macht mein Namensvetter leider auch so.
Grüße aus Wien
Matthias
Kann mir mal einer sagen wo in dem Programm mit dem Tiny 861 die
Tastatur abgefragt wird ? Das Programm würde für mich mehr Sinn machen,
wenn ich die Taster einzeln abfragen könnte, also pro PortPin ein Wave
abspielen.
Guten Morgen Ingo,
eine Änderung ist nicht notwendig.
Lege einfach je eine Datei für jeden Pin ab.
Bit 0 = 001.wav
Bit 1 = 002.wav
Bit 2 = 004.wav
:
Bit 7 = 128.wav
läuft super bei mir !
Die "Tasten" sind Taster und werden über den PinChange Interrupt
'abgefragt'.
Siehe in "main.c" die Funktion
Guten Morgen Ingo,
der Quellcode ist öffentlich und dort wird nicht unterschieden.
Ich habe ja SDHC verwendet ohne irgendwelche SW Anpassungen, der Autor
eine Micro SD Karte im Einsatz.
Was er dazu schreibt, steht hier:
http://elm-chan.org/works/sd20p/report.html
[I]A MicroSD card is used as storage media and also SD and MMC can be
used. It is controlled in SPI mode via USI.[/I]
Ok ?
Moin Moin
hab den Code von Holger soweit zum Laufen gebracht. Aber ich komme
irgendwie nicht drauf, wie man die Soundausgabe stoppen kann, so dass
man sie hinterher wieder starten kann (evntl auch mit nem anderen
Track).
wenn ich StopTimer(); und Fclose(); mache, dann kann ich danach nix mehr
abspielen mit PlayWave();
Hat einer da schon ne Lösung oder Idee?
Grüße Henning
Ist zwar schon einige Zeit her aber hier noch meine fertige Software mit
RFM01 Anbindung auf 433.300. RFM empfängt einen string der mit "WAV;"
beginnt und hinter dem Semikolon folgt der Dateiname der anzuspielenden
Wave Datei. Der Dateiname besteht aus 5 Buchstaben und der Endung ".WAV"
Damit spiele ich nun schon seit monaten Wave files ferngesteuert von
meinem AVR-NET board ab.
Der Code ist vielleicht nicht besonders "sauber" geschrieben aber es
funktioniert prima. Vielleicht kann jemand etwas damit anfangen.
Der Inhalt der SD Karte befindet sich im Verzeichnis "stimmen" des Zip
Files.
Sprachfiles erstelle ich normalerweise mit Bolabolka am PC.
Viel Spaß
Ingo Laabs schrieb:> warum ?> was hast du gemacht ?
Also, wie gesagt, ich hab versucht, das ganze mit Fclose() und
StopTimer() zu beenden. Dabei bin ich aber in dieser "ugly waitingloop"
hängengeblieben.
Hab dann einfach ein zusätzliches Abbruchkriterium hinzugefügt, und
schon konnte ich Tracks stoppen und danach wieder andere abspielen. Also
eigentlich wars n blöder Fehler, aber manchmal braucht man ja ein
bisschen um drauf zu kommen.
Hier der Code, damit du weißt , was ich meine:
void PlayWave(char *name)
//######################################################################
#############
{
unsigned char result;
unsigned int read_bytes;
//unsigned long chunksize;
test = 0;
result=Fopen(name,'r');
if(result==F_OK)
{
read_bytes = Fread(play_buffer0,0x3A); // skip the wave header (not
always 0x3A length!)
play_buffer_index = 0;
play_buffer_number = 0;
// fill first audio buffer
read_bytes = Fread(play_buffer0,PLAY_BUFFER_SIZE);
StartTimer(); // start playing
do
{
if(play_buffer_number & 1) // buffer number 1 is playing, read buffer
0
{
read_bytes = Fread(play_buffer0,PLAY_BUFFER_SIZE);
while((play_buffer_number & 1) && (test != 1)); // ugly waiting
loop, try to use a state machine
}
else // buffer number 0 is playing, read buffer 1
{
read_bytes = Fread(play_buffer1,PLAY_BUFFER_SIZE);
while(((play_buffer_number & 1) == 0 ) && (test != 1));
}
} while((read_bytes == PLAY_BUFFER_SIZE) && (test != 1));
// if read_bytes is smaller PLAY_BUFFER_SIZE ignore these samples
// or fill buffer with zero samples at the end
StopTimer();
Fclose();
}
}
Grüße Henning
Ingo Laabs schrieb:> hats auch irgendwo nen schaltplan ?
Hallo Ingo,
anbei was ich noch habe. Ich weiss aber nicht, ob ich zwischenzeitlich
noch Kleinigkeiten geändert habe, die ich nicht im Schaltplan habe.
Insbesondere bei der Beschaltung der SD Karte.
Für das Prinzipverständnis sollte es jedoch reichen. Schönheitsfehler in
der Zeichnung bitte ich zu entschuldigen. Ich habe sie nur für mich
selbst angefertigt.
Eingebaut habe ich das ganze in einen alten "PC Lautsprecher". Da dort
Netzteil und Verstärker schon eingebaut sind.
Grüße
Matthias