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.
Vielen Dank fuer die schnellen und hilfreichen Antworten. Das Prinzip merk ich mir ! :) daniel
@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. ...
>Wie kommst du auf 14.57Hz?
f = (quarz/prescale)/(65536-X)
und x ist hier 65000
Ohhhh nein stimmt gar nicht, die Formel gilt wenn man ihn von x starten lässt. Alles klar das erkärt einiges.
>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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.