PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem bei Frontblitzprogrammierung



DKM
19.04.2016, 16:43
Hallo,

ich versuche mich gerade an meiner ersten Programmierung.

Das Projekt ist ein Modellauto mit Dach-LED (ähnlich der Polizei) und Frontblitzern.

Nach langem ausprobieren (irgendwie versteh ich das mit dem Timer noch nicht so ganz) habe ich die Beleuchtung für das Dach realistisch hinbekommen. Aber die Schleifen für die Frontblitzer wollen nicht wirklich.

Das Resultat ist:

L _ R _ L_ _ _

Es sollte aber:

L_L_L_R_R_R_L_L_L_ _ _ _

sein. (L = Links / R = Rechts / _ = Verzögerung)

Hier mein Code:


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

Config Portb.3 = Output
Config Portb.2 = Output
Config Portb.4 = Output
Config Portb.1 = Output

Ocr1a = 51458
Ocr1b = 51599
Config Timer1 = Timer , Prescale = 1024 , Clear Timer = 1 , Compare A = Disconnect , Compare B = Disconnect
Enable Timer1
On Oc1a Timer1serv
On Oc1b Timer2serv
Enable Oc1a
Enable Oc1b
Enable Interrupts

Dim Rechts As Integer
Dim Links As Integer


Do

For Links = 0 To 5
Portb.1 = 1
Waitms 100
Portb.1 = 0
Waitms 100
Next Links

For Rechts = 0 To 5
Portb.4 = 1
Waitms 100
Portb.4 = 0
Waitms 100
Next Rechts

For Links = 0 To 5
Portb.1 = 1
Waitms 100
Portb.1 = 0
Waitms 100
Next Links

Waitms 1000

Loop

Timer1serv:
Toggle Portb.3
Return



Timer2serv:
Toggle Portb.2
Return



End

Bei weiteren Verbesserungsvorschlägen bin ich schon jetzt dankbar - aber dann bitte mit Erklärung :D :D

Achso - Die Frequenz für die Dachleuchten ist 1.11 Hz und 1.12 Hz - hab was relativ nahes genutzt.

Searcher
20.04.2016, 09:19
Hallo,
es gibt viel zu Deinem Programm zu sagen. Aber erst mal einen Anfang:

Die ersten Zeilen sollten auch noch
$framesize
$swstack
$hwstack
umfassen, sonst sind die in BASCOM eingestellten Werte unter "Options" - "Compiler" - "Chip" wirksam, die sonst versteckte Probleme bereiten können.

Der Wert für $crystal muß der CLKcpu Frequenz entsprechen. Bei einem fabrikneuen ATtiny85 ohne Fuse bzw Registermanipulationen ist die Defaulteinstellung 1MHz.

Stimmt der $crystal Wert und die tatsächliche Frequenz nicht überein, hat das Auswirkung auf die Zeiten zB für "waitms" und damit Deiner Verzögerung.

Du gibst die Verzögerung in Deiner Erklärung mit "_" an. Besser sind Werte wie zB Sollwert = 100ms und Istwert = 10ms. Das vermeidet Rätselraten und läßt dann Rückschlüsse auf bestimmte Fehler zu.

Die Schleifen zu Links/Rechts sollten aber schon die LEDs mehrfach ein/ausschalten. Da sehe ich erstmal keinen Fehler. Allerdings sind 100ms sehr kurz und läßt sich fast nicht sehen. Sicher, daß sie nur einmal an- und ausgehen bevor die andere Seite beginnt? Und was soll sein, wenn "L _ R _ L_ _ _" vorbei ist?

Datenblatt ist unbedingt erforderlich.
Im CONFIG TIMER1
schaltet Clear Timer = 1 den CTC Modus ein. Wozu, wenn Du OCR1C nicht nutzt (Erklärung im Datenblatt)

Timer1 ist ein 8-Bit Timer und die zugehörigen Register haben auch nur eine 8-Bit Breite.
Deshalb ist die Zuweisung "Ocr1a = 51458" sinnlos, da eine 8-Bit Zahl maximal bis 255 geht.

So, das war es erstmal bis hier.
Gruß
Searcher

DKM
20.04.2016, 10:03
Hallo Searcher und vielen Dank für deine ausführliche Antwort.

Ich habe versucht soweit alles umzuarbeiten. Bei den Timer Einstellungen habe ich zugegebenermaßen kopiert und war erstaunt, dass es funktioniert. Wie wären die Werte denn für den Timer richtig? Hab irre Schwierigkeiten das zu verstehen :/

Ziel ist es, dass die "Dachlampen" asynchron aufleuchten. Die eine mit 1.11 Hz und die andere mit 1.12 Hz Intervallen.

Das mit den Frontblitzern liegt wahrscheinlich an den Einstellungen die ich vorher mal durchprobiert habe - ich vermute, dass ich den ATTiny zu sehr umgestellt habe.

Hier ein korrigierte Codeausschnitt - die Schleifen sollten ja funktionieren:



$regfile = "attiny85.dat"
$crystal = 1000000
$framesize = 60
$swstack = 32
$hwstack = 60


Config Portb.3 = Output
Config Portb.2 = Output
Config Portb.4 = Output
Config Portb.1 = Output

Ocr1a = 51458
Ocr1b = 51599
Config Timer1 = Timer , Prescale = 1024 , Compare A = Disconnect , Compare B = Disconnect
Enable Timer1
On Oc1a Timer1serv
On Oc1b Timer2serv
Enable Oc1a
Enable Oc1b
Enable Interrupts

Searcher
20.04.2016, 12:30
Hallo,

Also wenn die 1,11 und 1,12 Hz nicht so genau stimmen müssen, würde ich es so in etwa machen:
Ist nur ein Gerüst. Die ISRs werden in etwa den Zeitabständen aufgerufen. Durch Setzen des Prescaler auf 2048 kann man die Frequenz verdoppeln wenn es für das Toggeln der LEDs nötig ist.



$regfile = "attiny85.dat"
$crystal = 1000000
$framesize = 24
$swstack = 32
$hwstack = 34

Config Portb.3 = Output
Config Portb.2 = Output
Config Portb.4 = Output
Config Portb.1 = Output

Ocr1a = 100 'Initialisieren, damit nicht sofort nach Starten des Timers ein Interrupt ansteht
Ocr1b = 200 'Initialisieren, damit nicht sofort nach Starten des Timers ein Interrupt ansteht

Config Timer1 = Timer , Prescale = 4096
'# Mit Prescaler 4096 wird Timer1 mit 1000000 / 4096 = 244,140625 Hz getaktet
'# Tcnt1 wird alle 1 /(1000000 / 4096) = 0,004096s erhöht

On Oc1a Timer1serv
On Oc1b Timer2serv

Enable Oc1a
Enable Oc1b

Enable Interrupts

Do
Loop

Timer1serv:
Ocr1a = Ocr1a + 220 'nächster Interrupt nach 220 * 0,004096s = 0,90112s (1,097Hz)
'.
'LEDs schalten
Return

Timer2serv:
Ocr1b = Ocr1b + 218 'nächster Interrupt nach 218 * 0,004096s = 0,892928s (1,1199Hz)
'.
'LEDs schalten
Return


OCR1A und B werden überlaufen, wenn die Addition über 255 hinausgeht. Das ist gewollt, da das TCNT zu den OCR1x Registern trotzdem immer die gleiche Zeit benötigt. Tritt bei 250 ein Compare-Interrupt auf, wird zu 250 eine zB 220 addiert. Im Register steht dann wg Überlauf 214. TCNT muß von 250 bis 255 über 0 nach 214 laufen - Zeitabstand gewahrt. Schön im Simulator zu betrachten.

Gruß
Searcher

PS Bitte gezielt fragen, da ich nicht weiß welche Voraussetzungen du hast.
Hier noch eine Seite in Deutsch, wenn Datenblatt Englisch ein Problem ist:
http://halvar.at/elektronik/kleiner_bascom_avr_kurs

i_make_it
21.04.2016, 08:44
Ich habe den Code jetzt nicht gelesen, aber für mich sagt der erste Post was anderes als der zweite Post, somit habe ich ein Verständniss Problem.

Zeichne doch mal ein Timingdiagramm von allen LEDs
In der Zeichnung unten ist die oberste Zeile das Timing, so wie ich es aus dem ersten Post verstanden habe.
Und Zeile 2 und 3 So wie ich es aus dem zweiten Post verstanden habe.
31527
Das Diagramm ist nicht maßstäblich sondern nur symbolisch und in Relation zueinander, zum besseren Verständniss des Textes.
(Frei nach dem Motto: ein Bild sagt mehr als 1000 Worte)

DKM
21.04.2016, 14:39
Hallo zusammen,

hier ein Beispiel für das Blaulicht (nicht von mir).
Achtet auf den Intervall vom linken Fahrzeug Fahrzeug. Dort sieht man, dass eine Seite schneller als die andere Seite "läuft", was realitätsnah ist.

https://www.youtube.com/watch?v=lwCvOzi8Fgc

Zu den Frontblitzern habe ich leider kein passendes Video gefunden. Aber ich habe versucht das gewünschte Timing-Diagramm zu erstellen.

Vom Prinzip her läuft es so:

Beginn der Schleife
Linke Seite -> 3 mal aufblitzen
sichtbare Pause und Wechsel zur

Rechten Seite: 3 mal aufblitzen
wieder sichtbare Pause und Wechsel nach

Links: 3 mal aufblitzen

längere Pause (1-2 Sekunden)
Ende der Schleife


31531

oberallgeier
21.04.2016, 17:54
... Vom Prinzip her läuft es so: .. Links: 3 mal aufblitzen ..Nur mal so, zur Sichtbarkeit. Bei meinem Pacer (https://www.roboternetz.de/community/threads/48271-ISP-zum-Aufklippen-f%C3%BCr-THT-Controller),

......https://dl.dropbox.com/s/4ocqv9atfna7irn/PCR80_2145.jpg?dl=0

einem Blinkgeber für Schritttakte (Jogging) leuchten die LEDs 100 ms, mit ca. 550 ms Pause. Das kann ich auch bei gutem Tageslicht noch einwandfrei erkennen.

i_make_it
22.04.2016, 08:28
Das Timing-Diagramm zeigt schon mal deutlich, daß man "waitms" die Aufgabe nicht programmiert bekommt.
Dadurch das 3 verschiedene Zykluszeiten vorliegen, verschieben sich die verschiedenen Zyklen relativ zu den anderen.
Jeder Zxklus besteht im Prinzip aus folgenden Zuständen:
Ein, Zeit1, AUS, Zeit2, Ein, Zeit1, AUS, Zeit2, Ein, Zeit1, AUS, Zeit3.
Bei Dach-L und Dach-R sind Zeit1 und Zeit2 anscheinend identisch.

Entweder man arbeitet mit ISRs und und ändert bei jedem Aufruf anhand des Zustands (den man mitzählen muß) die Zeiten, oder man arbeitet ganz ohne ISRs indem man den Wert eines Timers einer Variablen zuweist und bei jedem Durchlauf der Schleife überprüft ob der aktuelle Timerwert minus dem gespeicherten Wert gleich oder größer einer Variablen ist, die den für den jeweiligen Zustand richtige Zeit enthällt.

Man braucht dann also 4 Variablen die für jeden der 4 Zyklen den Zustand speichern.
Maximal 24 Konstanten (z.B. in 4 Arrays)für die Zeiten (womit man auch die Frontblitzer asynchon ansprechen könnte)
4 Variablen für den kleineren Timerwert
4 Variablen für die Vergleichsoperator die je nach Zustand mit den Zeitwerten der Konstanten geladen wird.

Mal schnell ein Pseudocodebeispiel.
Vermutlich sind noch Fehler drin, ich hoffe aber der Gedanke wird verständlich.



Preset/definition
Z1-ausgang = low
Z1-timealt = 0
Z1-zustand = 0
Z1-const(100,100,100,100,100,700)

Schleife
IF Timer - Z1-timealt >= Z1-zeit (
Toggel Z1-ausgang
Z1-zustand ++ 1
IF Z1-zustand >= 6 (Z1-zustand = 0)
Z1-zeit = Z1-const(Z1-zustand)
Z1-timealt = Timer
)
Ende


Den Block nimmt man für jeden Zyklus ein mal (Z1 bis Z4)
Im Preset definiert man die Startbedingung (macht die Schleife schlanker. Ich weis aber nicht ob das so in Bascom geht)

Je Block gibt es ein IF, ist die Bedingung nicht erfüllt, wird der ganze Block übersprungen und der nächste Programmblock kann bearbeitet werden (bis die Schleife einmal komplett durch ist).

Ist die Bedingung erfüllt, wird der entsprechende Ausgang umgeschaltet.
Dann wird der Zustandszähler inkrementiert, da es ja einen Zustandswechsel gegeben hat.
Darauf folgt eine Prüfung auf Wertebereichsüberschreitung des Zustandszähler (ist gegeben wenn der Zyklus einmal durchgelaufen ist) und bei Bereichsüberschreitung erfolgt das Zurücksetzen.
Danach wird die Vergleichsvariable für den Zeitvergleich aus der entsprechenden Konstante gesetzt.
Und zum Schluß noch der aktuelle Timerwert übernommen in die Variable für die Startzeit des aktuellen Zustands.

Im Gegensatz zu ISRs kann es bei diesem Konstrukt dazu kommen, das die einzelnen Zustände um einen Schleifendurchlauf länger dauern als die vorgegebene Zeit.
Wen das nicht sört, spart so ISRs für andere Aufgaben.

DKM
26.04.2016, 13:12
Hallo und danke für eure Hilfen,

ich habe den Code von Searcher soweit übernommen. Leider kam ich bisher nur zu einem sehr kurzen Testlauf, aber es sieht super aus. Die Zeiten für die Frontblitzer habe ich angepasst.

@i_make_it

Die Dachleuchten sind minimal unterschiedlich. Da fällt aber fast immer erst bei längerer Betrachtung auf. Das Phänomen kann man so beschreiben, dass sie mal gleichzeitig gehen, dann wechselnd. Daher auch nur der geringe Unterschied in der Frequenz.

Für mein erstes Mal denke ich, dass es gut gelungen ist. Nun muss ich mir noch Gedanken über die Stromversorgung machen (bin auf so nem niedrigen Level, dass mir nicht bewusst war, dass weiße LED's weitaus mehr Leistung benötigen als andere... )

Aber ich lerne ja - soweit ich Zeit habe :)

Eine Frage nebenbei - kennt Ihr das BASCOM Buch (http://www.elv.de/franzis-mikrocontroller-programmieren-mit-bascom-basic.html)von Franzis und kann ich das bedenkenlos kaufen?



P.S. Ein Video kommt noch, wenn ich wieder zu Hause bin. Das wird dann auch länger laufen, damit man die Unterschiede auf dem Dach ordentlich sieht :)

Grüße

DKM