www.mikrocontroller.net

Forum: Analoge Elektronik und Schaltungstechnik DC-Motor ansteuern


Autor: luke (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
Autor: OlliW (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: luke (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat mir keinen einen Rat? =)

Autor: Alexander Schmidt (esko) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: David R. (blackbird92)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: David R. (blackbird92)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was zwischen 5kOhm und 10kOhm dürften reichen.

Autor: luke (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: David R. (blackbird92)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael H. (michael_h45)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten!
Die teile sind bestellt =)

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <io.h>
#include <interrupt.h>

void mcu_init();
void pwm_init();
void usart_init(uint16_t baudrate);
uint8_t usart_receive();

//======================VARIABLEN============================

  uint8_t pwmlevel = 250;

//=======================MAIN===============================
  

int main(void)
{
  mcu_init();
  pwm_init();
  usart_init(11);
  while(1)
  {
    pwmlevel = usart_receive();              
  }
  return(0);
}


//=============================INIT===================================

void mcu_init()
{
  DDRA = 0xFF;
  DDRD = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFE;  //  PDO = RxD Input
  
  PORTA = 0;
  PORTB = 0;
  PORTC = 0;
  PORTD = 0;

  SP = RAMEND;
  sei();

}

void pwm_init()
{
  TCCR1A = ((1<<COM1A1)|(1<<WGM10));
  TCCR1B = (1<<CS10);                //PWM 1khz (Fclk/(2046*1kHz)
                                     //Vorteiler = 1;
  OCR1A = pwmlevel;
}

void usart_init(uint16_t baudrate)
{
  UBRRH = (uint8_t)(baudrate >>8);
  UBRRL = (uint8_t) baudrate;

  UCSRB |= ((1<<RXEN)|(1<<TXEN));
  UCSRC |= ((1<<URSEL)|(1<<USBS)|(1<<UCSZ1)|(1<<UCSZ0));
  
}

//==============================UP===================================

uint8_t usart_receive()
{
  while(!(UCSRA & (1<<RXC)))
  {
  }
  return UDR;

}

C# Anwendung:
 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void bt_open_Click(object sender, EventArgs e)
        {
            serialPort1.Open();
        }

        private void bt_send_Click(object sender, EventArgs e)
        {
            serialPort1.WriteLine(tb_send.Text);
        }

        private void bt_close_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
        }
    }


Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael H. (michael_h45)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

danke für eure Antworten! Habe meine main-schleife folgendermaßen 
geändert:
int main(void)
{
  mcu_init();
  pwm_init();
  usart_init(11);
  while(1)
  {
    OCR1A = usart_receive();              
  }
  return(0);
}

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!

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
 private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
             
            string data = "";
            data = serialPort1.ReadExisting();
             
            textBox1.Text = data;
        }
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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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'

Autor: Michael H. (michael_h45)
Datum:

Bewertung
0 lesenswert
nicht 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....
Außerdem kannst du beim Lesen auch gleich ReadByte verwenden.

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
=)
Ok ok. Hab da glaub das passende Tutorial gefunden:
"AVR-GCC-Tutorial/Der UART"

Bin aber etwas verwirrt...

// innerhalb von main

    uint16_t speed = 0;  //"speed" wird in main erhöht bzw. verringert (0-254). Aktueller Wert soll übertragen werden.

    char s[5];

    utoa(speed, s, 10);
    uart_putc(s);
 


// Methode

int uart_putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE)))  /* warten bis Senden moeglich */
    {
    }                             
 
    UDR = c;                      /* sende Zeichen */
    return 0;
}

So versteh ich zumindest das Turtorial, jedoch gehts noch nicht. Der 
UART sendet dauerhaft 'S'.
Hilfe!?
Danke!

Autor: Michael H. (michael_h45)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: luke (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Michael H. (michael_h45)
Datum:

Bewertung
0 lesenswert
nicht 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 =)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.