PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Ausführungsgeschwindigkeit: Grundlegende Frage zu Bascom



m_herr
03.02.2006, 11:59
Hallo Leute,

wie schon neulich geschrieben, habe ich ein paar Probleme mit der Zeit beim ausführen.

Nun hat sich herrausgestellt, daß das Zeitproblem ( https://www.roboternetz.de/phpBB2/viewtopic.php?t=16671), nicht auf die Hardware, sondern einzig auf die Software zurückzuführen ist.


Mit jeder Löschung von Quelltext steigt die Geschwindigkeit wieder an.


1. Habe einen Timer0 so eingerichtet, daß ich alle 0,001 sek einen
Zähler erhöhe.
2. Alle 0,01sek werden dann die 5adc-werte abgefragt und ein paar
Ganzahl-operationen durchgeführt.
3. alle 0,5sek Sollen dann die Ergebnisse, teilweise durch SUBS
formartiert, angezeigt werden.


Alles funktioniert auch soweit richtig, richtige Daten werden angezeigt, keine Abstürze/Hänger, keine Schleife wird ausgelassen und und und.

Nur das nicht alle 0,01. Sek der ADC ausgelesen wird, sondern alle 0,03Sek....das nicht alle 0,5Sek Daten angezeigt werden, sondern alle 1,5Sek
Die Zeit verdreifacht sich also.....


Lösche ich nun alles weg, daß nur noch



Do

If H_flag = 1 Then 'alle 0,001Sek ausführen
Incr H 'Zeitzähler Displayanzeige
Incr Rr 'Zeitzähler allgemein
H_flag = 0
End If


If H = 500 Then 'alle 0,5Sek anzeigen
Locate 1, 1
Lcd Rr
H = 0
End If
Loop

End


Timer0_isr:
Load Timer0 , Ticks0
H_flag = 1 'alle 0,001 flag setzen
Return

EDIT: war so frei und habe Code-Tags spendiert PicNick

dasteht, funktioniert alles genau.
Sobald aber nur eine schleife mit alle 0,01Sek die 5 ADC werte ausgelesen werden eingeschoben wird, war es das. Die Zeit verdoppelt sich...


Das stellt mich vor die Frage, ob Bascom überhaupt für zeitgenaue Sachen geeignet ist, oder ob ich einen Gedankenfehler habe.

Ist sehr ungünstig erst das Programm fertig schreiben zu müssen, um dann mit der Stop-Uhr den Zeitfehler zu messen und dann die Werte anzupassen....Oder reicht ein Quarzwechsel von 4 auf 8 MHZ aus und der Chip ist kräftig genug?[/code]

Vitis
03.02.2006, 12:36
naja, der getadc braucht halt n bissl,
das hat aber wenig mit dem Bascom zu tun,
sondern mit dem AVR.
die Wandlung braucht 65µs je 10Bit Sample.
du verwendest davon 5, macht 325µs oder 0,325ms.
das bremst die geschichte gewaltig aus.
der AVR hat ja nicht 6 bzw. 8 separate adc sondern
einen, der per multiplexer auf den jeweiligen kanal
durchgeschaltet wird. daher muß man die zeit für die
wandlung adieren.
abhilfe wäre z.b. durch einen externen schnelleren ad-wandler
zu schaffen.

super_castle
03.02.2006, 12:39
...naja, der getadc braucht halt n bissl,
das hat aber wenig mit dem Bascom zu tun,
sondern mit dem AVR...


stimmt nicht, ich habe die routinen als selbstgeschriebenen asm-routinen eingebunden und sind fast 6x schneller.


....Das stellt mich vor die Frage, ob Bascom überhaupt für zeitgenaue Sachen geeignet ist, oder ob ich einen Gedankenfehler habe. ...

nein, du machst kein gedankenfehler.


Castle

m_herr
03.02.2006, 12:51
es kann doch nicht sein, daß bascom so extrem mies ist, daß jede kleine anweisung sie so extrem auf die Laufzeit auswirkt, oder?

wenn ich mit einer for to-schleife 16mal den adc0 auslese um dann
einen mittelwert mit shift-operation zu bilden, daß dann alles einbricht?

if h1= 10 then '0,01sek

Ad0 = 0

For X = 1 To 16
Mtemp = Getadc(5)
Ad0 = Ad0 + Mtemp
Next X
Shift Ad0 , Right , 4



Ad0 = 0

For X = 1 To 16
Mtemp = Getadc(3)
Ad0 = Ad0 + Mtemp
Next X
Shift Ad0 , Right , 4

h1=0
end if


sorgt zb um einen Einbruch um 30 %. Also 1Sek=1,3Sek

Das kann es doch nicht sein, oder?

Ratber
03.02.2006, 14:49
Es ist vom Code abhängig wie weit die Zeiten abweichen.

Wenn du das LCD nutzt dann dauert das.
Wenn du den ADC nutzt dann dauert das auch.
Da gibt es feste Minimale Wartezeiten.
Jeder Befehl hat eine bestimmte Zahl an Taktzyklen.

Wenn du unbedingt genau Timen willst dann bist du gezwungen auch die Ausführungszeiten zu berücksichtigen.
Das gilt für Bascom genauso wie für Assembler oder C.

Wenn du die Ausführung optimieren willst dann kannst du zb. beim LCD direkt ansteuern anstatt die Eingebauten Routinen zu nehmen.
Das ist schneller weil die Eingebauten auf Nummer Sicher gehen da nicht alle Displays gleich langsam sind.
Beim AD-Wandler das gleiche.

Ja und bei den anderen Befehlen gibt es große Unterschiede wie man es macht.

For Next geht schneller wenn man es per Do Loop until macht.

Fließkommaoperationen kosten ebenfalls Zeit (Auch beim Mega wenn auch nicht soviel).
Aus einem A=A/1.78 macht man lieber
A=A*50
A=A/89

Das ist schneller und kostet weniger Platz.

usw.

Probier einfach mal Alternativen für die Routinen.
wirst sehen wie die Codegröße und die Zeiten schwanken.

Absolute Kontrolle hats du nur wenn du alles berücksichtigst.
Naturgegeben biste da bei Assembler besser aufgehoben wenn es um genaue Timings geht denn du kannst jeden Befehl sofort nachrechnen (Takte/Ausführungszeit).
Bei Bascom ist das etwas schwieriger da der Code je nach Konstellation anders ausfällt.

m_herr
03.02.2006, 15:08
ja, so ungefähr kenne ich das auch, aber die 3fache zeit??
da kann etwas nicht stimmen.
Ich bin, zumindest beim lesen, recht aktiv hier und auch in anderen foren, und von solchen extremen abweichungen habe ich noch nie gehört...

Ratber
03.02.2006, 15:29
Ich auch nicht.

Kann sein das dein Prog irgendwo noch ne Extrarunde dreht kann aber auch sein das Bascom da seine Probleme hat.

Ich meine das seit der 81/82 Timingprobleme bei einigen Befehlen da sind. (zb. Servo. Läuft unter 4 Mhz garnicht mehr)

Ich muß das mal mit ner alten 78er überprüfen

PicNick
03.02.2006, 15:30
In 0,01 sekunden macht der AVR mit 4MHZ 40000 cyclen, damit kann auch Bascom einiges tun.
Aber:
Wenn du in einer ISR eine Zähler erhöhst und in der DO-Schleife auf
"ist gleich" abfragst, wirst du den Wert öfter nicht erwischen

m_herr
03.02.2006, 15:42
@Picknick nein, den fehler hab ich früher gemacht, bevor du mir gezeigt hat,wie es anders geht




If H_flag = 1 Then
Incr H
Incr H1
Incr Rr
H_flag = 0
End If

Timer0_isr:
Load Timer0 , Ticks0
H_flag = 1

Return

so mache ich es jetzt und funzt super.


so, fehler eingekreist. hier ist der anker, der alles nach unten zieht:


Ad0 = 0
For X = 1 To 16
Mtemp = Getadc(0)
Ad0 = Ad0 + Mtemp
Next X
Shift Ad0 , Right , 4

sobald ich die for-schleife weglasse flutscht es. wo ist der fehler, daß
bascom bei einer kleinen zählschleife soextrem einstürzt?

Ratber
03.02.2006, 15:50
Das ist Logisch.

Du fragst 16x den ADC ab.
Du änderst 16x den Mux
Du rechnest alles 16x

Der Shift am Ende ist da schon nebensächlich.
Wenn man beachtet das der ADC max nur ca. 16ks/s schafft dann kommt man bei 16Mhz schnell auf 1/1000 Sekunde allein für die Abfrage.
Dh deine 0.001s fallen genau in das Raster.

Aber die anderen Befehle stehen hinten drann und verlängern die Zeit entsprechend iherer Laufzeit.

Das dürfte im groben gesagt der Fehler sein wenn ich mich jetzt nicht völlig vergallopiert habe.


Bascom läst ja sehr schön Inlinecode zu.
Versuchs mal mit ner Assemblerroutine für die Abfrage

PicNick
03.02.2006, 15:58
@m_herr: 'tschuldige, war ein Unterstellung

Das ist das, was Bascom draus macht, wer mag, kann die Zyklen zählen, viele sind es ja nicht



----------------------------------------------
Ad0 = 0
----------------------------------------------
LDI r24,0x00
LDI r25,0x00
LDI XL,0x60
LDI XH,0x00
ST X+,r24
ST X,r25

----------------------------------------------
For X = 1 To 16
----------------------------------------------
LDI r24,0x01
STS 0x0062,r24
L_0x008C:
LDS r16,0x0062
CPI r16,0x10
BRLO L_0x009A
BREQ L_0x009A
JMP L_0x00D6
L_0x009A:
----------------------------------------------
Mtemp = Getadc(0)
----------------------------------------------
LDI r24,0x00
OUT ADMUX,r24
CALL L_0x00F6
LDI XL,0x63
LDI XH,0x00
ST X+,r24
ST X,r25

----------------------------------------------
Ad0 = Ad0 + Mtemp
----------------------------------------------
LDI XL,0x60 ad0
LDI XH,0x00
LD r16,X+
LD r17,X

LDI XL,0x63 mtemp
LDI XH,0x00
LD r20,X+
LD r21,X

ADD r16,r20 add
ADC r17,r21

LDI XL,0x60 store ad0
LDI XH,0x00
ST X+,r16
ST X,r17

----------------------------------------------
Next X
----------------------------------------------
LDI XL,0x62 x
LDI XH,0x00
LD r24,X
SUBI r24,0xFF +1
ST X,r24 store x
BRCC L_0x00D6 exit for..next
JMP L_0x008C continue
L_0x00D6:

----------------------------------------------
Shift Ad0 , Right , 4
----------------------------------------------

LDI r25,0x04
LDI XL,0x60
LDI XH,0x00
CALL L_0x0108
----------------------------------------------
END
----------------------------------------------
CLI
L_0x00E2:
RJMP L_0x00E2

----------------------------------------------
GETADC()
----------------------------------------------
L_0x00F6:
SBI ADCSR,ADSC
L_0x00F8:
SBIC ADCSR,ADSC
RJMP L_0x00F8 wait bit clear
SBI ADCSR,ADSC set bit
L_0x00FE:
SBIC ADCSR,ADSC
RJMP L_0x00FE wait bit clear
IN r24,ADCL read low
IN r25,ADCH read high
RET

Die meiste Zeit vergeht beim Warten auf den ADC

m_herr
03.02.2006, 15:58
Config Adc = Single , Prescaler = 128 , Reference = Avcc

mh, ich dachte der adc macht mehre khz? also 4mhz/prescaler?
also 4000000/128=31250hz.
er müßte da doch die 16messungen nebenbei machen, oder habe ich da was falsch verstanden?

Ratber
03.02.2006, 16:01
Nö,der AVR hat genau "Einen" ADC und der kann logischerweise immer nur eine Messung machen.

Davor ist der Mux der die einzelnen Eingänge mit dem ADC verbindet.

In Assembler mußte ja jedesmal umschalten da merkt man das.
Bei Bascom geht das in der Automatisierung leicht unter.

Dann ist da noch der Umstand das der ADC ja nicht in einem Takt Wandelt (successive approximation) sondern ne gasnze Weile braucht (Parallelwandler sind kaum zu bezahlen wegen dem Aufbau)

Man kann sagen das ca. bei 16ks/s (Praktisch 15.x ks/s) Ende ist.


aber ich les jetzt nochmal nach bevor ich Unsinn verbreite.......



Edit:

Da ist die Textstelle:

"each conversion will require 25 ADC clocks."
Den Rest kannste dir dann ausrechnen.

izaseba
03.02.2006, 16:04
GETADC()
----------------------------------------------
L_0x00F6:
SBI ADCSR,ADSC
L_0x00F8:
SBIC ADCSR,ADSC
RJMP L_0x00F8 wait bit clear
SBI ADCSR,ADSC set bit
L_0x00FE:
SBIC ADCSR,ADSC
RJMP L_0x00FE wait bit clear
IN r24,ADCL read low
IN r25,ADCH read high
RET


Und wenn man das in ein ADC_Ready Interrupt verlagert?
Auf die Messungen muß er zwar noch warten, er hat dann aber Zeit um was anderes zu machen.

Gruß Sebastian

P.S. ach ja und den ADC in Freerunning Modus setzen.

m_herr
03.02.2006, 16:06
Gegenfrage :*g

Wie kann ich so schnell und gut wie es geht 16mal den ADXx auslesen und den Wert in Variable x speichern? Auch in Assembler wenn es sein muß.
Vielen Dank

PicNick
03.02.2006, 16:07
Klar, elegante Leute machen das mit Interrupt und tun derweil was anderes.
Ist aber ein anderes Konzept, da dann einen Average-Loop drüberzulegen.

izaseba
03.02.2006, 17:22
getadc:
clr ergebnisl
clr ergebnish
ldi tmp,(1<<anzahl)
start:
sbi ADCSR,ADSC
warte:
sbis ADCSR, ADIF
rjmp warte
in tmp2, ADCL
add ergebnisl, tmp2
in tmp2, ADCH
adc ergebnish, tmp2
dec tmp
brne start
ldi tmp,anzahl
teile:
lsr ergebnish
ror ergebnisl
dec tmp
brne teile
ret


Das sollte so funktionieren

tmp und tmp2 sollen 2 Register >= R16 sein
ergebnisl und ergebnish egal welche
anzahl ist dann eine konstante, wie oft die Schleife durchlaufen soll.
In Deinem Fall 16.
Das Ergebnis steht dann in ergebnisl und ergebnish.
Der Muxkanal muß auch davor eingestellt werden.
Das wäre dann pooling, ich finde es aber trotzdem besser, wenn das in ein Interrupt rein käme.
Ich hoffe, daß Du damit was anfangen kanst.

Gruß Sebastian
P.S.
@Picknick,
hab ich was falsch gesagt ?

m_herr
03.02.2006, 17:49
puh, das überfordert mich total, war bisher nur auf bascom ausgelegt...

da ich aber Icp1 und Ovf1 noch benutze und angst habe, daß es da probleme gibt, habe ich das extra mit der schleife die alle 10ms durchlaufen wird aufgebaut....

PicNick
03.02.2006, 17:53
@Picknick, hab ich was falsch gesagt ?
Neinnein, alles roger, ist ja richtig. Vom Programmablauf her ist das halt etwas schwieriger. :-)

izaseba
03.02.2006, 20:48
Ja nu, ich hab nicht gesagt das es einfach ist, aber irgendwas sollte man wirklich auslagern, sonst wartet sich der µC dumm.
Wie wird eigentlich die Ausgabe realisiert auch mit Warteschleifen?

Gruß Sebastian

m_herr
04.02.2006, 08:06
naja, der timer ist auf 0,001 eingestellt und setzt ein flag. Ist dieses gesetzt, dann wird im Main-Teil eine if-Schleife durchlaufen und ein paar Zeitzähler erhöht.

und anhand dieser Zähler wird dann sowohl der ADC (alle 10ms) als auch die Display-Ausgabe (alle 500ms) durchgeführt - so zumindest die Theorie. In der Praxis kommt halt ein zigfaches an Ausführungszeit herraus.


Da Timer1 mit Icp1 und Ovf1, sowie RS232 (9600) bestens funktionieren, habe ich die Hoffnung noch nicht aufgegeben, daß ich den Rest auch irgendwie noch gerade gebogen bekomme.

Hier mal das Grundgerüst

Do

If H_flag = 1 Then 'alle 0,001Sek ausführen
Incr H 'Zeitzähler Displayanzeige
Incr H1 ' Zeitzähler für ADC-Auswertung
Incr Rr 'Zeitzähler allgemein
H_flag = 0
End If



If H1 = 10 Then 'die Getadc-Anweisungen fressen Zeit
Ad0 = 0
For X = 1 To 16
Mtemp = Getadc(0)
Ad0 = Ad0 + Mtemp
Next X
Shift Ad0 , Right , 4

Ad0 = 1
For X = 1 To 16
Mtemp = Getadc(1)
Ad1 = Ad1 + Mtemp
Next X
Shift Ad1 , Right , 4


Ad0 = 2
For X = 1 To 16
Mtemp = Getadc(2)
Ad2 = Ad2 + Mtemp
Next X
Shift Ad2 , Right , 4

Ad3 = 0
For X = 1 To 16
Mtemp = Getadc(3)
Ad3 = Ad3 + Mtemp
Next X
Shift Ad3 , Right , 4


Bissel Ganzzahlrechnungungen mit AD0-AD3

H1 = 0
End If




If H = 500 Then 'alle 0,5Sek anzeigen
Locate 1, 1
Lcd Rr

Zeige noch einiges an auf dem Display

H = 0
End If

Loop

End


Timer0_isr:
Load Timer0 , Ticks0
H_flag = 1 'alle 0,001 flag setzen
Return

RR müßte ja vom Start ab innerhalb einer Minute 60000 groß sein (rr wird alle 0,001 Sek um 1 erhöht), ist aber bei vollem code 18000, also nicht einmal ein 3tel.

Wenn ich die Schleifen für die 16Messungen weglasse auf 4 erniedriege, ist RR 34500, also fast 50%.

Lasse ich die Getadc-Anweisungen komplett weg, komme ich auf RR 50000

Lasse ich alles weg, nur die Zählerhochzähler und eine einfache Display ausgabe ohne Rechnen etc komme ich gerade mal auf 59000.
Sobald aber Code hinzukommt, sinkt die Zahl.

Und das finde ich schon arg krass, das kann es nicht sein, oder?




aber irgendwas sollte man wirklich auslagern, sonst wartet sich der µC dumm

Was meinst du damit genau?
Ich dachte der MC ist im "Leerlauf" und wenn der gewünschte Zeitpunkt erreicht wird, dann macht er mal schnell ein paar Befehle - oder ist der Ansatz von mir da Falsch?

Wie soll zb sonst programmiert werden, daß nach xxZeit YYY ausgeführt wird?

izaseba
04.02.2006, 11:30
Ich dachte der MC ist im "Leerlauf" und wenn der gewünschte Zeitpunkt erreicht wird, dann macht er mal schnell ein paar Befehle - oder ist der Ansatz von mir da Falsch?


Ich bin zwar kein Bascomer, aber ich versuche mal das Programm zu beschreiben(aus meiner Sicht)

Die Haupftschleife wartet solange bis Die Variable H1 10 beträgt, und die wird mit hilfe von Timer Overflow Interrupt inkrementiert.
Wenn dann die magische 10 kommt startest Du Deine messungen und zwar in einer Riesenschleife 4 mal 16 Messungen.
So eine Getadc Funktion macht nichts anderes, als die Messung zu starten und
abzuwarten, bis sie beendet ist(laut Assembler Code von Picknick).
Du machst dann 64 mal nichts anderes als "Starte die Messung und tue nichts bis sie beendet ist".
Klar kommt zwischendurch noch der Timer und setzt da Deinen Flag, ich denke sogar mehrmals, das kriegst Du aber nicht mit weil Du noch auf Dein ADC wartest :-b .

Sollte ich da falsch liegen, wird man mich hier sicher darauf hinweisen, vielleicht sehe ich das falsch, wie gesagt ich bin kein Bascomer O:)

Besser wäre natürlich den ADC in Freilaufmodus zu starten und in einen ADC_Ready Interrupt Deine Muxkanäle umzuschalten und natürlich die 16 Messungen addieren und dividieren.
Die Ergebnise dann schön in Ram geschrieben, dann kann sich Deine Hauptschleife wirklich langweilen.

Gruß Sebastian

m_herr
04.02.2006, 11:39
So ungefähr, bzw richtig.

Die Hauptschleife wartet solange bis h1=10 (0,01Sek vergangen) ist und bildet dann aus 16 adc-Messungen den Mittelwert. Und dies für 5 ADC-Kanäle.

Also alle 10ms das 16mal-Messen und Mittelwertbilden von 5 ADC-Kanälen. Da kommt dann noch mit den ermittelten Variablen ein paar Rechnungen hinzu, aber das ist zu vernachläßigen was die Geschwindigkeitsprobleme angeht.

Knackpunkt ist einfach Getadc(x). Dieser Funktionsaufruf bremst alles extrem runter.

Somit scheint mir diese Funktion entweder vollkommen falsch von mir benutzt zu werden, oder aber sie ist nicht die Bits wert, die sie belegt..


Besser wäre natürlich den ADC in Freilaufmodus zu starten und in einen ADC_Ready Interrupt Deine Muxkanäle umzuschalten und natürlich die 16 Messungen addieren und dividieren.

Und da habe ich Angst, daß der ADC-Interrupt so oft aufgerufen wird, daß alle anderen Interrupts darunter leiden.
Bzw besteht die Möglichkeit mit Start/Stop ADC (Bascom-Befehl) das irgendwie zu bremsen, daß andere Interrupts (Timer0, Timer1, Icp1 und Ovf1) nicht darunter leiden?

izaseba
04.02.2006, 11:50
Also alle 10ms das 16mal-Messen und Mittelwertbilden von 5 ADC-Kanälen
Es ist nur die Frage, ob Du weniger als 10 ms für die 64 Messungen brauchst.

Und was Deine bedenken mit dem ADC-Interrupt angeht glaube ich nicht, daß sie berechtigt sind denn der Controller hat da nicht viel zu tun, überprüfen ob schon 16 Messungen abgeschlossen sind, den Mux umschalten und Ergebnisse speichern, da ist er schnell raus aus dem Interrupt glaub es mir.
Es ist zumindest einen Versuch wert.

Gruß Sebastian

m_herr
04.02.2006, 12:01
naja, also wenn der ADC mit Systemtakt/Prescaler arbeiter, also mit 4000000/128, dann hatte ich gedacht, daß er schnell genug ist 5x16 Messungen innerhalb von 10ms zu machen.
Oder habe ich da einen Denkfehler?

izaseba
04.02.2006, 12:11
hmmmm, also nach meinem Verstand ist es so:
Prescaller 128 ergibt ADC Freq. von 31,25kHz ein Takt Dauert also 32µs
Eine Wandlung dauert laut Dattenblatt 13 ADC Zyklen also 416 µs.
Und das ganze mal 64 -> 26,6 ms

Hab ich jetzt richtig gerechnet, oder ist da ein Denkfehler drin?

Gruß Sebastian

P.S. wieso nimmst Du nicht prescaller 32 ?

m_herr
04.02.2006, 12:19
verdammt, ich wußte da war ein haken *g

128 deswegen, weil ich ihn so langsam und damit so genau wie möglich haben wollte....

aber selbst eine ADC-Wandlung bringt den mc in die knie..

izaseba
04.02.2006, 12:23
ups, noch ein nachtrag :


GETADC()
----------------------------------------------
L_0x00F6:
SBI ADCSR,ADSC
L_0x00F8:
SBIC ADCSR,ADSC
RJMP L_0x00F8 wait bit clear
SBI ADCSR,ADSC set bit
L_0x00FE:
SBIC ADCSR,ADSC
RJMP L_0x00FE wait bit clear


Nochmal ein Ausschnitt aus dem Assembler, per GetAdc macht er 2 Messungen, um sich wohl "warmzulaufen" dann mußt Du die Zeit wohl noch mal mit 2 Multiplzieren :-k

PicNick
04.02.2006, 18:58
Musst du denn alle Messungen in der gleichen 1/100 Sekunde machen ?

m_herr
04.02.2006, 19:30
nein, muß ich nich, da kann schon 3-10/Sekunde abstand sein. Ich kann auch die 100/Sekunde-Schleife (also If h1=10 then ...) auch gut auf 100mS oder 150ms ausdehnen

Ratber
04.02.2006, 19:33
Ja,dann sollte das Problem gelöst sein.

PicNick
04.02.2006, 19:36
Ich würde eben versuchen, einfach jede 1/1000 Sekunde EINE einzelne Meßung zu machen und wär dann in 64 mS wohl fertig. da bliebe immer Zeit dazwischen für irgendwelches Nebenzeugs.
Ich find', diese spezielle 1/100 Sekunde ist einfach überladen. (IMHO)
Da eine Meßung ~ 100 µS fertig wäre, könnte man vielleicht auch flotter ticken, aber eben die Last immer schön verteilen.

(Wenn das von der Aufgabe her eben geht)

m_herr
04.02.2006, 20:33
Ja,dann sollte das Problem gelöst sein.

scheinbar nicht, habe mal h1=10 in h1=80 geändert, aber keine Besserung....


Ich find', diese spezielle 1/100 Sekunde ist einfach überladen. (IMHO)

ich bin für jede Lösung (am besten mit code-ansätzen O:) ) dankbar:
mindestens 10 mal in der sekunde 5 adc-kanäle mit mittelwertbildung (8 Messungen gingen auch) auswerten, ohne das andere Interrupts gestört werden.

Hätte nie gedacht, daß es so kompliziert ist mit getadc(x) zu arbeiten....

Ratber
04.02.2006, 21:40
Wenn die anderen Int nicht zu häufig kommen gibts auch kein Terror.

Ich rechne nochmal.

Eine Einzelwandlung dauert komplett 25 Taktzyklen (Lt. Datenblatt) und der Takt darf bei 10 Bit Auflösung max. 200 Khz betragen.
(Geht man höher dann leidet die auflösung aber es geht flotter.)
Das sind nach Adam Riese 125µs pro Wandlung wenn man streng nach Datenblatt geht)
Bei 5x10 bzw 5x8 Wandlungen am Block sind das 6.25 bzw. 5ms für alles.

Bei 100 Messungen/s wird also alle 10ms ein messzyklus gestartet.

Dh. du hast mit der einfachen Methode 5ms für dich alleine um was anderes zu machen.
Bei nem Systemtakt von 16Mhz also 80000 Taktzyklen für was anderseres.
Wenn du den ADC mit IRQ betreibst dann sogar wesentlich mehr da der ja die größte Zeit alleine läuft.


So und nun zum Praktischen Problemchen.
Und das Problem ist ja das Bascom den einfachsten Weg geht und nach dem Starten der Abfrage einfach wie nen Engländer am Busstop steht bis die Wandlung beendet ist.
Dazwischen passiert rein garnichts.

Für den Normalfall wenn einer alle Sekunde mal nen Kanal abfragt fällt das garnicht auf.
Auch einen Kanal 10x oder alle 8 jeweils 1x die Sekunde ist gut zu managen aber bei deinen 5000 bzw. 4000 Messungen/s ist dann schnell ende.
Das ist in Assembler schon nicht mehr so unbeachtet zu erledigen.(Weißt schon was ich meine)

Vieleicht wäre hier ein Mix aus Bascom und Assembler ne gute Idee.
Verleg einfach die AD-Wandlung manuell aus dann kannste den ADC-Int nutzen.
Einige µs Zeit sollten dabei schon rausspringen und der Code wird nur auf dem Papier größer.(Müßte eher kleiner werden denn du gibst ja schon genau vor)

Rein in Bascom gehts natürlich auch.

Äh,ja.
Ich hoff du kannst jetzt mit dem geschreibsel da oben was anfangen.
Is etwas wirr geworden.

m_herr
04.02.2006, 21:49
aber bei deinen 5000 bzw. 4000 Messungen/s ist dann schnell ende

nicht ganz. selbst bei 100 getadc(x) /Sek (alle 10ms nur eine Messung) bricht alles ein...also ist getadc nicht zu gebrauchen...


Werde nun versuche das mit dem ADC-Interrupt zu lösen und hoffen, daß es da keine Behinderungen gibt....

Ratber
04.02.2006, 22:18
nicht ganz. selbst bei 100 getadc(x) /Sek (alle 10ms nur eine Messung) bricht alles ein...also ist getadc nicht zu gebrauchen...

Ja,das meinte ich ja damit.

Bascom übersetzt ja nicht so optimal wie man das in Assembler machen würde.
Das ist eine Sache die bei allen Hochsprachen mehr oder weniger auftritt.
Bascom ist insgesammt schon recht gut und realtiv effizient in Punkto Codegröße aber auch das hat logischerweise Grenzen.

Wenn es absolut kritisch wird dann ist C oder Assembler die bessere Wahl.