Hallo,
zur Zeit versuche ich einen Motor über eine H-Brücke mit einem ATmega8
anzusteuern. Ziel soll es sein das der motor in einer "for" schleife
eine bestimmte Zeit rechts herum und anschliesend in einer zweiten
Schleife links herum dreht.
Ich habe mir schon einige Tutorials, das Datenblatt usw. durchgelesen.
Leider begreife ich nicht warum OCR1A und OCR1B nicht in die Schleife
dürfen. Steht nur einer dieser beiden Werte auserhalb der While geht
alles wuderbar - zumindest in eine Richtung. Stehen beide auserhalb der
while beinflussen sie sich gegenseitig entsprechend.
Wie mus man das machen das der Motor erst rechts und dann links herum
läuft?
Hier mein bisheriger Code - zum größten Teil aus dem Tutorial von dieser
Seite:
1
/* Standard Includes */
2
//#include <avr/interrupt.h>
3
#include<avr/io.h>
4
#define F_CPU 8000000UL /* Quarz mit 8 Mhz */
5
#include<util/delay.h>
6
#include<stdint.h>
7
#include<inttypes.h>
8
9
10
#define Draht1 _BV(PB1) //Motor vorwärts
11
#define Draht2 _BV(PB2) //Motor rückwärts
12
13
14
15
intmain(void)
16
{
17
DDRB=0xff;/* alle B Port Pins sind Outputs */
18
PORTB=0x00;/* fangen alle bei 0V an */
19
20
constuint16_tdelay=1000;
21
// OC1A auf Ausgang
22
//DDRB = (1 << PB1 ); // OC1A auf Ausgang
23
//DDRB = (1 << PB2 ); // OC1B auf Ausgang
24
//
25
// Timer 1 einstellen
26
//
27
// Modus 14:
28
// Fast PWM, Top von ICR1
29
//
30
// WGM13 WGM12 WGM11 WGM10
31
// 1 1 1 0
32
//
33
// Timer Vorteiler: 1
34
// CS12 CS11 CS10
35
// 0 0 1
36
//
37
// Steuerung des Ausgangsport: Set at BOTTOM, Clear at match
Hallo,
STK500-Besitzer schrieb:
> _delay mit Variablen funktioniert - soweit ich das weiß - nicht (ich> benutze es nicht).
_delay_xs funktioniert mit Variablen. Hat bei einer älteren Bastelei
auch funktioniert. Trotzdem habe ich die Variable erst mal gegen eine
1000 getauscht.
Falk Brunner schrieb:
> http://www.mikrocontroller.net/articles/AVR-GCC- >
Tutorial#Warteschleifen_.28delay.h.29
Daher habe ich das Grundgerüst für meinen Code. Ich Habe das Register
TCCR1A um COM1B1 erweitert damit auch der Pin PB2 als OC1B angesprochen
wird. Damit müsste ich ja eigentlich 2 Pins haben die über den Timer1
angesprochen werden. Jetzt, dachte ich mir, braucht jeder Pin nur noch
einen Vergleichswert, um so unterschiedliche Geschwindigkeiten zu
erzeugen.
Somit hatte ich in der zweiten for Schleife ursprünglich OCR1B = 0x6FFF;
statt OCR1A = 0x6FFF; stehen - aber das alles funktioniert nicht. der
Motor dreht dabei entweder immer nur in eine Richtung - oder alles ist
so falsch, dass der Motor garnicht dreht.
Danke für weitere Tips
fg Rocco
Ohne jetzt die Timer-Einstellungen genau angeschaut zu haben:
Ich verstehe Deine while-Schleife nicht.
Du willst doch die H-Brücke per Hardware-PWM ansteuern, richtig?
Dazu setzt Du in die OCR1A/B Register einfach den jeweiligen Wert und
gehst danach in eine delay-schleife.
Draht1 und Draht2 scheinen die Drehrichtung anzugeben, vllt. solltest Du
einen der Ports einfach abschalten bevor Du den anderen aktivierst?
Nicht dass Dir noch die Brücke durchschiesst.
btw, ein Schaltplan Deiner H-Brücke wäre hilfreich. Hast Du ein
Treiber-IC genommen oder diskret aufgebaut?
Christian T. schrieb:
> Ohne jetzt die Timer-Einstellungen genau angeschaut zu haben:> Ich verstehe Deine while-Schleife nicht.>> Du willst doch die H-Brücke per Hardware-PWM ansteuern, richtig?> Dazu setzt Du in die OCR1A/B Register einfach den jeweiligen Wert und> gehst danach in eine delay-schleife.>> Draht1 und Draht2 scheinen die Drehrichtung anzugeben, vllt. solltest Du> einen der Ports einfach abschalten bevor Du den anderen aktivierst?> Nicht dass Dir noch die Brücke durchschiesst.>> btw, ein Schaltplan Deiner H-Brücke wäre hilfreich. Hast Du ein> Treiber-IC genommen oder diskret aufgebaut?
Hallo Christian,
Das abschalten des Drahtes habe ich jetzt so gelöst:
1
while(1){
2
3
for(inti=0;i<100;i++){
4
OCR1A=0x3FFF;
5
_delay_ms(delay);
6
PORTB|=Draht1;//Motor vorwärts
7
_delay_ms(delay);
8
}
9
PORTB&=~Draht1;
10
for(intk=0;k<100;k++){
11
12
OCR1B=0x6FFF;
13
_delay_ms(delay);
14
PORTB|=Draht2;//Motor rückwärts
15
_delay_ms(delay);
16
}
17
PORTB&=~Draht2;
18
}
Leider dreht der Motor trotzdem nur in eine Richtung. Was auch seltsamm
ist ist, dass der Motor ca 2-3 min langsamm und dann 2min schneller
dreht
Die H Brücke habe ich mal fix geEAGLEed - siehe Anhang
Hi Rocco,
mir ist nicht ganz klar, was du eigentlich machen willst, aber ich
glaube, dass du was anderes im Sinn hast, als du programmiert hast.
1
for(inti=0;i<1;i++){// ist wohl eine sehr kurze for-schleife von 0 bis 0???
2
OCR1A=0x3FFF;// ok hier wird PWM für vorwärts mit 57% aktiviert (dein max ist ja laut erstem Posting 0x6FFF)
3
_delay_ms(delay);// dank PWM dreht sich der Motor jetzt mal selbstständig
4
PORTB|=Draht1;// => kurzes reinpfuschen in die PWM, wozu das???
5
_delay_ms(delay);// Motor dreht weiter
6
}
7
OCR1A=0x0000;// PWM ausschalten
8
9
...// und das ganze nochmal in die andere Richtung
Ist das wirklich das was du machen wolltest?
Probier mal zu Testzwecken ein kleines Programm, dass den Motor mal 5
Sek. mit 50% vorwärts und anschließend 5 Sek. rückwärts dreht und dann
den Motor abstellt.
(kleiner Tipp: du brauchst dafür keine for Schleifen und überleg dir wo
dein while(1) hinkommt.)
by(e)
Stephan
Hallo,
das mit der zu kurzen for Schleife 0 bis <1 ist natürlich mathematisch
totaler Unsinn. Habe jetzt noch mal mit meinen geringen
Programmierkenntnissen an meinem Quelltext herum gefuscht.
1
#include<avr/io.h>
2
#define F_CPU 8000000UL /* Quarz mit 8 Mhz */
3
#include<util/delay.h>
4
#include<stdint.h>
5
#include<inttypes.h>
6
7
8
#define Draht1 _BV(PB1) //Motor vorwärts
9
#define Draht2 _BV(PB2) //Motor rückwärts
10
11
uint8_thallsensor;
12
13
intmain(void)
14
{
15
DDRB=((1<<DDB1)|(1<<DDB2));/* B Port Pins sind Outputs */
16
DDRB&=~(1<<DDB0);/* B Port Pins sind Inputs*/
17
PORTB|=(1<<PB0);/*interne Pull up Wiederstände ein*/
18
PORTB=0x00;/* fangen alle bei 0V an */
19
20
constuint16_tdelay=3000;
21
22
hallsensor=PB0;// Status von PB0 in hallsensor kopieren
_delay_ms(delay);//Warten wegen Trägheit des Motors
41
for(floatk=0;k<124000;k++){
42
OCR1B=8186;//Geschwindigkeit
43
PORTB|=Draht2;//Motor rückwärts
44
}
45
PORTB&=~Draht2;//Motor aus
46
OCR1B=0x0000;//Geschwindigkeit 0
47
_delay_ms(delay);//Warten wegen Trägheit des Motors
48
// }
49
}
Ich finde das mit der for Schleife ja auch nicht so toll, schließlich
erzeugt diese ja bereits so was wie eine PWM. Wie ich das allerdings
ganz ohne Schleifen erleding sollte weis ich leider nicht. Bin halt noch
ein Anfänger. Allerdings würde ich mich über weitere Tips sehr freuen.
Später soll mal an irgend einem Pin "gehorcht" werden und je nachdem was
für ein binäres Signal anliegt soll der Motor bzw das Getriebe eine
bestimmte Anzahl an Umdrehungen links oder rechts herum drehen. Die
Umdrehungen messe ich z.Z. mit einem Hallsensor am Ende des Getriebes.
Danke für Eure Hilfe
fg Rocco
Wieso lässt du nicht erst mal die PWM weg und steuerst die H-Brücke über
den Controller per Tasten?
Die "Einschaltperiode", wie du sie mit den For-Schleifen machen willst,
kannst du auch vom Timer ableiten.
float ist auf (8Bit-)Mikrocontrollern nicht wirklich zu empfehlen, vor
allem nicht, wenn man damit nur zählen will.
Dafür gibt es genug ganzzahlige Datentypen.
Thilo M. schrieb:
>Die H-Brücke funktioniert so?>Sollten T1 und T2 nicht besser PNP sein?
In der aufgebauten Schaltung sind es auch PNP Transistoren. Warum ich
mich beim erstellen des Schaltplans in Eagle verguckt habe weis ich auch
gerade nicht...
STK500-Besitzer schrieb:
> Wieso lässt du nicht erst mal die PWM weg und steuerst die H-Brücke über> den Controller per Tasten?> Die "Einschaltperiode", wie du sie mit den For-Schleifen machen willst,> kannst du auch vom Timer ableiten.> float ist auf (8Bit-)Mikrocontrollern nicht wirklich zu empfehlen, vor> allem nicht, wenn man damit nur zählen will.> Dafür gibt es genug ganzzahlige Datentypen.
Das Steuern per Tasten ist sehr einfach. So was habe ich bereits
gemacht. Jetzt war es, wie ich finde, an der Zeit mich weiter zu
entwickeln und mal was mit den Sonderfunktionen des Atmega8 zu
probieren. PWM war dabei die erste Idee nachdem ich schon mit dem
Analogkomperator und den D/A A/D Wandlern herum gespielt habe.
Hat vieleicht einer etwas passenden Code wo ich mir so etwas mit Timern
statt der for Schleifen mal ansehen kann?
Danke Rocco