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


von Melvin (Gast)


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 :-)
1
#define F_CPU 8000000L           // Systemtakt in Hz
2
#define F_PWM 1000               // PWM-Frequenz in Hz
3
#define PWM_STEPS 1              // PWM-Schritte pro Zyklus(1..256)
4
#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt
5
6
struct motordata{   //Motordaten für jeden Motor einzeln
7
   uint8_t nbr;    //Nr. d. Motors, wird später der Pin am uC
8
  uint8_t period; //Zählergrenze für Periodendauer
9
  uint8_t duty;   //Zählergrenze für High-Pegel
10
  //uint8_t low;  //soll mit Low-Pegel begonnen werden? (noch nicht impl.)
11
  uint8_t stop;   //soll Motor aus sein; 1=aus
12
} motorOne = {1,20,10,0}, motorThree = {3,30,10,0};
13
14
15
unsigned int motorControl(struct motordata mtd) {
16
  static uint8_t cnt[8] = {1,1,1,1,1,1,1,1}; //kann wegen static nicht ins
17
                         //struct, also hier array dafür (geht das besser?)
18
  uint8_t tmp=0;
19
  if(mtd.stop != 1) //Motor an?
20
  {
21
    if(cnt[mtd.nbr]<mtd.period) //Periodendauer testen
22
    {
23
      if(cnt[mtd.nbr]<=(mtd.duty)) //Dutycycle testen
24
      {
25
        tmp |= (1<<mtd.nbr);
26
      }
27
      else 
28
      {
29
        tmp &= ~(1<<mtd.nbr);
30
      }
31
    }
32
    else
33
    {
34
      cnt[mtd.nbr] = 0;
35
    }
36
37
    cnt[mtd.nbr]++; //unsaubere Lösung, nach Nullsetzung gleich wieder um
38
           //eins erhöhen, ging aber so auf den ersten Blick am einfachsten
39
  }
40
  return tmp;
41
}
42
43
44
ISR(TIMER1_COMPA_vect) {
45
    uint8_t tmp=0;
46
 
47
    OCR1A += (uint16_t)T_PWM;
48
    //ab hier jetzt für jeden Motor einmal motorControl aufrufen
49
    tmp |= motorControl(motorOne);
50
    tmp |= motorControl(motorThree);
51
52
    PWM_PORT = tmp;                // PWMs aktualisieren
53
54
}

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

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.