www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmega8 mit rechts- links- Motoransteuerung


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

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe folgendes Problem:
Im Dateianhang findet ihr einen Teil des Schaltplans, ich habe nur den 
Teil beigefügt der mir Probleme bereitet. Folgendes, der Controller 
läuft mit dem Programm (Code unten)auf dem STK500 sehr gut und schaltet 
mir über je 2 Taster je einen Ausgang, mit dem ich je ein Relai 
ansteuern möchte um den rechts-links-lauf für einen Motor zu 
realisieren. Leider leuchten auf dem STK500 alle LEDs so wie sie sollen 
aber das Relai schaltet nicht so wie es soll und der Ausgang am 
Controller ist nie wirklich auf 0V. Es liegt immer eine Spannung an, 
4,87V oder geschaltet 1,76V und ich wüsste gerne warum ???
Zweites Problem, wie kann ich das schalten des Ausgangs im Programm am 
besten umkehren/negieren ???
Für Tips und Hilhen wäre ich euch sehr dankbar - ich habe langsam keine 
Gedult mehr, ist schon die dritte Platine......

Gruss Boris


____________________________________________________________________
#include <avr/io.h>

int main (void)
{

DDRB &= ~( 1 << PB0 ); //PB0 Eingang
DDRB &= ~( 1 << PB1 ); //PB1 Eingang
PORTB |= ( 1 << PB0 ); //Pull up an
PORTB |= ( 1 << PB1 ); //Pull up an
DDRC &= ~( 1 << PC2 ); //PC2 Eingang
DDRC &= ~( 1 << PC3 ); //PC3 Eingang
PORTC |= ( 1 << PC2 ); //Pull up an
PORTC |= ( 1 << PC3 ); //Pull up an
DDRC |= ( 1 << PC0 ); //PC0 Ausgang
DDRC |= ( 1 << PC1 ); //PC1 Ausgang


while(1)
{
if (PINB & (1 << PB0))//wenn PB0 High ist...
{
PORTC |= (1 << PC0); //PC0 High
}
if (PINB & (1 << PB1))//wenn PB1 High ist...
{
PORTC |= (1 << PC1); //PC1 High
}
if (PINC & (1 << PC2))//wenn PC2 High ist...
{
PORTC |= (1 << PC0); //PC0 High
}
if (PINC & (1 << PC3))//wenn PC3 High ist...
{
PORTC |= (1 << PC1); //PC1 High
}
// Eine Schleife
if (!(PINB & (1 << PB0))) //wenn PB0 Low ist...
{
PORTC &= ~(1 << PC0); //PC0 Low
}
if (!(PINB & (1 << PB1))) //wenn PB1 Low ist...
{
PORTC &= ~(1 << PC1); //PC1 Low
}
if (!(PINC & (1 << PC2))) //wenn PC2 Low ist...
{
PORTC &= ~(1 << PC0); //PC0 Low
}
if (!(PINC & (1 << PC3))) //wenn PC3 Low ist...
{
PORTC &= ~(1 << PC1); //PC1 Low
}

}

return 0;
}

____________________________________________________________________
sorry für den vielen Platz durch den Code !!!!    ;-)

Autor: Hubert G. (hubertg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du auch AVCC beschalten? Sonst funktioniert der PortC nicht 
richtig.

Autor: Boris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich habe so ziemlich alle Anschlüsse wie im Datenblatt verdrahtet, 
aber irgendwas läuft da nicht.   8-(

Gruss
Boris

Autor: Paul Baumann (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast Du wirklich AVCC, AGND und AREF richtig beschaltet?
Das "Andersherum" Schalten des Ausgangs kann man z.B.in BASCOM mit dem 
NOT - Befehl erreichen. Ob es den in C gibt, weiß ich nicht, davon 
verstehe ich nichts.

MfG Paul

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Boris,

ich kann mich meinen Vorrednern nur anschließen: nach Deinem Schaltplan 
liegt AVcc (Pin 20) nicht an Vcc!

Gruß

Fred

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

Bewertung
0 lesenswert
nicht lesenswert
Sorry,
habe ich in der Skizze leider vergessen - Pin 20 liegt an 5V VCC.
Ich habe jetzt mal LEDs an die Stelle der Relais gelötet und 
festgestellt, das sie ständig leuchten und nur dann heller werden, wenn 
ich einen Taster für links oder rechts drücke.
Stimmt etwas mit der Transistoransteuerung nicht oder das Programm ? auf 
dem STK500 geht es doch ???

Gruss Boris

Autor: Mike J. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Boris
Bau dir eine H-Bücke dafür.

Du musst den Motor eh erst stoppen bevor du ihn in eine andere Richtung 
drehen lässt.

Autor: Boris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
nein - eine H-Brücke ist nicht nötig, das ist ein Getriebemotor der 
sofort steht sobald der Taster losgelassen wird. Ich habe am Ausgang des 
Mic immer 4,8V stehen und sobald ich den Taster drücke, fällt der Pegel 
nur auf 1,2V ab. Abgesehen davon, das der Ausgang 0V liefern sollte und 
erst dann ca. 5V wenn der Taster gedrückt wird..... scheint das Programm 
zu laufen. Das mit dem umgekehrten Pegel liegt eben am STK500, das dreht 
den Pegel an den Ausgängen um.
Also es wäre nett, wenn mir jemand helfen könnte.
Danke !

Boris

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

Bewertung
0 lesenswert
nicht lesenswert
Hallo, hier nochmal der komplette aktuelle Schaltplan.
Was läuft da falsch ???

Gruss
Boris

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

Bewertung
0 lesenswert
nicht lesenswert
Ich hab jetzt dein Programm nicht in allen Einzelheiten
analysiert. Da sind mir einfach zuviele if then-else
die jeweils den Port-Pin verstellen.

Ich könnte mir aber vorstellen, dass in Wirklichkeit dein
PC0 bzw. PC1 Ausgang ständig den Pegel wechselt.

Warum machst du nicht einfach mal ein simples Testprogram
int main()
{
  DDRC = ( 1 << PC0 ) | ( 1 << PC1 );

  while( 1 ) {
    PORTC = 0x03;
  }
}

Jetzt müssen die beiden Relais sauber anziehen.
Tun sie das, dann kommt der Gegentest
int main()
{
  DDRC = ( 1 << PC0 ) | ( 1 << PC1 );

  while( 1 ) {
    PORTC = 0x00;
  }
}

Und die Relais sollten ruhig sein.

Wenn das hier klappt (ruhig auch mal die Spannungen am µC
Pin nachmessen), dann sieh dir nochmal dein Programm an.

Zieh es umgekehrt auf:
Geh nicht von den Eingängen aus und leite davon ab, was am
Ausgang passieren soll, sondern geh von den Ausgängen aus
und überleg dir, welche Bedingung an den Eingängen vorliegen
muss, damit der Ausgang 1 bzw. 0 sein soll. Formulier das
als eine einzige Bedingung. Dadurch läufst du dann nicht
Gefahr, dass ein Programmteil den Portausgang auf 1 setzt
und gleich darauf ein anderer Programmteil den Ausgang wieder
auf 0 runterzieht.

Autor: Boris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
vielen Dank - es ist genau wie Du geschrieben hast, die Ausgänge werden 
sauber geschaltet. Das ist mein erstes Projekt mit einem AVR - wie 
bekomme ich das hin, das ich die Ausgänge mit einem Taster sauber 
schalte - ohne ein flimmern ?
Gibt es da einen Trick, wie man die Ausgänge am sichersten schaltet ?
Vielen Dank !

Gruss

Buris

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

Bewertung
0 lesenswert
nicht lesenswert
Boris wrote:

> Gibt es da einen Trick, wie man die Ausgänge am sichersten schaltet ?

Der Trick ist, die Ausgänge nur an einer einzigen STelle im Code
schalten. Entweder ein oder aus. Aber nicht an 5 verschiedenen
Stellen verstreut über den ganzen Code.

Ich geh mal davon aus, dass dein Eingänge 2 von 2 Tastern
und 2 Endschaltern kommen.

Das heist, der Motor darf nur dann in eine Richtung fahren,
wenn der entsprechende Taster gedrückt und der entsprechende
Endschalter nicht erreicht ist.

Um das ganze übersichtlicher zu gestalten, schlage ich die
Einführung von ein paar Funktionen vor
uint8_t TasterRauf()
{
  PINB & ( 1 << PB0 );
}

uint8_t EndschalterOben()
{
  PINC & ( 1 << PC2 );
}

void MotorAuf()
{
  PORTC &= ~( 1 << PC1 );
  PORTC |=  ( 1 << PC0 );
}

void MotorZu()
{
  PORTC &= ~( 1 << PC0 );
  PORTC |=  ( 1 << PC1 );
}

void MotorStop()
{
  PORTC &= ~( 1 << PC0 );
  PORTC &= ~( 1 << PC1 );
}

Der Zweck dieser Hilfsfunktionen besteht darin, den eigentlichen
Code einfacher bzw. lesbarer zu gestaltet. Die Ganzen << und & und |
lenken sonst extrem vom eigentlichen Geschehen ab. Du willst dich
nicht ständig mit & und | herumschlagen, du willst dich mit deiner
Logik beschäftigen.
int main()
{
  ...

  while( 1 ) {

    // Wenn die Taste für 'Rauf' gedrückt ist, dann fährt der
    // Motor nach oben. Aber nur, wenn der Endschalter dafür
    // nicht schon erreicht ist

    if( TasterRauf() ) {
      if( !EndschalterOben() )
        MotorAuf();
    }

    // Wenn die Taste für 'Runter' gedrückt ist, dann fährt der
    // Motor nach unten. Aber nur dann, wenn der entsprechende
    // Endschalter nicht betätigt ist UND wenn die Kinder nicht
    // wieder mal ihre Patschehändchen auf beiden Tasten gleich-
    // zeitig haben. In dem Fall 'gewinnt' dann die Taste für
    // auf

    else if( TasterRunter() ) {
      if( !EndschalterUnten() )
        MotorZu();
    }

    // nichts ist gedrückt. Dann soll auch nichts passieren
    else
      MotorStop();
  }
}

Man beachte, wie der Code hier schon fast selbsterklärend wird.
Durch die Funktionen ist der Code schon fast sowas wie eine
Zusammenfassung des jeweils darüberstehenden Kommentars.

PS: Ich habe jetzt nicht darauf geachtet, ob die Schatlerfunktionen
korrekt auf PIN 0 oder 1 geschrieben sind. Da musst du
ev. nachbessern. Dazu würde ich mir gleich wieder mal ein Testprogramm
schreiben
int main()
{
  ...

  while( 1 ) {

    if( !EndschalterOben() )
      MotorAuf();
  }
}

Die Erwartung dieses Testprogramms: Der Motor fährt auf, bis
der Endschalter anspricht.
Jetzt vergleichst du die Realität mit der Erwartung. Tut die
Schaltung das erwartete? Wenn nein, dann untersuchst du
warum nicht. Es gibt nur eine Möglichkeit: Die Auswertung
des Endschalters ist genau verkehrt rum. Also korrigierst
du sie in der Endschalter Funktion.
Wenn das dann klappt, dann gehts ans überprüfen in die andere
Richtung.
Erst nachdem die Einzelteile geprüft sind, baust du dann wie
oben angedeutet, das komplette Programm zusammen.

Du musst anfangen modular zu arbeiten. Kleine Änderungen, die
jede für sich einzeln testbar sind.

Autor: Boris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super - vielen Dank !!!
ich werde mich gleich mal dran machen...so hört es sich schon viel 
besser an und ich glaube das könnte etwas werden.
Mit den Endschaltern ist eine gute Idee, nur die zwei weiteren Schalter 
wollte ich mir für später reservieren um das Projekt noch ausbauen zu 
können. Der Motor hat intern schon Endschalter und die Abschaltung 
wollte ich per Zeit machen - sicher ist sicher.
Aber das ist dann das nächste Problem, erst müssen die Ausgänge auf die 
Taster reagieren, danach möchte ich das jeder Ausgang nur ca.2 Minuten 
aktiv ist und dann automatisch wieder auf low geht.
Aber wie gesagt.... dieses Wochenende hoffe ich den Anfang zu finden und 
die Arbeitsweise zu begreifen.
Nochmals vielen Dank, Du solltest Lehrgänge anbieten - sehr gut erklärt 
!

Gruss

Boris

Autor: Boris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,
also mit dem Programm habe ich doch einige Probleme,
was bedeuten die "unit8_t..." kann ich jetzt direkt unit8_t TasterAuf 
aufrufen und es als Variable nutzen oder wofür steht es  ?
Und die Definition für void MotorAuf() kann ich die auch als Variable 
aufrufen ?
Also irgendwie bringt mich das jetzt doch durcheinander....
Muss ich die Ein-/Ausgänge nicht auch noch definieren ?
Danke !

mfg.
Boris


uint8_t TasterAuf()
{
  PINB & ( 1 << PB0 );
}

uint8_t ExtAuf()
{
  PINC & ( 1 << PC2 );
}

uint8_t TasterZu()
{
  PINB & ( 1 << PB1 );
}

uint8_t ExtZu()
{
  PINC & ( 1 << PC3 );
}

void MotorAuf()
{
  PORTC &= ~( 1 << PC1 );
  PORTC |=  ( 1 << PC0 );
}

void MotorZu()
{
  PORTC &= ~( 1 << PC0 );
  PORTC |=  ( 1 << PC1 );
}

void MotorStop()
{
  PORTC &= ~( 1 << PC0 );
  PORTC &= ~( 1 << PC1 );

int main(void)
{
  ...

  while( 1 )
  {

    // Wenn die Taster für 'Rauf' oder Taster "Extauf" gedrückt ist, 
dann  fährt der
    // Motor ca. 2 Minuten nach oben.
  // Wird ein Taster für "auf" gedrückt, stehen alle Ausgänge wieder auf 
"0".

    if( TasterRauf(PB0==0) )
  {

      if( Extauf(PC2==0) )
        MotorAuf(PC0==1);
    }

    // Wenn die Taste für 'Runter' oder Taster "Extzu" gedrückt ist, 
dann fährt der
    // Motor ca. 2 Minuten nach unten.
  // Wird ein Taster für "auf" gedrückt, stehen alle Ausgänge wieder auf 
"0".

    else if( TasterRunter(PB1==0) )
  {
      if( Extzu(PC3==0) )
        MotorZu(PC1==1);
    }

    // nichts ist gedrückt. Dann soll auch nichts passieren
    //else
      //MotorStop();
  //}
//}


//int main()
//{


  //while( 1 )
  //{

    //if( !EndschalterOben() )
      //MotorAuf();
  //}
//}

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

Bewertung
0 lesenswert
nicht lesenswert
Boris wrote:
> Hallo Karl Heinz,
> also mit dem Programm habe ich doch einige Probleme,
> was bedeuten die "unit8_t..."

uint8_t ist ein Datentyp. So wie int oder double oder long.
Nur ist dieser Datentyp so spezifiziert, dass er exakt einem
Byte entspricht.

> kann ich jetzt direkt unit8_t TasterAuf
> aufrufen

TasterAuf ist eine Funktion.
Die kann man einfach aufrufen und diese Funktion liefert einen
Wert. So wie sin(0.2) einen Wert liefert (nämlich den Sinus
des angegebwnwn Winkels), so liefert TasterAuf einen Wert.
Dieser Wert repräsentiert den Zustand der Taste 'auf'

> Und die Definition für void MotorAuf() kann ich die auch als Variable
> aufrufen ?

Das ist keine Variable. Das ist wieder eine Funktion. Wird die
aufgerufen, so sorgt sie dafür, dass der Motor in die 'Auf-Stellung'
läuft.

> Also irgendwie bringt mich das jetzt doch durcheinander....

C-Literatur besorgen. Eine Programmiersprache lernt man nicht
dadurch, dass man sich durchwurschtelt.

Modulares Programmieren (Programmieren indem man sich Funktionen
für bestimmte Aufgaben schreibt und diese dann verwendet) ist
das A und O einer vernünftigen Softwareentwicklung.

> Muss ich die Ein-/Ausgänge nicht auch noch definieren ?

Sicher musst du das. Da ich aber nicht 100% weiss, wo deine
Taster und Motoren am µC hängen, habe ich das in main() mit
den 3 Punkten ... angedeutet.

>     if( TasterRauf(PB0==0) )

TasterRauf liefert schon einen Wert (oder soll es zumindest), der
eine Aussage darüber trifft, ob der Taster gedrückt ist oder
nicht.

      if( TasterRauf() )

Autor: Boris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Karl Heinz,
nochmals Danke für Deine Hilfe - momentan bin ich auf der Arbeit sehr 
eingespannt - also sorry das ich mich erst jetzt wieder melde. In der 
Schule habe ich C und Pascal gehabt.... ist nur schon sehr lange her und 
ich komme da nur schwer wieder rein.

Also fange ich mal von ganz vorne an, Schritt für Schritt.

Ich benötige 4 Eingänge und 2 Ausgänge
PB0 oder PC2 schalten Ausgang PC0 auf "1"
PB1 oder PC3 schalten Ausgang PC1 auf "1"

(Die Eingänge liegen immer auf "1" und werden bei Betätigung auf "0" 
gezogen, die Ausgänge sollen "1" liefern wenn sie aktiv sind)

Was benötige ich dafür und was muss ich wie definieren damit das schon 
mal funktioniert ?

Danke !

Gruss
Boris

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.