- Akku Tests und Balkonkraftwerk Speicher         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: PWM Frage

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    27.07.2012
    Beiträge
    10

    PWM Frage

    Anzeige

    Praxistest und DIY Projekte
    Hallo Leute,

    ich habe ein kleines Problem:

    Ich habe ein Gehäuse mit Motoren des CC-RP5, AT89C5131 & einen PCF8591 welchen ich über I²C an den µC angebunden habe(zum auslesen von Analogsensoren). Das wird ein kleiner autonomer Roboter / ist es schon.

    Mein derzeitiges Programm :

    Code:
     /*------------------------------------------------------------------+
    |       File:       Roboterfahrzeug                                  |
    |       Autor:                                                            |
    |       Klasse:     E3GS1                                              |
    |       Controller: at89c5131                                        | 
    |       Datum:      27.03.13                                          |
    |       Version:    2                                                     |
    +--------------------------------------------------------------------+
    |  Beschreibung:                                                               |		
    |                              |		
    +-----------------------------------------------------------------------------*/
    
     #include <at89c5131.h>		// fuer Atmel AT89C5131
    
    /* adda_kniel.c *********************************************************************************
     * Hilfsprogramme für den AD- und DA- Umsetzer mit I2C-Bus ********************************                                           
     * An DA-Umsetzer	wert ausgeben:					void aout (unsigned char wert)
     * AD-Umsetzer einlesen, Kanal = 0,1,2,3:	unsigned char ain (unsigned char kanal)
     ******************************************************************************************/
    // geänderte Version 11/2007: Start und Stop-Bedingungen, funktioniert mit US-Sensoren
    // geänderte Version 12/2006: funktioniert endlich aus als Library: adda.obj mit 
    // Tool -> Library-Manager in die Bibliothek RC51atms.lib einfügen 
    
    #include <reg51.h>		// Registerdefinitionen													
    //#include <intrins.h>			//	für Rotationsfunktion
    
    //	!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!											
    //****** verwendete I2C-Leitungen *********************************************************
    sbit SDA = P4^1;	// SDA-Leitung: ED2-Boards P3_5, (USB-Boards P4_1)
    sbit SCL = P4^0;	// SCL-Leitung: ED2-Boards P3_4, (USB-Boards P4_0)									
    //****************************************************************************************
    //	!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!-!
    
    //***** verwendete Adressen und Kontrollbyte für den AD- und DA-Umsetzter ****************
    #define Motor1 P1
    #define Motor2 P2
    #define vor 0x50 
    #define zurueck 0x44
    #define stopp 0x40
    #define adr_lies 0x91	 	//	10010001	->	1001 fest, 000 durch Platine, 1 Wert lesen		
    #define adr_schreib 0x90	// 10010000	->	1001 fest, 000 durch Platine, 0 Wert lesen		
    #define contr_ain	  0x40	// 01000000	->	Kontrollbyte 4 einzelne ADU, Kanal= Offset dazu				
    sbit	acc7 = 0xE7;		//	für Aus- und Eingabe eines Bits des Akkus								
    //void warte(int z);
    // *****************************************************************************************
    // I2C- Routinen zur Ansteuerung eins I2C-Slaves
    // I2C-Bus-Funktionen i2c_init, i2c_start, i2c_stop, i2c_schreiben, i2c_lesen auch für andere
    // I2C-Bus-ICs verwendbar
    // *****************************************************************************************
    
    // **** Zeitverzögerung zur Verlangsamung der Datenübertragungsrate ***********************
    // **** i=2 bis i=100 wählen je nach I2C-IC und Pull-Up-Widerstand
    void zeit (void) {unsigned char i; for (i=5;i!=0;i--) ;}
    void vorwaerts (void);
    void rueckwaerts (void);
    void drehen (void);
    void speaker(void);
    void warte(int z);
    void stop(void);
    // ****************************************************************************************
    // ****** Initialiserung I2C-Bus **********************************************************
    void i2c_init (void)
    	{	
    	SDA = 1;				//	Leitungen in den Grundzustand High										
    	zeit ();	
    	SCL	= 1;
    	zeit ();
    	}
    	 
    // ****** Startbedingung I2C-Bus **********************************************************
    void i2c_start (void)
    	{
    	SDA = 1;			// Grundzustand
    	SCL = 1;			// neu eingefügt 11/07
    	zeit();
    	SDA = 0;			// Wechsel SDA von 1 -> 0 während SCL = 1
    	zeit ();
    	SCL = 0;
    	zeit ();
    	}
    	
    //****** Stoppbedingung I2C-Bus ***********************************************************
    void i2c_stop (void)
    	{
    	SDA = 0; // neu eingefügt 11/07
    	SCL = 1;		
    	zeit	();
    	SDA = 1;	// Wechsel von SDA 0 -> 1 während SCL =1
    	zeit ();
    	}
    	
    //*****************************************************************************************
    // * Byte ausgeben an I2C-Bus , Rückgabewert = Acknoledgebit = 0 wenn erfolgreich 	
    // ****************************************************************************************
    bit i2c_schreiben (unsigned char byte)
    	{
    	unsigned char z;				// Zähler 																	
    	bit ack;							// Acknoledge-Bit															
    	ACC = byte;						//	Rotationsregister Akku												
    	for (z = 8; z != 0; z --)	//	Zähler: serielle Ausgabe von 8 Bit								
    		{	
    		SDA = acc7;				//	Bit7 des Akku ausgeben												
    		zeit	();										
    		SCL = 1;					//	Daten sind gültig													
    		asm {0x23};					//	Akku links schieben
    		//ACC = _crol_ (ACC,1);	// links rotieren, Funktion von intrins.h							 
    		zeit	();
    		SCL = 0;					//	Datenausabe beendet													
    		zeit	();
    		}
    	SDA = 1;					//	Leitung freigeben für Acknoledge-Bit								
    	zeit	();
    	SCL = 1;					//	Slave kann bestätigen													
    	zeit ();						// warten																		
    	ack = SDA;				// Acknoledge-Bit lesen														
    	zeit	();
    	SCL = 0;					// Slave soll Ackn-Ausgabe beenden	
    	zeit();									
    	return (ack);				// Acknoledge-Bit ist Rückgabewert der Funktion	
    									//	ack = 0 bedeutet "verstanden" !!!!!!						
    	}
    
    
    //*****************************************************************************************
    // * Byte einlesen vom I2C-Bus. Bei Ack=1 wird Acknoledgebit gesendet, sonst nicht
    // *****************************************************************************************
    unsigned char i2c_lesen (bit ack)
    	{
    	unsigned char z,byte;
    	SDA = 1;								//	Leitung freigeben (high) für Daten						
    	for (z = 8; z != 0; z --)			//	Zähler: serielles Einlesen von 8 Bit					
    		{
    		SCL = 1;							//	Daten sind gültig												
    		zeit	();
    		acc7 = SDA;						//	Datenbit in den Akku													
    		asm {0x23};							//	Akku links schieben 
    		// ACC = _crol_ (ACC,1);			// links rotieren, Funktion von intrins.h		
    		//P2_7 = SDA;
    		zeit(); 	
    		SCL = 0;							//	Daten lesen beendet	
    		zeit();										
    		}
    	byte = ACC;								// Eingelesenes Byte 											
    	if (ack == 1)		{SDA = 0;}	// Acknowledge-Bit senden										
    					else	{SDA = 1;}	//	kein Acknowledge-Bit													
    	zeit	();		
    	SCL = 1;								//	Ackn. gültig													
    	zeit	();
    
    	SCL = 0;								// Ackn. beendet													
    	zeit	();
    	SDA = 0;								// Leitung SDA vorbereiten für Stoppbed.				
    	zeit ();
    	return (byte);							//	eingelesenes Byte = Rückgabewert													
       }
       
    //************************** ADU und DAU- Funktionen *************************************
    	
    //*****************************************************************************************
    // * AD-Umsetzter einlesen, Kanal = Nr des ADU: 0,1,2,3
    // *****************************************************************************************
    unsigned char ain (unsigned char kanal)
    	{
    	unsigned char wert;
    	i2c_init ();							//	I2C-Bus initialisieren	(Grundzustand)						
    	i2c_start ();							//	Startbedingung I2C-Bus ausgeben							
    	i2c_schreiben (adr_schreib);		//	Adresse des IC und Schreibwunsch (zur Kanalwahl)		
    	i2c_schreiben ( (kanal&0x03) | contr_ain);	//	Controll-Byte mit Kanalnummer					
    	i2c_stop ();							//	Stoppbedingung I2C-Bus ausgeben								
    	i2c_start ();							//	Startbedingung I2C-Bus ausgeben								
    	i2c_schreiben (adr_lies);			//	Adresse des IC und Lesewunsch									
     
       i2c_lesen (1);							//	neue AD-Wandlung	Acknoledge = 1								
    	wert = i2c_lesen (0);				// Wert abholen		Acknoledge	=0									
    	i2c_stop ();							//	Stoppbedingung I2C-Bus ausgeben								
    	return (wert);
    	}
    	
    //*****************************************************************************************
    // * An DA-Umsetzer	wert ausgeben
    // *****************************************************************************************
    void aout (unsigned char wert)
    	{
    	i2c_init ();							//	I2C-Bus initialisieren	(Grundzustand)						
    	i2c_start ();							//	Startbedingung I2C-Bus ausgeben								
    	i2c_schreiben (adr_schreib);		// Adresse ADU															
    	i2c_schreiben (contr_ain);			// Control-Byte acu für Analogwert einlesen					
    	i2c_schreiben (wert);				//	Wert ausgeben														
    	i2c_stop ();							//	Stoppbedingung I2C-Bus ausgeben								
    	}
    
    
    void main (void)        // Hauptprogramm
    {
    unsigned char wert;     //Definition Variable wert   
    unsigned char swert;    //Definition Variable swert zum abfragen
    P0=0x00;                // Port0 - Port3 als Ausgang deklarieren
    P1=0x00;
    P2=0x00;
    P3=0x00;
    while(1)                //While Schleife
        {
        P3_1=1;             //linke weiße LED ausschalten
        P3_3=1;             //linke rote LED ausschalten
        P3_5=1;             //rechte rote LED ausschalten
        P3_7=1;             //rechte linke LED ausschalten
        wert = ain(0);      //Kanal 0 einlesen und auf wert schreiben
        P0 = ~wert;          //wert auf P0 schreiben 
        swert=wert&0x80;    //swert = wert mit 80 Hex "und"-Verknüpft
        switch(swert)       // abfrage von swert
        {
        case 0x80: rueckwaerts(); //Wenn swert = 80 Hex dann führe das Programm rückwärtsfahren aus
        break;                     // Break um die Abfragen von einander zu trennen
        default: vorwaerts(); break; // Wenn swert ungleich 80 Hex dann führe das Programm vorwärtsfahren aus
        }
        wert = ain(1);
        P0 = ~wert;
        swert=wert&0x80;
        switch(swert)
        {
        case 0x80: rueckwaerts();
        break;
        default: vorwaerts();  break;
        }
        wert = ain(2);
        P0 = ~wert;
        swert=wert&0x80;
        switch(swert)
        {
        case 0x80: rueckwaerts(); 
        break;
        default: vorwaerts(); break;
        }
        }
    }
    
    void vorwaerts (void)  //Unterprogramm Vorwärtsfahren
    {
        Motor1 = vor;        // die höherwertige 1 ist der Enable Pin
        Motor2 = vor;        // die niederwertige 1 ist die Richtung des Motors
    }
    
    void rueckwaerts (void) //Unterprogramm Rückwärtsfahren
    {
        unsigned char hinten_abfrage;
        hinten_abfrage = ain(3);
        if(hinten_abfrage>=0x40)
        {
        drehen();
        }
        else
        {
        stop();         // Sprung ins Unterprogramm stop
        P3_1=0;         // LED links weiß an
        P3_3=1;         // LED links rot aus
        P3_5=1;         // LED rechts rot aus
        P3_7=0;         // LED rechts weiß an
        Motor1 = zurueck; // Motoren nach hinten fahren lassen
        Motor2 = zurueck;    
        speaker();      // Unterprogramm für den Piepser
        drehen();       // Verzweigungs ins Unterprogramm drehen
        }
    }
    
    void drehen (void)      // Unterprogramm drehen
    {
        double long x;      // Variable x mit einem großen Datenbereich adressieren
        Motor1 = zurueck;    // Motor 1 rückwärts fahren lassen
        Motor2 = vor;    // Motor 2 vorwärts fahren lassen
        for(x=0;x<2100;x++);    // Warteschleife in der x hochgezählt wird
    }
    
    void stop(void) // Unterprogramm stop & rote LEDS an
    {
    Motor1=stopp;  // Enable pin & Drehrichtungsangabe aus
    Motor2=stopp;
    P3_3=0;         // LED links rot an
    P3_5=0;         // LED rechts rot an
    warte(50);      // Sprung ins unterprogramm warte mit Übergabe einer Variablen
    }
    
    void speaker (void) // Unterprogamm für die Lautsprecher
    {
    P3_0=1;             // Lautsprecher an
    warte(25);          // Sprung ins unterprogramm warte mit Übergabe einer Variablen
    P3_0=0;             // Lautsprecher aus
    warte(10);          // Sprung ins unterprogramm warte mit Übergabe einer Variablen
    P3_0=1;
    warte(25);
    P3_0=0;
    }
    
    void warte(int z)      // Unterprogramm fürs Warten
    {
    int s, x;               // definieren von Variablen
    for(s=z;s>0;s--)        // s nimmt den Wert von z an welche vorher übergeben wurde. s wird runtergezählt
        {
        for(x=2000;x>0;x--);    // for schleife in welcher x runtergezählt wird
        }
    }
    Nun meine Frage : wie bekomme ich eine PWM zur Steuerung der Motoren möglichst einfach hin ? Die Motoren werden über einen L298 geschalten.
    Geändert von Regnator (23.04.2013 um 09:59 Uhr)

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Geistesblitz
    Registriert seit
    15.03.2011
    Ort
    Dresden
    Alter
    36
    Beiträge
    1.937
    Am einfachsten wäre wirklich Software-PWM, allerdings weiß ich nicht, wie man die unter C anspricht. Unter Bascom ist es jedenfalls ziemlich easy und ich denk mal, dass es mit C auch ähnlich gehen wird. Welche Timer sind denn noch frei? Wenn kein Timer mehr frei ist sieht es generell schlecht für PWM aus.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    27.07.2012
    Beiträge
    10
    Bis jetzt wird noch kein Timer verwendet.

    Sorry, hätte vielleicht noch erwähnen sollen, dass es in C ist. Als Compiler benutze ich Ride7.

    Hättest du mir dann ein Beispiel parat, um mir das mal zu verdeutlichen wie der ungefähre Aufbau aussieht ?

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Geistesblitz
    Registriert seit
    15.03.2011
    Ort
    Dresden
    Alter
    36
    Beiträge
    1.937
    Hmm, such da besser mal im Netz, ich kenn mich nämlich noch nicht so mit C aus (oder jemand anders ist so nett, das zu erzählen). Auf jeden Fall geht Hardware-PWM nur mit bestimmten Pins, die man sich mal im Datenblatt raussuchen sollte. Hab auch ganz übersehen, dass du gar keinen AVR verwendest. Keine Ahnung, ob das von mir Geschriebene dann noch gilt.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Zitat Zitat von Regnator Beitrag anzeigen
    Nun meine Frage : wie bekomme ich eine PWM zur Steuerung der Motoren möglichst einfach hin ? Die Motoren werden über einen L298 geschalten.
    Fragst du nach Software, nach Hardware oder bist du ergebnisoffen? Ganz viele Controller können PWM-Signale erzeugen, die man an die Eingänge /INH1 und /INH2 del L298 anschließt. Alternativ gibt es die Möglichkeit von I2C-fähigen PWM-Generatoren, Typen kenne ich nicht auswendig. Wenn der Anspruch an die PWM niedrig ist, z.B. 10 Stufen@100Hz, dann macht das ein evtl. schon laufender 1kHz-Interrupt nebenher mit.

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    27.07.2012
    Beiträge
    10
    Ich Suche eine Software-Pwm.

    Der Anspruch ist einfach nur, dass ich meine Motoren über ein High - Low getaktes Signal an dem L298 entsprechend langsamer laufen, oder ist das programmtechnisch nicht zu verwirklichen ?

    Hab da mitlerweile was zu meinem µC gefunden :
    // Initialisierung
    TMOD = 0x11; // setzt beide Timer in den 16-Bit Mode
    TR0 = 1; // Timer 0 läuft jetzt, mit jedem Maschinenzyklus
    // wird jetzt TH0:TL0 um 1 hochgezählt

    while(1)
    {
    // in der Endlosschleife
    if (TF0 == 1) // Flag wird beim Überlauf auf 1 gesetzt
    { TF0 = 0; // Flag erstmal löschen, der Timer zählt bereits munter weiter
    Tu_Was( ); // für was wolltest Du die Zeit nochmal nutzen??
    }
    Weitere_Aktionen( );
    }

    Kann ich wenn TF0 =1 einer Variable einen Wert zuweisen und mit meinem Signal der Motoren per & Verknüpfen ?

    Wenn ich einer geringere Zeit möchte kann ich ja einfach TH0 / TL0 schon einem Startwert zuweisen, oder ?
    Geändert von Regnator (23.04.2013 um 12:53 Uhr)

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Ein Timer genügt. Der wird abwechselnd auf den Startwert für High-Zeit oder Low-Zeit gesetzt. Das Überlaufflag kann doch vermutlich einen Interrupt auslösen, das erspart Polling auf dieses Flag. Je nach Arbeitstakt (High / Low) wird dann beim Überlauf der PWM-Ausgang umgeschaltet. Die Verknüpfung macht der L298 in Hardware via /INHn. Wenn du Ports sparen willst, geht die VerUNDung natürlich auch in Software.

    Dein Controller hat aber ein PWM-Modul auf dem Chip. Bist du an Software-PWM gebunden durch vorhandene Elektronik?

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    27.07.2012
    Beiträge
    10
    Ja, da meine Schaltung sozusagen schon fertig ist und ich die Software PWM als kleines Extra noch hinzufügen wollte, da ich noch ein paar Schalter frei habe und somit meine Frequenz veränderbar machen wollte.
    Mit deinem INHn meinst du den enable pin, oder ?
    Die PWM wollte ich schon über Polling laufen lassen, da mir der µC meinen Roboter ja nicht auf einmal im rückwärtsfahren stehen bleiben soll, weil er in den Interrupt springt.
    Leider sind meine Bilder zu groß, sonst hätte ich sie hochgeladen um mal zu veranschaulichen wie mein Stand der Dinge ist.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    12.11.2004
    Ort
    Hvalstad, Norwegen
    Beiträge
    140
    Im Datenblatt wird auf das Programmable Counter Array (PCA) verwiesen, das kann die PWM in Hardware erzeugen. Du must nur das Tastverhältnis der PWM ändern und die Zähler starten / stoppen. Danach läuft das ganze im Hintergrund und frisst keine Resourcen.

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    1.023
    Zitat Zitat von Regnator Beitrag anzeigen
    . . . meine Schaltung sozusagen schon fertig ist . . . Software PWM als kleines Extra noch hinzufügen . . . ein paar Schalter frei habe und somit meine Frequenz veränderbar machen wollte.
    Da will sich mir der Sinnzusammenhang einfach nicht erschließen! PWM ist kein kleines Extra sondern eine wichtige Funktionalität zur Begrenzung der Anlaufströmer der Motoren und zur Regelung des Geradeauslaufs. Frequenz und PWM (wohl eher Duty Cycle der PWM) sind zwei verschiedene Dinge. Wenn du noch in der Entwicklung bist, dann kümmere dich um dein Verständnis der OnChip-PWM-Erzeugung und lege die Schaltung dafür aus. Dafür sind die Peripheriemodule ja da. Kein Polling für Dinge, die eigentlich selbständig im Hintergrund laufen können. Anders gesagt: Es ist nicht die Aufgabe des Chefs (Hauptprogramm), stündlich (jede Millisekunde) zu kontrollieren, ob noch Klopapier auf der Rolle ist. Derartiges wird delegiert. Wenn du das jetzt nicht verbesserst, wirst du dich später bestimmt ärgern, weil du dir damit die Karten gelegt hast.
    Zitat Zitat von Regnator Beitrag anzeigen
    Mit deinem INHn meinst du den enable pin, oder ?
    Ja. Das n steht für die Ziffern 1 bzw. 2 der beiden quasi gleichartig wirkenden Inhibit-Eingänge des L298.
    Zitat Zitat von Regnator Beitrag anzeigen
    Die PWM wollte ich schon über Polling laufen lassen, da mir der µC meinen Roboter ja nicht auf einmal im rückwärtsfahren stehen bleiben soll, weil er in den Interrupt springt.
    Nein, nein, nein; sorry, aber das ist Unfug. Jedes Bit, jeder Pin behält seinen Zustand bei, solange, bis er vom Programm, von der Hardware oder der nächsten Stromunterbrechung verändert wird. Und das ist alles genauestens geordnet und im Datenblatt beschrieben. Ein Interrupt stört da entweder überhaupt nicht, oder man hat ihn falsch programmiert; aber das lässt sich ja korrigieren. Ganz im Gegenteil: Man _kann_ einen Interrupt als SW-Treiber für die Hardware konzipieren, sodass das Hauptprogramm letztlich unabhängig von der Hardware und Chip-individuellen Registerstruktur nur noch über Statusflags, Messwertvariablen und Steuervariablen im SRAM mit der Hardware Verbindung hat. Der Interrupt wirkt dann als "dienstbarer Geist" oder Haushalter unbemerkt im Hintergrund und managt die ganze Chose.
    Geändert von RoboHolIC (24.04.2013 um 16:00 Uhr) Grund: Ergänzung L298

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. Frage zu pwm
    Von tanger im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 05.11.2008, 06:57
  2. PWM Frage
    Von Martin. im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 22.07.2008, 16:01
  3. Frage zu PWM
    Von doolitle15 im Forum PIC Controller
    Antworten: 6
    Letzter Beitrag: 15.09.2007, 12:15
  4. Kurze Frage zur PWM
    Von x8r im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 14.03.2007, 15:40
  5. PWM DC/DC Wandler Frage
    Von guiliman im Forum Elektronik
    Antworten: 9
    Letzter Beitrag: 24.06.2006, 12:06

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Solar Speicher und Akkus Tests