Forum: Mikrocontroller und Digitale Elektronik Merkwürdige Sinunsaugabge


von Marius D. (lonestarr102)


Angehängte Dateien:

Lesenswert?

Ich möchte mit meinem Attiny44A eine Sinuswelle ausgeben. Hierfür habe 
ich eine 8-Bit Lookuptabelle in meinem Code eingefügt.

Die Ausgabe erfolgt per PWM-Signal, welches analog in eine Sinus-Welle 
konvertiert wird.

Die Eingabe erfolgt über einen Zähler (i) der durch die Sinustabelle 
durchläft. Wenn der Zähler bis 255 läuft entsteht ein unerklärlicher 
Pick (siehe Bild) in der Welle kurz vor derm Erreichen der 
Spitzenspannung. Stelle ich die Obergrenze des Zählers auf 240 oder 
kleiner passiert dies nicht. Ich kann mir das nicht erklären. Hat 
zufällig jemand eine Idee.

Wenn ich mir das PWM-Singal anschaue springt es beim Erreichen des 
höchsten Wertes ein paar ms wild hin und her.
1
#define divider  1
2
volatile uint8_t pwm_flag;
3
const uint8_t  sinewave[256]={
4
0x00,0x01,0x03,0x04,0x06,0x07,0x09,0x0A,0x0C,0x0E,0x0F,0x11,0x12,0x14,0x15,0x17,
5
0x19,0x1A,0x1C,0x1D,0x1F,0x20,0x22,0x24,0x25,0x27,0x28,0x2A,0x2B,0x2D,0x2E,0x30,
6
0x31,0x33,0x35,0x36,0x38,0x39,0x3B,0x3C,0x3E,0x3F,0x41,0x42,0x44,0x45,0x47,0x48,
7
0x4A,0x4B,0x4D,0x4E,0x50,0x51,0x53,0x54,0x56,0x57,0x59,0x5A,0x5C,0x5D,0x5F,0x60,
8
0x61,0x63,0x64,0x66,0x67,0x69,0x6A,0x6C,0x6D,0x6E,0x70,0x71,0x73,0x74,0x75,0x77,
9
0x78,0x7A,0x7B,0x7C,0x7E,0x7F,0x80,0x82,0x83,0x84,0x86,0x87,0x88,0x8A,0x8B,0x8C,
10
0x8E,0x8F,0x90,0x92,0x93,0x94,0x95,0x97,0x98,0x99,0x9A,0x9C,0x9D,0x9E,0x9F,0xA1,
11
0xA2,0xA3,0xA4,0xA5,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,
12
0xB4,0xB5,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,0xC0,0xC1,0xC2,0xC3,0xC4,
13
0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD1,0xD2,0xD3,
14
0xD4,0xD5,0xD6,0xD7,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDC,0xDD,0xDE,0xDF,0xDF,0xE0,
15
0xE1,0xE2,0xE2,0xE3,0xE4,0xE4,0xE5,0xE6,0xE6,0xE7,0xE8,0xE8,0xE9,0xEA,0xEA,0xEB,
16
0xEC,0xEC,0xED,0xED,0xEE,0xEE,0xEF,0xEF,0xF0,0xF1,0xF1,0xF2,0xF2,0xF3,0xF3,0xF3,
17
0xF4,0xF4,0xF5,0xF5,0xF6,0xF6,0xF6,0xF7,0xF7,0xF8,0xF8,0xF8,0xF9,0xF9,0xF9,0xFA,
18
0xFA,0xFA,0xFA,0xFB,0xFB,0xFB,0xFB,0xFC,0xFC,0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFD,
19
0xFD,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF
20
};
21
22
23
//uint16_t adcval;
24
volatile uint8_t i=0;
25
26
int main(void) 
27
{
28
    DDRA = (1 << DDA1) | (1 << DDA2) | (1 << DDA3) | (1 << DDA4) | (1 << DDA5);
29
    TIMSK1 |= ( 1 << TOIE1); // enable Timer Overflow Interrupt
30
    SREG |= BIT7;  //sei();  // ebable interrupts
31
  TCCR1A |= (1 << COM1B1) | (1 << COM1B0) | (1 << WGM10); // | (1 << WGM11);  
32
  TCCR1B |= (1 << WGM12)  | (1 << CS10);
33
34
  
35
  while(1)
36
  {
37
  
38
    if ( pwm_flag == 1 )
39
    {
40
      OCR1B = 255;
41
      _delay_ms (2);
42
      OCR1B = 0;
43
      _delay_ms (2);
44
      pwm_flag = 0;
45
      i = 0;
46
    }
47
  }
48
}
49
ISR ( TIM1_OVF_vect ) {
50
    if ( i <= (255-1))
51
    {
52
      OCR1B = sinewave[i];
53
      i=i+ 1;
54
      //_delay_ms(75); // PWM-test dealy
55
      }
56
    else
57
      pwm_flag = 1; 
58
59
}

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Marius D. schrieb:
> PWM(0x00);

Upps - was ist das denn?

> SREG |= BIT7;  //sei();  // ebable interrupts
Auch sehr kreativ, aber nimm ruhig sei(), das läuft auch dann, wenn das 
I-Bit prozessorabhängig mal woanders sein sollte.

Marius D. schrieb:
> OCR1B = 255;
>       _delay_ms (2);
>       OCR1B = 0;
>       _delay_ms (2);
>       pwm_flag = 0;
>       i = 0;

Erklär mal bitte. Wenn deine ISR also 254 erreicht hat, dann kommt das 
hier ins Spiel? Was bezweckst du damit?
Weiterhin ist deine 'Sinustabelle' gar keine, du hast lediglich die 
ansteigende Kurve, aber nirgendwo wird dann rückwärts gezählt, um den 
abfallenden Sinus auszugeben.
Im Allgemeinen ist es keine gute Idee, in der ISR an OCR1B rumzufummeln 
und das auch im Hauptprogramm zu machen, das schlägt der ISR ein 
Schnippchen.

Definiere dir ein Flag, das das Hoch- und Runterzählen koordiniert und 
nutze das dann konsequent nur in der ISR.
Als Tipp lies mal die AVR314 Application Note. Da werden per 
Sinustabelle DTMF Töne erzeugt, was hier nützlich werden könnte.

von Tassilo H. (tassilo_h)


Lesenswert?

Hat der Attiny44a nicht nur 256 Bytes RAM?! Dann passt deine 
Sinustabelle da nicht rein. Mach da mal
const __flash uint8_t  sinewave[256]={
draus.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Tassilo H. schrieb:
> Hat der Attiny44a nicht nur 256 Bytes RAM?! Dann passt deine
> Sinustabelle da nicht rein. Mach da mal
> const __flash uint8_t  sinewave[256]={
> draus.

Eigentlich sollte 'const' schon dafür sorgen, ist aber auf jeden Fall 
ein guter Hinweis. Ältere gcc futtern auch sowas:
1
const PROGMEM uint8_t sinetable[256]

Denke dran, wenn die Tabelle im Flash steht, kommst du da nur mit
1
OCR1B = pgm_read_byte(sinetable+offset);
 ran.

: Bearbeitet durch User
von Tassilo H. (tassilo_h)


Lesenswert?

const alleine reicht nicht.
Bei neueren GCCs einfach const __flash und dann ganz normal drauf 
zugreifen. Bei alten GCCs PROGMEM und Zugriff dann nur mit den 
pgm_read_... Funktionen. Wenn du nicht sicher bist, wie alt dein GCC 
ist, einfach mit const __flash probieren, wenn der Compiler nicht 
meckert, ist er neu genug :-)

von public (Gast)


Lesenswert?

Was ist eigentlich dein Problem? Das der Sinus kein Sinus ist, oder der 
"lustige" Spannungseinbruch?

beste grüße
public

von Marius D. (lonestarr102)


Lesenswert?

Tassilo H. schrieb:
> Hat der Attiny44a nicht nur 256 Bytes RAM?! Dann passt deine
> Sinustabelle da nicht rein. Mach da mal
> const __flash uint8_t  sinewave[256]={
> draus.

Danke sehr das hat sehr geholfen. Funktioniert jetzt sehr gut.

@ Matthias Sch.

werde deine Tipps beherzigen und schauen das ich es anders umsetzen 
kann.

@ public (Gast)
Der Spannungseinbruch.

: Bearbeitet durch User
von public (Gast)


Lesenswert?

Marius D. schrieb:
> @ public (Gast)
> Der Spannungseinbruch.

Also das sieht nach einem zu großen Verbraucher aus, der kurze Zeit 
später nicht mehr da ist bzw. durch den nachfolgenden Schaltungsteil 
ausgeglichen werden kann.
Was kann da in der Software parallel passieren?
Gibt es einen elektrischen Verbraucher der Anfängt die Quelle (µC) zu 
belasten?

Am besten nochmal Testen und Punkt für Punkt rückwärts messen bis zum 
Ursprung deines Signals (µC)... ist da überhaupt eine Schaltung 
dahinter?

beste grüße
public

von Klaus Dieter (Gast)


Lesenswert?

public schrieb:
> Also das sieht nach einem zu großen Verbraucher aus, der kurze Zeit
> später nicht mehr da ist bzw. durch den nachfolgenden Schaltungsteil
> ausgeglichen werden kann.

Ich glaube, das Problem ist behoben (s.o. Flash / RAM-Problematik)

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.