Technik > Tech-Talk Design & Konzepte

Digitale Steuerung

<< < (19/24) > >>

Sebastian:
Hallo,

Also, das Ganze wird so nicht gehen, da ich die PWM nicht schnell genug kriege. Die Interrupt-Routine hält schon alles auf, obwohl da nicht viel passiert. Werde mal versuche, den Teil in ASM zu machen, der C Compiler macht jedenfalls zu viele anscheinend unnütze Befehle daraus. Unter 555Hz komme ich nicht bei 4,19MHz. Eine PWM Periode dauert 100 Interrupts (womit die Auflösung schon stark eingeschränkt wäre).

Wäre gut, wenn da einer weiterhelfen könnte...

M f G (und frohes Fest)
Sebastian

Stephan G.:
Hi, Folks!

Wie sieht Dein Programm denn aus?

Viel passieren muss eigentlich auch gar nicht. Der Timer-Interrupt könnte auch nur wie ein TICK verarbeitet werden  - bzw. eigentlich muss er ja nur einen Zähler beeinflussen, der die Zeitschlitze nummeriert ...

Wichtig ist, dass die normalen Routinen in der Zeit zwischen 2 Timer-Interrupts komplett abgearbeitet werden.

Das ist am Besten in Assembler hinzukriegen!

PLAY LOUD!!  :guitar:

Sebastian:
Hallo,

So sieht die Interrupt-Routine aus. Wie man sieht, passiert auch nicht viel. Jedes 100. Mal wird einfach der Zähler hochgezählt und entsprechend dem Wert von "an" das Puls-Pausen-Verhältnis geändert. Kann man auch schön aufm Oszi sehen, das geht also soweit. Der Timer läuft ohne Vorteiler und der Interrupt löst aus, sobald der Timer-Wert von 0x4B erreicht ist (geringere Werte bringen nichts, da es nicht schneller wird).
4,19 Mhz / 0x4b / 100 = 559 Hz


ISR (TIMER0_COMP_vect)
{
   zaehler ++;
   if (zaehler == 100)               //100 => 1 Periode
   {
      zaehler = 0;   
   }
      if (an > zaehler)
      {
         PORTB |= (1 << PB3);         
      }
      else
      {
         PORTB &= ~(1 << PB3);            
      }
}   



Aus dem bisschen Code macht der Compiler 56 ASM Befehle, wobei mehr als die Hälfte davon aus zeitraubenden Pushs und Pops besteht, alles also suboptimal.


M f G
Sebastian

Stephan G.:
Hi, Folks!

Kannste mal zeigen, was der Compiler draus macht?

Die Struktur des Programms kann man noch etwas effizienter gestalten, wenn man auf die ELSE verzichtet.
Ich würde zu Beginn der Periode den Ausgang einschalten und mit dem PWM-Wert wieder ausschalten. Die IF muss dann eigentlich nur "Vergleichen" und nicht "Verzweigen"...

Interessant wäre auch, wie die Funktion aufgerufen wird und wo die "Hauptschleife" läuft ...

PLAY LOUD!!  :guitar:

Sebastian:
ISR (TIMER0_COMP_vect)
{
   zaehler ++;
   if (zaehler == 100)               //100 => 1 Periode
   {
      zaehler = 0;   
   }
      if (an > zaehler)
      {
         PORTB |= (1 << PB3);         
      }
      else
      {
         PORTB &= ~(1 << PB3);            
      }
}   

void init(void)
{
    DDRB = 0xff;                   //PORTA Ausgang
   OCR0 = 0x4B;                  //Compare-Wert   
   TCCR0 = 0x09;                  //Prescaler   
   TIMSK = (1 << OCIE0);            //Timer0 Interrupt an
}


int main (void)
{      
   init ();
   sei();             //globaler Interrupt an
   an = 50;         //50% Helligkeit
   for (;;){}
}


Hallo, so sieht der Rest aus, also nicht viel dran.



21:       {
+00000047:   921F        PUSH    R1               Push register on stack
+00000048:   920F        PUSH    R0               Push register on stack
+00000049:   B60F        IN      R0,0x3F          In from I/O location
+0000004A:   920F        PUSH    R0               Push register on stack
+0000004B:   2411        CLR     R1               Clear Register
+0000004C:   932F        PUSH    R18              Push register on stack
+0000004D:   933F        PUSH    R19              Push register on stack
+0000004E:   938F        PUSH    R24              Push register on stack
+0000004F:   939F        PUSH    R25              Push register on stack
+00000050:   93CF        PUSH    R28              Push register on stack
+00000051:   93DF        PUSH    R29              Push register on stack
+00000052:   B7CD        IN      R28,0x3D         In from I/O location
+00000053:   B7DE        IN      R29,0x3E         In from I/O location
22:          zaehler ++;
+00000054:   91800060    LDS     R24,0x0060       Load direct from data space
+00000056:   5F8F        SUBI    R24,0xFF         Subtract immediate
+00000057:   93800060    STS     0x0060,R24       Store direct to data space
23:          if (zaehler == 100)               //100 => 1 Periode
+00000059:   91800060    LDS     R24,0x0060       Load direct from data space
+0000005B:   3684        CPI     R24,0x64         Compare with immediate
+0000005C:   F411        BRNE    PC+0x03          Branch if not equal
25:             zaehler = 0;   
+0000005D:   92100060    STS     0x0060,R1        Store direct to data space
27:             if (an > zaehler)
+0000005F:   91800060    LDS     R24,0x0060       Load direct from data space
+00000061:   2F28        MOV     R18,R24          Copy register
+00000062:   2733        CLR     R19              Clear Register
+00000063:   91800061    LDS     R24,0x0061       Load direct from data space
+00000065:   91900062    LDS     R25,0x0062       Load direct from data space
+00000067:   1728        CP      R18,R24          Compare
+00000068:   0739        CPC     R19,R25          Compare with carry
+00000069:   F434        BRGE    PC+0x07          Branch if greater or equal, signed
29:                PORTB |= (1 << PB3);         
+0000006A:   91800038    LDS     R24,0x0038       Load direct from data space
+0000006C:   6088        ORI     R24,0x08         Logical OR with immediate
+0000006D:   93800038    STS     0x0038,R24       Store direct to data space
+0000006F:   C005        RJMP    PC+0x0006        Relative jump
33:                PORTB &= ~(1 << PB3);            
+00000070:   91800038    LDS     R24,0x0038       Load direct from data space
+00000072:   7F87        ANDI    R24,0xF7         Logical AND with immediate
+00000073:   93800038    STS     0x0038,R24       Store direct to data space
+00000075:   91DF        POP     R29              Pop register from stack
+00000076:   91CF        POP     R28              Pop register from stack
+00000077:   919F        POP     R25              Pop register from stack
+00000078:   918F        POP     R24              Pop register from stack
+00000079:   913F        POP     R19              Pop register from stack
+0000007A:   912F        POP     R18              Pop register from stack
+0000007B:   900F        POP     R0               Pop register from stack
+0000007C:   BE0F        OUT     0x3F,R0          Out to I/O location
+0000007D:   900F        POP     R0               Pop register from stack
+0000007E:   901F        POP     R1               Pop register from stack
+0000007F:   9518        RETI                     Interrupt return


Das macht der Compiler aus der Interruptroutine.

Ich gebs zumindest mal im Moment auf mit PWM. Wenn man sich den Triaxis anguckt, dann sieht man vorne 10 ICs mit verschiedenen Rs. Das sieht für mich nach Latches / DAs aus.
http://www.student.oulu.fi/~kemppaja/Triaxis%20001.jpg

Leider ist genau der Teil im Plan von tubefreak.com nicht dokumentiert, der Rest des Plans deutet aber auch darauf hin.

Ich werde es auf jedem Fall auch mal so probieren. Ein PCF8574 kostet gerade mal 1,7€. Paar Rs dabei und das wars. Das sind vll 2,5€ mehr pro LDR, dafür kann ich mir aber viel Aufwand im Programm sparen und kann mir sicher sein, dass ich damit nie Zeitprobleme kriege... einfach nen Wert reinschreiben und nicht mehr drum kümmern.


M f G
Sebastian







Navigation

[0] Themen-Index

[#] Nächste Seite

[*] Vorherige Sete

Zur normalen Ansicht wechseln