www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer und Stepper, Bascom -> Hilfe


Autor: Manfred R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gemeinde,

ich glaub ich komm noch öfters... leider. Ich hab vor einer guten Woche 
angefangen mit mich einem atmega32 zu beschäftigen. Mein erstes Projekt 
soll eine Kamera für Langzeitaufnamhmen steuern. Zusätzlich zur 
Kamerasteuerung muss ein Schrittmotor für eine Nachführung gesteuert 
werden. Der Aufbau ist Hardwareseitig bis auf ein paar optimierungen 
abgeschlossen. Probleme bereiten mir jetzt allerdings Zeitkritische 
Programmabläufe. Bin leider nicht so der Bascom Held, da auch erst eine 
Woche.... naja, folgendes Problem:

Über ein Menü kann ich belichtungszeiten einstellen. Das was aus dem 
Menü ausgewählt wird, wird an eine Routine übergeben (Sekunden). Diese 
Routine löst die Kamera aus, und hält die Auslösung solange, bis die 
Zeit T vorüber ist. Und während dieser Zeit muss ein Motor um x Schritte 
kontinuirlich bewegt werden. Der Stepper macht 1,8°, also 200 Schritte. 
Bei einer Auslösezeit von 60 Sekunden soll der Stepper genau diese 200 
Schritte machen. Bei einer Auslösezeit von 1 Sekunde soll der Stepper 
genau 3.3333 Schritte machen.

Die Anzahl der Schritte habe ich noch gar nicht im griff, der Rest 
vermutlich auch nicht. Folgende Teile sind dabei relevant:

In main wird geprüft, ob an einer geiwssen Stelle Enter gedrückt wird 
(Menü für Belichtungszeiten):
  If Kp = Keye And Submnu(i) > 1300 And Submnu(i) < 1399 And Sekmnu = 0 Then
      T = Val(mnutext(i))
         Call Ausloesen(t)
      Return
   End If
Wenn wahr, werden die sekunden an die subrutine übergeben. Diese macht 
folgendes:
Sub Ausloesen(byval T As Word)

      Wartezeit = Val(sftime)
      If T = 999 Then
         Fokus = 1
         Waitms Wartezeit
         Ausloesung = 1
      End If
      If T < 999 Then
         Locate 1 , 1 : Lcd Chr(5) ; " mit " ; T ; " sek."
         Fokus = 1
         Waitms Wartezeit
         Ausloesung = 1
         Do
            Locate 2 , 1 : Lcd "                "
            Locate 2 , 1 : Lcd "Noch " ; T ; " sek."
            Gosub Tstq
            Call Vollschrittvor()
            T = T - 1
            If T = 0 Then
               Call Motoraus()
               Exit Do
            End If
         Loop Until Kp > 0
      End If
End Sub
Wenn Tastq aufgerufen wird, wird lediglich geprüft, ob eine Taste 
während der ausführung gedrückt wird. Der interessante Teil ist in do zu 
finden, und zwar Vollschrittvor():
Sub Vollschrittvor()
   For Sti = 1 To 4
      Incr Vollschrittindex
      If Vollschrittindex > 4 Then
         Vollschrittindex = 1
      End If
      A1 = Vollschrittarray(vollschrittindex).1
      B1 = Vollschrittarray(vollschrittindex).2
      A2 = Vollschrittarray(vollschrittindex).3
      B2 = Vollschrittarray(vollschrittindex).4
      Waitms 250
   Next Sti
End Sub
Vollschrittarray(vollschrittindex) beinhaltet die Matrix um den Motor zu 
steuern. Dummerweise benötige ich hier extrem exakte wait angaben, da 
das ding auch schonmal ne halbe stunde oder auch stunde laufen kann am 
stück.
Dummerweise macht der Motor jetzt noch zuviel schritte pro minute, weill 
ich die 4 Ports immer 4 mal unterschiedlich schalten muss, also pro 
impuls eigentlich 4 schritte mache... ich glaub ich hab mich da in was 
verrant, das muss doch anders und besser, vor allem genauer gehn? Wer 
noch mehr Infos braucht findet das ganze Programm in Anhang. Über die 
ein oder andere Hilfe würde ich mich sehr freuen.

Danke und Grüße
Manfred

Autor: Manfred R. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Attachment... sorry

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ich glaub ich hab mich da in was
> verrant, das muss doch anders und besser, vor allem genauer gehn?

Genau.
Dein Ansatz die Zeitsteuerung mit Waitms zu machen ist schon völlig 
falsch. Das führt zu nichts.

Was du brauchst ist sowas wie eine interne Uhr. Dazu kannst du einen 
Timer nehmen, der alle parr Zehntel-ms eine Interrupt Funktion aufruft. 
In dieser Funktion machst du dann die Dinge, die in einem Zeitschritt 
notwendig sind.

Also: zb wenn die Kamera auslösen soll und nach 50 ms wieder schliessen 
soll, dann
  wird beim Auslösen der Kamera ein Zähler auf 0 gesetzt

Deine 0.1 ms Interrupt Routine zählt den Zähler hoch und wenn der 500 
erreicht hat, sind 50 ms vergangen (weil 500 * 0.1 ja 50 ist) und die 
Interrupt Routine schliesst den Auslöser wieder.

Und genauso kann dann selbige Interrupt Routine alle (Hausnummer) 2 ms 
den Steppermotor weiterschalten. Auch dazu wird wieder ein Zähler 
benutzt und wenn der 20 erreicht hat, weiss die Interrupt Funktion, dass 
es Zeit ist den Steppermotor weiterzuschalten.

Autor: Manfred R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo KJarl Heinz,

vielen Dank für Deine ausführliche Antwort. Ich denke das ist so 
definitiv die richtige Spur und auf diese werde ich mich mal begeben.

Eine Frage dazu hätte ich noch. Multitasking gibt es so ja nicht, mit 
diesem extrem schnellen timer habe ich aber dennoch die möglichkeit viel 
schnell, und vorallem genau zu erledigen?! Also Quasi ein ganz anderer 
Ansatz als das Programm mit waitms zu unterbrechen... ich glaube das hab 
ich mir dann grad auch selbst beantwortet :-)

Danke und Gruß Manfred

Autor: Manfred R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Gemeinde,

nachdem ich mich nun etwas in die Timer Geschichte eingelesen habe, habe 
ich, so glaube ich zumindest, das ganze verstanden. Damit ich mir sicher 
bin dass es so richtig läuft bitte euch kurz folgenden Part anzuschauen:
T0_isr:

   Incr N
   Incr N1
   If N = 3906 Then
      Toggle Buzzer
      N = 0
      Incr Sek
   End If
   If N1 = 1171 Then
    Call Vollschrittvor(1)
   End If

   If N1 = 2342 Then
    Call Vollschrittvor(2)
   End If

   If N1 = 3515 Then
    Call Vollschrittvor(3)
   End If

   If N1 = 4684 Then
    Call Vollschrittvor(4)
    N1 = 0
   End If
   If Sek = 120 Then
      Disable Timer0
      A1 = 0
      B1 = 0
      A2 = 0
      B2 = 0
   End If
  Return

Sub Vollschrittvor(byval Vollschrittindex As Integer):
      A1 = Vollschrittarray(vollschrittindex).1
      B1 = Vollschrittarray(vollschrittindex).2
      A2 = Vollschrittarray(vollschrittindex).3
      B2 = Vollschrittarray(vollschrittindex).4
End Sub
Mein Timer benötigt 3906  durchlüfe um eine Sekunde zu schaffen. Also 
zähle ich bis 3906, geh in eine Subrutine oder was auch immer, und führe 
entsprechend etwas aus. Beim Stepper habe ich allerdings 3.3 Aktionen 
pro sekunde, also rechne ich das entsprechend hoch....

Sollte doch so korrekt sein, oder?

Danke und Gruß
Manfred

Autor: Weingut Pfalz (weinbauer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm ich würds anders herum aufziehen.
wie lang ist denn dein zeitintervall für einen
Schritt?
Ich würde dann einfach bei gegebener Zeit
die zu gehenden Schritte berechnen und den
Timer dann auf die Zeit für einen Schritt
einstellen.
Dann noch die Schritte zählen bis die Zeit
eben voll ist und die Blende schließen.

Autor: Manfred R. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Fhutdhb Ufzjjuz

Also, ich muss umgerechnet 200 Schritte pro Minute machen. Das ergibt 
3.33333 Schritte in der Sekunde. Die ganze Anwendung ist allerdings 
sekunden basiert, der Stepper ist eigentlich nur ein nebenprodukt... da 
ich viele Zeitkritische routinen habe die auf Sekundentakt aufbauen, ist 
es da dann nicht einfacher den Timer im Sekundentakt rennen zu lassen?

Autor: Weingut Pfalz (weinbauer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hmmm ... das sind dann 200 Steps / Minute
sind 300ms je Schritt.

$regfile = "m16def.dat"
$crystal = 1000000

declare sub schritt_vorwärts()
declare sub kamera_auf_zu(byval kamera_status as byte)

dim minuten_zaehler as word
dim schritt_zaehler as word

Config Timer1 = Timer, Prescale = 64
On Timer1 Timer_irq
Const Timervorgabe = 18681
const kamera_auf = 1
const kamera_zu = 0

Enable Timer1
Enable Interrupts

minuten_zaehler=0 ' an der Stelle steht irgendeine Routine zur Eingabe 
der Minuten die laufen sollen

minuten_zaehler=minuten_zaehler*200

Do
'Hier könnte Ihr Hauptprogramm stehen
Loop

Timer_irq:
  Timer1 = Timervorgabe
  if minuten_zaehler<schritt_zaehler then
     call schritt_vorwärts()
     call kamera_auf_zu(kamera_auf)
     incr schritt_zaehler
  else
     call kamera_auf_zu(kamera_zu)
  endif
Return
end

irgendwie so wär mein Ansatz

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.