www.mikrocontroller.net

Forum: Compiler & IDEs ATmega32, 8PWMs @ 8 Frequenzen, 8 Tastverhältnisse


Autor: Melvin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin!
Ich habe hier schon sehr viel im Forum gesucht und leider keine passende 
Lösung gefunden. Folgende Aufgabenstellung:
Ich muss mit einem Controller 8 PWM-Signale erzeugen um 8 Motoren 
anzutreiben. Dafür sind ja auch viele Beispiele vorhanden. Die 
Besonderheit bei mir ist aber: ich muss für JEDEN Kanal einzeln 
FREQUENZ, TASTVERHÄLTNIS und ob das Signal mit Low- oder High-Pegel 
anfängt festlegen können. Und zudem sollen die Motoren beliebig 
gestartet und gestoppt werden können.
Ich habe folgenden Code programmiert (bin erst seit kurzem dabei, von 
daher nicht der sauberste :-)
Meine Überlegung: ich nutze den Timerinterrupt als globalen Taktgeber, 
jeder Kanal hat seinen eigenen Zähler, dessen Grenzen einzeln festgelegt 
werden können. So wie der Code unten steht erzeugt der Zähler jede ms 
einen Interrupt, und ruft dann für jeden Motor die Funktion MotorControl 
auf, die entsprechend der Werte des Motors die PWM erzeugt. Im Beispiel 
unten habe ich zwei Motoren, einen mit der Periodendauer 20ms (50Hz) und 
einem Tastverhältnis von 0.5 (duty=10ms) und einen Motor mit 
Periodendauer 30ms (33,3Hz) und Tastverhältnis 1/3 (duty=10ms).
Das ganze basiert auf dem Soft-PWM-Artikel-Beispiel.

Habt ihr Ideen, wie man das besser lösen kann? Vor allem macht mir 
sorgen, dass die motorControl ja innerhalb des Interrupts achtmal 
aufgerufen wird, was ja wohl ziemlich ungünstig ist.
Und dann fehlt noch die komplette Logik falls ich nicht mit einem 
High-Pegel starten will, sondern mit einem Low-Pegel.. Das Signal soll 
dann nicht invertiert werden, sondern genau um den Low-Pegel verschoben 
sein (also einfach einmal den LowPegel vorm High-Pegel durchlaufen 
lassen, danach nicht wieder). Ich dachte, das wäre ganz einfach, isses 
aber wohl doch nicht :-)
#define F_CPU 8000000L           // Systemtakt in Hz
#define F_PWM 1000               // PWM-Frequenz in Hz
#define PWM_STEPS 1              // PWM-Schritte pro Zyklus(1..256)
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt

struct motordata{   //Motordaten für jeden Motor einzeln
   uint8_t nbr;    //Nr. d. Motors, wird später der Pin am uC
  uint8_t period; //Zählergrenze für Periodendauer
  uint8_t duty;   //Zählergrenze für High-Pegel
  //uint8_t low;  //soll mit Low-Pegel begonnen werden? (noch nicht impl.)
  uint8_t stop;   //soll Motor aus sein; 1=aus
} motorOne = {1,20,10,0}, motorThree = {3,30,10,0};


unsigned int motorControl(struct motordata mtd) {
  static uint8_t cnt[8] = {1,1,1,1,1,1,1,1}; //kann wegen static nicht ins
                         //struct, also hier array dafür (geht das besser?)
  uint8_t tmp=0;
  if(mtd.stop != 1) //Motor an?
  {
    if(cnt[mtd.nbr]<mtd.period) //Periodendauer testen
    {
      if(cnt[mtd.nbr]<=(mtd.duty)) //Dutycycle testen
      {
        tmp |= (1<<mtd.nbr);
      }
      else 
      {
        tmp &= ~(1<<mtd.nbr);
      }
    }
    else
    {
      cnt[mtd.nbr] = 0;
    }

    cnt[mtd.nbr]++; //unsaubere Lösung, nach Nullsetzung gleich wieder um
           //eins erhöhen, ging aber so auf den ersten Blick am einfachsten
  }
  return tmp;
}


ISR(TIMER1_COMPA_vect) {
    uint8_t tmp=0;
 
    OCR1A += (uint16_t)T_PWM;
    //ab hier jetzt für jeden Motor einmal motorControl aufrufen
    tmp |= motorControl(motorOne);
    tmp |= motorControl(motorThree);

    PWM_PORT = tmp;                // PWMs aktualisieren

}

oh, jetzt ist das ganz schön viel Text geworden, ich hoffe, es findet 
sich jemand, der Lust hat, das alles durchzulesen :-)

ps: die Frequenzen sind später nicht sehr hoch, mit denen die Motoren 
angesteuert werden, die liegen im Bereich 1-5Hz (statt PWM könnte man 
vllt auch besser periodisches An/Ausschalten sagen, das PWM-Signal wird 
nicht dazu genutzt, die Drehzahl zu regulieren)

pps: gleichzeitig kommuniziert der Controller noch per UART mit einem 
SteuerungsPC, so dass dafür auch noch Leistungsreserven übrig sein 
müssen

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.