Forum: Mikrocontroller und Digitale Elektronik Starthilfe Programmierung


von Matthias (Gast)


Lesenswert?

Hallo,

auf der Suche nach Steuerungsmöglichkeiten für Fensterheber bin ich über 
Atmel Mikrocontroller gestolpert und war doch sehr überrascht, wie 
einfach es gehen kann (könnte). Momentan beschränken sich meine Versuche 
auf AVRStudio4 und einen emulierten AT90S8515 (was wohl auch erst mal 
reicht...).

Folgende Vorstellung geistert durch meinen Kopf: Einmal auf hoch oder 
runter tippen (t<0,5s) und der Motor wird für 8s angesteuert (hoch bzw. 
runter), es sei denn es wird in die andere richtung getippt, dann stoppt 
der Antrieb.
Liegt das Eingangssignal länger als 0,5s an, wird der Motor so lange 
angesteuert, wie das Signal anliegt.
Das Ganze sollte auch mit allen Ein- und Ausgängen simultan 
funktionieren, da ansonsten die Fenster nur der Reihe nach bedient 
werden könnten.

Ist sowas generell mit einem Controller möglich (kann ich einzelne Bits 
ansprechen oder nur das komplette Byte), oder braucht es da vier Stück? 
Wo finde ich denn den Befehlssatz samt einer kurzen Beschreibung für 
einen MC?

Gruß,
Matthias

von Retro (Gast)


Lesenswert?

Hallo Matthias!

Sowas ist mit einem Microcontroller problemlos möglich, Datenblätter von 
den einzellnen Controller bekommst du direkt bei ATMEL oder ganz bequem 
von http://www.avrfreaks.net/.

Natürlich kannst du auch einzellne Bits von einem Port auf high/low 
ziehen, ich weiss nicht auf welcher Platform du deinen Controller 
programmieren willst (C, ASM, Pascal, BASCOM) aber jedenfalls gibt es 
dafür Befehle und Möglichkeiten.

von H.Howey (Gast)


Lesenswert?

Hallo...
Bitte bedenke das: Wenn ein Kind usw. seinen Arm aus dem Fenster hält, 
muss der Motor abgeschaltet werden bzw wieder herunter gefahren werden. 
Da gab es mal div. Tests mit Äpfeln ...
Das Abschalten kann man z.B. über die Stromaufnahme des Motors machen. - 
Nur - dazu muss man sie messen und verarbeiten.
Es hängt da also noch mehr drann.
Gruß
Holger

von Matthias (Gast)


Lesenswert?

Hallo,

naja, ASM sieht ganz nett aus. Irgendwann hab' ich damit mal auf meiner 
CPU rumgespielt und es kam mir mal nicht sooo schwer vor...
Mit welchem MC wäre sowas denn möglich? Ich hätte da Bedenken wegen der 
gleichzeitigen Ansteuerung im Bezug auf die Anzahl der Verfügbaren 
Timer. IMHO bräuchte ich für jedes Fenster einen, da er unter Umständen 
bis zu acht sekunden "belegt" ist, oder gibt es da eine andere Lösung?

Gruß,
Matthias

von Matthias (Gast)


Lesenswert?

@Howey

Aber an die Strommessung habe ich schon gedacht und möchte mir dafür 
entweder einen Port des MCs freihalten oder den Motor extern abschalten.
lassen wir vorerst mal die Kirche im Dorf, ich bin Froh wenn ich das 
erste Problem mal gelöst bekomme. Bis jetzt hab' ich da noch keinen 
blassen Schimmer... wenn also jemand ne idee hat??

gruß,
matthias

von Stefan (Gast)


Lesenswert?

Vielleicht klappt das:

Du nimmst einen Timer und stellst ihn so ein, dass er z.B. alle 0,1s 
einen Interrupt auslöst. Wenn der Interrupt ausgelöst wird, schaust Du 
welche Motoren alle für 8s laufen sollen (z.B. könnte in einem 
bestimmten Register jeweils ein Bit für einen Motor gesetzt werden, wenn 
die Taste weniger als 0,5s gedrückt wurde; um die betreffenden Bits zu 
setzen könntest Du einen zweiten Timer Interrupt verwenden). Für jeden 
Deiner Motoren zählst Du einfach ein Register hoch und schaltest den 
entsprechenden Motor ab, wenn sein Register 80 erreicht hat (und setzt 
natürlich Bit und Register zurück und verlässt den Interrupt).


Schöne Grüße

Stefan

von Matthias (Gast)


Lesenswert?

klingt gut, aber dafür brauche ich zwei große Zähler (2Byte). Bei 'nem 
kleinen Timer liegt die längste Zeit bei 0,06528 (4MHz), oder irre ich 
mich da?
Vielleicht kann jemand ein paar Code-Beispiele posten, die die 
Interrupts und Timer behandeln...

Vielen Dank,
Matthias

von Stefan (Gast)


Lesenswert?

Du könntest als Zeitbasis genauso auch 0,05 Sekunden nehmen und bis 160 
zählen.

Aber das Prinzip müsste auch mit nur einem Timer funktionieren. Wenn der 
Interrupt auslöst, wird zuerst geguckt, welche Tasten gedrückt sind. Die 
Motoren dieser Tasten werden angeschaltet (falls notwendig) und für jede 
dieser Tasten wird ein Register um eins erhöht.

Bei den nichtgedrückten Tasten wird geguckt, ob der Wert der jeweiligen 
Register kleiner 10 (bei 0,05s Zeitbasis) und ungleich null ist. Falls 
nein Motor abschalten und Register zurücksetzen, falls ja Motor 
laufenlassen und Register um eins erhöhen.

Zuletzt muss noch überprüft werden, ob eines der Register 160 erreicht 
hat. Falls ja, Motor abschalten. Anschließend wird der Interrupt 
verlassen.

Ein AVR Code-Beispiel kann ich Dir leider nicht anbieten, weil ich 
bisher nicht für AVRs sondern für 8051er programmiert habe. Im Moment 
bin ich damit beschäftigt Pony Prog (www.lancos.com/prog.html) 
nachzubauen und dann werde ich wohl umsteigen. Aber ein Beispiel für 
8051 kann ich Dir schicken, falls es Dir etwas nützt.

von Matthias (Gast)


Lesenswert?

hallo stefan,

daran sitze ich schon den halben tag. momentan verzweifle ich gerade an 
der richtigen INT-Adresse für Timer0, da ja fast jeder Controller eine 
andere tabelle hat...

auf dein angebot mit "code-häppchen" komme ich gerne zurück, denn noch 
habe ich ja keinen mc, sondern nur das avrstudio4 - bin also noch 
völligst offen. welcher wäre denn für diese anwendung am besten 
geeignet? mir wäre halt eine am liebsten, der pro port acht nutzbare 
ein/ausgänge hat und das ganze mal 3 (für die sicherheitsschaltung), da 
ich so bei meinen momentanen Kenntnissen leichter den überblick behalte: 
eine reihe eingänge, eine reihe ausgänge...

gruß,
matthias

von Stefan (Gast)


Lesenswert?

Hi!

Tja, da erwischst Du mich ein wenig auf dem falschen Fuß, schließlich 
habe ich, wie gesagt, bisher überhaupt keine Erfahrung mit AVRs. Ich 
kann Dir also nur meine ehrliche, wenn auch möglicherweise 
unqualifizierte Meinung anbieten.

Du könntest natürlich einen 8051er verwenden, die gibts auch als 
Flash-Controller von Atmel ;-)) (AT89S8252).

Aber ich denke mit dem 90S8515 hast Du schon eine gute Wahl getroffen. 
Der hat schließlich vier 8 Bit Ports und dürfte ansonsten schon über 
mehr Peripherie verfügen, als Du in Deinem Fall brauchst. In der PLCC 
Version ist er z.B. bei Reichelt auch mit 8,10 Euro recht günstig. An 
Deiner Stelle würde ich es einfach mal mit dem versuchen.


Tschüss

Stefan

von Uwe (Gast)


Lesenswert?

Hi!
Mit einem 8 Bit Timer ist bei 4MHz eine max. Verzögerung von 65,563 ms 
für einen TOV = Timerüberlauf zu erreichen.
Du must nur den Vorteiler (TCCR0) auf 5 (Bit0+2=1)setzen dann wird der 
Timer aller 256 mys um 1 erhöht. Wenn das 195 mal gemacht wurde sind 
49,92ms vergangen also ~50ms.
Das ist doch eine gute Zeitbasis. Die 195 kannst du einfach in's TCNT0 
eintragen indem du schreibst:
(ich nehme jetzt mal r16 als tmp)
.def tmp =r16
.def Fe_1 =r17 ;Fenster 1
.def Fe_2 =r18 ;Fenster 2
.equ 8s   =160 ;Zählwert für 8sek

TOV_ISR:
ldi tmp,0-195 ;Überlauf ist von $FF nach 0(~50ms)
out TCNT0,tmp ;Ausgabe in's Timerreg.
tst Fe_1      ;Zeit Fenster 1 schon abgelaufen?
breq cls1     ;wenn 0 Fenster 1 abschalten
dec Fe_1      ;sonst Zeit Fe_1 - 1
brne F2       ;jetzt 0?, bei nein -> F2
cls1: "Befehl für Reset Fensterbit,kann mit"cbi Port,Bit" ein Ausgang 
sein"
F2:tst Fe_2   ;Zeit Fenster 2 schon abgelaufen?
breq cls2     ;wenn 0 Fenster 2 abschalten
dec Fe_2      ;sonst Zeit Fe_2 - 1
brne ende       ;jetzt 0?, bei nein -> ende
cls2: "Befehl für Reset Fensterbit,kann mit"cbi Port,Bit" ein Ausgang 
sein"
ende: reti    ;TOV_ISR ende

Im Hauptprog. stellst du mit den Tasten fest was gemacht werden soll 
zb.:
Fenster1 stop = clr Fe_1
oder Fenster1 8sek ein = ldi Fe_1,8s ;Wert 160->Fe_1

Alles andere erledigt dann die TOV_ISR

Als Anregung sollte das erstmal reichen, viel Spass
Uwe
Ps.:hoffentlich kann man's lesen, Anhang wäre vermutlich besser.

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

hallo uwe,

das waren schon mal ein paar sehr hilfreiche tipps - danke! ich habe mal 
versucht sie umzusetzen, scheitere allerdings immernoch an den 
Interrupts. Wenn ich den Cursor in die erste Zeile der INT-Routine setze 
(unter TOVISR:) und dann auf "run to cursor" klicke, kommt er nie dort 
an. Der Counter rennt aber munter weiter, auch über den Overflow 
drüber...

Code liegt im Anhang, vielleicht hat jemand nen Tipp.

Gruß,
Matthias

von Uwe (Gast)


Lesenswert?

Hi!
Habe zwar nicht alles geprüft aber:
1. wo ist denn dein Stackinit???? Ganz wichtig!
2. Zeit für Fenster 2 wird nicht geladen, nur Fe_1.
3. wenn eine Zeit gesetzt wurde, auf 0 warten, nicht neu
   laden
4. rjmp F1
 F1:       Das sind unsinnige Befehle,verschwenden Platz
5. Eingänge brauchst du nicht def.,alle Pin's sind das
   nach Reset
Ansonsten sollte es klappen.
Ich habe aber gestern nochwas vergessen. Du solltest in der TOV_ISR das 
S-Reg. sichern und zurückschreiben, es kann sonst zu Fehlern im "MEIN" 
kommen.
Das kann so aussehen:
.def isr_tmp=r19    ;zum SREG sichern in allen ISR's
...
...
TOV_ISR:
    in isr_tmp,SREG
...
...
...
...
ende:out SREG,isr_tmp
     reti

Viel Spass
Uwe

von Matthias (Gast)


Angehängte Dateien:

Lesenswert?

hi,

ich habe deine punkte soweit umgesetzt, nr.3 müsstest du mir aber 
nochmal erläutern. Die Interrupts funktionieren immer noch nicht, den 
geänderten code hab' ich nochmal angehängt.

gruß,
matthias

von Uwe (Gast)


Angehängte Dateien:

Lesenswert?

Hi!
Auf ein neues. Habe jetzt mal genau hingeschaut, die 
Int.Einsprungadresse war falsch es ist noch ein
Timer1 compareB Handler vorhanden. Die TOV_ISR konnte also per timer0 
nicht gefunden werden.
Den Cursor solltest du aber nicht in die ISR setzen, das gibt bei "reti" 
Stackfehler. Setze besser TCNT0 auf 255 und mache 1024 Step's oder setze 
einen Breakpoint vor TOV_ISR und lasse mit Run laufen.
Jetzt zu deiner Frage. Wenn du dein Progr.so lässt,läuft die Zeit von 8s 
ab dem loslassen der jeweiligen Taste, ist bestimmt nicht gewollt. Habe 
es mal für Fe_1 umgeschr. Dabei ist mir was aufgefallen. Du setzt deine 
Ausgänge alle einzeln, wenn du aber den neuen Merker am Ende deiner 
TOV_ISR auf das Port schreibst hast du das selbe Ergebnis. Genauso 
könnte man natürlich auch die entspr. Portpin's abfragen um mehrfaches 
laden der Zeit zu vermeiden. Der Möglichkeiten gibt es halt viele.
Ich hoff du verstehst was ich meine.
Gruss Uwe
Ich hänge die Änderungen an.

von Uwe (Gast)


Lesenswert?

Mist habe Müll geschrieben.
Die Zeile
andi  merke_Fe,$2    ;F1DN-Bit löschen
bitte ändern in
andi merke_Fe,0b1111100

Mache es doch überall im Bin Format, das ist übersichtlicher.
Wenn mein Tag schon 18 Stunden alt ist darf das mal sein.
Gruss Uwe

von Matthias (Gast)


Lesenswert?

hallo zusammen,

ich möchte mich an dieser stelle mal für die doch sehr umfangreiche 
hilfe von euch bedanken... insgesamt geht es schneller und einfacher 
vorwärts als ich mir das anfangs gedacht habe. da ich in diesen tagen 
umziehen muss, werde ich den "starthilfe-thread" erst mal schließen 
(wenn man das so sagen kann) und dann bei gelegenheit einen neuen 
fensterheber-thread öffnen.

gruß,
matthias

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.