Hallo Leute, ich habe ein Problem mit der µC Programmierung. Ich bin leider noch ein ziemlicher Anfänger in dieser Geschichte. Ich würde gerne einen Motor mit einem PWM ansteuern. Die Drehzahl soll durch einen Analogeingang erfolgen. Dieser hat eine Spannung von 0-5V. Bei 10Bit sozusagen von 0-1023 Werte. Das einlesen der Analogwerte funktioniert soweit. Es wäre super wenn mir einer Helfen könnte diese Werte auf ein PWM-Signal zu übertragen für eine Geschwindigkeitsregelung. Als µC verwende ich einen at90can. Der PWM Ausgang liegt auf dem PINB6 und der Analog eingang ist der PINF0. Gruß Alex
Also grob durch 4 teilen geht immer recht gut. Damit kommst du in etwa auf 8bit PWM-Werte. 1023 / 4 = 255.75 Programmablauf wäre dann in etwa so: 1. ADC einlesen 2. Wert durch 4 teilen 3. Wert ausgeben 4. Zurück zu 1 MfG Leonhard
Alex schrieb: > Das einlesen der Analogwerte funktioniert soweit. > Es wäre super wenn mir einer Helfen könnte diese > Werte auf ein PWM-Signal zu übertragen für > eine Geschwindigkeitsregelung. Regeln oder Stellen? Für eine Regelung brauchst du eine Rück-'Meldung' vom Motor. Sprich du müsstest die effektive Motordrehzahl messen und mit der Vorgabe aus dem ADC Wert vergleichen. Ist die effektive Drehzahl zu niedrig, dann muss die PWM erhöht werden, damit der Motor die Vorgabedrehzahl erreicht. Ein Steller hingegen nimmt einfach den ADC Wert und errechnet sich daraus einen Wert den er auf die PWM gibt. Wie schnell dann auch immer der Motor mit dieser Einstellung dreht. Und ach ja. Die PWM machst du in Hardware, wobei ich jetzt nicht weiß, an welchem Pin bei deinem µC die PWM abgegriffen werden kann. FAQ: Timer
Danke für die Antowrten. Ehm ne nicht regeln sonder stellen. Ok danke werd mir mal des mit den Timern durchlesen. Gruß Alex
Hallo Leute, also es tut immer noch nicht. Leider habe ich kein Oszi da um den PWM Ausgang zu testen. Mein Code sieht wie folgt aus: #include <avr/io.h> #include <avr/interrupt.h> #include "lcd_ks0066_4bit_io.h" #include "Define_Inputs.h" #include "Define_Outputs.h" #include <stdlib.h> #include <inttypes.h> void initial(void) { // **** Einrichten von Ein- und Ausgängen ******************************************************* DDRB = 0x40; // PortD Ausgänge // **** Einrichten von PWM Betrieb *************************************************************** // Der Timer 0 wird im Fast PWM Modus betrieben TCCR0A = ((1 <<WGM01)|(1<<WGM00)) ;// waveform generation mode auf "Fast PWM" setzen // WGM02 in TCCR0B bleibt auf 0 (default) TCCR0A |=(1<<COM0A1 ) ; // set compare output mode to non inverting mode) // COM0A0, COM0B1 and COM0B0 bleiben auf 0 (default) //TCCR0B =(1<<CS01|1<<CS00);// set clk prescaler to 64 (macht 122,1Hz PWM Frequenz) TCCR0A =(1<<CS02 ) ; // set clk prescaler to 256 (macht 15,3Hz PWM Frequenz) // WGM02, FOC0A and FOC0B bleiben auf 0 (default) OCR0A=0; // set initial value of OCR0A (0x00 erzeugt einen spike am output) TCNT0 = 0 ; // reset timer / counterregister sei() ; } void ADC_Init(void) { uint16_t result; ADMUX = (1<<REFS0); // AVCC als Referenzspannung nutzen ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler 8 ==> 1.000.000/8 = 125.000Hz ADCSRA |= (1<<ADEN); // ADC aktivieren /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */ ADCSRA |= (1<<ADSC); // eine ADC-Wandlung while (ADCSRA & (1<<ADSC) ); // auf Abschluss der Konvertierung warten /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen. */ result = ADCW; } // *ADC Einzelmessung ************************************************************************ ****** uint16_t ADC_Read( uint8_t ch ) { // select the corresponding channel 0~7 // ANDing with '7' will always keep the value // of 'ch' between 0 and 7 ch &= 0b00000111; // AND operation with 7 ADMUX = (ADMUX & 0xF8)|ch; // clears the bottom 3 bits before ORing // start single conversion // write '1' to ADSC ADCSRA |= (1<<ADSC); // wait for conversion to complete // ADSC becomes '0' again // till then, run loop continuously while(ADCSRA & (1<<ADSC)); return (ADC); } // ************************************************************************ ********** // Display integer 0-9999 // Durch geschicktes multiplizieren und dividieren wird die Integer-Zahl // in ihre einzelnen Stellen zerlegt und diese dann am LCD ausgegeben. // Es wird nicht abgefragt, ob die Zahl größer als 9999 ist! // Währe dies der Fall, wird ein falsches Zeichen am LCD angezeigt. // ************************************************************************ ********** void print4(unsigned int x) { unsigned int y; y=x/1000;lcd_data(y+0x30);x-=(y*1000); y=x/100;lcd_data(y+0x30);x-=(y*100); y=x/10;lcd_data(y+0x30);x-=(y*10); lcd_data(x+0x30); } int main(void) { //++++++++++ INPUTS +++++++++++++ //########## Digital ############ DDRA |= 0x00; PORTA = 0xF8; //########## Analog ############# DDRF |= (0<<PINF0) | (0<<PINF1); PORTF = 0x00; //++++++++++ OUTPUTS ++++++++++++ DDRB |= (1<<PINB4) | (1<<PINB5); // High-Side Ausgang X13/14 als Ausgang deklariert DDRC |= (1<<PINC5) | (1<<PINC6); // High-Side Ausgang X15/16 als Ausgang deklariert DDRE |= (1<<PINE4) | (1<<PINE5) |(1<<PINE6) |(1<<PINE7); // Die Pins E4,5,6,7 wurden als Outputs deklariert // H-Brücke DDRG |= (1<<PING2); DDRC |= (1<<PINC7); DDRB |= (1<<PINB6); DDRE |= (1<<PINE6) | (1<<PINE7); //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // H-Bridge Ausgabe // Enable if(STATE_DI3_INPUT_X5) { PORTC &= ~(1<<ENABLE_H_Bridge_A_PINC7); PORTG &= ~(1<<ENABLE_H_Bridge_B_PING2); } else { PORTC |= 0x80; // PINC7 PORTG |= 0x04; // PING2 } // Motor links rechts lauf if (STATE_DI4_INPUT_X6) { PORTE &= ~(1<<OUT_H_Bridge_Right_A_PINE6); PORTE |= 0x80; //PINE7 } else { PORTE &= ~(1<<OUT_H_Bridge_Left_B_PINE7); PORTE |= 0x40; //PINE6 } //############################################### // AD Wandlung int variable = 0; char pwm_sollwert = 0; initial(); // Initialisierung Ports etc. ADC_Init(); // Initialisierung Analogeingang lcd_init(LCD_DISP_ON); lcd_clrscr(); while(1) { // *LCD Anzeige ******************************************************************** variable = ADC_Read(0); lcd_gotoxy(0,0); lcd_data( 'A' ); // Ausgabe einzelner Zeichen am LCD lcd_data( 'D' ); lcd_data( 'C' ); lcd_data( '0' ); lcd_data( '=' ); print4(variable); // Ausgabe einer vierstelligen Integer-Zahl am LCD _delay_us(20); // ************************************************************************ ************************ // *PWM Sollwert setzen ******************************************************************** pwm_sollwert = variable/4; // hätte man auch direkt nach OCR0A speichern können OCR0A=(pwm_sollwert); // ************************************************************************ ************************ } // Ende while(1)Endlosschleife return 0; } Mich würde jetzt interressieren ob dies funktioniert sprich ob der PWM Ausgang PB6 ein PWM ausgibt mit dem Wert "pwm_sollwert". Danke schon mal für die Hilfe Gruß Alex
Alex schrieb: > TCCR0A =(1<<CS02 ) ; // set clk prescaler to 256 (macht 15,3Hz PWM > Frequenz) Wenn ich da durch deine auskommentierten Zeilen richtig durchblicke, machst du mit dieser Zeile die gesamte vorige Initialisierung wieder platt. Als PWM Test kannst du an den Ausgang eine LED anschliessen (mit 220R -330R Vorwiderstand). Übrigens ist PB7 der Ausgang für OC0A, nicht PB6.
Ok danke. Ja hab des im Inet gefunden und mal ein bisschen umgeschrieben. Werde gleich mal des testen bzw umschreiben. DANKE
also bis jetzt tut sich noch nix. Mal dumm gefragt: Kann ich Theoretisch auch mit einem Multimeter das PWM testen? Einfach um zu schauen ob der Ausgang schaltet. Ah ja ich habe keine 1Mhz Taktfrequenz sonder 16. Die Auskomentierung habe ich noch nicht geändert da ich dieses Programm aus dem inet habe. Zum Thema testen: Also ich habe einen Motor angeschlossen an eine H-Brücke. Somit kann ich die Sache testen. Dies funktioniert auch. Ich habe Einfach von hand 5V angeschlossen und der Motor hat sich gedreht. Gruß Alex
Alex schrieb: > also bis jetzt tut sich noch nix. Wirf den Code weg und schreib ihn neu. Aber diesmal schreibst du ihn selber und holst dir maximal von einem einfachen PWM-Beispiel den Code zur Ansicht. Dein erstes Programm hat keinen ADC, keine UART, kein LCD, kein gar nichts, sondern nur die PWM.
1 | int main() |
2 | {
|
3 | Pins auf Ausgang stellen |
4 | |
5 | Timer konfigureieren |
6 | und auf PWM einstellen |
7 | |
8 | while( 1 ) { |
9 | OCR0A = 128; |
10 | }
|
11 | }
|
(die fehlenden Teile schreibst DU!) und damit testest du erst mal, ob deine Hardware überhaupt funktioniert, ob sich also dein Motor dreht. Danach veränderst du die 128 im COde auf andere Werte und beobachtest deinen Motor, ob er jetzt mit anderer Drehzahl dreht. Und erst dann, wenn dieser Punkt abgehakt ist, erst dann nimmst du die ADC mit dazu! Nicht alles auf einmal. Sonst stehst du mit einem Haufen Code da, der nicht funktioniert, und von dem du keine Ahnung hast, wo du mit Fehlersuche anfangen sollst. Immer in Schritten arbeiten, wobei man mit ganz einfachem Code anfängt, den testet und dann nach und nach in die richtige Richtung ausbaut. Eigentlich fehlt da sogar noch eine Vorstufe. Ehe man eine PWM auf die Pins loslässt, schaltet man sie ganz einfach erst mal von Hand auf 'Motor soll VOllgas drehen' - einfach Pin auf Ausgang und nach Bedarf eine 1 bzw. 0 an die jeweiligen Pins.
> Kann ich Theoretisch auch mit einem Multimeter das PWM testen? > Einfach um zu schauen ob der Ausgang schaltet. Niemand hindert dich daran, da ein VOltmeter drann zu halten. Aber eine LED ist deutlich einfacher. Ist der Pin auf 0, dann leuchtet die LED (oder umgekehrt, je nachdem wie sie angeschlossen ist), bzw. sie leuchtet nicht. Toggelt der Pin mit unterschiedlichen Tastgraden, dann leuchtet die LED eben nicht mehr voll, sondern in unterschiedlichen Dimmgraden. Da genügt 1 Blick von der Ferne um das zu erfassen und man muss keine Zahlenwerte ablesen und interpretieren.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.