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


von Manfred R. (Gast)


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):
1
  If Kp = Keye And Submnu(i) > 1300 And Submnu(i) < 1399 And Sekmnu = 0 Then
2
      T = Val(mnutext(i))
3
         Call Ausloesen(t)
4
      Return
5
   End If
Wenn wahr, werden die sekunden an die subrutine übergeben. Diese macht 
folgendes:
1
Sub Ausloesen(byval T As Word)
2
3
      Wartezeit = Val(sftime)
4
      If T = 999 Then
5
         Fokus = 1
6
         Waitms Wartezeit
7
         Ausloesung = 1
8
      End If
9
      If T < 999 Then
10
         Locate 1 , 1 : Lcd Chr(5) ; " mit " ; T ; " sek."
11
         Fokus = 1
12
         Waitms Wartezeit
13
         Ausloesung = 1
14
         Do
15
            Locate 2 , 1 : Lcd "                "
16
            Locate 2 , 1 : Lcd "Noch " ; T ; " sek."
17
            Gosub Tstq
18
            Call Vollschrittvor()
19
            T = T - 1
20
            If T = 0 Then
21
               Call Motoraus()
22
               Exit Do
23
            End If
24
         Loop Until Kp > 0
25
      End If
26
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():
1
Sub Vollschrittvor()
2
   For Sti = 1 To 4
3
      Incr Vollschrittindex
4
      If Vollschrittindex > 4 Then
5
         Vollschrittindex = 1
6
      End If
7
      A1 = Vollschrittarray(vollschrittindex).1
8
      B1 = Vollschrittarray(vollschrittindex).2
9
      A2 = Vollschrittarray(vollschrittindex).3
10
      B2 = Vollschrittarray(vollschrittindex).4
11
      Waitms 250
12
   Next Sti
13
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

von Manfred R. (Gast)


Angehängte Dateien:

Lesenswert?

Attachment... sorry

von Karl H. (kbuchegg)


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.

von Manfred R. (Gast)


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

von Manfred R. (Gast)


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:
1
T0_isr:
2
3
   Incr N
4
   Incr N1
5
   If N = 3906 Then
6
      Toggle Buzzer
7
      N = 0
8
      Incr Sek
9
   End If
10
   If N1 = 1171 Then
11
    Call Vollschrittvor(1)
12
   End If
13
14
   If N1 = 2342 Then
15
    Call Vollschrittvor(2)
16
   End If
17
18
   If N1 = 3515 Then
19
    Call Vollschrittvor(3)
20
   End If
21
22
   If N1 = 4684 Then
23
    Call Vollschrittvor(4)
24
    N1 = 0
25
   End If
26
   If Sek = 120 Then
27
      Disable Timer0
28
      A1 = 0
29
      B1 = 0
30
      A2 = 0
31
      B2 = 0
32
   End If
33
  Return
34
35
Sub Vollschrittvor(byval Vollschrittindex As Integer):
36
      A1 = Vollschrittarray(vollschrittindex).1
37
      B1 = Vollschrittarray(vollschrittindex).2
38
      A2 = Vollschrittarray(vollschrittindex).3
39
      B2 = Vollschrittarray(vollschrittindex).4
40
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

von Weingut P. (weinbauer)


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.

von Manfred R. (Gast)


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?

von Weingut P. (weinbauer)


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

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.