Forum: Mikrocontroller und Digitale Elektronik TCNT0 anhalten oder "einfrieren"


von emax (Gast)


Lesenswert?

Das Problem hatten doch sicher schon viele:

Kann man TCNT0 irgendwie anhalten? Ich meine nicht den
Überlauf-Interrupt, den kann ich ja disablen. Aber soweit ich es
gesehen habe, wird TCNT0 IMMER hochgezählt, egal ob der Interrupt
anabled ist oder nicht.

Warum das Ganze? Weil ich gerne bei Eintritt in eine bestimmte
Interruptroutine den Zustand des Zählers einfrieren würde. Denn während
ich in der ISR rumhantiere, verändert sich ja ständig TCNT0, und was am
schlimmsten ist: er kann auch überlaufen, und ist dann null oder vier
oder sowas, obwohl er auf z.B. auf 252 stand, als die ISR begann.

Andere Timer etc. kann ich nicht nehmen, werden für was anders
gebraucht.

Wie löst man sowas?

e.

von Axel Rühl (Gast)


Lesenswert?

im TCCR0 Register die Bits 2,1 und 0 löschen.
Das hält den Timer an:  Prescaler = 0 -> Timer gestoppt
alten Prescaler wieder laden: Timer läuft weiter

in R16, TCCR0
andi R16,0b11111000
out TCCR0,r16

Ich weiß jetzt nicht, mit welchem Prescaler dein Timer0 arbeitet,
aber mit

in R16, TCCR0
ori R16, 0b00000001      ;läuft der Timer volle Kanne weiter
out TCCR0,r16

mit oriR16,0b00000010    ;prescaler von 8
          ,0b00000011    ;--''--       64
          ,0b00000100    ;256
          ,0b00000101    ;1024

du liesst das Timercontrolregister ein und setzt die PrescalerBit's
entsprechend wieder, ohne die anderen Bits zu beeinflussen. Zum stoppen
löscht Du mit Bitweiser UND Verknüpfung alle Prescaler Bits, ebenfalls
ohne die anderen evtl. gesetzten Bits zu stören. Ich hoffe mein
Assemblercode ist von der Syntax her richtig...

@ALL
Berichtigt mich, wenn ich falsch liege

Gruß und schönen Abend noch
Axel

von leo9 (Gast)


Lesenswert?

eine der Standardantworten:
wennst schreibst welchen Prozessor du nimmst wird man dir sicher helfen
können.
Ich tipp mal auf avr: Clock Source auf null setzen
(CS02=0,CS01=0,CS00=0 im TCRR0)

grüsse leo9

von emax (Gast)


Lesenswert?

Jou, hast Recht leo: AT90S8535

Aber die Antworten haben mir schon geholfen, Danke.

Ein Problem bleibt trotzdem: auch wenn ich die Registerorgie
durchziehe, und den Timer einfriere: überlaufen kann er bis zu diesem
Moment trotzdem noch.

Hat da einer ne Idee? Oder könnte man in der ISR einfach ungefähr sowas
machen:

SIGNAL (blabla)
{
  if (TCNT0 <=4) {  // Timerüberlauf ....
    foo();
   }
...
}

von leo9 (Gast)


Lesenswert?

Warum stört das Überlaufen so? mir fällt beim besten Willen nichts ein
warum er nicht weiterlaufen soll (Eigentlich ist ja das der große
Vorteil von Timern dass sie zählen, egal was der uP sonst macht).

Vielleicht könntest du das Gesamtproblem skizzieren, ich denke da dann
findet sich sicher eine Lösung.

grüsse leo9

von emax (Gast)


Lesenswert?

Weil ich den Timer in eben dieser ISR auswerte.

Ich habe einen Timer0 mit Vorteiler 8 laufen. In der Überlauf-ISR
(OVERFLOW0) addiere ich die Überläufe.

Wenn nun ein bestimmtes Ereignis eintritt (Flanke an int1), dann messe
ich die zeit:

PulseLen = Overflows * 256 + TCNT0.

Wenn nun JUST IN DIESER ISR der Timer überläuft, dann stimmt die ganze
Arie nicht nicht mehr. Denn erstens wird dann NACH der ISR die
OVERFLOW0 Routine ausgeführt, und somit "Overflows" hochgezählt. Das
wäre aber (in dieser Anwendung) falsch. Und zweitens kann es natürlich
passieren, das bei meiner Berechnung von "PulseLen" der Wert von
TCNT0 nicht mehr 250 (o.ä.) war, wie zum Zeitpunkt der Flanke, sondern
mittlerweile übergelaufen ist, und dehalb z.B. nur den Wert 8 hat. Und
das ist erst recht falsch.

Ein echtes Dilemma. Deshalb habe ich die Hoffnung, das irgend jemand
iese Nuss schon geknackt hat.

von Axel Rühl (Gast)


Lesenswert?

Hi,
ich zähle eine integer variable hoch. bei steigender flanke setze ich
diese Variable auf null, bei fallender flanke werte ich die variable
aus.
Ist für meinen Fahrregler.
Der mega8 kann ja beim Interrupt0 bei jedem flankenwechsel einen
Interrupt auslösen.
Ich programmiere mit FastAVR...

Gruß
axel

von emax (Gast)


Lesenswert?

@Axel

Wir lösen, wie scheint, das gleiche Problem. Ich möchte eine 4-8 KHz
PWM zur Steuerung mehrerer BUZ o.ä verwenden, um 50V bei bis zu 80A zu
regeln. Das Eingangssignal kommt von einer Fernsteuerung, die üblichen
0,8 bis max. 2 Millisekunden.

Das Hochzählen der Int-Variable ist aber genau das Problem: wo zählst
Du die denn hoch? Ich mach das mit dem erwähnten 8-Bit Timer und einem
Überlaufzähler. Genau wie Du setze ich bei steigender Flanke die Werte
auf Null, und werte das bei fallender Flanke aus.

Läuft während dieser Aktion der Timer über, stimmt das Ganze nicht
mehr.

Hier die geschilderte Routine:

/*-----------------------------------
  Interrupt bei steigender/fallender
  Flanke an PD3 (int1)
  -----------------------------------*/
SIGNAL (SIG_INTERRUPT1) // vector 2
{
  if (bit_is_set(MCUCR, ISC10)) // rising edge
    {
      TCNT0 = 6;    // 6 where lost up to here
      SET_INT1_FALLING_EDGE();       // set int1 to falling edge
      OverFlows = 0;
    }
  else        // we are at falling edge
    {
      Pulse =  OverFlows * 256  + TCNT0;
      SET_INT1_RISING_EDGE();       // set int1 to rising edge
    }
}


Und hier das Routinchen für den 8-Bit Timer:

SIGNAL (SIG_OVERFLOW0) // vector 9
{
  // diser 8-Bit timer läuft immer nach (Vorteiler * 256) Clocks über
  OverFlow++;
} // SIGNAL(SIG_OVERFLOW0)

von Henning (Gast)


Lesenswert?

beim eintrit in die interruptroutine einfach erst den letzen timerwert
sichern (tmp1) und hier kann der überlaufzähler ja nicht verändert
werden, weil man ja schon im interrupt ist.

ich messe erst x ms nach der hiflanke, da mich der bereich ja nicht
interessiert (immer hi). habe meinen T0 aber ebenfalls auf Fosc/8
laufen lassen und maximal einen überlauf dabei -> das overflowflag flag
abfragen und gut is. Besser: (um auch vor störimpulsen gewappnet zu
sein) wie ihr das ganze schon hab mit überlaufzähler. Die aus den 8bit
überlauf und 8bit timer bestehende 16bit zahl einfach einen nach rechts
schieben ( /2 ) und die unteren 8bit enthalten den wert.
vorher testen ob der überlaufzähler nen wert über 1 hat und dann nichts
tuen, ausser eben wieder die fehlerzahl zählen und ggf. abschalten.

ganz ideal passt das ganze allerdings nich zu meinem empfängersignal,
aber ich habe in den grenzen einen bereich von 10 einheiten als
vollgas, und den unteren bereich, so das es passt (rund 30 einheiten)
als stillstand akzeptiert.

so ist der untere berreich, in dem der motor nur brummen würde auch
ausgeblendet. die fets schalte ich per PWM bei etwa 1,8 kHz

hab das ganze in asm gemacht, mit einem 2313 zum testen. bin auch
vorgestern schonmal damit gefahren.

mich würde eure fet-ansteurung interessieren: ich treibe im mom 3
parallele buz11 mit jeweil einem 56R gate widerstand und einem
gemeinsamen treibertransistor davor. Freilaufdiode am ausgang und das
wars auch schon. muss man noch mehr zum entstören machen?! (ausser die
3 C´s am motor direkt)
hab einen 0,22uF Folienkondi (1000V) parallel zur Freilaufdiode gepackt
aber trotzdem ist die ausgangsspannung ganzschön zerhackt (vom wechsel
auf das nächste kollektorfeld (?)), hat also scheinbar nix geholfen.

von Peter D. (peda)


Lesenswert?

Timer anhalten bringt Dir nur eine Verfälschung der Zeitmessung.

Das ist doch der Witz daran, daß die Timer durchlaufen und damit exakt
und unabhängig von der Software arbeiten.


Das Kaskadieren per Software ist einfach:

Du liest zuerst den Timer und dann das Overflow-Bit.
Wenn das Overflow-Bit gesetzt ist, heißt daß, der Timer ist
übergelaufen, aber der Timerinterrupt hat noch nicht das High-Byte
hochzählen können.
Also prüfst Du noch das Bit7 des gerade gelesenen Timerwertes.
Ist es 1, dann hast Du es vor dem Überlauf gelesen.
Ist es aber 0, dann hast Du es nach dem Überlauf gelesen, d.h. Du must
das High-Byte nach dem Lesen einmal hochzählen und alles stimmt
wieder.


Peter

von Axel Rühl (Gast)


Lesenswert?

Hi,

ohoo, auf dem linken Fuß erwischt, ich probier mal in C, mache ja
eigentlich mit FastAVR-Basic.

Ich verwende einen Mega8
im MCUCR das Bit2(ISC10) setzen : Interrupt1 bei jedem Flankenwechsel
SIGNAL (SIG_INTERRUPT1) // vector 2
{
if (pind.3) //steigende flanke löste int1 aus
   {
     pulscounter=0;
    }
    else //fallende Flanke löste Interrupt1 aus
   {
     pwm_accl_tabl_index = pulscounter // steht bei mir so zwischen 247
und 350

wert der Tabelle entnehmen und dem linken oder rechten PWM-kanal
zuweisen. In Abhängigkeit davon die oberen gegenüberliegenden P-Mos
setzen.
   }
}

soviel zum Interrupt; ich weiß leider nicht, wie man in C den Portpin
d.3 abfragt, in FastAVR geht das jedenfalls so. Hier in der else
schleife erledige ich alles andere gleich mit. Mittelwert bilden,
selbstlernfunktion, störimpulsausblendung (sender aus->motor aus)
Bremslicht, Bremse, Rücklicht. Zeit ist ja genug da.
Timer0 OHNE Vorteiler benutzen!
overflow als Integer deklarieren, (wie auch immer das in C geht)
int overflow , glaube ich.

SIGNAL (SIG_OVERFLOW0) // vector 9
{
    OverFlow++;
} // SIGNAL(SIG_OVERFLOW0)

Soo, ich habe auch schon an anderen Stellen im Forum berichtet.
Noch mal ein Bild gefällig?( ich will niemenden langweilen)

Gruß
AxelR.

von emax (Gast)


Lesenswert?

@Henning

"beim eintrit in die interruptroutine einfach erst den letzen
timerwert
sichern (tmp1) und hier kann der überlaufzähler ja nicht verändert
werden, weil man ja schon im interrupt ist."

Zwar nicht der Überlaufzähler, aber der Timer. Der läuft nämlich erst
mal weiter und kann deshalb überlaufen. Schau oben mal genauer hin: der
Wert könnte zum Zeitpunkt der Flanke z.B. 0xFE gewesen sein, und in der
Routine dann mit 0x02 ankommen.

Der Überlaufzähler macht an dieser Stelle zwar noch keine Probleme,
aber wenn die Routine fertig ist, wird der T0 overflow nachgeholt, und
dann der Überlaufzähler erhöht. Das wäre aber falsch, da die ISR (je
nach Flanke) eine NEUE Zählung starten soll, und deshalb auch den
Overflow-Zähler zurücksetzt. Wenn der unmittelbar nach dem Ende der
Routine inkrementiert wird, stimmts dann nicht.

"mich würde eure fet-ansteurung interessieren:"

Da ists bei mir noch zappenduster, ich verstehe von Analogtechnik nicht
sehr viel. Muss mir dass zu gegebener Zeit zusammensuchen.

@Peter
"Timer anhalten bringt Dir nur eine Verfälschung der Zeitmessung.
Das ist doch der Witz daran, daß die Timer durchlaufen und damit exakt
und unabhängig von der Software arbeiten."

Stimmt im reinen Timerfall sicher, aber hier messe ich ja nur die Zeit
zwischen zwei Flanken (hi/lo). Wenn die HiFlanke kommt, wird sowiso der
Rimer auf Null gesetzt. Wenn dann die fallende Flanke kommt, dann isses
im Moment des Aufrufs der ISR ja bereits passiert. Ich möchte ja genau
bis zur Flanke zählen, und nicht weiter. Für die Folgemessungen ist es
eh wurscht, ob der Timer erst mal gestoppt ist, oder nicht: da ich nur
die High-Zeiten messen möchte, und nicht die Lowzeiten, ist im  Ablauf
also ohnehin eine Messlücke, in der ich dem Timer gar nicht brauche.

"Du liest zuerst den Timer und dann das Overflow-Bit.
Wenn das Overflow-Bit gesetzt ist, heißt daß, der Timer ist
übergelaufen, aber der Timerinterrupt hat noch nicht das High-Byte
hochzählen können"

Diese Idee ist solange praktikabel. wie man keine PWM einsetzt. Wie
oben bereits geschrieben habe, möchte ich aber genau das nutzen: PWM.
Im AT90S8535-Manual heisst es dazu auf Seite 28:

"Bit 0   TOV0: Timer/Counter0 Overflow Flag The bit TOV0 is set (one)
when an overflow occurs in Timer/Counter0."

Das hört sich zunächst gut an. Aber zwei Sätze weiter heisst es:

"In up/down PWM mode, this bit is set when Timer/Counter1 advances
from $0000."

Und das finde ich oberblöd. Wundert mich eh: was hat das TOV0 Bit mit
der PWM zu tun?

Oder ist das ein Manual-Bug, oder hab ich was falsch verstanden?

@Axel
"pulscounter // steht bei mir so zwischen 247 und 350"

Ich komme mit 8MHz und einem t0-prescaler von 8 auf Werte zwischen 819
und 2120. Das entspricht fast genau den Microsekunden der Pulse, die
mein Servotester generiert (ist bei einem 8MHz Quarz und einem
Vorteiler von 8 eigentlich auch logisch...).

Ich kann  also etwa 1200 Schritte abbilden, und so für diesen Bereich
ganz wunderbar eine 10Bit PWM realisieren.

Die Anlagen im richtigen Leben arbeiten allerdings nur zwischen 830 und
1500 microsekunden,

Eigentlich reicht Deine Genauigkeit aber aus. Aber die Modellfuzzis
(ich bin auch einer) stehen nun mal auf solche "Genauigkeit", wenns
im Grunde auch Blödsinn ist.

Wie sind Deine Erfahrungen in der Praxis: Braucht man eine nichtlineare
Tabelle mit Regelwerten, oder kann man die Messwerte einfach linear
umgesetzt in die PWM übergeben? Also z.B. bei einem Messbereich von
1024 Schritten (z.B. 850-1873) den Messwert (Value - 850) einfach der
10Bit-PWM übergeben?

e.

von Axel Rühl (Gast)


Lesenswert?

da alle meine Variablen im SRAM stehen, brauchst bei mir etwas mehr
zeit, bis alles umgeschaufelt ist. so ist mein relativ kleiner
zählerwert zu erklären. Die genauigkeit reicht allemale aus. Ich habe
zwei tabellen: eine für vorwärts und eine für rückwärts. Fährt sich
besser, hängt auch viel vom Motor und vom Getriebe ab. so habe ich
(nach abzug der Totzone um die Mittelstellung herum) 40 Stufen für
vorwärts und 40 für rückwärts. den unteren Bereich habe ich gedehnt.
Ich hab's ja gut: mein Meag8 hat zwei PWM-Kanäle (timer0), die kann
ich direkt auf die N-MOSFET's packen. 2 Portpins schalten dann die
P-MOSFETS. Sieht in FastAVR auch alles ganz einfach aus, sind keine
200Zeilen Quelltext. PWMA = Acc_table(pulscounter),PWMB = 0. oder eben
umgekehrt. Aufpassen muss man aber, das nicht der 'linke' PMOS und
die'linke'PWM gleichzeitig an ist.
axel

von Peter D. (peda)


Lesenswert?

"oder hab ich was falsch verstanden?"

Ja, T0 hat gar keine PWM !


"aber hier messe ich ja nur die Zeit zwischen zwei Flanken (hi/lo)"

Dann ist doch die Capture-Funktion von T1 die erste Wahl.
Warum die Umstände mit T0 ?
Capture und PWM gehen doch gleichzeitig.


Peter

von Uwe (Gast)


Lesenswert?

Hi!
@Peter: na weil er mit T1 die PWM macht und da geht das mit dem IC
nicht.
@Axel: Du verwechselst was! TOV1 wird nur von T1 gesetzt, nicht T0!
Es sollte also kein Problem sein das TOV0 Flag auszuwerten und es dann
auch noch zu löschen(verhindert TOV0-Int.)

MFG Uwe

von emax (Gast)


Lesenswert?

@peter

"Ja, T0 hat gar keine PWM !"

Na eben, genau das sag ich doch: deshalb verstehe ich ja genau nicht,
warum im Handbuch über das TOV0 (!) Bit: steht:

------------------------------------------------------------------
"In up/down PWM mode, this bit is set when Timer/Counter1 advances
from $0000."
------------------------------------------------------------------

"Dann ist doch die Capture-Funktion von T1 die erste Wahl."

Die werd ich mir sicher mal genauer anschauen, nützen tut sie mir in
diesem Fall aber trotzdem nichts. Ich möchte doch PWM einsetzen, und da
ist T1 dann belegt.

@Uwe

"Du verwechselst was! TOV1 wird nur von T1 gesetzt, nicht T0!
Es sollte also kein Problem sein das TOV0 Flag auszuwerten und es dann
auch noch zu löschen(verhindert TOV0-Int.)"

Siehste, das wäre auch logisch. Aber nochmal: im Handbuch steht was
anderes: TOV0 wird angeblich bei PWM gesetzt, wenn der Zähler bei $00
umkehrt. Das steht übrigens so nicht nur im AT90S8535 - Handbuch,
sondern auch im Handbuch des ATMega128 ....

e.

von Peter D. (peda)


Lesenswert?

@Uwe

"na weil er mit T1 die PWM macht und da geht das mit dem IC
nicht."

???

Und wo steht das ?

Beide Funktionen haben doch ihre eigenen Bits und Register.


Peter

von emax (Gast)


Lesenswert?

Im Handbuch steht:

"Timer/Counter1 can also be used as an 8-, 9- or 10-bit Pulse Width
Modulator. In this mode the counter and the OCR1A/OCR1B registers serve
as a dual glitch-free standalone PWM with centered pulses."

Ich verstehe "in this mode" so, dass man nur eine von beiden
Betriebsarten zur gleichen Zeit nutzen kann? Korrigiert mich, wenn das
falsch ist.

Aber auch wenn man beides gleichzeitig nutzen kann: Der Timer kann
nicht mit zwei verschiedenen Geschwindikeiten gleichzeitig laufen.  Ist
es nicht so, dass ich dann mit Timer1 zwangsweise den Vorteiler
benutzen muss, den ich für die PWM eingestell habe?

Im Handbuch steht für die 8Bit PWM Ftck/510, für 9Bit Ftck/1022 und für
10Bit Ftck/2046

Allerdings ist mir nicht so ganz klar, welche Frequenz nun Ftck ist -
wenn ich es richtig verstanden habe, dann ist das bereits eine
vorgeteilte Frequenz.

Wie könnte sowas denn aussehen?

von Axel Rühl (Gast)


Lesenswert?

Hi Leute,

...Zitat

den unteren Bereich habe ich gedehnt.
Ich hab's ja gut: mein Meag8 hat zwei PWM-Kanäle (timer0), die kann
ich direkt auf die N-MOSFET's packen.

...Zitat ende

muss natürlich (timer1) heißen, sorry.

Axel

von Henning (Gast)


Lesenswert?

das mit dem vorteiler (bei 2 Funktionen 1 Timer) kann man noch
ausgleichen, aber der Tackt der fernsteuerung (wann die Hi flanke
kommt) ist nicht die selbe wie die des PWM timers. ausserdem zählt der
PWM hoch und wieder runter, was das wohl so umständlich macht, das mans
auch lassen kann und gar per polling die impulse messen könnte.

zu den fets gibt´s (nich brandaktuelle aber ganz gute) infos bei
www.nessel.info

hat sich schonmal jemand bei den Brushless Motoren versucht? Gibt nen
selbstbau projekt Speedy-BL aber den kann man nur als bausatz kaufen
für ~75Euro. http://www.megra-elektronik.de/html/speedy_bl.html

von Peter D. (peda)


Lesenswert?

@Emax,

hast recht, der T1 wechselt im PWM-Mode ständig die Richtung und damit
ist dann die Capture-Funktion witzlos.


Peter

von Uwe (Gast)


Lesenswert?

Hi!
Du kannst schreiben was du willst, ich finde die von dir erwähnte Zeile
nicht.Bei mir steht:

Bit 0 - TOV0: Timer/Counter0 Overflow Flag
The bit TOV0 is set (one) when an overflow occurs in Timer/Counter0.
TOV0 is cleared by hardware when executing the
corresponding interrupt handling vector. Alternatively, TOV0 is cleared
by writing a logic one to the flag. When the SREG Ibit,
and TOIE0 (Timer/Counter0 Overflow Interrupt Enable), and TOV0 are set
(one), the Timer/Counter0 Overflow interrupt
is executed.

Entweder habe ich ein anderes Manual oder ich bin zu blöde es zu
finden.Eigentlich ist es ja auch unsinnig mit PWM in T1 das TOV0 zu
setzen. das versaut ja einen ganzen Timer.
Ich vermute mal einen Manual-Bug.

MFG Uwe

von emax (Gast)


Lesenswert?

Original Atmel-PDF:

http://www.atmel.com/dyn/resources/prod_documents/DOC1041.PDF

Seite 28 unten, Absatz "Bit 0-TOV0".

von Henning (Gast)


Lesenswert?

ok, es steht da, aber der absatz ist fast exakt gleich mit dem 2 höher:
Handbuchfehler.

in meinem buch AVR-risc mikrocontroller steht es nich (muss aber ja nix
heissen).

trotzdem währe die funktion unlogisch... probier´s doch mal in avr
studio aus, da wird man das sicherlich bestätigt finden.

von emax (Gast)


Lesenswert?

Das werd ich wohl auch machen.

Was mich verunsichert hatte war, dass dieser Text auch im ATMega128-PDF
so drin steht.

Allerdings habe ich die Errata noch nicht konsultiert, auf die Idee
komme ich grade eben...

von Uwe (Gast)


Lesenswert?

Hi!
Das ist tatsache ein anderes Manual un ich behaupte das ist ein
Schreibfehler. Der selbe Satz steht ja auch bei TOV1.
Noch deutlicher wird es wenn man sich das Blockdiagramm T1 anschaut.
Ganz deutlich wird es auf Seite 42 unter Tab 16:

In PWM mode, the Timer Overflow Flag1 (TOV1) is set when the counter
advances from $0000. Timer Overflow Interrupt1 operates exactly as in
normal Timer/Counter mode,i.e., it is executed when TOV1 is set,
provided that Timer Overflow Interrupt1 and global interrupts are
enabled. This also applies to the Timer Output Compare1 flags and
interrupts.

Wäre ja auch Mist wenn ich mir T0 mit T1 versaue!

MFG Uwe

von emax (Gast)


Lesenswert?

Woher hast Du denn Deins? Vielleicht lad ich mir das auch runter?

Schau doch mal nach dem Auflage-Datum oder so.

Vielleicht sind im ATMEL-PDF noch mehr Bugs.

von Uwe (Gast)


Lesenswert?

Hi!
Auflage? Das einzige was ich finde ist: Rev 1041A-05/96. Es ist also
schon recht alt und den Namen habe ich natürlich geändert.
Da aber 2,6MB, ist es als Anhang leider zu gross.

MFG Uwe

von emax (Gast)


Lesenswert?

Na ist nicht weiter schlimm. Ist ja wohl auch ein Atmel-Pdf, die
Revisionsnr. ist genauso aufgebaut. Bei mir steht

Rev. 1041H 11/01

drauf. Also neuer, dafür MIT Fehler ...

Gut zu wissen, dass man die Handbücher ruhig auch mal in Frage stellen
kann.

bis denne
e.

von Axel Rühl (Gast)


Lesenswert?

Hi leutz, hi emax,

ich gehe nochmal ein Stück zurück, emax schrieb:

--schnnipp

else        // we are at falling edge
    {
      Pulse =  OverFlows * 256  + TCNT0;
      SET_INT1_RISING_EDGE();       // set int1 to rising edge
    }
--schnipp ende

wenn du den Timer nun ohne vorteiler laufen lassen würdest, kommen
deine overflows in den zeitbereich hinein, wie jetzt deine tcnt0 takte
kommen. die TCNT0-Takte beachte ich garnicht!! du brauchst also dann
nur die overflows zählen. Ein Overflow mehr oder weniger, ist egal,
merkt kein mensch. nimmst du die overflows mal 256, da fällts dann
schon auf.
Oder du lässt den Vorteiler auf 8, um dann ,wie du ja schon geschrieben
hast, mikrosekundenimpulse hast.
von 0.8ms bis 2ms sind's 1200us. Der Knüppel in Mittelstellung liegt
bei -sagen wir- 1450us, dann hast du 650 Stufen nach hinten und
550Stufen nach vorn. Viiel zu viele! Stell deinen Timer, wie ich, auf
10us, dann kommt das besser: 55 Stufen nach vorn und 65 nach hinten.
hängt ja immer vom Trimming des Knüppels ab. KOmmt ja noch der
Totbreich von +-5 Stufen rein. Dann passt das. eine 8Bit-PWM im
Fastpwm-Mode, und eine kleine Tabelle im Flash zum zuordnen der
Beschleunigungswerte. Die Motorleistung steigt sonst nicht linear,
sondern Quadratisch an, wenn man keine Tabelle nimmt. Fährt sich eher
doof.

den timer1 lasse ich, wie gesagt, im fast-pwm mode laufen. er zählt
also nur nach oben. Darüber habe ich mir aber auch überhaupt keine
Gedanken gemacht. die Motorfrequenz kann ich zwar nur grob über den
Prescaler vom Timer1 einstellen, kommt aber genau hin, hab'szwar nicht
gemessen, aber der Motor pfeift vor sich hin (3-4Khz?).

Grüße aus Potsdam
AxelR

Auf die Manual-Diskussion gehe ich mal nicht ein, man weiss doch, was
man macht. die Registerdefinitionen sind doch logisch angelegt, naja...

von emax (Gast)


Lesenswert?

Mit den Fahrstufen hast Du völlig recht, es sind natürlich viel zu
viele.

Aber ich wollte einfach mal das Machbare testen, und das Ergebnis ist
erstaunlich:

Ich kann (immer mit 8MHz Clock) 4Khz bei 10Bit, 8KHz bei 9 Bit und
16KHz bei 8 Bit Auflösung realisieren.

D.h, ich kann eine Schaltfrequenz z.B. von 16KHz fahren (genau sind es
8MHz/510 = 15,68KHz), und dabei immer noch 256 Fahrstufen
unterscheiden, das ist enorm.

Ausserdem betreibe ich nebenher (auf dem Entwqicklungsboard) noch noch
mein HD44780 und die Dekodierung der Fernbedienung, weil ich damit zu
Testzwecken alle möglichen Bits interaktiv ein und ausschalten kann,
und zeige die Ergbenisse noch als Klartext an.

Dabei ist der Prozessor hauptsächlich immer noch gelangweilt. PWM ist
echt ne dolle Sache. Hardware ist eben nur durch Hardware zu ersetzen,
genau wie der Hubraum beim Auto.

Was heisst das für mein Projekt?

Dass ich mir genau das gleiche überlegt habe wie Du: das Ding ist
Overpowered. Deshalb kann ich das ganze sicher mit viel langsamerer
Clock fahren, und so auch noch Strom sparen (und der ist bei z.B.
Flugreglern ein echtes Thema).

Ich muss mal nachsehen welche AVRs auch mit internem Quarz -1MHz wird
reichen- betrieben werden können, da spart man dann gleich wieder ein
paar Bauteile ein.

Zu lösen ist jetzt noch die Frage der Nullpunktprogrammierung und die
MIN/MAX Erkennung der Empfänger-Impulse.

von Axel Rühl (Gast)


Lesenswert?

MIN/MAX? huups hab ich garnicht, wohl vergessen...

von emax (Gast)


Lesenswert?

Hm, weiss nicht, ob mans unbedingt braucht, aber ich nehme nicht an,
dass alle Fernsteuerungen exakt gleiche Impulslängen liefern. Und das
Ding soll ja universell funktionieren.

Auch die Nullpunkteinstellung möchte ich "intelligent" machen. Nicht
fix im Programm, sondern Benutzer-einstellbar. Der kann dann selber
entscheiden, wieviel Rückärts und wieviel Vorwärts-Regelweg er hat.

Muss ich noch ein bischen drüber grübeln. Vielleicht mit Jumper, oder
aber auch mit einer bestimmten Steuerknüppel-Sequenz....

Es gibt noch mehr Gimmicks, die man machen kann: SENDER AUS/MOTOR AUS,
zum Beipiel. Oder Überlastschutz bei zu hoehen Strömen (blockierte
Räder, oder im Schlamm eingegrabener Propeller). Die Strombegrenzung
könnte man auch wiederum Benutzer-programmierbar machen, z.B.
Abschaltung nach 3 Sekunden, oder Abschaltung bei mehr als 30 Ampere,
oder beides: 30 Ampere für nicht mehr als 3 Sekunden ....

Ausserdem kann man noch eine Spannungsüberwachung für die Akkus
einbauen: wenn die Spoannung unter 5,5 Volt sinkt, liesse sich die
Leistung des Motors soweit reduzieren, dass wieder genug Spannung für
Servos etc. vorhanden ist.

Ach ich hab noch viele Ideen....

Man kann sich an so was "trivialem" wie eine Fahrtregler schon ganz
schön verausgaben...

e.

von Axel Rühl (Gast)


Lesenswert?

@emax:
naa, weitergekommen mit deinem Vorhaben?
ICh muss jetzt tatsächlich Min und max ermitteln, die fahrstufen
dynamisch im SRAM linear oder logaritmisch verteilen und vorhalten,
keine Ahnung, wie ich das machen soll. Ich will doch keinen Setup-Knopf
anbauen. Ausserdem habe ich keine Idee, wie die Formel aussehen muss.

max-min/anzahl der fahrstufen= schrittweite

Motorpower = schrittweite* messwert der letzten Pulsmessung.

oder wie?

Gruß
Axel

von emax (Gast)


Lesenswert?

Hi Axel,

> ICh muss jetzt tatsächlich Min und max ermitteln

wie kommts denn? Bislang warst Du doch auch ohne zufrieden?

Ich hab' mein Projekt ein ganzes Stück weiter gebracht, im Moment
liegt es aber auf Eis - zuviel anderes zu tun.

Min/Max-Ermittlung - das ist ein ziemlich wüstes Thema gewesen. Genau
wie Du wollte ich ja keinen Setup-Knopf oder sowas haben. Deshalb hab
ich mir einfach mal angesehen, wie die "grossen" Hersteller das
machen. Und siehe da - die kochen auch nur mit Wasser: Die ermitteln
hierzu aus den "Benutzereingaben", was passieren soll, und zwar mit
dem Steuerknüppel.

Ich hab' das so gelöst:

1. beim Einschalten mach ich erst mal gar nix: könnte ja ein Versehen
sein, und deshalb wird der Motor nicht hochgefahren.
2. nun warte ich zu allererst auf ein Sendesignal. Bis dahin ist
weiterhin Ruhe.
3. Wenn das da ist, dan warte ich, bis der Knüppel überhaupt mal für
"längere Zeit"  bewegt wird, bis dahin passiert also immer noch nix.
4. Wenn endlich eine Signaländerung eintritt, dann werden eine Reihe
von Entscheidungen getroffen:
  a) Ist im eeprom eine gültige Konfiguration ? Wenn ja, dann nimm die
als Grundlage für die Ermittlung des Steuerknüppelzustandes.
  b) wenn nicht, dann wird alles unter 1,3ms als NULL/Neutral und alles
über 1,6ms als EINS angenommen. Ausserdem gehe ich in diesem Falls
zwangsweise ins Setup.
5. Auf Grund der unter Punkt 4 getätigten Entscheidungen kann ich nun
feststellen: Gibt der User NULL-Gas? Dann gehts los - normaler
Fahrtreglerbetrieb. Gibt der User Vollgas (Stellung EINS) - dann ist
das Setup aufzurufen.

Warum das Ganze? Weil so sichergestellt ist, dass bei versehentlichem
Vollgas kein Unheil geschieht. Der User MUSS für Normalbetrieb zuerst
mal auf Leerlauf gehen. Oder, wenn er beim Einschalten schon auf NULL
war, mindestens ein mal "kurz" auf EINS und dann auf NULL gehen. Ich
nehme als Feedback eine LED, die blinkt je nach Zustand meiner
"Statemachine" unterschiedlich schnell und oft auf. Geht der User
also ins Setup, dann blinkt die LED schnell. Geht er versehentlich ins
Setup, dann geht mein Regler nach 8 Sekunden ohne
Steuerknüppel-Kommando automatisch in den Normalzustand, und wartet auf
NULL-Stellung (wieder anderes Blinken der LED)

Diese Zustände (NULL oder EINS) müssen natürlich über einen gewissen
Zeitraum anliegen - eine oder mehrere Sekunden - damit macht man die
Sache ruhiger und sicherer, auch bei Fehlsignalen.

Im Setup passieren nun die komplizierteren Sachen.

1. muss man sich eine Art "Dialog" ausdenken, der nur durch NULL und
EINS - Knüppelstellungen und die LED stattfindet: der User macht
Eingaben (z.B: 0,0,1 - Knüppel auf NULL/MITTE/NULL/MITTE/EINS/MITTE),
und man reagiert darauf. Als Bestätigung blinkt die LED unterschiedlich
oft oder lang.

2. muss man sich ein Timing überlegen, innerhalb dessen der User diese
Eingaben machen kann oder muss.

3. Man braucht auch ein ENDE Kommando, also z.B. 1,1,1 (Knüppel drei
Mal auf EINS und wieder in die Mitte.

Jedes dieser "Kommandos" entspricht einem Befehl. Z.B.:

001 - Strombegrenzung eingeben
010 - Nullstellung festlegen
011 - Schaltfrequenz festlegen
100 - MIN und MAX ermitteln
usw...
111 - Ende und Speichern

Gibt der User nun 010 ein, also "Nullstellung festlegen", dann blinkt
die LED schnell, und die Software wartet, bis der Steuerknüppel sich
z.B. 2 Sekunden lang nicht mehr bewegt (plus-minus Toleranz von z.B.
xyz-Mikrosekunden oder xyz-Prozent). Der User kann also in Ruhe seine
Position festlegen. Hat er das endlich getan, so leuchtet als
Bestätigung die LED beständig für sagen wir 4 Sekunden, und man
speichert die ermittelte Knüppelstellung als neuen Leerlaufwert.

Und so gehts weiter für alle Werte.

Wenn der User sich unsicher ist, und abbrechen will, so drückt er Reset
oder schaltet aus. Anderfalls kann er mit 1,1,1 bestätigen, und alles
wird im Eeprom gespeichert.

Alles in allem ziemlich aufwändig. In meiner Version nimmt alleine die
Setup-Routine mit den Knnüppel-Abfragen 80% des Programms in Anspruch -
und ich bin mit den "Feeling" für den User immer noch nicht
zufrieden....

Einfacherer Weg: Setup über serielle und PC. Nur hat den auf dem
Flugfeld keiner dabei.

Kontronik (glaube ich) gibt Rückmeldungen nicht über eine LED, sondern
lässt als Antwort den Motor "brummen" (vibrieren), was ich allerdings
für Blödsinn halte: erstens hat man vielleicht gerade gar keinen Motor
dran, und zweitens hört man's nicht, wenn nebenan gerade einer an
seinem OS-MAX die Vollgasstellung sucht.

Du brauchst vor allem ein paar Routinen, die verlässlich die
Knüppelaktivitäten feststellen

- warte, bis Knüppel für n Zehntelsekunden stillsteht
- warte, bis Knüppel sich mindestens n Zehntelsekunden lang bewegt

usw.

Wenn Du nun MIN und MAX auf diese Art ermittelt hast, und ausserdem die
Null-Stellung (Leerlauf) kennst, dann musst Du Dir überlegen, was Du
damit anstellst. Soll heissen, Du musst Dir einfach überlegen, wie
Deine Software mit diesen Werten umgeht. Ich selber hab mir ein
Excel-Sheet gebastelt, in dem ich meine Steuerroutine simuliere.

Und warum das Ganze? Weil ich im Programm keinesfalls mit
Float-Variablen arbeiten wollte (viel zu langsam), sondern alles mit
Integern gelöst habe. Also alles in Excel mit INT(Wert) verarbeiten. Du
wirst dann ziemlich schnell feststellen, wie bockig deine Regelei wird,
weil sie nicht genau genug ist - es geht einfach zuviel verloren. Ein
Beispiel:

Sechs geteilt durch sieben ist schlicht NULL - wenn mans in Integern
macht. Dabei müsste es eigentlich etwa 0,86 sein, was eben 86 Prozent
(von irgendwas) wären.

Was also tun? Die Antwort heisst: Skalieren .....

Soll heissen: 60/7 ist (in Integern) immerhin schon 8. Also wesentlich
genauer. Und wenn man ein bischen nachdenkt, und seine Skalierungen
richtig wählt (immer an den Wertebereich denken :-)), dann kann man
auch mit Integern saumässig genau werden. Ich habs auf 0,5 Prozent
Rechen-Genauigkeit gebracht, und dabei nur schnelle
Integer-Berechnungen gewählt. Im Beispiel "60/7" würde ich
kaufmännisch runden, und auf die "60" zum Beispiel 5 draufaddieren:
65/7 .... und siehe da: das ergibt 9, was exakt kaufmännischer Rundung
entspricht, und damit genauer ist. Achja: gerundet wird IMMER NUR AM
SCHLUSS ...

Das ganze ist (immer) ein ziemlich aufwändiger Prozess, aber er führt
zu sehr grundsätzlichen Erkenntnissen der µP-Programmierung.

In meinem Programm gebe ich zur Kontrolle alles auf mein LCD-Display
aus. Die Knüppelstellung, die Millisekunden, den prozentualen Vorwärts-
oder Rückwärts-Gasweg usw.

Erst dann, wenn Du diese Werte richtig ermitteln kannst, ist es
sinnvoll, an eine Regel-Kurve zu denken. Und ob die nun linear oder
logarithmisch ist, ist völlig wurst: sie wird ohnehin als Zahlenreihe
im eeprom abgelegt - alles andere wäre zu langsam.

Diese Kurve zu ermitteln ist reine Erfahrungssache: wenn Deine Software
läuft, dann regel einfach mal linear drauflos (PWM natürlich), und Du
wirst schon selber merken, wo Du ab und zu geben musst. Dieses "ab und
zu geben" ist das, was die Hersteller als ihr KnowHow bezeichnen, und
dürfte bei Car-Reglern z.B. anders ausfallen, als bei Flugreglern.

Diese Abweichungen kannst Du nun in ein Array eintragen und fertig ist
deine Regelkurve. Macht halt a bisserl Arbeit ....

Wenns ganz super sein soll, dann kann man im Setup noch erlauben, aus
verschiedenen solchen Kurven auszuwählen (Car-Charakteristik, oder
Flugregler...), und ggf. noch eigene Mutliplikatoren festlegen lassen -
sagen wir mal "Rally" und "Omnibus" - Variante.

Das wär dann schon fast ne echte Kennfeld-Regelung, geil was? Tja, und
damit wären dann in der Marketingabteilung angelangt....

So, ich denke, da kannste jetzt erst mal verdauen.

Beste Grüsse
e.

von Axel Rühl (Gast)


Lesenswert?

mach ich, aber offline
danke erstmal
axel

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
Noch kein Account? Hier anmelden.