Hallo zusammen, ich habe mir gerade das Tutorial zu "Motoransteuerung mit PWM" angeschaut. Möchte dann das ganze mal praktisch mit dem beiligen Schaltplan aufbauen. Könnt ihr mal drüberschauen, ob das mit den ausgesuchten Bauteilen so passt? Ich weiß, dass Symbol für den Mosfet ist falsch, aber VISIO gibt nichts anderes her. Als µC verwende ich einen ATmega16. Den Motor hab ich aus nem alten Funkgesteuerten Modellauto. Den Mosfet habe ich ausgewählt, weil man ihn laut Datenblatt direkt mit den 5V der PWM betreiben kann. Den Kondensator habe ich hier rumliegen, im Tutorial wird ein 1000µF verwendet, reichen meine 470µF aus? Der µC ist nich auf dem Schaltplan, da ich ein STK500 verwende. Danke und Gruße Luke
:
Verschoben durch Admin
der Motor sollte vielleicht noch mit 1 o. 2 o. 3. Kondensatoren funkentstört sein, vielleicht noch ein Widerstand an das Gate des Fets, man könnte auch noch einen Kondensator parallel zur Diode anbringen, die Diode sollte Schotky sein, aber sonst wird das z.B. im RC-Modelbau auch genauso benutzt.
Hallo OlliW, danke für die schnelle Antwort. Der Motor ist bereits funkentstört. Habe die Diode durch eine SB 120 Schotky ersetzt. Einen Widerstand am Gate habe ich auch eingefügt. Laut Datenblatt soll dies 25 Ohm haben. Wie meinst du "man könnte auch noch einen Kondensator parallel zur Diode anbringen" Hab es im Schaltplan mal so eingezeichnet, richtig so? Welche Kapazität sollte dieser Kondensator dann haben? Danke!
luke schrieb: > Wie meinst du > "man könnte auch noch einen Kondensator parallel zur Diode anbringen" 10nF Keramisch, möglichst nah am Motor befestigen. Kann man auch weglassen.
Ich würde noch einen widerstand von gate nach masse empfehlen. So hat der mosfet einen definierten leitzustand (aus) auch wenn der pin des µC eventuell mal hochohmig ist.
Ok, danke für eure antworten! Den 10nF Kondensator werde ich noch berücksichtigen. Wie groß sollte der Widerstand von gate nach masse den ca. sein? Ziemlich klein, oder? Danke!
luke schrieb: > Ok, danke für eure antworten! > Den 10nF Kondensator werde ich noch berücksichtigen. > > Wie groß sollte der Widerstand von gate nach masse den ca. sein? > Ziemlich klein, oder? Ich würde eher sagen: ziemlich groß, damit der Ausgangspin möglichst wenig dagegen ankämpfen muss, wenn er das Gate auf Vcc ziehen will. Ich würde mal so um die 1k oder 10k vorschlagen. Es geht ja nur darum, dass es eine Verbindung zu Masse gibt, sollte der 'reguläre Eingang' noch kein sinnvolles Eingansgssignal erhalten.
Durch den Widerstand gegen Masse ergibt sich ja dann praktisch mit dem 27 Ohm Widerstand zusammen ein Spannungsteiler. Die Ausgangspannung sollte dann ja trotzdem noch nahe an den 5V liegen. Richtig? (10k / (10k + 27)) x 5V = 4,986V Hört sich gut an!? Sry für die plumpen fragen ;) Hab auch mal nen überarbeiteten Schaltplan beigefügt. Danke!
Ja, das sieht gut aus. Ich sehe keinen grund, warum es nicht funktionieren sollte. Viel glück bei der inbetriebnahme xD. Schreib uns, ob alles geklappt hat.
Falls du noch Probleme beim µC bekommst, kannst du die Versorgungen für Controller und Motor mit jeweils einem LC-Glied entkopplen. Als Richtwert: 47µH für die Motorseite, 1µH für die µC-Seite.
Hallo zusammen, habe nun eine Frage zur Programmierung. Die Erzeugung eines PWM - Signal funktioniert soweit. Verwende dazu die 8Bit "Phase-Correct-PWM". Das PWM - Signal möchte ich nun verändern (0-254) um unterschiedliche Drehzahlen des Motors zu erhalten. Dies soll mit Hilfe des UART und einer kleinen C# Anwendung geschehen. Da ich alles erst mal sehr einfach halt will, möchte ich den UART zunächst nicht im Interrupt Betrieb betreiben. Wie gesagt, die PWM läuft, jedoch lässt sich das PWM-Signal nicht verändern. Könnt ihr mal bitte drüberschauen ob es mit unten angegeben Code überhaupt so gehen würde? PS: verwende ein STK500 Danke
1 | #include <io.h> |
2 | #include <interrupt.h> |
3 | |
4 | void mcu_init(); |
5 | void pwm_init(); |
6 | void usart_init(uint16_t baudrate); |
7 | uint8_t usart_receive(); |
8 | |
9 | //======================VARIABLEN============================
|
10 | |
11 | uint8_t pwmlevel = 250; |
12 | |
13 | //=======================MAIN===============================
|
14 | |
15 | |
16 | int main(void) |
17 | {
|
18 | mcu_init(); |
19 | pwm_init(); |
20 | usart_init(11); |
21 | while(1) |
22 | {
|
23 | pwmlevel = usart_receive(); |
24 | }
|
25 | return(0); |
26 | }
|
27 | |
28 | |
29 | //=============================INIT===================================
|
30 | |
31 | void mcu_init() |
32 | {
|
33 | DDRA = 0xFF; |
34 | DDRD = 0xFF; |
35 | DDRC = 0xFF; |
36 | DDRD = 0xFE; // PDO = RxD Input |
37 | |
38 | PORTA = 0; |
39 | PORTB = 0; |
40 | PORTC = 0; |
41 | PORTD = 0; |
42 | |
43 | SP = RAMEND; |
44 | sei(); |
45 | |
46 | }
|
47 | |
48 | void pwm_init() |
49 | {
|
50 | TCCR1A = ((1<<COM1A1)|(1<<WGM10)); |
51 | TCCR1B = (1<<CS10); //PWM 1khz (Fclk/(2046*1kHz) |
52 | //Vorteiler = 1;
|
53 | OCR1A = pwmlevel; |
54 | }
|
55 | |
56 | void usart_init(uint16_t baudrate) |
57 | {
|
58 | UBRRH = (uint8_t)(baudrate >>8); |
59 | UBRRL = (uint8_t) baudrate; |
60 | |
61 | UCSRB |= ((1<<RXEN)|(1<<TXEN)); |
62 | UCSRC |= ((1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0)); |
63 | |
64 | }
|
65 | |
66 | //==============================UP===================================
|
67 | |
68 | uint8_t usart_receive() |
69 | {
|
70 | while(!(UCSRA & (1<<RXC))) |
71 | {
|
72 | }
|
73 | return UDR; |
74 | |
75 | }
|
C# Anwendung:
1 | public partial class Form1 : Form |
2 | {
|
3 | public Form1() |
4 | {
|
5 | InitializeComponent(); |
6 | }
|
7 | |
8 | private void bt_open_Click(object sender, EventArgs e) |
9 | {
|
10 | serialPort1.Open(); |
11 | }
|
12 | |
13 | private void bt_send_Click(object sender, EventArgs e) |
14 | {
|
15 | serialPort1.WriteLine(tb_send.Text); |
16 | }
|
17 | |
18 | private void bt_close_Click(object sender, EventArgs e) |
19 | {
|
20 | serialPort1.Close(); |
21 | }
|
22 | }
|
luke schrieb: > habe nun eine Frage zur Programmierung. > Die Erzeugung eines PWM - Signal funktioniert soweit. Verwende dazu die > 8Bit "Phase-Correct-PWM". > Das PWM - Signal möchte ich nun verändern (0-254) um unterschiedliche > Drehzahlen des Motors zu erhalten. Dies soll mit Hilfe des UART und > einer kleinen C# Anwendung geschehen. Ehe du einen 2 Frontenkrieg aufmachst, solltest du erst mal eine Verbdindung von einem Terminalprogramm aus herstellen. Da weißt du zunächst mal, dass das Terminalprogramm auf PC_Seite tatsächlich funktioniert und auf der eingestellten Baudrate sendet. > while(1) > { > pwmlevel = usart_receive(); > } OK. Das erhaltene Zeichen (was auch immer das war), wird an pwmlevel zugewiesen. Nur: wie kommt es von dort ins Register OCR1A? die PWM wird verstellt, indem du in OCR1A einen anderen Wert einträgst. Was du an die Variable pwmlevel zuweist, interessiert die PWM einen feuchten Kehrricht.
> serialPort1.WriteLine(tb_send.Text);
lass mich raten:
In die Textbox gibst du zb 198 ein, und dann erwartest du, dass sich die
PWM auf 198 stellt.
Nope. So funktioniert das nicht.
Ein Grund mehr, dass du zunächst mal mit einem Terminalprogramm auf PC
Seite anfängst.
So wie du den µC programmierst, empfängt der 1 Zeichen und nimmt das als
Steuerwert für die PWM.
Schau in eine ASCII Tabelle. Jedes 'Zeichen' hat einen bestimmten Code.
zb ist der Code für 'A' die 0x41, oder dezimal 65. Drückst du am
Terminal daher die Buchstabentaste 'A' (großes A), dann wird der Code 65
an den µC geschickt und die PWM stellt sich auf 65 (wenn du die
Zuweisung richtig stellst und deine UART überhaupt funktioniert).
Drückst du '~', so hat die den ASCII Code 0x7E oder dezimal 126. Nach
dem Drücken der Taste stellt sich die PWM auf den Wert 126.
Aber ehe du dich auf nicht sichtbare Funktionalität verlässt (die UART
wird schon funktionieren), solltest du deren Funktion erst mal sicher
stellen. Sonst stocherst du schon wieder im Nebel.
Funktionen ohne Übergabeparameter müssen mit void deklariert werden: uint8_t usart_receive( void ) { while ... Nicht jeder Compiler macht das von alleine. > Wie gesagt, die PWM läuft, jedoch lässt sich das PWM-Signal nicht > verändern. In der while-Schleife in main veränderst du ja auch immer nur die Variable pwmlevel, setzt aber das zugehörige Timer-Register nicht.
Hallo zusammen, danke für eure Antworten! Habe meine main-schleife folgendermaßen geändert:
1 | int main(void) |
2 | {
|
3 | mcu_init(); |
4 | pwm_init(); |
5 | usart_init(11); |
6 | while(1) |
7 | {
|
8 | OCR1A = usart_receive(); |
9 | }
|
10 | return(0); |
11 | }
|
Verbinde ich den µC nun mit dem Terminalprogramm kann ich durch eintippen der Zeichen das PWM - Signal verändern. Muss dann meine C# - Anwendung in diese Richtung ändern. Vielen Dank!
Hallo zusammen, bin jetzt momentan soweit die PWM mit einer C# Anwendung zu verändern. Nun will ich per UART den aktuellen PWM-level (0-254 da 8-Bit-PWM), praktisch als Kontrolle, wieder an die C# Anwendung zurückgeben. Teste ich die Anwendung mit einem Terminalprogramm, bekomme ich im ASCII - Code alle werte von 0 - 254. Bekomme sie natürlich nicht dezimal, sondern in ASCII-Zeichen angezeigt. Meine C# Anwendung sieht folgendermaßen aus:
1 | private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) |
2 | {
|
3 | |
4 | string data = ""; |
5 | data = serialPort1.ReadExisting(); |
6 | |
7 | textBox1.Text = data; |
8 | }
|
Hier bekomme ich nun alle ASCII Zeichen bis 0-127 Angezeigt, natürlich wieder in ASCII-Zeichen. Ist das PWM-Level nun größer als 127, werden bis 254 nur "?" angezeigt. Das ganze hat ja bestimmt damit zu tun, dass ASCII eigentlich eine 7-Bit Zeichenkodierung ist. Kennt jemand einen Kniff um die Zeichen größer 127 in C# anzuzeigen? Der nächste Schritt wär dann, dass ASCII Zeichen in eine dezimalzahl zu wandeln. Da steh ich auch noch ein wenig auf dem Schlauch. Danke schonmal!
luke schrieb: > Der nächste Schritt wär dann, dass ASCII Zeichen in eine dezimalzahl zu > wandeln. Nicht 'der nächste' im Sinne von irgendwann mal. Das ist der nächste Schritt im Sinne von 'das ist jetzt zu tun'
Die System.IO-Klasse stellt für übrigens auch eine Funktion zur Verfügung, die dir erlaubt, ein byte oder char zu übertragen, das du dann natürlich auch als Hex-Wert angeben kannst. Dann sparst du dir immerhin schon mal den Umweg beim Senden. http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.write(v=VS.90).aspx Außerdem kannst du beim Lesen auch gleich ReadByte verwenden.
=) Ok ok. Hab da glaub das passende Tutorial gefunden: "AVR-GCC-Tutorial/Der UART" Bin aber etwas verwirrt...
1 | // innerhalb von main
|
2 | |
3 | uint16_t speed = 0; //"speed" wird in main erhöht bzw. verringert (0-254). Aktueller Wert soll übertragen werden. |
4 | |
5 | char s[5]; |
6 | |
7 | utoa(speed, s, 10); |
8 | uart_putc(s); |
9 | |
10 | |
11 | |
12 | // Methode
|
13 | |
14 | int uart_putc(unsigned char c) |
15 | {
|
16 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ |
17 | {
|
18 | }
|
19 | |
20 | UDR = c; /* sende Zeichen */ |
21 | return 0; |
22 | }
|
So versteh ich zumindest das Turtorial, jedoch gehts noch nicht. Der UART sendet dauerhaft 'S'. Hilfe!? Danke!
Du gehst die Sache von der falschen Seite an. Die Umrechnung von String zu Zahl findet (sinnvoller Weise) im PC statt, nicht im AVR. Außerdem: Wenn du am PC 145 als PWM-Wert angeben willst, sind das 3 Chars, nicht eins. Dein Ansatz auf dem Atmel würde also so einfach nicht funktionieren.
Ok, dass ist zumindest mal ne erkenntnis =) Ich will am PC nicht den PWM-Wert eingeben (z.B. 145) sonden per Tastendruck nur erhöhen oder verringern. Das geht auch soweit. Jetzt möchte ich den aktuellen PWM-Wert des µC an den PC übertragen. Die Übertragung geht, jedoch bekomme ich die ASCII zu dezimal "wandlung" nicht hin.
ASCII - Zeichen von 0-127 bekomme ich in meiner C#-Anwendung angezeigt. Werte darüber werden nur als '?' angezeigt. Hier liegt momentan das Problem.
Du wirkst mir im Moment ein bisschen zerstreut. Geh dein Konzept aus dem ersten Software-Beitrag nochmal durch - das passt nämlich recht gut. Es wird ein Byte vom PC zum AVR übertragen und zur Kontrolle wieder ein Byte zurückgeschickt. luke schrieb: > ASCII - Zeichen von 0-127 bekomme ich in meiner C#-Anwendung angezeigt. > Werte darüber werden nur als '?' angezeigt. Hier liegt momentan das > Problem. Nein, liegt es nicht. Entschuldige ^^ Dem PC ist es egal, wie er dir das Zeichen anzeigen soll - ob als ASCII-Zeichen, binär, hex oder dezimal ist ihm völlig einerlei. Intern heißt 'A' = 0x41 = 65 immer 0b01000001. Wichtig ist, dass du die Übertragung des einen Zeichens (= 1 Byte) hinbekommst und nicht ein String übertragen wird. Da kann der Compiler dann nämlich auch mal ein 2-Byte-Unicode-Zeichen draus machen oder einen NULL-Character zum Abschluss dazusenden... Hier passt ein Byte, darum nimmt man es auch. Wenn die Variable am PC dann mal byte ist, gibt es die Funktionen, die ich dir weiter oben schon verlinkt habe, zum Senden und Emfpangen. Zum Umwandeln des am PC im Textfeld eingegebenen Strings in ein byte findest du hier eine passenden Funktion: http://msdn.microsoft.com/en-us/library/bds4fye2.aspx Die richtige rauszusuchen überlass ich dir =)
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.