Forum: Mikrocontroller und Digitale Elektronik Atmega128 in Simulationen Arschlahm Lieber im Vorfeld auf ARM7 umsteigen?


von Cagara (Gast)


Lesenswert?

Hallo,

Im moment setze ich in einer Simulation einen Atmega128 ein der ein 
Rotary Encoder in einer Schleife abfragt um dann einen Counter hoch bzw 
runterzuzählen, je nach Drehrichtung versteht sich.

Doch der Atmega128 scheint jetzt schon überfordert zu sein ... Statt 
dass alles zackzack geht braucht er 1 Sekunde für das Abfragens der PINS 
(wo der Encoder dranhängt)

Eigentlich kaum zu fassen, aber ich möchte einen Flüssigen Drehregler 
haben und keinen der nur einmal pro Sekunde hochzählt.



Ich überlege mir daher direkt zu einem ARM7 (LPC2138) zu wechseln ...
Kann ich damit eventuell ein "Flüssiges" am Drehregler-Drehen 
implementieren?

Danke im Voraus und liebe Grüße

von Timmo H. (masterfx)


Lesenswert?

Der Simulator arbeitet natürlich nicht in Echtzeit. Schau doch mal Links 
auf den Cycle Counter!!! Jeder Takt dauert Counter/XTAL. Da stehen auch 
die us, allerdings stehen die glaub ich bei reiner Software Simulation 
auf 4MHz. Abfragen eines Pins sollte glaub ich nur 1-2 Takte dauern

von Cagara (Gast)


Lesenswert?

Naja also die Takte werden schon schnell simuliert.

Wenn ich ne Whileschleife mache die einfach nur den Counter hochzählt 
und auf dem LCD ausgibt schiesst der so schnell hoch, da kann ich nicht 
gucken!

Frage ich aber PortB ab und vergleiche mit der temporären Maske ab um 
rauszufinden ob der Drehregler links oder rechts gedreht wurde dauert 
das Ewig ... An die 5 Sekunden habe ich gerade gestoppt.

von Stefan E. (sternst)


Lesenswert?

Wie kommst du darauf, dass die Zeit, die die Simlation benötig, 
irgendetwas mit der Laufzeit zu tun hat? Du gehst doch nicht etwa davon 
aus, dass die Simulation in Echtzeit stattfindet, oder? Im Simulator 
(wlcher überhaupt?) findest du sicher auch eine Anzeige der Laufzeit 
oder der Taktzyklen. Die ist relevant, und nicht die Zeit, die während 
der Simulation auf deiner Uhr vergeht.

von Matthias L. (Gast)


Lesenswert?

Poste doch mal den Quellcode, den du simulierst.


>geht braucht er 1 Sekunde für das Abfragens der PINS
Das ist nämlich unsinn. Die reine Abfrage dauert 2Prozessortakte. Oder 
steht dieser auf 1Hz?

von Cagara (Gast)


Lesenswert?

Der ISIS Simulator der bei Proteus dabei ist.
Ja Simulatorzeit wird angezeigt und hinkt nur Minimal der 
Realen-Laufzeit hinterher.

Ich würde sagen der Simulator ist nur 5-10% langsamer als Echtzeit!

von Stefan E. (sternst)


Lesenswert?

Cagara wrote:

> Ich würde sagen der Simulator ist nur 5-10% langsamer als Echtzeit!

Immer? Hast du das ganz konkret mit der Laufzeit/Zyklen-Anzeige 
verglichen?

von Frank N. (arm-fan)


Lesenswert?

Nein, der ARM7 kann das auch nur in 0.58 Sekunden erledigen.
IMHO würde ich gleich auf die neue ATOM Plattform setzen.

SCNR!

von Cagara (Gast)


Lesenswert?

Also hier schonmal der simple Code:


Zwar funktionieren die Messungen rein garnicht, aber ich habe einen 
kleinen "Zykluscounter" und der steigt nur 1 mal die Sekunde ... Nehme 
ich die Port abfrage raus gehts super super flott.


Und zum Letzten Beitrag ... Ein Billig-China-Radio mit Drehtuner kriegt 
das doch auch hin, dass man flüssig die Frequenz Zurechtdrehen kann ... 
OHNE Atom Platform :)



#define ENCODER PINB
#define CHANNEL_A 2 // Encoder 'A' channel input
#define CHANNEL_B 3 // Encoder 'B' channel input
#define CHANNEL_MASK ((1<<CHANNEL_A) | (1<<CHANNEL_B))
#define DIR_LED 7   // Encoder direction bit

unsigned char EncoderCurrent;
unsigned char EncoderLast = 0;
unsigned char EncoderIndex = 0;
char EncoderCount = 0;
const char ENCODER_STATE[] = {0x04, 0x0C, 0x08, 0x00};


unsigned char I_O_Debounce(unsigned char Port, unsigned char Bit) {
         static unsigned char LastKey;
         unsigned int DebounceCount = 0;

         do {
            if ( LastKey != (Port & Bit) )
               DebounceCount = 0;

            LastKey = Port & Bit;
         } while (DebounceCount-- != 100);

         return (~LastKey & Bit); // Negated for use with the 
STK500/STK600
}


int main(){


// Initialize Display
glcd_setup();
glcd_init();
glcd_clear_text();

int Counter=0;
int zyk=0;
 do {
        // Assuming the encoder is connected to PORTD
        EncoderCurrent = I_O_Debounce(ENCODER, CHANNEL_MASK);
        if (EncoderLast != EncoderCurrent) {
           if ((EncoderCurrent & CHANNEL_MASK) == 
ENCODER_STATE[EncoderIndex]) { // Encoder forward direction
              EncoderIndex = ++EncoderIndex & 0x03;
             Counter--;
           }
           else { // Encoder reverse direction
                EncoderIndex = --EncoderIndex & 0x03;
               Counter++;
           }
           EncoderLast = EncoderCurrent;
        }
    zyk++;
    PrintFrequency(Counter,zyk);
     }

   while(1);





}

von Cagara (Gast)


Lesenswert?

Der korrektheit halber muss ich sagen dass ich den Code von
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62118&start=20

zurechtgecopy-pasted hab!

von Peter Diener (Gast)


Lesenswert?

Hallo,

einen Drehencoder sauber auszuwerten, ist mit einem AVR mühelos möglich, 
auch während in Echtzeit richtig aufwändige andere Sachen drauf laufen.

Ich gehe davon aus, dass es sich nur um einen Drehknopf handelt, nicht 
etwa um einen hochdrehenden Spindelencoder von einer Fräsmaschine mit 
2048 Counts pro Umdrehung.

Vergiss einfach den Simulator, programmier es interruptgesteuert und es 
funktioniert.

Pin1 löst Interrupt aus und dort wird geprüft, ob Pin2 gesetzt ist. 
Fertig. Schalterentprellung am besten in Hardware.

Viele Grüße,

Peter

von Cagara (Gast)


Lesenswert?

Schalterentprellung?

Wäre lieb wenn du mir kurz zeigen oder sagen könntest wie man einen 
solchen Intterupt / Callback auf einen Pin setzt!

Und ja: Ist ein ganz simpler Drehschalter, da ich aber gerade erste 
Versuche in sachen AVR mache und ein bisschen Experimentiere fehlt mir 
natürlich jetzt die Info mit dem Interrupt!

von Michael G. (linuxgeek) Benutzerseite


Lesenswert?

Cagara wrote:
> Hallo,
>
> Im moment setze ich in einer Simulation einen Atmega128 ein der ein
> Rotary Encoder in einer Schleife abfragt um dann einen Counter hoch bzw
> runterzuzählen, je nach Drehrichtung versteht sich.
>
> Doch der Atmega128 scheint jetzt schon überfordert zu sein ...

Mit Sicherheit nicht.
Wenn Du die Sache dann noch richtig programmierst funktioniert das auch 
und kostet fast garnichts an Rechenzeit.

von Peter Diener (Gast)


Lesenswert?

Hallo,

du setzt so wie es im Datenbatt des Controllers gezeigt ist, die Special 
function Register. Damit aktivierst du einen Interrupt auf einem der 
Pins an denen der Drehknopf hängt und stellst die Flanke entsprechend 
deiner Schaltung ein. Fallend oder steigend, je nachdem ob die Schalter 
nach Vcc oder Gnd ziehen. Dann gibst du den Pin Interrupt drei und gibst 
den global interrupt enable frei.

Jetzt brauchst du eine Interruptroutine, die aufgerufen werden kann, 
wenn der Interrupt auftritt. Wie das geht, steht im libc manual des gcc 
compilers. Vergiss nicht, das Interruptflag am Ende der Interruptroutine 
zurückzusetzten, sonst kommt er von alleine immer wieder.

In der Interruptroutine kannst du dann den Status des anderen Pin 
auswerten. Je nach dem, ob high oder low ist ein rechts oder links Tick 
aufgetreten.

Du musst jede Variable, die sowohl im Interrupt als auch im 
Hauptprogramm verwendet wird als volatile deklarieren.

Natürlich muss einer der Schalter auch an einem Interruptfähigen Pin 
angeschlossen sein.

Viele Grüße,

Peter

von Matthias L. (Gast)


Lesenswert?

Streiche mal folgende Zeile aus dem Quellcode und simuliere nochmal:
1
PrintFrequency(Counter,zyk);


>Wie das geht, steht im libc manual des gcc compilers. Vergiss nicht, das 
>Interruptflag am Ende der Interruptroutine zurückzusetzten, sonst kommt er >von 
alleine immer wieder.

Das liegt nicht am µC, sondern an der fehlenden Entprellung !
Eine solche Abfrage macht man nicht mit Interrupts!
Besagtes Bit wird vom µC automatisch beim Anspringen der ISR gelöscht!

>Pin1 löst Interrupt aus und dort wird geprüft, ob Pin2 gesetzt ist.
>Fertig. Schalterentprellung am besten in Hardware.

Ich erwarte demnächst eine ganz bestimmte Antwort eines ganz bestimmten 
Mitredners ;-)

von Peter Diener (Gast)


Lesenswert?

Hallo,

meine Antwort bezog sich nicht auf das Programm von oben, sondern auf 
ein neues. Das Rücksetzen des Interruptflags habe ich mit einem anderen 
Prozessor verwechselt. Es würde aber auch nicht schaden, es zu clearen. 
Aber du hast an dieser Stelle natürlich Recht.

Und eine Abfrage von einem Drehencoder macht man immer mit einem 
Interrupt, es sei denn, man möchte seine Rechenleistung vergeuden. Eine 
Lösung ohne Interrupt funktioniert mit Programmzykluszeiten von 500µs 
und abwärts vernünfig. Dann  macht der Controller aber wirklich nichts 
anderes mehr.

Das kann man mal machen, wenn man nur seinen Encoder testen will, aber 
wenn der Prozessor noch andere Sachen erlegigen soll, ist das extrem 
kontraproduktiv, gerade beim ATMEGA128 mit 8 (?) Hardwareinterrupts.

Dass er eine Entprellung braucht, habe ich doch erwähnt. Diese in 
Software zu lösen, ist jedoch bei Auslösen von Interrupts 
kontraproduktiv. Natürlich trotzdem möglich.

Ich verstehe nicht, warum ihr unbedingt den obigen Code umbauen wollt, 
das geht neu programmiert 10 mal schneller.

Peter

von Matthias L. (Gast)


Lesenswert?

>Und eine Abfrage von einem Drehencoder macht man immer mit einem Interrupt

>>Ich erwarte demnächst eine ganz bestimmte Antwort eines ganz bestimmten
>>Mitredners ;-)

von Peter Diener (Gast)


Lesenswert?

Hallo,

was soll der Unsinn?
Ich hab sowas schon programmiert, du auch?
Probier doch mal eine Version ohne Interrupts, wenn nebenher ein 
Phasenanschnitt für einen Drehstromthyristorsteller, ein Grafik-LCD mit 
Touchpanel, eine Temperaturregelung auf 1mK genau und dafür 3 PID Regler 
in Floatingpoitarithmetik laufen!

Dein Kunde wird dir dein Gerät um die Ohren hauen, weil es bescheiden 
auf den Drehknopf reagiert, wenn er was verstellen will.
Natürlich kannst du damit die immer gewünschte Stellbeschleunigung bei 
schnellem Drehen auch nicht.

Und jetzt erwarte ich eine Antwort. Und eine funktionsfähigen Code.

von Peter D. (peda)


Lesenswert?

Cagara wrote:
> Wenn ich ne Whileschleife mache die einfach nur den Counter hochzählt
> und auf dem LCD ausgibt schiesst der so schnell hoch, da kann ich nicht
> gucken!

Soso und das soll also am Drehgeber liegen?

1. Wie lange braucht denn das LCD alleine?
2. Muß ein LCD überhaupt schnell sein, weil ja jeder Mensch eine Million 
Werte pro Sekunde ablesen kann?

Hint: Ergonomisch sind 2..5 Werte, dann ist der Mensch am Anschlag.


Bezüglich Drehgeber:

Beitrag "Drehgeber/Encoder 1-, 2- oder 4-schrittig"


Peter

von Matthias L. (Gast)


Lesenswert?

>Ich hab sowas schon programmiert, du auch?

Ja. Da wir ja nur von Hand-Encodern reden. Diese haben ja bekanntlich 
relativ geringe Auflösungen und geringe Drehzahlen, gegenüber Drehgebern 
der Industrie.

Also :

Jede (µC) Applikation benötigt eine (konstante) Zeitbasis, resp. einen 
Timer.
Somit gibt es immer einen freilaufenden TImer (meist Null), der zB im 
ein oder zehn Millisekunden Takt überläuft und somit einen INT auslöst.

Innerhalb dieses INTs, werden die beiden Spuren eingelesen, und zB nach 
4Q-Manier ausgewertet. Es wird geprüft, ob der Encoder einen korrekten 
Sprung (nach Gray-Code) ausgeführt hat, wenn ja, Wert erhöhen, 
verkleinern.
/Somit entsteht, unabhängig vom Encoder eine konstante niedrige 
µC-Last./

Was passiert denn bei INT-gesteuerter Abfrage, wenn der Encoder prellt 
oder um eine Position pendelt? Da bläst du den µC mit INTs zu.

>Natürlich kannst du damit die immer gewünschte Stellbeschleunigung bei
>schnellem Drehen auch nicht.
Die habe ich noch nicht reingebracht, aber warum sollte die hier nicht 
gehen?

>Ich erwarte demnächst eine ganz bestimmte Antwort eines ganz bestimmten
>Mitredners ;-)
Gut, dann mach ich das mal.
klick mal drauf, und lies das durch
Drehgeber

von Peter Diener (Gast)


Lesenswert?

Hallo,

diese Lösung ist auch ellegant, wenn man sich die Zeit im Timerinterrupt 
leisten kann.

Peter

von Peter D. (peda)


Lesenswert?

Peter Diener wrote:
> diese Lösung ist auch ellegant, wenn man sich die Zeit im Timerinterrupt
> leisten kann.

Ich wüßte jetz keine Anwendung, die an ~30 Zyklen (2µs) scheitert.

Man kann Timerinterrupts aber auch mit SEI am Anfang unterbrechbar 
machen, falls der unwarscheinliche Fall eintritt, daß schon 30 Zyklen 
stören.


Peter

von Matthias L. (Gast)


Lesenswert?

>Und jetzt erwarte ich eine Antwort. Und eine funktionsfähigen Code.
>diese Lösung ist auch ellegant, wenn man sich die Zeit im Timerinterrupt
>leisten kann.

Interessante Tonlagenänderung....

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.