Code:
//---------------------------------------------------------------------------
// Title : DC Motor Steuerung V7.0
// Schaltung : Steuert zwei DC Motoren PAN&TILT über Tasten NORD, SÜD, OST, WEST
// Motoren werden über PWM Ausgänge betrieben, Hall Geber über ext Interrut,
// Anzahl der Schritte über SW vorgebene
//----------------------------------------------------------------------
// Prozessor : ATmega8
// Takt : 3.6864 MHz
// Sprache : C
// Datum : 27.05.2010
// Version : 9.0
// Autor : Sven Thomson
// Programmer : ...
// Port : ...
//---------------------------------------------------------------------------
#define F_CPU 3686400 // Taktfrequenz des myAVR-Boards
#include <avr\io.h> // AVR Register und Konstantendefinitionen
#include <util\delay.h> // Bibliothek mit Warteroutinen
#include <math.h>
#include <inttypes.h>
#include <avr\interrupt.h>
//----------------------------------------------------------------------
//------------------------Globale VARIABLEN-----------------------------
// Varaiablen für PAN-Motor
int PRichtung=0; // PAN Drehrichtung Osten:-1, Stillstand:0, Westen=1
int PZaehler_A=0; // PAN Zählerstand am Anfang
int PKorrektur=0; // PAN Korrekturwert
int PWeg_Kor=0; // PAN korrigierter Weg
// Varaiablen für TILT-Motor
int TRichtung=0; // TILT Drehrichtung Norden:-1, Stillstand:0, Süden=1
int TZaehler_A=0; // TILT Zählerstand am Anfang
int TKorrektur=0; // TILT Korrekturwert
int TWeg_Kor=0; // TILT korrigierter Weg
//durch interrupt veränderbare Varaiablen
volatile int PZaehler=0; // PAN Zähler der HALL Impulse
volatile int TZaehler=0; // TILT Zähler der HALL Impulse
// Der Modifizierer "volatile" teilt dem Compiler mit,
// daß eine Variable möglicherweise von einer
// Hintergrundroutine, einer Interruptroutine
// oder einem I/O-Port verändert wird.
//---------------------------------------------------------------------
//----------------INTERRUPT ROUTINE EXTERN ÜBER INT0-------------------
ISR (INT0_vect) // Interruptroutine für den INT0 - PortD2
{ // hier Hall Sensor Auswertung PAN (weisse Leitung)
PZaehler++; // sobald Flanke am PAN Motor, Zähler erhöhen
}
//----------------INTERRUPT ROUTINE EXTERN ÜBER INT1-------------------
ISR (INT1_vect) // Interruptroutine für den INT1 - PortD3
{ // hier Hall Sensor Auswertung TILT (blaue Leitung)
TZaehler++; // sobald Flanke am TILT Motor, Zähler erhöhen
}
//----------------ALLEGEMIEN DELAY FUNKTION ------------------------------------------------------
void delay_us(unsigned int count)
{
_delay_loop_2(count);
}
//----------------PWM AUSGÄNGE B1, B2 INITIALISIEREN------------------------------------------------------
void initPWM()
{
DDRB=0b00000110; // PWM Ausgänge B1, B2
TCCR1A=0b10100011; // Timer/Counter 1 Control Register A
TCCR1B=0b00000010; // Timer/Counter 1 Control Register B
}
//----------------PORTS INITILAISIEREN ------------------------------------------------------
void initPORTS()
{
DDRB = 0b11111111; // PORT-B = als Ausgang festlegen
DDRC = 0b00000000; // PORT-C = als Eingang festlegen
PORTC = 0b00111111; // PORT-C = PULL-UP
DDRD = 0b00000000; // PORT-D = als Eingang festlegen
PORTD = 0b11111111; // PORT-D = PULL-UP
}
//----------------EXTERE INTERRUPT EINGÄNGE INITIALISIEREN------------------------------------------------------
void initEXISR()
{
GICR = 0b01000000; // für mega8 - Bit 7,6 - Exteren Interrupt einschalten für INT1, INT0 also PORTD3,2
//EIMSK = 0b00000011; // für mega 168 - Bit 1,0 - Exteren Interrupt einschalten für int1, int0 also PORTD3,2
MCUCR = 0b00001010; // Interrupt bei fallende Flanke, int0:PORTD2 - für PAN, int1:PORTD3 - für TILT
}
//----------------UART INITIALISIERUNG------------------------------------------------------
void initUART()
{
UBRRL = 23; //für mega 8 - 9600Baud siehe Baudratentabelle
UCSRB = 8 + 16; //Sender enable, (Empfänger enable)
}
//----------------UART SENDEFUNKTION FÜR 1 ZEICHEN (8 BIT)-------------------
void putChar (char data) // sendet nur ein 8Bit Zeichen
{
//warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
while (!(UCSRA&32));
//sende
UDR=data;
}
//----------------UART SENDEFUNKTION FÜR ZEICHENKETTE------------------------
void putChar(char *buffer)
{
for (int i=0; buffer[i] !=0;i++)
putChar (buffer[i]);
}
//----------------UART SENDEFUNKTION FÜR ZAHL 16BIT------------------------
void uart_uint(uint16_t zahl)
{
unsigned char text[20];
int ziffer;
int i = 0;
do
{
ziffer = zahl % 10; // ziffer ist die erste Ziffer 128->8
zahl = ( zahl - ziffer ) / 10; // zahl ist nun Restziffer(n) 128->12
text[i++] = ziffer + 0x30;
}
while ( zahl != 0 ); // solange Restziffern da sind
while (i > 0)
{
putChar( text[--i] );
}
}
//----------------TASTENAUSWERTUNG für PAN & TILT MIT RICHTUNG------------------------
void TastenSTG()
{
if (!(PINC&0b00000100)) PRichtung=1; // PAN, Bit 2 = 0 -> Drehrichtung WESTEN
if (!(PINC&0b00001000)) PRichtung=-1; // PAN, Bit 3 = 0 -> Drehrichtung OSTEN
if (!(PINC&0b00010000)) TRichtung=1; // TILT, Bit 4 = 0 -> Drehrichtung SÜDEN
if (!(PINC&0b00100000)) TRichtung=-1; // TILT, Bit 5 = 0 -> Drehrichtung NORDEN
}
//------------------------------- MOTORSTEUERUNG---------------------------------
//--------------------------------------------------------------------------------
// ---------------------------- PAN MOTOR --------------------------------
void PanMotorGo(int PDir, int PWeg)
{
while (PDir==1) // PAN Drehrichtung -> WESTEN
{
PDir=0; // setzte Drehrichtung wieder auf null -> damit nur ein Durchlauf
putChar(" PZ_:"); // Kontrollausgabe
uart_uint(PZaehler); // PAN Zählerstand über UART
putChar("B"); // Kontrollausgabe, Zeilenumbruch
PKorrektur=PZaehler-PZaehler_A-PWeg_Kor; // Berechne Korrekturwert für nächsten lauf
PZaehler_A=PZaehler; // merke Zählerstand vor dem Lauf
PWeg_Kor=PWeg-PKorrektur; // Berechne korrigierten Weg
while (PZaehler<PZaehler_A+PWeg_Kor-5) // Laufe solange bis gewünschter Zählerstand-Rampe erreicht
{
OCR1A=1000; // schneller Lauf, mit hohem PWM Wert
PORTB|=0b00000001; // Laufe Drehrichtung WESTEN
}
while (PZaehler<PZaehler_A+PWeg_Kor) // Laufe Rest solange bis Rampe zuende
{
OCR1A=500; // lansamer Lauf, mit reduziertem PWM Wert
PORTB|=0b00000001; // Laufe Drehrichtung WESTEN
}
}
while (PDir==-1) // PAN Drehrichtung -> OSTEN
{
PDir=0; // setzte Drehrichtung wieder auf null -> damit nur ein Durchlauf
putChar(" PZ_:"); // Kontrollausgabe
uart_uint(PZaehler); // PAN Zählerstand über UART
putChar("B"); // Kontrollausgabe, Zeilenumbruch
PKorrektur=PZaehler-PZaehler_A-PWeg_Kor; // Berechne Korrekturwert für nächsten lauf
PZaehler_A=PZaehler; // merke Zählerstand vor dem Lauf
PWeg_Kor=PWeg-PKorrektur; // Berechne korrigierten Weg
while (PZaehler<PZaehler_A+PWeg_Kor-5) // Laufe solange bis gewünschter Zählerstand- Rampe erreicht
{
OCR1A=1000; // schneller Lauf, mit hohem PWM Wert
PORTB|=0b00001000; // Laufe Drehrichtung OSTEN
}
while (PZaehler<PZaehler_A+PWeg_Kor) // Laufe Rest solange bis Rampe zuende
{
OCR1A=500; // lansamer Lauf, mit reduziertem PWM Wert
PORTB|=0b00001000; // Laufe Drehrichtung OSTEN
}
}
PORTB&=0b11110110; // Keine Taste gedrückt -> also STOP, Bit 0&3->0
}
// ---------------------------- TILT MOTOR --------------------------------
void TiltMotorGo(int TDir, int TWeg)
{
while (TDir==1) // TILT Drehrichtung -> SÜDEN
{
TDir=0; // setzte Drehrichtung wieder auf null -> damit nur ein
putChar(" TZ_:"); // Kontrollausgabe
uart_uint(TZaehler); // TILT Zählerstand über UART
putChar("B"); // Kontrollausgabe, Zeilenumbruch
TKorrektur=TZaehler-TZaehler_A-TWeg_Kor; // Berechne Korrekturwert für nächsten lauf
TZaehler_A=TZaehler; // merke Zählerstand vor dem Lauf
TWeg_Kor=TWeg-TKorrektur; // Berechne korrigierten Weg
while (TZaehler<TZaehler_A+TWeg_Kor-5) // Laufe solange bis gewünschter Zählerstand-Rampe erreicht
{
OCR1B=1000; // schneller Lauf, mit hohem PWM Wert
PORTB|=0b000010000; // Laufe Drehrichtung SÜDEN
}
while (TZaehler<TZaehler_A+TWeg_Kor) // Laufe Rest solange bis Rampe zuende
{
OCR1B=500; // lansamer Lauf, mit reduziertem PWM Wert
PORTB|=0b000010000; // Laufe Drehrichtung SÜDEN
}
}
while (TDir==-1) // TILT Drehrichtung -> NORDEN
{
TDir=0; // setzte Drehrichtung wieder auf null -> damit nur ein
putChar(" TZ_:"); // Kontrollausgabe
uart_uint(TZaehler); // TILT Zählerstand über UART
putChar("B"); // Kontrollausgabe, Zeilenumbruch
TKorrektur=TZaehler-TZaehler_A-TWeg_Kor; // Berechne Korrekturwert für nächsten lauf
TZaehler_A=TZaehler; // merke Zählerstand vor dem Lauf
TWeg_Kor=TWeg-TKorrektur; // Berechne korrigierten Weg
while (TZaehler<TZaehler_A+TWeg_Kor-5) // Laufe solange bis gewünschter Zählerstand- Rampe erreicht
{
OCR1B=1000; // schneller Lauf, mit hohem PWM Wert
PORTB|=0b000100000; // Laufe Drehrichtung NORDEN
}
while (TZaehler<TZaehler_A+TWeg_Kor) // Laufe Rest solange bis Rampe zuende
{
OCR1B=500; // lansamer Lauf, mit reduziertem PWM WertM
PORTB|=0b000100000; // Laufe Drehrichtung NORDEN
}
}
PORTB&=0b11001111; // Keine Taste gedrückt -> also STOP, Bit 4&5->0
}
// ********************* HAUPTBPROGRAMMTEIL ******************************
// **********************************************************************
// **********************************************************************
main (void)
{
// ************************ Variablen *******************************
// ********************* Initialisierungen **************************
initPWM(); //Initialisiere PWM Ausgänge
initPORTS(); //Initialisiere die Ports
initEXISR(); //Initialisiere den Exteren Interrupt
initUART(); //Initialisiere UART für Kontrollausgabe
sei(); //Ermögliche Interrupts
// ************************* HAUPTSCHLEIFE *****************************
// **********************************************************************
while (true) // Mainloop
{
TastenSTG(); // Tastenabfrage für Motorstart mit jew. Richtung
PanMotorGo(PRichtung,100); // Fahre PAN Achse in jew. Richtung mit 100 Schritten
TiltMotorGo(TRichtung,100); // Fahre TILT Achse in jew. Richtung mit 100 Schritten
_delay_ms(100); // warte 100 ms bis Motor endgülig steht
// AUSGABE der Variablen über UART zu Kontrollzwecken
if (PRichtung!=0) // Einmalige Kontrollausgabe über UART nach PAN Lauf
{
putChar(" PK:"); // Kontrollausgabe PAN Korrekturwert
uart_uint(PKorrektur);
putChar(" PZ_A:"); // Kontrollausgabe PAN Zählerstand am Anfang
uart_uint(PZaehler_A);
putChar(" PW_K:"); // Kontrollausgabe PAN korrigierter Weg
uart_uint(PWeg_Kor);
putChar(" PZ:"); // Kontrollausgabe PAN Zähler der HALL Impulse
uart_uint(PZaehler);
putChar("B"); // Zeilenumbruch
putChar("B"); // Zeilenumbruch
}
if (TRichtung!=0) // Einmalige Kontrollausgabe über UART nach TILT Lauf
{
putChar(" TK:"); // Kontrollausgabe TILT Korrekturwert
uart_uint(TKorrektur);
putChar(" TZ_A:"); // Kontrollausgabe TILT Zählerstand am Anfang
uart_uint(TZaehler_A);
putChar(" TW_K:"); // Kontrollausgabe TILT korrigierter Weg
uart_uint(TWeg_Kor);
putChar(" TZ:"); // Kontrollausgabe TILT Zähler der HALL Impulse
uart_uint(TZaehler);
putChar("B"); // Zeilenumbruch
putChar("B"); // Zeilenumbruch
}
PRichtung=0; // PAN Drehrichtung wieder auf Null -> Motor Stop
TRichtung=0; // TILT Drehrichtung wieder auf Null -> Motor Stop
}
}
// ************************* ENDE HAUPTSCHLEIFE ************************
// **********************************************************************
Lesezeichen