Staind
26.10.2011, 02:38
Hallo,
ich bin noch ein ziemlicher Neuling wenn es ums uC programmieren geht. Ich weiß auch das hier ältliche Themen über PWM stehen, wie es funktioniert. Naja wie es funktioniert weiß ich in der Regel schon.
Meine Servos kann ich auch ansteuern, aber halt nicht präzise.
Habe ein Atmega644 (6PWM Ausgänge (2x10Bit/4x8Bit)) der mit einen 16 Mhz Quarzoszillator getaktet ist.
Hier versuche ich mal mein Problem zu beschreiben
Habe wie im unteren Bild, oberes Signal, folgende Impulse. Wenn ich für OCR0A den Wert 8 eingebe (Den Wert OCR0A = 8 kann mit Hilfe eines C# Programmes, welches ich geschrieben habe ändern)
habe ich ein Impuls von 0,6ms und der Servo steht ganz links. Wenn ich dagegen den Wert 39 eingebe steht der Servo ganz rechts. Somit habe ich 31 Schritte um den Servo von links nach rechts zu fahren. Dieses ist mir aber zu grob...
20373
Darum meine Frage: Kann man die Impulse Zählen so das nur jeder 4te Impuls ausgegeben wird? Habe hierzu nochmal ein Bild gezeichnet.
Hier habe ich eine Periode von 4ms. Wenn ich jetzt nur jeden 4ten Impuls durchlasse so kann ich die Servos mit 122 Schritten genauer steuern.
20374
Ist das möglich? Wenn ja wie realisier ich das?
ich gebe euch mal mein Programm mit rein vielleicht könnt ihr da ein wenig dran rumbasteln und das für ein PWM Signal fertig machen. Ober ein Linkverweis, wo genau das beschrieben ist wäre auch nicht schlecht.
//-------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------//
// //
// Miniprojekt Roboterarm V.1.0 //
// von Thomas B. & André K. //
// //
//-------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------
// Include Datein
//-------------------------------------------------------------------------------------------
#include <avr/io.h>
#include <inttypes.h>
#include "lcd-routines.h" //LCD-Display
#include <util/delay.h>
#define BAUD 9600UL // Baud einstellen 9600
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
//-------------------------------------------------------------------------------------------
// Methoden
//-------------------------------------------------------------------------------------------
// USART initialisieren
uart_init(void)
{
// Baudrate einstellen (Normaler Modus)
UBRR0H = (uint8_t) (UBRR_BAUD>>8);
UBRR0L = (uint8_t) (UBRR_BAUD & 0x0ff);
// Aktivieren von receiver und transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSR0C = (1<<UCSZ01)|(3<<UCSZ00);
}
//-------------------------------------------------------------------------------------------
// Hauptschleife
//-------------------------------------------------------------------------------------------
main(void)
{
//-------------------------------------------------------------------------------------------
// Initialisierung
//-------------------------------------------------------------------------------------------
uart_init();
lcd_init();
// Variablen
uint8_t buffer=150;
//PWM 1 & PWM 2
DDRD = (1 << PD4 )|(1 << PD5 );
TCCR1A = (1<<WGM11) | (1<<COM1A1)|(1<<COM1B1);
TCCR1B = (1<<CS12)|(1<<WGM13)|(1<<WGM12);
ICR1 = 800; //Zählt bis zu diesen Wert
OCR1A = 120; //Bei diesen Wert wird eine 0 gesetzt
OCR1B = 200; //Bei diesen Wert wird eine 0 gesetzt
//PWM 3 & PWM 4
DDRB = (1 << PB3 )|(1 << PB4 );
TCCR0A = (1<<WGM01) |(1<<WGM00) | (1<<COM0A1) |(1<<COM0B1);
TCCR0B = (1<<CS00) |(1<<CS02);
OCR0A = 120;
OCR0B = 120;
//PWM 5 & PWM 6
DDRD |= (1 << PD6 )|(1 << PD7 );
TCCR2A = (1<<WGM21) |(1<<WGM20) | (1<<COM2A1) |(1<<COM2B1);
TCCR2B = (1<<CS20) |(1<<CS21) |(1<<CS22)|(0<<WGM22); // Datenblatt S.149
OCR2A = 120;
OCR2B = 120;
//-------------------------------------------------------------------------------------------
// Display
//-------------------------------------------------------------------------------------------
//Zeile 1
lcd_setcursor( 0, 1) ;
lcd_string("Zeile 1");
//Zeile 2
lcd_setcursor( 0, 2 );
lcd_string("Zeile 2");
//Zeile 3
lcd_setcursor( 20, 1 );
lcd_string("Zeile 3");
//Zeile 4
lcd_setcursor( 20, 2 );
lcd_string("Zeile 4");
//-------------------------------------------------------------------------------------------
// Schleife
//-------------------------------------------------------------------------------------------
while (1)
{
// Warten bis Daten empfangen wurden
if ( (UCSR0A & (1<<RXC0)) )
{
buffer = UDR0;
}
else
{
}
OCR2B=buffer;
}
return 0; // never reached
}
Hoffe auf schnelle Antwort. Muss in den Ferien noch viel schaffen.
Gruß André
ich bin noch ein ziemlicher Neuling wenn es ums uC programmieren geht. Ich weiß auch das hier ältliche Themen über PWM stehen, wie es funktioniert. Naja wie es funktioniert weiß ich in der Regel schon.
Meine Servos kann ich auch ansteuern, aber halt nicht präzise.
Habe ein Atmega644 (6PWM Ausgänge (2x10Bit/4x8Bit)) der mit einen 16 Mhz Quarzoszillator getaktet ist.
Hier versuche ich mal mein Problem zu beschreiben
Habe wie im unteren Bild, oberes Signal, folgende Impulse. Wenn ich für OCR0A den Wert 8 eingebe (Den Wert OCR0A = 8 kann mit Hilfe eines C# Programmes, welches ich geschrieben habe ändern)
habe ich ein Impuls von 0,6ms und der Servo steht ganz links. Wenn ich dagegen den Wert 39 eingebe steht der Servo ganz rechts. Somit habe ich 31 Schritte um den Servo von links nach rechts zu fahren. Dieses ist mir aber zu grob...
20373
Darum meine Frage: Kann man die Impulse Zählen so das nur jeder 4te Impuls ausgegeben wird? Habe hierzu nochmal ein Bild gezeichnet.
Hier habe ich eine Periode von 4ms. Wenn ich jetzt nur jeden 4ten Impuls durchlasse so kann ich die Servos mit 122 Schritten genauer steuern.
20374
Ist das möglich? Wenn ja wie realisier ich das?
ich gebe euch mal mein Programm mit rein vielleicht könnt ihr da ein wenig dran rumbasteln und das für ein PWM Signal fertig machen. Ober ein Linkverweis, wo genau das beschrieben ist wäre auch nicht schlecht.
//-------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------//
// //
// Miniprojekt Roboterarm V.1.0 //
// von Thomas B. & André K. //
// //
//-------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------//
//-------------------------------------------------------------------------------------------
// Include Datein
//-------------------------------------------------------------------------------------------
#include <avr/io.h>
#include <inttypes.h>
#include "lcd-routines.h" //LCD-Display
#include <util/delay.h>
#define BAUD 9600UL // Baud einstellen 9600
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
//-------------------------------------------------------------------------------------------
// Methoden
//-------------------------------------------------------------------------------------------
// USART initialisieren
uart_init(void)
{
// Baudrate einstellen (Normaler Modus)
UBRR0H = (uint8_t) (UBRR_BAUD>>8);
UBRR0L = (uint8_t) (UBRR_BAUD & 0x0ff);
// Aktivieren von receiver und transmitter
UCSR0B = (1<<RXEN0)|(1<<TXEN0);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSR0C = (1<<UCSZ01)|(3<<UCSZ00);
}
//-------------------------------------------------------------------------------------------
// Hauptschleife
//-------------------------------------------------------------------------------------------
main(void)
{
//-------------------------------------------------------------------------------------------
// Initialisierung
//-------------------------------------------------------------------------------------------
uart_init();
lcd_init();
// Variablen
uint8_t buffer=150;
//PWM 1 & PWM 2
DDRD = (1 << PD4 )|(1 << PD5 );
TCCR1A = (1<<WGM11) | (1<<COM1A1)|(1<<COM1B1);
TCCR1B = (1<<CS12)|(1<<WGM13)|(1<<WGM12);
ICR1 = 800; //Zählt bis zu diesen Wert
OCR1A = 120; //Bei diesen Wert wird eine 0 gesetzt
OCR1B = 200; //Bei diesen Wert wird eine 0 gesetzt
//PWM 3 & PWM 4
DDRB = (1 << PB3 )|(1 << PB4 );
TCCR0A = (1<<WGM01) |(1<<WGM00) | (1<<COM0A1) |(1<<COM0B1);
TCCR0B = (1<<CS00) |(1<<CS02);
OCR0A = 120;
OCR0B = 120;
//PWM 5 & PWM 6
DDRD |= (1 << PD6 )|(1 << PD7 );
TCCR2A = (1<<WGM21) |(1<<WGM20) | (1<<COM2A1) |(1<<COM2B1);
TCCR2B = (1<<CS20) |(1<<CS21) |(1<<CS22)|(0<<WGM22); // Datenblatt S.149
OCR2A = 120;
OCR2B = 120;
//-------------------------------------------------------------------------------------------
// Display
//-------------------------------------------------------------------------------------------
//Zeile 1
lcd_setcursor( 0, 1) ;
lcd_string("Zeile 1");
//Zeile 2
lcd_setcursor( 0, 2 );
lcd_string("Zeile 2");
//Zeile 3
lcd_setcursor( 20, 1 );
lcd_string("Zeile 3");
//Zeile 4
lcd_setcursor( 20, 2 );
lcd_string("Zeile 4");
//-------------------------------------------------------------------------------------------
// Schleife
//-------------------------------------------------------------------------------------------
while (1)
{
// Warten bis Daten empfangen wurden
if ( (UCSR0A & (1<<RXC0)) )
{
buffer = UDR0;
}
else
{
}
OCR2B=buffer;
}
return 0; // never reached
}
Hoffe auf schnelle Antwort. Muss in den Ferien noch viel schaffen.
Gruß André