Timer nutzen beim ATmega16 für Stepper

Gast #682846
Lesenswert?

Hallo zusammen,

Ich hoffe, Ihr könnt mir weiterhelfen. Ich brauche einen sinnvollen 
Ansatz für mein Projekt:

Ich will den ATmega16 nutzen, um einen Stepper-Motor in ziemlich 
einfacher Betriebsart zu betreiben.

Ich brauche eigentlich "nur" eine Timer-Funktion, die folgende Features 
aufweist/zulässt:

- Ich drücke eine Taste, somit wird an einen Ausgang 6400 mal ein 
Rechtecksignal (ton/toff=1) ausgegeben und diese Schleife dann sofort 
beendet.
- Bei Betätigung einer anderen Taste wird der Puls am selben ausgang z. 
b. nur 1000 mal ausgegeben usw.

Ich habe nun das Datenblatt, das Tutorial usw. durchgearbeitet, 
anscheinend bin ich aber zu blöd.

Vielen Dank im Voraus.

Gruß

Tom
#682874
Lesenswert?

Na das klingt doch erst einmal recht einfach.
Ich nehme an du meinst einen Schrittmotor. Da solltest du dir als erstes 
einen Treiber bauen, der den entsprechenden Strom zur Verfügung stellt.
Anschließend brauchst du 4 Signalleitungen, die für die spezielle 
Ansteuerung der Phasen benötigt werden. Soweit die Hardware.

Software:

Du kannst mit deinem Taster einen beliebigen Port nehmen und diesen mit 
einer Endlosschleife abfragen lassen. Sinnvoller wäre den ext.Int. zu 
verwenden. In den Speicher musst du nun die benötigten Ansteuerwerte für 
Halb-,Viertel-Schritt,... hintereinander ablegen, die dann entsprechen 
oft durchlaufen und Ausgegeben werden.

Gruß Alexander
Gast #682880
Lesenswert?

Hallo Travel Rec.

erstmals vielen Dank für Deine schnelle Antwort. Anbei siehst Du einen 
kleinen Code.

Kannst Du mir hierzu kurz Hilfestellung bieten, wie ich diesen abändern 
muss, um meinem Ziel näher zu kommen?

Danke und Gruß

Tom




#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>

#define TAKT 8000000UL
#define TEILER 65535UL-(TAKT/4096UL)


typedef unsigned int uint16;
typedef signed int sint16;
typedef unsigned short uint8;
typedef signed short sint8;

uint16 step=0;

SIGNAL(SIG_OVERFLOW1)
{
  TCNT1 = TEILER;
  step++;
  PORTB = step;
}

int main (void)
{
  DDRB = 0x01;
  PORTB = step;
  TCNT1 = TEILER;
  TCCR1B = 0x05;
  TIMSK |= (1<<TOIE1);
  sei();
  while(1) {}
}
Gast #682886
Lesenswert?

Hallo Alexander,

Danke auch Dir für Deine Antwort.

Hardwareprobleme habe ich zum Glück keinerlei.

Ich benötige nur einen Code, der mir weiterhilft, bzw. auf den ich 
aufbauen kann. Ich brauche nur einen kurzen Anstoß, damit ich die 
Timer-Sache kapiere, dann kanns vermutlich losgehen.

Betreffend der Taster:
Ich will keine ext. Interrupts verwenden, sondern nur die Ports pollen.

Danke

Tom
#682910
Lesenswert?

Tom wrote:
> #include <avr/signal.h>
signal.h ist veraltet. Wenn noch nicht geschehen, installier am besten 
erstmal ne aktuelle Version von WINAVR/AVR-GCC+AVR-libc.

> typedef unsigned int uint16;
> typedef signed int sint16;
> typedef unsigned short uint8;
> typedef signed short sint8;
Und sowas sollte man auch nicht machen. Dafür gibts typedefs in der 
stdint.h. Die heißen dann uint16_t, uint8_t, int16_t und int8_t. Und das 
ist dann auch portierbar...

> SIGNAL(SIG_OVERFLOW1)
Zum Thema "SIGNAL" siehe oben.

> {
>   TCNT1 = TEILER;
>   step++;
>   PORTB = step;
> }
>
> int main (void)
> {
>   DDRB = 0x01;
>   PORTB = step;
>   TCNT1 = TEILER;
>   TCCR1B = 0x05;
>   TIMSK |= (1<<TOIE1);
>   sei();
>   while(1) {}
> }
Timer-Zählregister vorladen ist Murks. Sowas macht man beim AVR mit 
einer Compare-Einheit z.B. im CTC-Modus. Schau Dir Datenblatt und 
AVR-GCC-Tutorial daraufhin mal an.
#682914
Lesenswert?

OK. Bin auch bei ASM zu Haus. Aber logisch kann man ja mal rangehen.


Für den Timer-Int. benötigst du folgende Angaben:

TCCR1B --> Register für Taktvorteiler
TCNT1  --> Zählwert des Counters bis zum Überlauf
TIMSK  --> Interrupt Maske (Overflow_Int freigeben)

Also diese Register müssen zuerst beschrieben werden.

Die Interrupt-Routine existiert ja schon.

Du schaltest zu beginn den Overflow-Int. inaktiv und pollst deinen PORT.
Wird ein Wert  (also Tastendruck) am PORT registriert, beschreibst du 
ein Register mit dem Zählwert(Anzahl von Ausgangsimpulsen) und löscht 
den aktuellen Schritt ("step") . Dann wird die der Overflow_Int. 
aktiviert.
Die Schleife dafür ist vorhanden. Du vergleichst nun im Hauptprogramm 
ständig Ist und Soll, bis beide gleich sind. Anschließend wird der 
Overflow_Int deaktiviert und an den programmstart gesprungen.

Vielleicht hilf der grobe Ablauf ja weiter.
#682943
Lesenswert?

Ich würde die Sache trotzdem immer noch umdrehen, wie es weiter oben
schon mal angesprochen wurde.

Anstatt den Zähler hochzählen zu lassen, würde ich ihn von
einem Startwert bis auf 0 herunterzählen lassen. Auf lange Sicht
gesehen funktioniert das meist besser unter anderem auch deshalb,
weil dann Änderungen im Zielwert leichter (mit weniger Code)
durchführbar sind, wenn im Zähler immer die Anzahl der noch
ausständigen Schritte enthalten ist. Auch ist das Beenden
der ganzen Zählerei (Notstop) einfacher möglich: Einfach den
Zähler auf 0 setzen und gut ists (Alles klar: Ein Notaus
sollte immer mit Hardware realisiert werden, es schadet aber
nichts, wenn die Software dafür auch eine einfache Möglichkeit
hat).
1
uint16_t StepsLeft;
2

3
ISR( .... )
4
{
5
  if( StepsLeft > 0 ) {
6
    ... Hardwareschritt ausführen
7
    StepsLeft--;
8
  }
9
}
10

11
int main()
12
{
13
  ....
14

15
  while( 1 ) {
16
    if( PINxx & ( 1 << irgendwas ) ) {  // das Polling der Taste
17
      cli();
18
      StepsLeft = 10000;
19
      sei();
20
    }
21

22
    if( PINxx & ( 1 << irgendwasanderes ) ) { // Polling der 2.ten Taste
23
      cli();
24
      StepsLeft = 3000;
25
      sei();
26
    }
27

28
    if( PINxx & ( 1 << nochwasanderes ) ) {   // sofort abschalten
29
      cli();
30
      StepsLeft = 0;
31
      sei();
32
    }
33
  }
34
}

Zum Thema Tasten-polling:
Keine gute Idee. Taster sind notorische Preller. Die Entprellroutine
von PeDa (Artikelsuche benutzen) ist die Ideallösung für die
Auswertung von Tasten. Was anderes braucht man nicht um eine 100%
funktionierende, zufriedenstellende, problemlose Lösung zu bekommen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren