Moin zusammen
Ich versuche gerade ein Rechteckgen. von 0 - 5KHz (linear) zu
Programmieren. Der Compiler ist Bascom. Da der Analogwert nur zu 1024
auflöst ist das ganze gestaffelt 0-1000 1000-2000 usw.. Die Linearität
ist natürlich ein Problem, da die Rechnung an sich zeit, braucht und der
Sprung in die ISR Beziehung auch ihre zeit benötigt. Das sind aber
Fehler die Leicht ausgeglichen werden können da der Sprungfehler Linear
wächst und der Rechnungsfehler beinahe statisch ist.
Alllsooo meine frage an die Community.
1.0 Wie kann ich z.b. einer Variable (single) sagen das sie nur 2
stellen hinter dem komma auflösen soll.
1.1 Ich kann natürlich auch z.b Long variable nehmen und den wert *100
rechnen. Nur dann muß ich das Komma setzen.
Wie setzt man ein Komma.
2.0 Das Hauptproblem ist aber das mein 16 Bit timer ab einem bestimmten
wert anfangen soll zu zählen 0-65535. Der nimmt aber je nach prescale
nur werte ab 23000 an. WARUM
Dazu wäre noch zu sagen das der Aufbau in der Form ist:
$regfile = "m8def.dat"
$crystal = 8000000
Config Portd = Output
Dim A as Word
Config Timer1 = Timer , Prescale = 256
Enable Timer1
On Timer1 Isr_von_timer1
Enable Interrupts
Timer1 = A
Do
A = xxx
blablabla
usw.
Loop
End
Isr_von_timer1:
Timer1 = 34285
Toggle Portd.0
Return
wenn der wert A < ca 30000 wird nicht in die Isr beziehung gesprungen.
>Do>A = xxx>blablabla>usw.>Loop>End
Interessant, was Bascom so an Befehlen unterstützt.
Übrigens unterstützt der mega8 schon in Hardware die PWM bzw. vriable
Frequenzerzeugung...Sowas steht wie immer im Datenblatt.
>Ich versuche gerade ein Rechteckgen. von 0 - 5KHz (linear) zu>Programmieren.
Das will ich sehen. Man kann zwar die Periodendauer linear verändern,
aber die Frequenz?
Ciesla tim wrote:
> Moin zusammen>> Ich versuche gerade ein Rechteckgen. von 0 - 5KHz (linear) zu> Programmieren. Der Compiler ist Bascom. Da der Analogwert nur zu 1024> auflöst ist das ganze gestaffelt 0-1000 1000-2000 usw..
Warum willst Du den Wert über ein Poti einstellen? Damit hast Du doch
immer etwas Jitter drauf. Nimm doch lieber eine digitale Einstellung per
Taster oder Drehencoder.
> Die Linearität> ist natürlich ein Problem, da die Rechnung an sich zeit, braucht und der> Sprung in die ISR Beziehung auch ihre zeit benötigt.
Das verstehe ich nicht. Du musst doch nur den Timer in die Betriebsart
einstellen, dass er bei Compare den OC-Pin toggelt und von 0 beginnt
(siehe Datenblatt, Kapitel Timer). Dann wird die Frequenz ohne Interrupt
im Hintergrund von der Hardware erzeugt. Um sie einzustellen, legst Du
die Dauer einer halben Periode (in Timerticks gemessen) in das
OCR-Register.
> Das sind aber> Fehler die Leicht ausgeglichen werden können da der Sprungfehler Linear> wächst und der Rechnungsfehler beinahe statisch ist.
Was ist ein Sprungfehler?
> Alllsooo meine frage an die Community.
Gute Idee.
>> 1.0 Wie kann ich z.b. einer Variable (single) sagen das sie nur 2> stellen hinter dem komma auflösen soll.
Das Rechnen mit gebrochenen Zahlen ist für den AVR Schwerstarbeit, das
sollte man vermeiden.
>> 1.1 Ich kann natürlich auch z.b Long variable nehmen und den wert *100> rechnen. Nur dann muß ich das Komma setzen.
Das ist der bessere Weg.
> Wie setzt man ein Komma.
In Assembler könnte ich Dir das erklären, in BASCOM weiß ich das nicht.
>> 2.0 Das Hauptproblem ist aber das mein 16 Bit timer ab einem bestimmten> wert anfangen soll zu zählen 0-65535. Der nimmt aber je nach prescale> nur werte ab 23000 an. WARUM
Auch das kann ich nicht nachvollziehen.
Um einen Timer zum Zählen zu bewegen, trägt man eine Taktquelle (z.B.
Vorteiler) in sein entsprechendes Steuerregister ein. Dazu kommen noch
die entsprechenden Bitmuster ("Schalterstellungen") für die gewünschte
Betriensart des Timers. Nicht jede Betriebsart erfordert, dass der Timer
Interrupts auslöst, das Toggeln des OC-Pins oder das Erzeugen einer PWM
geht komplett in Hardware ohne Interrupt.
...
Erstmal danke für die schnellen Antworten.
Ich habe nicht sonderlich viel Erfahrung mit Controllern. Darum viel mir
als erstes Timer und toggeln ein.
Die Idee war eigentlich über ein zweites Poti2 Verschiedene
Bereiche Anzusprechen z.b 0-1000 Hz.
Die Zuweisung erfolgt mit einer case Anweisung in der Prescale jedes mal
neu definiert wird. In jeder case Anweisung soll der wert des Poti1
abgefragt werden und über eine einfache Rechnung soll der Startwert von
timer1 neu eingetragen werden. Diesen wert steht in der case Anweisung
und in der Isr Bez.
So habe ich auf dem Qsi eine schöne Rechteckspannung.
Da ich den Timer1 aber nicht von 0 an zählen lassen kann sondern von
einem viel höheren wert sind einige Frequenzbereiche nicht zu
Generieren(Scheiße).
Wenn das ganze über die Hardware laufen kann ist das natürlich um
einiges besser. Ich versuche mich mal in dieser Richtung schlau zu
machen.
Jetzt zur Pwm Idee. Da müste ich doch auch so vorgehen und Über das poti
den Wert abfragen und eintragen oder.
ps: mit sprungfehler meine ich die Zeit die benötigt wird um die
unterfkt aufzurufen zu toggeln und zurückzuspringen.
Hi!
Schau dir mal die CTC-Mode eines 16 Bit-Timers an.
Mit 16 MHz Takt kannst du dein Rechtecksignal mit einem Raster von
62,5ns verstellen. Der Frequenzbereich erstreckt sich dann von
122,072..Hz bis
8 MHz ohne Vorteiler. für deine geforderten 5KHz ist die Auflösung also
recht akzeptabel. unter den 122.. Hz musst du nur den Vorteiler mit
einschalten.
Sollte das nicht ausreichend sein?
Viel Erfolg, Uwe
Ich muß da noch mal Nachfragen.
Irgendwie bekomme ich das mit den variablen nicht hin. Sind sie single
für die genauigkeit ist der wert genau nur tritt dann ein timigfehler
auf. Mit Word ist der Rundungsfehler echt mies und das timing ist
besseer. Dann muß ich das Ergebnis ja noch auf dem LCD Display ausgeben
wofür ich wieder rechnen muß und die Rundungsfehler noch gravierender
werden(Word).
Neue Idee die Frequenzen 0-5KHz zu generieren das klappt schon. Nur die
Genauigkeit laßt zu wünschen übrig.
Um Ressourcen zu Sparen da alles schon sehr labil ist wäre es dann nicht
sinnvoll die Frequenzen zu generieren und über einen Zweiten Atmega8
diese zu messen und auszugeben?
Ich setzt mich jetzt mal hin und schau ab das besser klappt.
Wenn jemand eine Bessere Idee hat nur her damit
Ciesla tim wrote:
> Ich muß da noch mal Nachfragen.>> Irgendwie bekomme ich das mit den variablen nicht hin. Sind sie single> für die genauigkeit ist der wert genau nur tritt dann ein timigfehler> auf.
Das Rechnen mit Fließkommazahlen ist für den AVR Schwerstarbeit. Wenn Du
dann noch den Pin vom Programm aus toggeln musst, dann kommt der AVR
nicht mehr nach.
> Mit Word ist der Rundungsfehler echt mies und das timing ist> besseer. Dann muß ich das Ergebnis ja noch auf dem LCD Display ausgeben> wofür ich wieder rechnen muß und die Rundungsfehler noch gravierender> werden(Word).
Meiner Meinung nach benötigst Du eine 16-Bit-Ganzzahl, die in einigen
Hochsprachen auch 'Integer' genannt wird. Denn der Timer arbeitet ja mit
16-Bit-Ganzzahl, 'Single' (also Fließkommazahl einfacher Genauigkeit)
kennt der Timrer nicht, warum um alles in der Welt sollte man damit
rechnen??
>> Neue Idee die Frequenzen 0-5KHz zu generieren das klappt schon. Nur die> Genauigkeit laßt zu wünschen übrig.
0 kHz klappt immer, lass das Gerät einfach aus. Aber zwischen 0 und dem
unteren einstellbaren Wert wird es problematisch. Der untere
einstellbare Wert wir durch den Zählumfang des Timers (64K, also 65536)
begrenzt. Zwar auch durch den Vorteiler, aber im Sinne einer feinen
Abstimmbarkeit sollte dieser möglichst klein gehalten werden.
> Um Ressourcen zu Sparen da alles schon sehr labil ist wäre es dann nicht> sinnvoll die Frequenzen zu generieren und über einen Zweiten Atmega8> diese zu messen und auszugeben?
Nein, das ist nicht sinnvoll, denn die Ressourcen des AVRs sind allemale
ausreichend. Du musst sie nur nutzen. Also:
- Frequenzerzeugung am OC-Pin per Hardware des Timers
- Einstellung der Periodendauer statt der Frequenz (Umrechnung in
Frequenz
nur für die Anzeige)
- ADC-Abfrage mit Hysterese nachrüsten, um (funktionsbedingten) Jitter
zu
vermeiden
> Ich setzt mich jetzt mal hin und schau ab das besser klappt.>> Wenn jemand eine Bessere Idee hat nur her damit
Bessere Idee?
- Datenblatt (Vollversion) des AVRs lesen (und verstehen), besonders
das Kapitel Timer
- BASCOM-Dokumentation lesen und versuchen zu ergründen, wie viele
Ressourcen von ganz simpel erscheinenden BASIC-Befehlen gefressen
werden
...
Danke Hannes
Ich bin gerade im Praktikum (FH) und das ich Bascom Volllenasteniker bin
geht's hier nur um das Ergebnis. Ich will hier auch niemanden ein Loch
in den Bauch fragen.
Darum habe ich mich für die 2 AVR Variante entschieden.
Ich messe die Impulse pro Sekunde, das klappt für f >500 erstaunlich
genau. Und bei f<500 messe ich die Zeit zwischen 2,4 oder 8 Impulsen muß
noch schauen was das beste Ergebnis bringt.
Trotzdem bin ich weiten Vorschlägen nicht abgeneigt
Am Wochenende werde ich mir dann wohl oder übel den Langenscheid
schnappen und mir das Datenblatt vorknüpfen.
Wenn dann mal alles Klappt setzte ich den Quell-code hier rein.
>Meiner Meinung nach benötigst Du eine 16-Bit-Ganzzahl, die in einigen>Hochsprachen auch 'Integer' genannt wird. Denn der Timer arbeitet ja mit>16-Bit-Ganzzahl, 'Single' (also Fließkommazahl einfacher Genauigkeit)>kennt der Timer nicht, warum um alles in der Welt sollte man damit>rechnen??
Ich will dem timer keine Single verpassen. Nur die Rechnug damit der
Rundungsfehler klein bleibt. Denn bei einigen bereichen von prescale
kommt es auf die letzte zahl an. Hab die Rechnung von 1-5KHz(besser) für
jedes Prescale mit c++ ausgeben lassen da sieht man das ganz gut. Nur
der letzte wert habe ich in word konvertiert. Und das ist schon sehr
ungenau.
Mein erster Vorschlag war eine Tabelle mit 5000 einträgen a 5 zeichen na
ja das ging dann nicht ganz.
@Hannes
> Wie setzt man ein Komma.> In Assembler könnte ich Dir das erklären, in BASCOM weiß ich das nicht.
Das wuerde mich mal fuer Assembler interressieren.
Also ich habe eine binaere Zahl in einem Register des ATmega8. Sagen wir
123 und nun soll es eine 12,3 sein. Wie wird das in Assembler
programmiert ?
Vielen Dank
daniel
Meine Hedanken dazu nochmal zum Mitmeißeln:
- Mit der Eingabe (Poti-ADC, besser was Digitales wie Taster oder
Drehgeber) nicht die Frequenz eingeben wollen, sondern die (halbe)
Periodendauer, also die Ganzzahl, die Du in das Compare-Register
des Timers schreibst. Da Du den Timer nicht mit einer "Frequenz"
füttern kannst, sondern nur mit einer (halben) Periodendauer, macht
das Eingeben einer Frequenz und anschließende Umrechnen in die
Periodendauer (zum Timer füttern) keinen Sinn.
- Den Timer in die Betriebsart schalten, in der er den OC0A oder
OC0B-Pin
direkt beim Compare-Ereignis toggelt und sich selbst löscht, ohne dass
ein Interrupt ausgelöst werden muss. Das kostet dann keine (absolut
keine!!) Rechenzeit.
- Den eingestellten Periodenwert zur Frequenz umrechnen und am LCD
anzeigen. Damit bekommt der Benutzer das Gefühl, die Frequenz
eingegeben zu haben, obwohl er ja nur einen timertauglichen Wert für
die Periodendauer eingibt/ändert.
- Falls die Eingabe per Poti erfolgen muss, dann noch eine Hysterese
einbauen, die dafür sorgt, dass ein neuer Wert erst dann übernommen
wird, wenn er mehr als 2..3 Werte vom alten Wert entfernt ist. Das
beruhigt die Eingabe und damit auch die erzeugte Periodendauer bzw.
Frequenz.
- Sinnvoll wäre vermutlich eine Art Bereichswahl mittels Up/Down-Tasten
und eine Feinabstimmung innerhalb des Bereiches. Mit den Up/Down-
Tasten stellst Du den Grundwert (16 Bit Ganzzahl) im Raster von 1024
ein, zu dem Du dann den (per Hysterese beruhigten) ADC-Wert des Potis
addierst.
...
daniel wrote:
> @Hannes>>> Wie setzt man ein Komma.>>> In Assembler könnte ich Dir das erklären, in BASCOM weiß ich das nicht.>> Das wuerde mich mal fuer Assembler interressieren.> Also ich habe eine binaere Zahl in einem Register des ATmega8. Sagen wir> 123 und nun soll es eine 12,3 sein. Wie wird das in Assembler> programmiert ?
Eine Zahlenausgaberoutine für 16 und 24 Bit findest Du in der
Include-Datei LCDprint auf dieser Seite:
http://www.hanneslux.de/avr/stopuhr/index.html
Das genze Projekt ist zwar (aus heutiger Sicht) nicht das Nonplusultra,
aber es funktioniert.
>> Vielen Dank> daniel
Nix zu danken
...
Gar nicht.
Der springende Punkt ist, dass du das Komma nur zur
Anzeige brauchst. Du speicherst nach wie vor 123 im
Register. Und bei der Ausgabe gibst du vor der Einerstelle
ein Komma aus.
Das ist ein bischen so wie beim Rechnen mit Geld.
Du willst €2.20 und €3.70 addieren, hast aber
keine Kommastellen zur Verfügung.
Kein Mensch sagt aber, dass du das in Euro rechnen musst.
Rechne es halt in Cent. €2.20 sind 220 Cent. €3.70 sind
370 sind. Jetzt haben wir schöne ganze Zahlen.
220 + 370 macht 590. Bei der Ausgabe schmuggeln wir vor
der 2.ten Stelle wieder ein Komma an und schreiben
noch ein € davor: €5.90
Natürlich gibt es Fälle, bei denen man echte Gleitkomma-
arithmetik braucht. Aber gerade im µC Bereich kommt man
mit so einer Systematik (die man Fixkomma nennt) sehr, sehr
weit.
@Hannes
> Eine Zahlenausgaberoutine für 16 und 24 Bit findest Du in der> Include-Datei LCDprint auf dieser Seite:> http://www.hanneslux.de/avr/stopuhr/index.html> Das genze Projekt ist zwar (aus heutiger Sicht) nicht das> Nonplusultra, aber es funktioniert.
Da ich gerade an Erweiterungen im AVR-Tutorial arbeite:
Darf ich mir aus deinen Sourcen Dinge dafür klauen.
Ich wäre auch froh, wenn du ein oder 2 Kapitel übernehmen
könntest. Was ich in nächster Zeit brauchen würde:
Einführung in den ADC; wie steuert man ein Servo an.
Karl heinz Buchegger wrote:
> @Hannes
Grüß Gott, Karl Heinz...
>>> Eine Zahlenausgaberoutine für 16 und 24 Bit findest Du in der>> Include-Datei LCDprint auf dieser Seite:>> http://www.hanneslux.de/avr/stopuhr/index.html>> Das genze Projekt ist zwar (aus heutiger Sicht) nicht das>> Nonplusultra, aber es funktioniert.>> Da ich gerade an Erweiterungen im AVR-Tutorial arbeite:> Darf ich mir aus deinen Sourcen Dinge dafür klauen.
Selbstverständlich darfst Du das. Es ist ja auch nicht alles auf meinem
Mist gewachsen, Ich habe da nur (auf niedrigerem Niveau)
nachgeschrieben, was ich an Beispielen von Peter, Andreas, Andy und
einigen anderen verstanden habe. Wohlbemerkt, verstanden und
nachempfunden, nicht blind kopiert...
>> Ich wäre auch froh, wenn du ein oder 2 Kapitel übernehmen> könntest. Was ich in nächster Zeit brauchen würde:> Einführung in den ADC; wie steuert man ein Servo an.
Mit dem WIKI tu ich mich sehr schwer. Außer der gelegentlichen Korrektur
einiger Tippfehler oder einiger falschen bzw. missverständlichen
Aussagen halte ich mich da sehr zurück.
Der Grund liegt darin, dass es dort einige "hochwissenschaftliche"
Darstellungen gibt, die zwar sehr intelligent aussehen, aber jeden
Einsteiger sofort zum Rückzug animieren. In dieser Liga kann und will
ich nicht mitspielen. - Sorry...
...
Hannes Lux wrote:
> Das Rechnen mit Fließkommazahlen ist für den AVR Schwerstarbeit. Wenn Du> dann noch den Pin vom Programm aus toggeln musst, dann kommt der AVR> nicht mehr nach.
Na na, nicht gleich übertreiben.
O.k. kann schon mal ne ms dauern und ist damit noch 1000-mal schneller,
als Du nen neuen Wert eingibst.
Und das ist ja das hüpfende Komma:
Die Rechnung ist nur bei Frequenzänderung einmalig notwendig !
Auf die Genauigkeit der Frequenz hat also die Rechenzeit keinerlei
Einfluß.
Also nimm ruhig float, wenn Du kannst.
Der Rest wurde ja schon gesagt: Timer in Mode 4 und Pin-Toggle
anschalten, fertig.
Peter
P.S.:
Wert mit Potis eingeben ist total ungenau, nimm einfach die UART und ein
Terminalprogramm.
Morgen zusammen. (nochmal)
Irgendwie scheine ich das Prinzip noch nicht so ganz geschnallt zu
haben.
So sieht das Testprog bei mir aus.
$regfile="m8def.dat"
$cristal=8000000
$baud=9800
Config pinb.1=output
Enable Timer1
Config Timer1=timer,Prescale 1024,Compare A=toggle
start Timer 1
Do
Compare1a=65000
loop
end
Da müßte b.1 doch mit 14,57 Hz toggeln. Tut er aber nicht. Wo ist der
Fehler.
Die Sache mit dem Drehgeber ist echt genial werde ich auf jeden fall
versuchen einzubauen.
Falls hier einer drin ist im Prog sind keine Schreibfehler!
> 14,57 Hz toggeln
Wie kommst du auf 14.57Hz?
8000000 / 1024 = 7812.5 Hz
7812.5 / 65000 = 0.12 Hz
Also alle ~ 8 Sekunden toggelt der Pin
Ob die Timer-Konfiguration so stimmt, kann ich nicht sagen.
Da versteh ich zuwenig von BASCOM.
> Falls hier einer drin ist im Prog sind keine Schreibfehler!
Dafür gibt es ja auch Cut&Paste.
Im Programmeditor vom BASCOM markierst du deinen kompletten
Text und drückst Strg-C.
Dann gehst du hier ins Forum und setzt den Text mittels Strg+V
wieder ein. -> geht schneller, ist weniger Tippaufwand und
du postest hier die gleichen Fehler die du auch in deinem
Programm hast.
> Ob die Timer-Konfiguration so stimmt, kann ich nicht sagen.> Da versteh ich zuwenig von BASCOM.
Und hier zeigt sich der Hauptmangel von BASCOM.
Durch diese unsinnigen Config-Möglichkeiten wird der Benutzer
(Programmierer?) davon abgehalten, die Steuerregister des AVRs (seiner
internen Peripherie) selbst einzustellen, sich also selbst um jedes Bit
zu kümmern, wie es das ASM-Programmierer und der C-Programmierer tun
muss. Und daher sprechen wir (BASCOMer <-> Rest der Welt)
unterschiedliche Sprachen und verstehen uns nicht bzw. selten.
Weniger ist manchmal mehr. Mit einem BASCOM, das auf diesen ganzen
Config-Krams verzichtet, dafür aber den erzeugten ASM-Code bereitstellt,
hätte ich mich vermutlich anfreunden können, wenn ich es rechtzeitig in
die Hände bekommen hätte.
...
>f = (quarz/prescale)/(65536-X)>und x ist hier 65000
ja, macht ja nichts.
Du benutzt ja (offensichtlich) den Toggle-Modus. Da wird bei jedem
Erreichen des OCR1-Wertes der Ausgang umgeschaltet.
Und das passiert etwa alle 8 Sekunden...
Was hindert dich eigentlich daran, dir mal das Datenblatt anzugucken und
dazu Fragen zu stellen? Mit irgendwelchen Rate-Bascom-Programmen wird
das nichts.
Ju hu alles geht wie es soll (fast).
Ich lasse den Timer1 ab einem bestimmten wert starten, bei Überlauf
toggeln und (man möge mir verzeihen) mit einem 2 AVR Messen. Das ganze
ist sogar ziemlich genau.
Nun das hoffentlich letzte Problem.
Daten:16MHz Quarz, prescale 1 ab 400, 16 bit timer
Man muß zwei mal toggeln um eine Periode zu generieren das ist klar.
Bei 5 KHz sind das 10000 Wechsel. Da der Timer aber nur Ganzzahlen Frist
ist die Auflösung bei 5 KHz pro zahl 2,5 Hz. Gibt es eine Möglichkeit
das genauer zu bekommen.
Manchmal frag ich mich schon warum der Rest des Forums
sich eigentlich den Mund fusselig redet. (Äh: die
Finger wund tippt)
Benutze den CTC Modus des Timers und du kannst das
alles lösen. Auf einem Mega8. Und der fadisiert sich
dabei noch und kann nebenbei noch teuflisch schwierige
quadratische Gleichungen lösen.
CTC = Clear Timer on Compare
Du lässt den Timer laufen und stellst den Endwert ein.
Wenn der Timer den Endwert erreicht hat, toggelt er
den Pin und setzt sich selbst auf 0 zurück.
Und das alles in Hardware. Du brauchst nichts tun.
Du musst nur den Timer richtig konfigurieren und den
gewünschten Endwert einstellen, den Rest macht der Timer
ganz alleine.
Ciesla tim wrote:
> Daten:16MHz Quarz, prescale 1 ab 400, 16 bit timer> Man muß zwei mal toggeln um eine Periode zu generieren das ist klar.> Bei 5 KHz sind das 10000 Wechsel. Da der Timer aber nur Ganzzahlen Frist> ist die Auflösung bei 5 KHz pro zahl 2,5 Hz. Gibt es eine Möglichkeit> das genauer zu bekommen.
Ja, das geht bei diesem Prinzip nicht anders:
16MHz 2 1600 = 5000Hz
16MHz 2 1599 = 5003Hz
D.h. Du hast bei 5kHz etwa 3Hz Schritte.
Allerdings kann man tricksen, indem man bei jedem Compareinterrupt nen
anderen Comparewert lädt entsprechend dem Fehler.
Dann ist zwar ne einzelne Periode auch nicht genauer, aber im Mittelwert
über mehrere Perioden wirds besser.
Peter