Hallo ihr guten... Ich muss die Wissen den hier mal mit meiner Frage Nerven. Ich möchte den ADC meines Atmega644 etwas beschleunigen, momentan braucht er für das Abfragen eines ADC Wertes ( Getadc(0) ) ca 0.1ms laut Oszi. Der Atmega läuft mit 20Mhz ... Hier mal mein Bascom Code: 'CONTROLER BESTIMMEN $regfile = "m644def.dat" 'STACKANWEISUNGEN ------------------------------------------------------------- $framesize = 64 $swstack = 40 $hwstack = 48 'FREQUENZ DES VERWENDETEN QUARZES --------------------------------------------- $crystal = 20000000 Enable Interrupts 'DER ANALOG- DIGITAL CONVERTER WIRD EINGESTELLT UND AKTIVIERT ----------------- Config Adc = Single , Prescaler = Auto , Reference = Avcc Start Adc 'PIN ZUM PRÜFEN DER LAUFZEITEN Config Pind.6 = Output timecut Alias Portd.6 Do X = Getadc(0) Toggle timecut Loop ------------------------------------------------------------------------ -- Nun meine Frage, wie kann ich es ermöglichen das der ADC Schneller Arbeitet als jetzt ? Dafür müsste ich doch rein Theoretisch den Prescaler manuell einstellen auf einen entsprechenden Wert oder ? Dann hätte ich noch eine frage was den 8bit Betrieb angeht ... Wenn ich den ADC beschleunige werden die letzten 2 bit ( beim 10 bit betrieb ) ja ungenauer ! Mir würde auch eine 8 bit auflösung des ADC`s reichen, aber wie genau stellt man das eine und fragt die werte dann auch ab ?! Kann ich mir das mit dem 8 bit Modus auch wirklich so vorstellen das 0V = 0 und 5V = 255 und nicht 1023 ist ??? Ich wäre euch für eine unterstützung echt dankbar !!!
Lordnicon schrieb: > Nun meine Frage, wie kann ich es ermöglichen das der ADC Schneller > Arbeitet als jetzt ? Dafür müsste ich doch rein Theoretisch den > Prescaler manuell einstellen auf einen entsprechenden Wert oder ? Die Frage ist, was eine Prescaler Einstellung von Auto eigentlich macht. Ich kann mir nicht vorstellen, dass sich dazu in der BASCOM-Hilfe nichts findet. > betrieb ) ja ungenauer ! Mir würde auch eine 8 bit auflösung des ADC`s > reichen, aber wie genau stellt man das eine und fragt die werte dann > auch ab ?! Auch dazu wirst du sicherlich in der BASCOM Hilfe fündig > Kann ich mir das mit dem 8 bit Modus auch wirklich so vorstellen das 0V > = 0 und 5V = 255 und nicht 1023 ist ??? Yep. > Ich wäre euch für eine unterstützung echt dankbar !!! Falls du in der BASCOM Hilfe nichts findest (was ich mir nicht vorstellen kann), dann bleibt immer noch das Datenblatt des Prozessors. Man kann auch in BASCOM die Konfigurationsregister direkt einstellen. Aber erst mal solltest du deine Hausaufgaben machen und die Hilfe konsultieren.
>Kann ich mir das mit dem 8 bit Modus auch wirklich so vorstellen das 0V >= 0 und 5V = 255 und nicht 1023 ist ??? Es bleibt bei 1024 Schritten aufloesung. Nur die beiden unteren Bits sind ungenauer. Teil das Ergebnis durch 4 und du hast deine 8 Bit Aufloesung. Gruss Helmi
Das Problem ist, dass Bascom's GETADC(n) als Funktion arbeitet und das Argument (Kanal-Nummer) erst dann übergibt, wenn es eigentlich bereits das Ergebnis haben will. Dies erfordert Wartezeit. Das lässt sich umgehen, indem man auf GETADC() verzichtet und den ADC wie ein ASM-Programmierer benutzt. Man wählt den Kanal, startet ihn und kümmert sich wieder um andere Dinge, die getan werden müssen. Später dann schaut man mal im ADC-Register nach dem Ergebnis. Braucht man nur einen Kanal, dann lässt man den ADC im Hintergrund frei laufen oder von einem anderen Ereignis triggern (schau mal ins Datenblatt Deines Mega644, dessen ADC kann bedeutend mehr, als Bascom an Unterstützung bietet). Braucht man mehrere Kanäle, so fragt man den ADC zyklisch ab (ADCC-Interrupt oder nebenbei im Timer-Interrupt), sichert sein Ergebnis in einem Array, setzt nach dem Auslesen den neuen Kanal, startet den ADC neu und widmet sich während der Wandlung den übrigen Arbeiten. Ist alles kein Problem und geht wunderbar, man muss nur bereit sein, auf einige kontraproduktive Befehle und Funktionen von Bascom zu verzichten. ...
Hallo an euch Also zum Prescaler steht in der Bascom Hilfe folgendes: >The prescaler divides the internal clock by 2,4,8,16,32,64 or 128 >Because the ADC needs a clock from 50-200 KHz >The AUTO feature, will select the highest clockrate possible Nun nehme ich an das der Prescaler von Bascom Automatisch auf 128 eingestellt wird und damit bei 20Mhz eine Abtastfrequenz von ca. 156 Khz eingestellt wird .. Nun habe ich aber schon mehrfach gelesen das man den ADC auch mit mehr als 200Khz betreiben kann, aber dann die 10 Bit genauigkeit darunter leidet ... Was den 8bit betrieb angeht findet man in der Bascomhilfe leider nichts... bzw. Ich finde da einfach nichts zu .... >>Kann ich mir das mit dem 8 bit Modus auch wirklich so vorstellen das 0V >>= 0 und 5V = 255 und nicht 1023 ist ??? >Es bleibt bei 1024 Schritten aufloesung. Nur die beiden unteren Bits >sind ungenauer. Teil das Ergebnis durch 4 und du hast deine 8 Bit >Aufloesung. Also was mir zur ungenauigkeit des 10 bit betriebes vorschwebt ist folgendes... wenn ich jetzt meinen ADC wegen mir nicht mit 156 Khz abtasten lasse ( Auto Prescaler ) sondern Manuell mit einem Prescaler von 32 ( 625 Khz ), was bedeutet das für meine Werte ? Im Datenblatt steht das der ADC +-2 LSB Absolute Accuracy hat, leider verstehe ich nicht genau was das bedeutet. Aber wie Weit könnten die Werte den Abweichen? Hat da schon jemand erfahrung mit gemacht ? Wenn ich z.B. 2.5V Anlege müsste ich ja Theoretisch einen ADC Wert von 511 erhalten. Wenn ich den ADC nun aber Hochtakte und die Genauigkeit von 10 Bit nichtmehr sauber eingehalten werden kann, mit welchen Werten wäre dann zu rechnen ?!?! 511 +- 20 oder so in der Art !!! Sorry das ich mich ein bisschen dämlich ausdrücke, aberichussleider immer alles begründet und verdeutlicht haben... Also ich möchte jaauch selber zur lösungmeines Problems beitragen, desswegen möchte ich hier meinen Gedankengang gradeNiederschreiben! Wenn ich jetzt hergehe und den Prescaler auf 32 einstelle, läuft der ADC mit ca 625 Khz , aber die Genauigkeit wird leiden ... wenn ich jetzt den Ausgelesenen ADC Wert durch 4 Teile ( um 8 Bit zu erhalten ) Teile ich ja auch den evtl. vorhandenen Messfehler durch 4 ( sehe ich das richtig ). Meine Messgeschwindigkeit Steigt aberauch um Faktor 4 an ??!!!??? ... Somit würde ein Messzyklus nichtmehr 100µs sondern nurnoch 25µs brauchen.. Was Assembler befehle angeht bin ich leider völliger neuling....
> Was Assembler befehle angeht bin ich leider völliger neuling.... Es geht nicht um Assembler-Befehle, es geht um das Benutzen des System-Register ADMUX, ADCSRA, ADCSRB, ADCL und ADCH, ferner auch noch DIDR0. Das sind nämlich die Schnittstellen zum ADC, in denen einzelne Bits bestimmte Schalterwirkung haben, andere Bitgruppen Zahlen repräsentieren. Um das zu verstehen, brauchst Du kein ASM zu lernen (obwohl das keinesfalls schaden würde), sondern nur im Datenblatt die Funktion des ADC und besonders seiner (oben aufgezählten) Register nachzulesen (und zu verstehen). Bascom bietet zwar die Funktion GETADC(), die taugt aber im Alltag nix, da sie zuviel Zeit vertrödelt. Denn sie muss: - den zu messenden Kanal einschalten (Kanalnummer und Referenzquellen- Nummer in ADMUX schreiben) - den ADC starten (ADEN und ADSC im Steuerregister ADCSRA setzen, sowie den Vorteiler in ADCSRA einstellen) - warten, bis das Bit ADIF in ADCSRA gesetzt ist, was das vereinbarte Zeichen ist, dass der ADC fertig ist und ein Ergebnis hat - das Ergebnis aus ADCL und ADCH auslesen und dem aufrufenden Programm zurückgeben. Das Problem dabei ist, dass die Programmabarbeitung solange warten muss, bis das Ergebnis vorliegt, das ist nunmal bei "Funktionsaufruf" so. Es verlangt aber keiner, dass Du diese Funktion benutzt. Stattdessen kannst Du die Handgriffe selbst in Programmcode formulieren und zur rechten Zeit ausführen. Angenommen, Du brauchst nur einen ADC-Eingang 8-bittig zu messen. Dann schreibst Du Die Mess-Quelle schon bei der Initialisierung in ADMUX. Im Register ADMUX findest Du (beim Mega644) 2 REFS-Bits, 5 MUX-Bits und das Bit ADLAR. Die REFS-Bits bestimmen die Referenzspannungsauswahl, siehe Tabelle 21-3 des Datenblatts. ADLAR bestimmt die Ausrichtung des Resultats, bei gesetztem Bit wird linksbündig ausgerichtet, die oberen 8 Bits stehen dann in ADCH, was das Auslesen des 8-Bit-Messwertes erleichtert und beschleunigt (der ADC misst aber trotzdem 10-bittig, die unteren 2 Bit liegen dann in ADCL und verfaulen, weil sie keiner abholt). Mit den MUX-Bits wird angegeben, welcher Kanal gemessen werden soll, siehe Tabelle 21-4 des Datenblatts. Du baust Dir nun das gewünschte Bitmuster zusammen und schreibst es in ADMUX. Das erfordert keinerlei missverständlichen CONFIG-Kram, sondern nur eine einfache Zuweisung. Da Bascom leider nur die Registernamen kennt, nicht aber die Bitnamen, musst Du auf die symbolischen Bitnamen verzichten und das Bitmuster numerisch angeben (was den Code gegenüber ASM oder C unübersichtlich macht und oftmals Protest aus der C-Liga bewirkt...). ADC0 gegen AVcc 8-Bittig gemessen ergibt dann folgende Initialisierung für ADMUX: ADMUX = &b01100001 ^^^^^--- Mess-Quelle 0 laut Tabelle 21-4 ^-------- linksbündige Ausgabe (ADLAR) ^^--------- AVcc als Referenz laut Tabelle 21-3 Du hast also mit einer einzigen Zuweisung Referenz, Kanal und Format eingestellt. Ist das nicht viel eindeutiger als das Config-Geraffel? Ebenso gehst Du mit ADCSRA vor, das enthält den Vorteiler und weitere Bits zum Schalten und Steuern. Mit einer Zuweisung konfigurierst und startest Du den ADC. Wird nur eine Quelle gemessen, dann lohnt sich der Freerun-Mode, also das Setzen von ADATE (heißt bei älteren AVRs ADFR), dann klappert der ADC nach dem Starten im Hintergrund vor sich hin und kann irgendwann mal nebenher ausgelresen werden, ohne dass das Programm dabei warten muss. Für ADC0 gegen AVcc 8-Bittig gemessen ergibt dann folgende Initialisierung für ADCRSA: ADCSRA = &b11100110 ^^^--- Vorteiler 64 (Tabelle 21-5) ^------ kein Interrupt aktivieren ^------- Interrupt-Flag ist hier nicht relevant ^-------- Free-Run, siehe ADCSRB ^--------- ADC starten ^---------- ADC einschalten Der Vorteiler hängt von der Taktfrequenz des AVRs ab, er soll so gewählt werden, dass der ADC mit 50kHz bis 200kHz getaktet wird. Er braucht (ohne Umschaltung der Quellen) 13 Takte für eine Wandlung, hat also Vorteiler mal 13 Takte ein neues Ergebnis, das so lange in ADCL und ADCH verfügbar ist, bis es vom nächsten Ergebnis überschrieben wird. Un nun das neueste Ergebnis zu erfahren, muss dein Programm es nur auslesen: wert = ADCH Wobei "wert" als Byte dimensioniert sein sollte. Da dies wieder nur eine einfache Zuweisung ist, kostet das keinerlei Wartezeit. Und solltest Du (durch ungünstige Programmplanung) den Wert zu oft abfragen, dann bekommst Du den alten Wert eben nochmal, solange noch kein neuer ermittelt wurde. Ähnliches wie beim ADC wirst Du bei den Timern entdecken. Die Timer der neueren Controller können viel mehr als Bascom per Config-Geraffel bietet. Schau Dir das Datenblatt an, das ist verbindlich, verzichte auf den Config-Kram und greife durch einfache Zuweisungen auf die interne Peripherie der AVRs zu, Du wirst sehen, dass damit das Programmieren auch in Bascom bedeutend einfacher und stressfreier wird. ...
Hallo Hannes Mensch vielen Dank für die Tolle Erklärung.... Das nenne ich doch mal eine ausführliche erklärung ..... Also um es zu Konkretisieren, ich muss 2 ADC Werte haben ( Später könnten es auch 4 werden ... ) Dann könnte mein Programm so aussehen ?! 'CONTROLER BESTIMMEN $regfile = "m644def.dat" 'STACKANWEISUNGEN ------------------------------------------------------------- $framesize = 64 $swstack = 40 $hwstack = 48 $crystal = 20000000 'ADC EINSTELLEN ( NICHT IM FREERUN ) ADCSRA = &b11000110 'VORAUSWAHL VOM ADC 0 WOMIT DAS PROGRAMM BEGINNT ADMUX = &b01100000 'PIN ZUM PRÜFEN DER LAUFZEITEN Config Pind.6 = Output timecut Alias Portd.6 Do X = ADCH 'JETZT UMSCHALTEN ZUM ADC CHANNEL 1 ADMUX = &b01100001 'NUN MACHE ICH IRGENDWAS DAMIT DER ADC MIN 13 TAKTE ZEIT HAT DAS NEUE 'ERGEBNIS BEREIT ZU STELLEN ...... ..... .... ... .. . 'NUN HOLE ICH DAS ERGEBNISS VON CHANNEL 1 AB Y = ADCH 'JETZT WIEDER UMSCHALTEN ZUM ADC CHANNEL 0 ADMUX = &b01100000 ...... ..... .... ... .. . Loop KANN ICH DAS SO RICHTIG VERSTEHEN ??? Und der Wert den ich da abhole ist dann 8bit 0V = 0 und 5V = 255 ?????
> KANN ICH DAS SO RICHTIG VERSTEHEN ??? Vermutlich nicht... > 'ADC EINSTELLEN ( NICHT IM FREERUN ) > ADCSRA = &b11000110 > 'VORAUSWAHL VOM ADC 0 WOMIT DAS PROGRAMM BEGINNT > ADMUX = &b01100000 Falsch herum. Immer erst den Multiplexer einstellen, dann den ADC einschalten, sonst schaltest Du ihm ja die Quelle unterm Hintern um, was den ersten Messwert (ohne FreeRun gibt es keinen zweiten) verfälschen kann. > X = ADCH > 'JETZT UMSCHALTEN ZUM ADC CHANNEL 1 > ADMUX = &b01100001 > 'NUN MACHE ICH IRGENDWAS DAMIT DER ADC MIN 13 TAKTE ZEIT HAT DAS NEUE > 'ERGEBNIS BEREIT ZU STELLEN Es sind nicht 13 Controllertakte, sondern 13 ADC-Takte. Das ist viel Zeit. Ich sehe hier auch noch ein Problem. Du arbeitest mit maximalem Takt und dem größten DIL-AVR und hast eine Mainloop ohne Bremse. Soll das Teil in Echtzeit eine Rakete steuern?? Ich komme meist mit kleinen AVRs aus, takte sie selten höher als 3,6864 oder 7,3728 MHz (meist nutze ich die internen 1MHz) und kann damit die meisten Aufgaben lösen. Wie oft und wozu brauchst Du die Messwerte? Was soll das Ding eigentlich machen? Ohne diese Info ist keine optimale Strategie möglich. ...
Hier mal als Beispiel ein Auszug aus einem Mega8-Programm, dass den ADC5 als Eingang für 2 Taster nimmt. In der Init (unter Anderem):
1 | Admux = &B01100101 'ADC_5 linksbündig gegen Vcc messen |
2 | Adcsra = &B11100110 'ADC freilaufend mit Vorteiler 1:64 |
3 | |
4 | Ocr1a = Reload 'Timer1-Zählumfang für 20ms |
5 | Tccr1b = &B00001010 'CTC-Modus mit Vorteiler 1:8 |
6 | |
7 | Enable Oc1a 'Timer1-CompareA-Interrupt freigeben |
8 | Enable Urxc 'UART-RXC-Interrupt freigeben |
9 | Enable Interrupts 'Interrupts global freigeben |
In der Mainloop werden nur bedingte Jobs aufgerufen:
1 | Do 'Hauptschleife |
2 | If Rix > 9 Then Neutelegramm 'neues Telegramm eingetroffen? - ja... |
3 | If Neutext = 1 Then Gibaus 'Textausgebe erforderlich? - ja... |
4 | If Tame = 1 Then 'Menütaste gedrückt? |
5 | Reset Tame 'Tastendruck entwerten |
6 | Incr Mp 'Menüpunkt hoch |
7 | Mp = Mp And 3 'und auf 0..3 begrenzen |
8 | If Mp = 3 Then Relais_aus 'Akku entfernen um Strom einzustellen |
9 | End If |
10 | If Tago = 1 Then 'Go-Taste gedrückt? |
11 | Reset Tago 'Tastendruck entwerten |
12 | Select Case Mp 'in Menüpunkt |
13 | Case 0 '"Fazit" |
14 | Incr Weka 'Wert-Kategorie hoch |
15 | If Weka > 5 Then Weka = 1 'und begrenzen |
16 | Case 1 To 2 'Schnelladen |
17 | Anu = 1 'Start mit Akku 1 |
18 | Set Mp.2 'Laden aktivieren (Mp= 5 oder 6) |
19 | Case 3 'Strom einstellen |
20 | Tazz = Taz(mp) 'Tastendauer Tiny26-Taste |
21 | Set T26taste 'Tiny26-Taste einschalten |
22 | End Select |
23 | End If |
24 | Loop |
Die ADC-Abfrage erfolgt in der Timer-ISR:
1 | Zeittakt: 'ISR, Timer1CompareA (20ms) |
2 | Dim Itmp As Byte 'temp in ISR |
3 | Dim Taste As Byte 'Tasten-Nummer |
4 | If Timout <> 0 Then 'wenn Telegramm-Timeout aktiv ist, |
5 | Decr Timout 'Timeout herunterzählen |
6 | If Timout = 0 Then Set Fertig 'abgelaufen? - ja, melden |
7 | End If |
8 | Itmp = Adch 'ADC 8bittig lesen |
9 | Select Case Itmp 'welche Taste? |
10 | Case 120 To 136 'Menü-Taste |
11 | Taste = 1 |
12 | Case 160 To 180 'Go-Taste |
13 | Taste = 2 |
14 | Case Else 'keine gültige Taste |
15 | Taste = 0 |
16 | End Select |
17 | If Taste <> Tas Then 'wenn Tastendruck anders |
18 | If Taste = Tao Then 'ist Taste = vorheriger Wert |
19 | Incr Prz 'Prellzähler hoch |
20 | If Prz > 5 Then 'Prellzeit erreicht? |
21 | Tas = Taste 'ja, Taste übernehmen |
22 | If Taste = 1 Then Set Tame 'Menü-Taste |
23 | If Taste = 2 Then Set Tago 'Go-Taste |
24 | End If |
25 | Else |
26 | Prz = 0 'Prellzähler löschen |
27 | Tao = Taste 'akt. Taste als Vorwert übernehmen |
28 | End If |
29 | End If |
30 | If Tazz <> 0 Then 'wenn Tiny26-Tastenzeit läuft |
31 | Decr Tazz 'Tastenzeit herunterzählen |
32 | If Tazz = 0 Then Reset T26taste 'abgelaufen? - ja, Taste aus |
33 | End If |
34 | If Wartez <> 0 Then 'Akku-Umschaltung |
35 | Decr Tazz 'Wartezeit herunterzählen |
36 | If Wartez = 0 Then Relais_ein 'abgelaufen? - ja, Relais ein |
37 | End If |
38 | Return 'fertig, zurück... |
Nur mal so als Denkanstoß... ...
Hallo Hannes ... Also was will ich mit dieser Anwendung machen ... Es handelt sich dabei um eine Safety für ein Lasersystem .. Die beiden ADC Werde sind Feedbackwerte des Galvo systems, Es soll also Laufend und möglichst Schnell überprüft werden ob das System noch Läuft .. Signale ( Sinus, Dreieck, Trapetz förmige Signalverläufe ) Dann soll innerhalb 5 - 25 millisekundne entschieden werden ob das System Abgeschaltet werden muss oder ob die Parameter eingehalten wurden ... Ausserdem will ich Ranges festlegen in denen die laser grundsätzlich ausgeschaltet werden müssen ( Safe Areas ... z.B Puplikum ). Da die Signale bis zu 500Hz Schnell laufen muss das Ganze sehr zügig von Statten gehen ! Wenn du Geduld und Interesse hast können wir das Thema gerne vertiefen, ich würde mich wahnsinnig über Hilfe freuen ... Mfg:
Es wäre schön, wenn Du versuchen würdest, Deutsch mit mir zu reden/schreiben. Denn mit meinen 6 Jahrzehnten habe ich es nicht so mit den coolen Anglizismen. Gut, dann brauchst Du erstmal eine schnelle Bereitstellung der ADC-Werte mehrerer Quellen im Hintergrund. Dazu müssen erstmal die Eckpunkte geklärt werden. Wieviele Bewegungs-Achsen müssen überwacht werden? Es bringt nämlich nix, klein anzufangen und später "aufbohren" zu wollen. Gehen wir in der ersten Betrachtung von 4 Achsen aus, deren Steuerwerte auf den ADC-Messbereich angepasst vorliegen. Legen wir diese auf ADC0 bis ADC3. Es reicht 8 Bit Auflösung. Der AVR läuft mit 20 MHz. Der ADC-Takt soll im Interesse einer schnellen Wandlung möglichst nah am Limit (200 kHz) sein. Es stehen Vorteiler 64 und 128 bereit. Bei VT=128 erreichen wir nur 156,25 kHz, schöpfen also das Limit nicht aus. Bei VT=64 erreichen wir 312,5 kHz, das erscheint mir bereits etwas "übertaktet", da werden die Messwerte schon arg zittern. Mit 16 MHz Controllertakt und VT=64 wäre 250 kHz ADC-Takt erreichbar, was ich für 8-Bit-Messung für akzeptabel halte. Gehen wir also erstmal von 250 kHz ADC-Takt aus. Der ADC müsste dann im Interrupt-Betrieb laufen und in der ISR folgende Aufgaben erledigen:
1 | isr_adc_complete: |
2 | wert(idx) = adch |
3 | incr idx |
4 | if idx > 4 then |
5 | idx = 1 |
6 | set neuwert |
7 | endif |
8 | admux = muxwert(idx) |
9 | adcsra = adcstart |
10 | return |
Dazu müssen natürlich die beiden Arrays "wert()" und "muxwert()" sowie der Index "idx" global (als Byte) dimensioniert (und mit 1 initialisiert) werden und das Array "muxwert()" mit den benötigten Bitmustern für ADMUX gefüllt werden. Auch die Konstante "adcstart" muss vordefiniert werden, also das Bitmuster zum Starten einer ADC-Wandlung mit Interruptunterstützung enthalten. Dann brauchst Du noch eine Variable vom Typ Boolean, die ich hier "neuwert" genannt habe. Ich nutze zu solchen Zwecken meist die Variable "merker" vom Typ Byte und benenne (mit Alias) die Bits einzeln zu Merkern. Der ADC wird also nach jeder Messung in den Interrupt verzweigen, den Messwert sichern, den Index erhöhen und begrenzen, auf die neue Messquelle umschalten und den ADC wieder starten. Nach jeder kompletten Runde setzt er den Merker "neuwert". Die Mainloop prüft nun nur den Merker "neuwert" und verzweigt zu einer SUB, wenn "neuwert" gesetzt ist. Diese Sub löscht (resettet) "neuwert" wieder (der der Arbeitsauftrag wird ja erledigt) und erledigt die Überprüfungen der Grenzbereiche der 4 ADC-Werte. Dazu nutzt die SUB das Array "wert()", darf aber nicht die Variable "idx" benutzen, die ist für die ISR als Schrittzähler reserviert. In wert(1) steht dann der Wert von ADC0, in wert(2) der Wert von ADC1 (bzw. der Wert der an "muxwert(2)" gemessen wurde). Die Mainloop (bzw. deren Jobs) bekommt auf diese Weise fast die volle Rechenzeit des Controllers, da nirgends auf den ADC gewartet werden muss. Nun ein paar Zeitbetrachtungen dazu: Wir gingen von 250kHz ADC-Takt (16MHz Quarz, ADC-Vorteiler=64) aus. Das sind bei 13 Takten je Wandlung und einer kleinen Pause, weshalb ich 14 Takte rechne, etwa 17,857 kHz. Eine Runde macht 4 Messungen, das sind etwa 4,46 kHz bzw. 224 µs pro Runde. Das ist mehr als ausreichend, um rechtzeitig auf Stillstand oder verbotene Bereiche reagieren zu können. Rechnen wir es nochmal für 20 MHz Quarz und ADC-Vorteiler 128 durch: Das sind 156,25 kHz ADC-Takt. Macht bei 14 Takten 11,16 kHz Samplerate. Auf 4 Kanäle verteilt bleibt 2,79 kHz Samplerate pro Kanal, bzw. eine Runde dauert 358,4 µs. Die ADC-Werte kommen hier zwar etwas langsamer rein, dafür hast Du aber mehr Rechenzeit pro Runde und die Werte zappeln nicht so stark, denn der ADC läuft im "grünen Bereich" ist also nicht übertaktet. So, ich hoffe, Du hast genügend Denkanstöße bekommen. Schau Dich mal bei RN-Wissen um, da sollen allerhand brauchbare Beispiele zu finden sein. Ich kann Dir aber keine konkreten Links geben, ich interessiere mich nicht dafür, da ich hauptsächlich in Assembler programmiere. Viel Erfolg ...
Hallo Hannes Ich bedankemich bei dir auf jeden fall schonmal für diese mehr als ausführliche Hilfestellung, ich werde mir jetzt mal alles zu gemüte führen und darüber nachdenken wie ich das am besten umsetzen kann ! Wobei du mir ja schon sehr weiter geholfen hast... Es sollte mehr von solchen Leuten geben die sich zeit für eine sehr gute erklärung nehmen... Vvviiiiieeeelllleeeennnn Dank erstmal ... Mfg:
Hallo Autor: Hannes Lux (hannes) , ich möchte hier als Leser deines Beitrages mal hervorheben, dass Deine Ausführungen super gut sind. Als langjähriger Bascom-Nutzer habe ich auch schon oft die Erfahrungen gemacht, dass bei Verwendung einiger config Statements nicht immer das passiert, was man eigentlich möchte. Wenn ich also mal eben schnell etwas in Bascom zusammenkloppe und am Ende nicht das richtige rauskommt fange ich zunächst an , die logische Bombe in meinen Gedankengängen zu suchen. Wenn ich dann nach mehrmaliger intensiver Prüfung meiner Idee immer zu dem Schluss komme, dass der fehler eigentlich nicht bei mir liegt, fange ich an das Bascom zu verdächtigen. Durch Umschreiben des Programmes und der intensiven Nutzung der entsprechenden Kontrollregister kommt man der sache dann sehr gut auf die Spur. Die Erfahrung zeigt einfach, dass Bascom voller Fettnäpfchen und Fallstricken steckt und man auf der hut sein muss. Bisher habe ich diese Strategie der Nutzung der Kontrollregister nur bei den Timern angewandt und auf meiner "TO-DO-Liste" stand noch die analyse des Getadc befehles. Im endeeffekt hast du mir durch deine Ausführungen aber jetzt schonmal einen guten Erkenntnisstand übermittelt. Es wird mir viel Arbeit sparen. Danke also .. Hannes Vielleicht sollte man hier noch erwähnen, dass Bascom beim compilieren auch immer ein *.obj File erzeugt. Dieses kann man im AVR-Studio öffnen und sehen , was Bascom so anstellt. Dann wird alles viel klarer. Man kann in AVR-Studio den Bascom Quelltext sehen und das daraus resultierende ASM Compilat und es Schritt für Schritt gedanklich analysieren. Manchmal hilft es auch, in den Bascom Quelltext vor und hinter einer fragwürdigen Instruktion eine gewisse Anzahl NOP-Befehle einzufügen. (z.B. 3 stück vor dem Befehl und 5 Stck. dahinter) diese Marke lässt sich dann leicht auffinden. Also dann Libe Grüsse Klaus
Erstmal danke für die Blumen, es gibt aber auch Leute, die das anders sehen... > Man kann in AVR-Studio den Bascom Quelltext sehen und das daraus > resultierende ASM Compilat und es Schritt für Schritt gedanklich > analysieren. Ich weiß jetzt nicht genau (ich programmiere fast nur in ASM, also mit Hammer und Nägeln), aber ich glaube, AVR-Studio kann die Objekt-Datei sogar simulieren. Der Simulator ist zwar nicht so schön bunt wie der von Bascom, zeigt einem aber schön so manchen logischen Trugschluss. ...
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.