www.mikrocontroller.net

Forum: Digitale Signalverarbeitung / DSP Drei Frequenzbereiche mit FFT bestimmen


Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Ich hab schon mehrere Einträge im Forum zu FFT gefunden, jedoch nicht 
wirklich das passende.
Ich will ganz simpel die Amplitude von drei Frequenzbereiche aus einem 
Audiosignal erhalten. Zum Beispiel der Mittelwert zwischen 80 und 250 
Hz, dann der Wert von 350 bis 550 Hz und als letzten Wert zwischen 750 
Hz und 1500 Hz.
Die Abtastrate wäre mit 100ms voll ausreichend.
Leider peil ich des mit FFT überhaupt nicht. Vielleicht ist dieses 
Verfahren für meine Bedürfnisse auch schwachsinnig. Deshalb brauch ich 
eure Hilfe.
Die Schaltung soll auch so einfach wie möglich sein. Am besten ohne 
großen Aufwand direkt in einen ATMEGA8. Meint ihr das es funktionieren 
könnte?

Hatte auch immer an den BA3830, ein Bandpassfilter, gedacht, aber den 
gibts nirgens mehr zu kaufen. Ich wäre dann über mehrere AD-Eingänge in 
den µC gegangen, um die Werte dann im eigentlichen Programm zu nützen.

Danke im Vorraus.

Simon

: Verschoben durch Admin
Autor: Ale (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich wurde es so machen :

1. Bestimmung von "sampling-frequency" : F (mindestens 2*1500)

2. Bestimmung von wie viele Werte pro band brauche ich. W

3. Quellcode von FFT bekommen/schreiben

100 ms maximal pro rechnung ?... toll


Für 1500 Hz Maximal:

10 kHz sampling freq.
512 "samples" (512*10 us = 5,12 ms) pro rechnung gibt ein Wert je ~20 
Hz, nicht schlecht. und vielleicht machbar.






Autor: Christian (Guest) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
4 Anregungen:

BP Filter
ggf. bei MAXIM scheuen
andere habe aber auch welche, MAXIM schickt muster zu uni-s


Analog geht das auch: da gibt-s software, die die
schaltung auslegt im Internet.


digi. Filter können auch mit dem uC gemacht werden und dann
einfach eine max. wert-bestimmung = Ampli. des Freq. bereichs.


FFT braucht ggf. nicht vollständig berechnt zu werden, wenn:
- freq bekannt
- abtast bekannt, etc.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also Sampling-Frequenz wäre 3kHz, weil ja 1500 Hz maximale Frequenz.

Ein Wert je 20Hz wäre sogar zu übertrieben. Denke mit 256 Samples würde 
es auch reichen. dann hät ich 40 Hz.
Also zwischen 80 und 250Hz (sind 170) würde es mir ca. 4 Werte liefern, 
daraus dann den Mittelwert und ich hät was ich brauch.

Mit 100ms mein ich nur, wie oft ein neuer Mittelwert akualisiert werden 
soll. Also wie oft die ganze Rechenoperation ausgeführt wird.

Punkt 3 ist ein kniffliger Punkt. Ich kenn mich überhaupt nicht mit FFT 
aus. Bin deshalb nicht in der Lage, mir mal schnell einen Code zu 
schreiben. Des weiteren sind meine Kentnisse in Assembler <= 1%.

Es wäre daher echt nett, wenn jemand einen Assambler-Code so anpassen 
könnte, dass dieser einfach nach dem Aufrufen drei Variablem mit dem 
entsprechenden Wert füllt.

mfg Simon

Autor: Ale (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was Christian hat gesagt ist Korrekt, ein Digitales Filter kann im 
prinzip alles eingfacher machen. Gibt schon hier ein Thread. Hast du es 
gelesen ? (ich hab nicht)

FFT Quellcode, gibt jede menge. für AVR... ich glaube gibt (ich habe für 
HC11 und sicher es ist nutzlich).

hier: avr FFT auf asm :

Beitrag "Wer kennt diesen Hersteller ?"

Viel Spaß

Ale

Autor: Axel R. (axelr) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
panzerfahr'n? ;-))

Autor: Ale (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Axel Rühl:

Was bedeutet "panzerfahr'n? ;-))" für die Leute wie ich, daß es niht 
können ? (kein Spaß!)

Ale

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Ale,

klick mal selbst Deinen Link (Beitrag "Wer kennt diesen Hersteller ?") 
an ;-))

Da Deutsch scheinbar nicht Deine Muttersprache ist:
"panzerfahr'n" ist eine (in diesem Fall humorvoll gemeinte) Verkürzung 
von "Panzer fahren" und bedeutet in etwa "Es würde sehr viel Spaß machen 
mit einem Panzer durch die Gegend zu fahren und ohne Rücksicht auf 
Verluste einfach alles platt zu walzen".

CU

Autor: Ale (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das war blöd ! Sche***e Copy und Paste !!!!!

Die richtige link war :

Beitrag "FFT auf dem AVR"

Ich wollte kein Spaß mit seine Frage machen !, Entschuldigung :-)

Autor: Axel R. (axelr) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es tut auch mir leid. Ich wollte mich nicht lustig machen.
Ich wollte (auch) darauf hinweisen, dass der Link nicht richitg ist.

Wenn man auf der Seite ganz nach unten scrollt, kommt ein Bild von einem 
Panzer. daher mein amüsante Frage. Weil es doch so garnichts mit FFT zu 
tun hatte. Was auf keinen Fall böse gemeint!
Beitrag "Re: Wer kennt diesen Hersteller ?"

sorry for that

AxelR.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na super, 9 Antworten, aber irgendwie doch nicht wirklich hilfreich. Hät 
mir mehr erwartet.

Was mir noch bei den ganzen Schaltungen aufgefallen ist, ist der MAX293. 
Kann man das nicht auch ohne den machen. Grad für meine Aufgabe müsste 
es doch anders gehen.

mfg Simon

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, ich bins nochmal.
Hab grad rausgefunden, dass für meine Anwendung der Goertzel-Algorithmus 
voll ausreichend ist.
Hab auch einen Code gefunden, der einen DTMF-Decoder entspricht.
Sample code for a DTMF detector

#define SAMPLING_RATE       8000
#define MAX_BINS            8
#define GOERTZEL_N          92

int         sample_count;
double      q1[ MAX_BINS ];
double      q2[ MAX_BINS ];
double      r[ MAX_BINS ];

/*
 * coef = 2.0 * cos( (2.0 * PI * k) / (float)GOERTZEL_N)) ;
 * Where k = (int) (0.5 + ((float)GOERTZEL_N * target_freq) / SAMPLING_RATE));
 *
 * More simply: coef = 2.0 * cos( (2.0 * PI * target_freq) / SAMPLING_RATE );
 */
double      freqs[ MAX_BINS] = 
{
  697,
  770,
  852,
  941,
  1209,
  1336,
  1477,
  1633
};

double      coefs[ MAX_BINS ] ;


/*----------------------------------------------------------------------------
 *  calc_coeffs
 *----------------------------------------------------------------------------
 * This is where we calculate the correct co-efficients.
 */
void calc_coeffs()
{
  int n;

  for(n = 0; n < MAX_BINS; n++)
  {
    coefs[n] = 2.0 * cos(2.0 * 3.141592654 * freqs[n] / SAMPLING_RATE);
  }
}


/*----------------------------------------------------------------------------
 *  post_testing
 *----------------------------------------------------------------------------
 * This is where we look at the bins and decide if we have a valid signal.
 */
void post_testing()
{
  int         row, col, see_digit;
  int         peak_count, max_index;
  double      maxval, t;
  int         i;
  char *  row_col_ascii_codes[4][4] = {
    {"1", "2", "3", "A"},
    {"4", "5", "6", "B"},
    {"7", "8", "9", "C"},
    {"*", "0", "#", "D"}};


  /* Find the largest in the row group. */
  row = 0;
  maxval = 0.0;
  for ( i=0; i<4; i++ )
  {
    if ( r[i] > maxval )
    {
      maxval = r[i];
      row = i;
    }
  }

  /* Find the largest in the column group. */
  col = 4;
  maxval = 0.0;
  for ( i=4; i<8; i++ )
  {
    if ( r[i] > maxval )
    {
      maxval = r[i];
      col = i;
    }
  }


  /* Check for minimum energy */

  if ( r[row] < 4.0e5 )   /* 2.0e5 ... 1.0e8 no change */
  {
    /* energy not high enough */
  }
  else if ( r[col] < 4.0e5 )
  {
    /* energy not high enough */
  }
  else
  {
    see_digit = TRUE;

    /* Twist check
     * CEPT => twist < 6dB
     * AT&T => forward twist < 4dB and reverse twist < 8dB
     *  -ndB < 10 log10( v1 / v2 ), where v1 < v2
     *  -4dB < 10 log10( v1 / v2 )
     *  -0.4  < log10( v1 / v2 )
     *  0.398 < v1 / v2
     *  0.398 * v2 < v1
     */
    if ( r[col] > r[row] )
    {
      /* Normal twist */
      max_index = col;
      if ( r[row] < (r[col] * 0.398) )    /* twist > 4dB, error */
        see_digit = FALSE;
    }
    else /* if ( r[row] > r[col] ) */
    {
      /* Reverse twist */
      max_index = row;
      if ( r[col] < (r[row] * 0.158) )    /* twist > 8db, error */
        see_digit = FALSE;
    }

    /* Signal to noise test
     * AT&T states that the noise must be 16dB down from the signal.
     * Here we count the number of signals above the threshold and
     * there ought to be only two.
     */
    if ( r[max_index] > 1.0e9 )
      t = r[max_index] * 0.158;
    else
      t = r[max_index] * 0.010;

    peak_count = 0;
    for ( i=0; i<8; i++ )
    {
      if ( r[i] > t )
        peak_count++;
    }
    if ( peak_count > 2 )
      see_digit = FALSE;

    if ( see_digit )
    {
      printf( "%s", row_col_ascii_codes[row][col-4] );
      fflush(stdout);
    }
  }
}


/*----------------------------------------------------------------------------
 *  goertzel
 *----------------------------------------------------------------------------
 */
void goertzel( int sample )
{
  double      q0;
  ui32        i;

  sample_count++;
  for ( i=0; i<MAX_BINS; i++ )
  {
    q0 = coefs[i] * q1[i] - q2[i] + sample;
    q2[i] = q1[i];
    q1[i] = q0;
  }

  if (sample_count == GOERTZEL_N)
  {
    for ( i=0; i<MAX_BINS; i++ )
    {
      r[i] = (q1[i] * q1[i]) + (q2[i] * q2[i]) - (coefs[i] * q1[i] * q2[i]);
      q1[i] = 0.0;
      q2[i] = 0.0;
    }
    post_testing();
    sample_count = 0;
  }
}

Theoretisch müsste man den Code doch einfach nur auf meine Frequenzen 
umschreiben. Wollte den Code eigentlich auch in Basic haben. Außerdem 
weiß ich nicht, was im Code der ADC-Wert ist, und in welcher Variable 
die Level stehen.

mfg Simon

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Input -> int Sample
Output Görtzel -> r[]
Output Tastencode in PostProcessing() -> row_col_ascii_codes[row, col]

Gruß Hagen

Autor: Ale (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Simon:

"Na super, 9 Antworten, aber irgendwie doch nicht wirklich hilfreich. 
Hät
mir mehr erwartet."

Ich habe auch viele mahle etwas gefragt und nicht immer die Antwort ich 
habe gedach gut war und ich erwartete bekommen. Es ist so, vielleicht du 
hast Glück und jemand kennt ganz genau was du brauchst, manchmal nicht. 
Aber über was du zuerst gefragt hast glaube ich, es wäre 2 gute 
möglichkeiten.

(Ich wurde nicht viel von Float rechnen mit ein AVR, am besten mit int, 
wir viel schneller sein).

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich dachte, es ginge um die Messung von drei Amplituden, dafür ist 
Goertzel nicht so geeignet, eher für Schwellenüberschreitung, also 
"Tondecoder".
Soweit ich das verstanden habe, ist ein "Goertzel" ein einfacher 
IIR-Bandpass, der periodisch wieder genullt wird, da er sonst überläuft.
Es wird nur in diesem Zeitraum entschieden, ob die Amplitude innerhalb 
der Bandbreite des Filters einen Schwellenwert überschritten hat. Für 
einen echte Messung müßte ja ein Messwert herauskommen.

Autor: Axel R. (axelr) Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für ein Discolauflicht reicht das allemale.
Man gibt einen Wert vor und zieht dann den Takt aus der Musik. Ich 
denke, so etwas in der Art soll es wohl werden.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Axel Rühl wrote:
> Für ein Discolauflicht reicht das allemale.
> Man gibt einen Wert vor und zieht dann den Takt aus der Musik. Ich
> denke, so etwas in der Art soll es wohl werden.

Wenn das stimmt, dann frag ich mich doch glatt obs nicht ein
paar simple RC-Filter auch tun:
http://www.b-kainka.de/bastel85.htm


Autor: Andreas Lang (andi84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt da auch eine recht nette FFT Bibliothek für den AVR. (müsste nur 
noch den Link wiederfinden). Die Verwende ich selbst, um in einem etwas 
umfangreicheren DMX-Controller eine Lichtorgel und einige andere Späße 
zu implementieren.
Da ist aber auch noch ein guter Happen Analoggekrümele auf Lochraster 
vornedran (das meiste davon aber nur Beaterkennung). FFT braucht aber 
auf jeden Fall richtig böse viel Speicher. Für die 256 Samples wären das 
512 Bytes für int16_t samples. 1kB für den komplexenwertigen 
Eingangspuffer und ggf. nochmal 1kB für den Ausgangspuffer. Da ist dann 
recht schnell der RAM voll bis unter'n Rand.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die tollen Antworten!
Hät schon gedacht, ich werd meine Idee bald verwerfen können.

@ Hagen Re:
Kann ich dann einfach die Goertzel-Funktion immer wieder 
(timer-gesteuert) aufrufen und der Variable Sample den Analogwert von 
meinem ADC-Eingang geben, also die Variable durch den Eingang ersetzten?
In r[] stehen dann so wie von mir gewünscht die Amplituden?

@ Axel Rühl:
Genau das hab ich vor. Ein Discolauflicht. Werde dann einfach die drei 
Pegel von meinen Frequenzen vergleichen und dann einfach gesagt jeweils 
ein Licht switchen.

@ Karl Heinz:
Genau die Schaltung hab ich schon testweise aufgebaut. Bin aber vom 
Ergebnis stark enttäuscht. Entspricht leider nicht meinem Vorhaben, denn 
die Verbindung zum µC und die Frequenzen machen Probleme.

@ Andreas Lang:
Super, dass trifft auch auf mich zu. Es handelt sich später auch um 
einen DMX-Controller, der die Sound-to-Light-Steuerung in ordentlicher 
Qualität bereitstellt.
Meinst du wirklich, dass der Goertzel-Algorithmus nicht ausreicht?
Wer nett, wenn du doch noch die Bibliothek finden könntest.

Wär cool, wenn Ihr mir auf diese Fragen auch noch Antwort geben könnt.

ciao Simon

Autor: Andreas Lang (andi84)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Simon:
Ich poste einfach mal hier den Code, die FFT-Bibliothek ist von Chan 
(elm-chan.org). Das Ganze befindet sich sehr stark im Fluss, die 
Hardware ist ein mittelschweres IC-Massengrab und auch sonst ist das 
drumherum nicht so dolle derzeit. Was man aber (denke ich mal) verwerten 
kann, ist der DMX-Transmitter (separater Mega8, wegen Speicherplatz) und 
mal die Grundsätzlichen Funktionen (Master Fader, All On, Crossfade, 
Interruptbsierter ADC und FFT2Light).
@All:
Der Code im angehängten File ist noch sehr pre-alpha. Irgendwie 
funktioniert er, ist aber weder gut kommentiert noch irgendwas. Ich 
werde aber wohl die relevanten Stellen noch hier im Forum hervorheben.
Brauchbar ist schonmal der Kram im Ordner dmxtx. Das ist ein kompletter 
DMX-Transmitter mit SPI-Interface. Das DMX-Timing wird komplett im mit 
Interrupts erledigt. Der Code ist eher mäßig gut kommentiert, aber 
insgesamt doch recht verständlich, da nicht zu komplex. Der Kram in 
chaser.c ist allerdings recht wüster Spaghetticode.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Leider habs ich net so mit C. Was hats mit ffft.h auf sich?
Wär echt no ah Sach, wenn du dein Code erklären könntest.

Für die Datei dmxtx.c interessiere ich mich auch. Du hast geschrieben, 
dass man den Chip über SPI ansteuern und dadurch DMX-Daten versenden 
kann. Wie schaut da des Protokoll und natürlich der Schaltplan aus?

mfg Simon

Autor: Andreas Lang (andi84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der DMX-Transmitter-Code ist für einen Mega8@16MHz geschrieben. Man 
hängt ihn einfach 1:1 an den SPI der Master-CPU (trennbar, wenn man ISP 
macht) und sendet mit der Master-CPU Daten per SPI.
Mit zwei Nullbytes hintereinander kann man eine aus dem Tritt geratene 
Übertragung wieder resetten, ansonsten: 1. Byte Kanalnummer, 2.Byte 
Kanalwert.
Am TXD hat man dann DMX512 mit einem max 255 Kanäle großen Universe.
Die größe des Universe ist im Quelltext des Transmitters angegeben und 
lässt sich dort leicht ändern. Der Transmittercode ist recht kompakt und 
sollte auch ohne große C-Kenntnisse verständlich sein.

ffft.h ist die Include-/Headerdatei für die Assembler-FFT-Bibliothek 
(ffft.S).

> Leider habs ich net so mit C.

Mir gings mal ähnlich. Aber es wäre geschickt, wenn Du dich für etwas 
wie einen DMX-Controller in C einarbeitest, da das ganze mit BASIC, 
insbesondere mit BASCOM echt Tierquälerei ist.

Was du aber auf jeden Fall brauchst ist viel RAM. Schon ein ganz 
normaler Chaser (Lauflicht) braucht bei z.B. 12 unterstützten Kanälen 12 
Bytes pro Schritt. Will man das dann noch etwas intelligenter oder mit 
variabler Fade-Time, dann wirds noch mehr. Ein Speicherplatz für einen 
Chaser sollte mindestens 32 Schritte fassen können. Die sind z.B. ganz 
schnell weg, wenn man evtl. irgendwelche Scanner oder was auch immer 
damit steuern will. Für Anwendungen, bei denen nur Lampen dran sind, 
würden wohl auch noch 16 Positionen reichen.

Ganz nett sind sogenannte Memorys und Memory Chaser. Man erstellt dann 
erst einzelne Lichtstimmungen (Szenen) und speichert diese. Dann packt 
man diese in einen Chaser. Damit kann man sehr schnell sehr hübsches 
Licht machen.
Wenn man dann noch mehrere Chaser parallel zusammenmixen kann, ist das 
dann ganz edel, braucht man für die Kellerdisco aber eher nicht.
Hier tun es schon 3-12 (je nachdem, wieviele Lampen man hat) 
unterschiedliche Chaser, die hin- und wieder mal gewechselt werden.

Wenn man LED-Pars als Lampen verwenden möchte (gerade im Partykeller 
recht nützlich, weil die nich eben mal 0,3-1kW pro Lampe ziehen) braucht 
man pro Lampe schon mal 5-6 Kanäle, ein einfacher Scanner ist mit 7-11 
Kanälen dabei. Deswegen gleich einen AVR mit iel RAM nehmen und Sachen, 
wie Bedienelemente (LC-Display, Menüführung oder was auch immer) gleich 
in einen extra µC packen und den per UART anbinden.


Der Schaltplan ist so 'ne Sache. Das Gerät dazu ist stückchenweise um 
einen Mega16 herum gewachsen und verteilt sich auf 2 Ebenen von 
Lochrasterkarten. Das meiste darauf ist eine eher mittelmäßige 
Beaterkennung (Schaltplan siehe ELV-Beatcounterbausatz, auf deren 
Website) und was man halt sonst noch so braucht (Erzeugung der negativen 
Betriebsspannung für die OPs, Gleichrichter und RC-Glied fürs VU-Meter 
(und eine eventuelle AGC, damit man nicht immer von hand auf 0db 
einstellen muss; das passt dann aber in das jetzige Gehäuse nicht rein).
Da das ganze in erster Linie frei Schnauze bzw "Stift und Schmierzettel" 
entstanden ist, werde ich wohl zunächst einmal anhand des Quelltextes 
die direkte Peripherie/Anschlussbelegung des Mega16 reverse-engineeren.
Den Analogkram bekomm ich auch so wieder zusammen, wenn ich das Teil 
wieder vor mir liegen hab (liegt aber halt grad 200km entfernt).
Hier mal eine grobe Übersicht, was da so drin ist:
- Mega16
- Mega8
- Quarzoszi 16MHz
- 3 LM324
- MAX232
- irgendwas, das zum OPA2134 pinkompatibel ist (der ist viel zu 
hochwertig dafür, steckt aber trotzdem im Sockel, weil ich grad nix 
anderes dahatte)
- MC34063 oder wie er heißt
- Jede menge Hühnerfutter (2 SMCC-Spulen, diverse Kondensatoren und 
Widerstände)
- 2 Potis
- 2 Kippschalter, davon einer mit Mittelstellung
- 1 Duoled
- 13 normale LEDs

Bilder hab ich leider grad keine von. Werde aber mal welche machen, wenn 
ich das Gerät wieder zu fassen kriege.

Autor: Andreas Lang (andi84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach so, nen RS485-Transceiver ist auch noch einer drin.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Beschreibung zum DMX-Transmitter. Ach ja, könnte mir 
jemand ne hex-File vom Code schicken. Hab grad kein C-Compiler parat.
Und noch ne Frage: Müss ich stetig über SPI die Bytes für jeden Kanal 
schicken oder merkt sich der µC die letzten Settings?
Output wird wohl TxD sein?

Bin schon gespannt auf die Bilder und vielleicht einen groben 
Schaltplan.

Unterstützt der ATMEGA8 eigentlich Hardware-Multiplikation und Addition?

mfg Simon

Autor: Andreas Lang (andi84)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Der µC merkt sich die Kanalwerte. Mit dem Code, wie er jetzt ist, hat 
man 128 Kanäle. Der Mega8 hat einen Hardwaremultiplizierer. Addieren 
kann er auch. Wenn du einen MAC (Multiply an Accumulate) meinst, den hat 
er nicht. Da der ATMega aber sehr schnell multiplizieren und addieren 
kann, kann man das in Software nachbilden.
z.B. in C:
uint16_t summe;
uint8_t wert[8], faktor[8];
//Werte auffüllen
summe=0;
for (uint8_t i=0;i<8;i++) {
   summe+=((wert[i]*faktor[i])>>8);
}

Wobei man bei einem Lichtpult wohl eher Kanalwerte gewichtet addieren 
und dann den Kanalwert auf 255 begrenzen möchte:
if (summe>0xff)
   sume=0xff;

Das .hex-File hänge ich mal an.
Lade dir aber mal am besten WinAVR runter.
Dann musst du nur noch in das Verzeichnis zu wechseln und "make" 
eingeben.

Autor: Andreas Lang (andi84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ein Crossfade wäre dann so zu bauen:
kanal=(((255-fade)*cch[i])>>7)+((fade*nch[i])/0xff);

  

Autor: Andreas Lang (andi84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ähm, so ist es richtig:
ch[i]=(((255-fade)*cch[i])/0xff)+((fade*nch[i])/0xff);

Autor: Andreas Lang (andi84)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wobei man das ggf. mit Bitschieben schneller machen kann. Allerdings ist 
255*255 um 8 Bits nach rechts geschoben nur 254. Aber das kann man wohl 
trotzdem als 255 gelten lassen. Dann sieht das so aus:
ch[i]=(((255-fade)*cch[i])>>8)+((fade*nch[i])>>8);
Geht jedenfalls schneller al erst mal eine richtige Division 
auszuführen.
Man könnte auch erstmal die beiden Werte in einen Vorzeichenfreien 
16-Bit Integer addieren und den dann 8 Bits nach rechts schieben. Das 
ist dann noch etwas schneller, da nur einmal um 8 Bits schieben nötig 
ist, bzw. man einfach das high-byte nimmt und gut ist. Spart wohl ein 
paar Takte.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.