Forum: Analoge Elektronik und Schaltungstechnik DC-Motor ansteuern


von luke (Gast)


Angehängte Dateien:

Lesenswert?

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
von OlliW (Gast)


Lesenswert?

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.

von luke (Gast)


Angehängte Dateien:

Lesenswert?

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!

von luke (Gast)


Lesenswert?

Hat mir keinen einen Rat? =)

von Alexander S. (esko) Benutzerseite


Lesenswert?

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.

von David R. (blackbird92)


Lesenswert?

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.

von luke (Gast)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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.

von David R. (blackbird92)


Lesenswert?

was zwischen 5kOhm und 10kOhm dürften reichen.

von luke (Gast)


Angehängte Dateien:

Lesenswert?

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!

von David R. (blackbird92)


Lesenswert?

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.

von Michael H. (michael_h45)


Lesenswert?

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.

von luke (Gast)


Lesenswert?

Danke für eure Antworten!
Die teile sind bestellt =)

von luke (Gast)


Lesenswert?

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
    }

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Michael H. (michael_h45)


Lesenswert?

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.

von luke (Gast)


Lesenswert?

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!

von luke (Gast)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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'

von Michael H. (michael_h45)


Lesenswert?

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.

von luke (Gast)


Lesenswert?

=)
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!

von Michael H. (michael_h45)


Lesenswert?

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.

von luke (Gast)


Lesenswert?

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.

von luke (Gast)


Lesenswert?

ASCII - Zeichen von 0-127 bekomme ich in meiner C#-Anwendung angezeigt. 
Werte darüber werden nur als '?' angezeigt. Hier liegt momentan das 
Problem.

von Michael H. (michael_h45)


Lesenswert?

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
Noch kein Account? Hier anmelden.