timer und pwm

vianney

Neues Mitglied
11. Nov. 2009
7
0
0
Sprachen
hallo an alle
ich hoffe ihr könnt mir helfen, hab folgendes problem. ich muss mittels taster die periode und die pulsbreite eines pwm-signals an einem atmega88 mit avr steuern. idealerfall wäre mit 2 taster meine periode ändern d.h wenn s1 gedrückt (inkremetiert) die periode wird größer, wenn auf s2, wird kleiner. und das gleich auch für die pulsbreite mit den 2 restlichen tastern. die period sollte zwischen 50ms-250ms sein, und die pulsbreite zwischen 4ms-20ms.ich hab halt schon mien pwm erzeugt, und wie man die tasteer ansteuert weiss auch schon, hab schon sogar schon geschaft meine pulsbreite zu steuern, durch mein ocr1b-wert. aber jetzt will wiessen wie ich dann meine period mit den restlichen tastern ansteuern sollte, ob ich dafür ein interrupt brauche? ich schicke auch anbei mein bis jetzt fertiges code damit irh euch es auch angückt
danke
Code:
// Funktion Tastenentprellen
// ----------------------------------
inline uint8_t debounce(volatile  uint8_t *port, uint8_t pin) // uint8 = unsigned int 8 bit (eigentlich char)
                                                      // inline= einlesen, volatile = übergabe vom port und pin von HW
{
    if(!(*port & (1<<pin)))
    {    //pin wurde auf masse gezogen, 100ms warten
        _delay_ms(100);
        if((*port &(1<<pin)))
        {    // Anwender Zeit zum Loslassen des Tasters gegeben
            _delay_ms(100);
            return (true);
        }
    }
    return 0;
}

int main (void)
  //Hauptprogramm
{               
    DDRB |= (1 << PB2);
    TCCR1A |= (1<<COM1B0)|(1<<COM1B1) ;            
    TCCR1B |= (1<<WGM13)|(1<<CS10)|(1<<CS12);
    OCR1B=410;  //min pulsbreite 4ms
    ICR1 = 450;  //min period 50ms
      while(1)
    {
        ButtonControl();
        
    if(S1) // für die pulsbreite
        {
            OCR1B=OCR1B-9;
             S1=false;
            if(OCR1B<270)
                {
                OCR1B=270;
                }    
        }

    if(S2)  //für die pulsbreite

        {
            OCR1B=OCR1B+9;
             S2=false;

             if(OCR1B>410)
                {
                OCR1B=410;
                }           
        }
            
    if(S3)  // für die period

        { 
        }    
    if(S4)  // für die period

        {       
        }
   
 }
  return 0;
}
void ButtonControl()
{    
    char SavePORTC = PORTC; 
    char SaveDDRC  = DDRC;     
    PORTC |= (1<<PC0) | (1<<PC1)| (1<<PC2)| (1<<PC3) ;    
    //Interne Pull-Up-Widerstände einschalten
    DDRC &= ~((1<<DDC0) | (1<<DDC1)| (1<<DDC2)| (1<<DDC3));
    //Port C auf Input(0) geschalten
    if (debounce(&PINC, PC0))    //Taste S1
    {   
        S1=true;    
    }
    if (debounce(&PINC, PC1))     //Taste S2
    {
        S2=true;    
    }
    if (debounce(&PINC, PC2))     //Taste S3
    {
        S3=true;            
    }
    if (debounce(&PINC, PC3))     //Taste S4
    {
        S4=true;    
    }
    PORTC = SavePORTC;
    DDRC = SaveDDRC;                
}
 
Hallo,

wollte nicht noch ein neues thema auf machen und denke, mein Problemchen passt schon ganz gut hier hin. Ich kaspere mit dem Timer 1 herum und möchte eine Diode damit dimmen. dieses Thema hatte ich hier schon einmal angesprochen, Markus hatte mir zuletzt dabei auch auf die Sprünge helfen wollen, doch meine Zeit, das Ganze zu Ende zu führen, fehlte mir damals und ich muss auch gestehen, dass ich das Thema hier nicht wiedergefunden habe; dafür schäme ich mich auch!:bad::bad:

Hier erst mal der Code:

Code:
$regfile "m8def.dat"
$crystal = 1000000
$framesize = 100
$hwstack = 100
$swstack = 100

Config Lcdpin = Pin , Rs = Portc.5 , E = Portc.4 , Db4 = Portc.3 , Db5 = Portc.2 , Db6 = Portc.1 , Db7 = Portc.0
Config Lcd = 16 * 4
Config Lcdbus = 4

Config Pinb.0 = Output
Config Pinb.1 = Output
Config Pinb.2 = Output
Config Pinb.3 = Output
Config Pind.0 = Output

Dim A As Bit
A = 0
Dim X As Bit
X = 1
Dim Y As Word
Y = 0

'20 sec
Dim Z As Byte
Z = 0

Config Timer0 = Timer , Prescale = 1024
Timer0 = 61
Enable Timer0
On Timer0 Ontimer0

Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
Compare1a = 0

Pwm1a = 0

Enable Interrupts


Config Clock = Soft , Gosub = Sectic
 Time$ = "00:00:00"

Cursor Off
Cls



Do

Locate 1 , 4
 Lcd Time$


Locate 3 , 4
 Lcd Pwm1a ; "   "


  If X = 1 Then
  If Z = 0 Then
   Incr Pwm1a
   End If
   End If
If Z = 0 Then
If X = 0 Then
   Decr Pwm1a
  End If
 End If

   If Pwm1a > 254 Then
   Pwm1a = 255
      X = 0
   End If


   If Pwm1a < 1 Then
   Pwm1a = 0
   X = 1
   End If

'Zur Kontrolle, was hier ankommt
If Z = 0 Then
Portb.0 = 1
Else
Portb.0 = 0
End If

Loop

Sectic:

Toggle Portd.0

Incr Z
If Z = 10 Then
Z = 0
End If
Return


Ontimer0:
Timer0 = 61
Return


Das Dimmer klappt für sich gesehen ganz gut, mit dem Takt der Sub sectic wollte ich die Dimmgeschwindigkeit zwischen 2 PWM-Werten ändern ( 10 sec oder so). Das geht mit diesem Code aber nur dann, wenn die Variable Z ungleich 0 ist. In der Zeit (1 s), in der 0 ist, rast der PWM Wert um schlappe 40 nach oben oder nach unten. Ich möchte aber erreichen, dass sich der Wert kontinuierlich um eins vergrößert oder verkleinert und zwar dann, wenn Z gerade 0 ist. Mit For und Wait ist das machbar, dann zählt aber die Uhr nicht weiter, weil der Prozessor in der Fop-Schleife festhängt. Hängen im Schacht, jedenfalls bei mir momentan. Wenn ich die fallende flanke, wenn Z von 1 auf 0 springt, per Codetext auswerten könnte, wäre mir geholfen. Dazu fehlen mir aber die (Bascom-) Worte. :( Hat jemand vllt. eine Idee, wie ich das gebacken kriegen könnte?

Beste Grüße
robin
 
Hallo,
habe mal den Hauptteil in die sectic gepackt und es funktioniert gut. Bleibt aber die Frage für mich offen, ob es auch so machbar oder sinnvoll ist?

Gruß
Robin
 
Hallo,
soweit ich das recht in Erinnerung habe, generiert config clock (neben diversen Variablen) mittels eines Timerinterruptes (welchen Timer und welchen Interrupt wird nicht konkret angegeben) einen 1-Sekunden-Takt. Du hast jetzt (optional) programmiert, daß die Subroutine "sectic" dann immer einmal ausgeführt wird. Also jede Sekunde ein mal. Z wird in sectis jedesmal um 1 erhöht, wobei es von 9 nach 0 überläuft. Z ist also eine Sekunde lang 0, eine Sekunde lang 1, usw.
...Das geht mit diesem Code aber nur dann, wenn die Variable Z ungleich 0 ist. In der Zeit (1 s), in der 0 ist, rast der PWM Wert um schlappe 40 nach oben oder nach unten. Ich möchte aber erreichen, dass sich der Wert kontinuierlich um eins vergrößert oder verkleinert und zwar dann, wenn Z gerade 0 ist...
Klar, wenn Z also eine Sekunde lang 0 ist, ist in dieser Sekunde bei JEDEM Durchlauf der Hauptschleife die Bedingung Z=0 wahr, wird also bei jedem Durchlauf der PWM hoch- oder runtergezählt:
Code:
  If X = 1 Then
  If Z = 0 Then
   Incr Pwm1a
   End If
   End If
If Z = 0 Then
If X = 0 Then
   Decr Pwm1a
  End If
 End If
wobei sich der wesentliche Zeitverbrauch durch die Displayausgabe ergeben sollte. Des weiteren werden die Interrupts der Softclock im Hintergrund die Schleife etwas verzögern.
Nebenbei, diese Begrenzungen:
Code:
   If Pwm1a > 254 Then
   Pwm1a = 255
      X = 0
   End If

   If Pwm1a < 1 Then
   Pwm1a = 0
   X = 1
   End If
könnten direkt hinter das jeweilige increment/decrement. Und "wenn PWM1A=255 dann PWM1A=255" (bzw mit 0) bringt gar nichts/kann raus/hat keinen Effekt (die Begrenzung kommt durch das "Umschalten" von X).

Du hast ja selbst erkannt, daß Du die Manipulation am OCR1A (PWM) nicht ausführen lassen willst, wenn Z=0 ist, sondern wenn Z 0 wird. Folglich gehört dieser Code entweder bei sectic mit rein (also hinter die "Überlaufbedingung" von Z), oder Du setzt dort ein "Zehnsekundenflag", welches Du statt Z dann in der Hauptschleife auswertest und zurücksetzt.
(Läuft sectic innerhalb des Interruptes der softclock, oder außerhalb? Also sind währenddessen IRQ global zugelassen?)
 
Hallo LotadaC
Danke für deine Infos. Als Zehnsekundenflag meinst du das so?

Dim A_flag as Byte
A_flag=0

in sectic

Incr A_flag


In der Hauptschleife dann:

If A_flag=10 then

Programmtext

A_flag = 0



Nun habe ich noch ein Problem, wenn ich mehrere Werte mal hintereinander anzeigen will. Hier bei der Zeit und dem Dimmwert passt ja alles schön auf einer Anzeige 4x16 drauf. Wenn nun nicht nur die Uhrzeit sondern auch Ein-Auszeiten gleichzeitig angezeigt, danach der Dimmwert und zuletzt Temperaturen angezeigt werden sollen, gibts Salat auf der LCD. Bei mir jedenfalls. Der Grund meiner Frage ist der, dass ich mal ein Aquarienregelprogramm bauen möchte, mit dem ich diese Werte einzeln auf Tasterdruck oder automatisch immer wiederkehrend anzeigen möchte. Bis dahin ist es noch ein weiter Weg. Es gibt viele Programme im Netz, auch hier im Forum, aber da blicke ich noch nicht ganz durch und ich möchte eigentlich das Programm (weitestgehend) selbst aufbauen. Aber ohne Hilfe geht es leider noch nicht.
Mir ist dabei nicht klar, ob man die Programmteile, die sich auf die LCD Darstellung beziehen in eine Sub schreibt (Debounce)? Das hat bei mir alles noch nicht funktioniert. Alles nicht so einfach!

Gruß
robin
 
Habs mal mit dem "A_flag" probiert und funktioniert super zwischen Do ... loop.:rap:
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)