Forum: Mikrocontroller und Digitale Elektronik AT Tiny44 bei PWM-Modus reagiert zu langsam


von JvH (Gast)


Lesenswert?

Hallo,
ich baue einen Frequenzgenerator bei dem über ein Poti das 
Puls-Pausen-Verhältnis und mit Hilfe von drei Jumpern die Frequenz 
eingestellt wird.
Ich benutze dafür ein AT Tiny 44.
Leider reagiert der µC beim Umschalten der Frequenzen unregelmäßig 
schnell und grundsätzlich sehr langsam.Auch das ausschalten dauert sehr 
lange.
Woran kann das liegen?
Danke fur Antworten im Voraus.

von Karl H. (kbuchegg)


Lesenswert?

* definiere 'unregelmäßig schnell'
* definiere 'grundsätzlich sehr langsam'

Über welche Zeiten sprechen wir?

Das der aktuell laufende PWM Zyklus zu Ende gefahren werden muss, dürfte 
klar sein.

Abgesehen davon liegt der Fehler, wie immer wenn es nicht ein 
systembedingter Fehler ist, in deinem Programm.

von JvH (Gast)


Lesenswert?

Also wenn ich von den hohen zu den niedrigen Frequenzen wechsel dauert 
es bis zu 7 Sekunden bis sich die neue Frequenz einstellt. Vorher läuft 
die alte weiter. Andersherum geht es oft etwas schneller.
Will ich den PWM-Modus beenden dauert es sogar bis zu 11 Sekunden.
Das Programm ist recht einfach gestaltet und läuft an sich mit 
1,3kHz(Port togglen in der while-Schleife).

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

JvH schrieb:
> Also wenn ich von den hohen zu den niedrigen Frequenzen wechsel dauert
> es bis zu 7 Sekunden bis sich die neue Frequenz einstellt.

Dann bräuchten wir wohl auch mal einen Schaltplan ... und das
Programm auch, wenn's nicht gerade geheim ist.

Klingt, als hättest du einen floatenden Eingang.

von Peter D. (peda)


Lesenswert?

Wenn Du den Comparewert runter setzt, mußt Du auch den Timer auf 0 
setzen.
Ansonsten muß der erstmal über 65535 laufen, ehe der nächste Compare 
auftritt.


Peter

von JvH (Gast)


Lesenswert?

Das mit dem Timer hat die Verzögerung zwar nciht behoben aber immerhin 
soweit eingegrenzt dass ich mit arbeiten kann.
Danke für die Hilfe.

von Karl H. (kbuchegg)


Lesenswert?

JvH schrieb:
> Das mit dem Timer hat die Verzögerung zwar nciht behoben aber immerhin
> soweit eingegrenzt dass ich mit arbeiten kann.

Bei 7 Sekunden hast du einen gröberen Bock im Programm.
Warum zeigst du es nicht? So schlimm?

Spätestens nach 1/f[s], wobei f die alte Frequenz ist, muss die 
Einstellung stehen und die PWM umgeschaltet sein. Und ich glaube nicht 
dass du Frequenzen im Bereich 0.14Hz erzeugst.

von JvH (Gast)


Lesenswert?

Okay, dann hier das Programm. Ich hoffe der "Bock" ist nur für mich 
versteckt und jemand findet ihn schnell.
1
int main(void)
2
{
3
4
/*****Variablen*****/
5
6
uint8_t adc_temp = 0;      // Variable für den gemessene Analogspannung
7
uint8_t ocr0a_temp = 0;      // Hilfsvariable fürs rechnen
8
uint8_t Jumper_Status = 0;  // Variable für Status der Frequnezen
9
uint8_t Jumper_Status_alt = 0;
10
  
11
 /******Initialisierungen*****/
12
 clock_prescale_set(7);        //CPU-Freuqeunz = 8Mhz/128
13
 init_ports();
14
 init_ADC();
15
 
16
17
18
    
19
while(1)
20
 {
21
  
22
  adc_temp = ReadAdc();
23
24
  Jumper_Status = 0;
25
26
  if(JUMPER1_SET)
27
    {
28
    Jumper_Status = J1_AKTIV;
29
    }
30
31
  if(JUMPER2_SET)
32
    {
33
    Jumper_Status = J2_AKTIV;
34
    }
35
36
  if(JUMPER3_SET)
37
    {
38
    Jumper_Status = J3_AKTIV;
39
    }
40
41
42
  if (Jumper_Status != Jumper_Status_alt)
43
  {
44
    switch (Jumper_Status)
45
    {
46
    case (J1_AKTIV):
47
      TCCR0B |= ((1<<CS00)|(1<<CS01));  //Teilungsfaktor 64 
48
      ocr0a_temp = 96;
49
      OCR0A = ocr0a_temp;
50
      TCNT0 = 0;              //Timer-Reset
51
      OCR0B = ((ocr0a_temp<<4)/adc_temp);
52
      init_TCCR();
53
      break;
54
55
    case (J2_AKTIV):
56
       TCCR0B &= ~(1<<CS00); 
57
      TCCR0B |= (1<<CS01);        //Teilungsfaktor 8 
58
      ocr0a_temp = 156;
59
      OCR0A = ocr0a_temp;
60
      TCNT0 = 0;              //Timer-Reset
61
      OCR0B = ((ocr0a_temp<<4)/adc_temp);
62
      init_TCCR();
63
      break;
64
65
    case (J3_AKTIV):
66
       TCCR0B &= ~(1<<CS00); 
67
      TCCR0B |= (1<<CS01);        //Teilungsfaktor 8 
68
      ocr0a_temp = 76;
69
      OCR0A = ocr0a_temp;
70
      TCNT0 = 0;              //Timer-Reset
71
      OCR0B = ((ocr0a_temp<<4)/adc_temp);
72
      init_TCCR();
73
      break;
74
75
    default:
76
      TCCR0A = 0;
77
      TCCR0B = 0;
78
      OCR0A = 0;
79
      TCNT0 = 0;              //Timer-Reset
80
      OCR0B = 0;
81
      break;
82
    }
83
    Jumper_Status_alt = Jumper_Status; 
84
  }
85
  else
86
  {
87
    if (Jumper_Status != 0)
88
    {
89
      adc_temp = ((255<<4)/adc_temp);
90
      OCR0B = ((ocr0a_temp<<4)/adc_temp);
91
    }
92
  }
93
  
94
  
95
  
96
 }
97
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Was genau macht denn init_ports()?

Ich hatte oben schon mal die Vermutung geäußert, dass du floatende
Pins hast, an denen deine Taster hängen, darauf bist du nicht
eingegangen.  Vielleicht postest du ja doch einmal den Schaltplan
und den kompletten Sourcecode.

von JvH (Gast)


Lesenswert?

Den Schaltplan habe ich leider nicht digital. Aber an den Eingängen für 
den Jumper-Status hängen jeweils nur ein 1k Vorwiderstand, ein 
Kondensator zum Entstören und dass ganze wird dann per Jumper mit 5V 
verbunden. Nichts aufwendiges also.

Meine zweite Source FIle ist von einem anderen Projekt übernommen. Sie 
enthält  den Ablauf der AD-Messung und dürfte nach Copy-Paste-Methode 
keine Fehler enthalten. Die dritte Source FIle mit den Inits sieht wie 
folgt aus:
1
//#include <stdio.h>
2
#include<avr/io.h>
3
#include "ports.h"
4
#include "init.h"
5
6
7
void init_ports()
8
{
9
/****PortA****/
10
  DDRA |= (1<< PA7);  //alle Ports als Eingang(0), Port A7 als Ausgang(1)
11
  PORTA =0x00;    //alle Pull-Ups deaktiviert(0), keiner aktiviert(1)
12
13
/***PortB***/
14
  DDRB  = 0x00;      //PortB2(OC0A) als Ausgang(1)
15
  //PORTB =0x04;      //PortB2 als HIGH-Output(1)
16
17
}
18
19
void init_ADC()
20
{
21
  ADMUX =0x00;              //Vcc als Referenz(00), PortA0 als Eingang für ADC(0)
22
  ADCSRB |= (1<<ADLAR);    //Bits werden zuerst in ADCH geschrieben
23
  
24
25
}
26
27
void init_TCCR()
28
{
29
  TCCR0A |=(1<<COM0B1)|(1<<WGM01)|(1<<WGM00);  //Impulsreihenfolge High/Low|Modus ist Fast PWM
30
  TCCR0B |=(1<<WGM02);            //Fast PWM mit OCRA als Referenz
31
  //TCCR0B |= ((1<<CS00)|(1<<CS01));      //Teilungsfaktor 1/64 zu CPU-Clock
32
  DDRB |= (1<<OCR0A);
33
}

von Karl H. (kbuchegg)


Lesenswert?

JvH schrieb:
> Den Schaltplan habe ich leider nicht digital. Aber an den Eingängen für
> den Jumper-Status hängen jeweils nur ein 1k Vorwiderstand, ein
> Kondensator zum Entstören

wie groß?

> und dass ganze wird dann per Jumper mit 5V
> verbunden.

Das klingt nicht gut.
Wenn der Jumper nicht gesetzt ist, wer zieht den Eingang auf 0?

> Nichts aufwendiges also.

Noch unaufwendiger wäre es gewesen, den ganzen Klimbim zu lassen, eine 
vernünftige softwaremässige Entprellung zu machen und die Jumper wie 
üblich gegen Masse schalten zu lassen. Dazu die internen Pullup 
Widerstände und deine Aussenbeschaltung ist bis auf die Jumper: 0 - 
njente - nada - nothing

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz Buchegger schrieb:
> JvH schrieb:
>> Den Schaltplan habe ich leider nicht digital. Aber an den Eingängen für
>> den Jumper-Status hängen jeweils nur ein 1k Vorwiderstand, ein
>> Kondensator zum Entstören
>
> wie groß?
>
>> und dass ganze wird dann per Jumper mit 5V
>> verbunden.
>
> Das klingt nicht gut.
> Wenn der Jumper nicht gesetzt ist, wer zieht den Eingang auf 0?

Schalte mal direkt von den entsprechenden Pins einen 10k Widerstand nach 
Masse, wenn du nicht schon einen hast.

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.