Sinus lookup tabel

Arco

Special Member

Voor een applicatie moet ik met PWM sinustonen opwekken. Momenteel gebruik ik daar een 256 staps sinustabel voor.
Om geheugen te besparen wil ik een 64 staps tabel gaan gebruiken, maar geeft dit veel verlies in kwaliteit?

Ik neem aan dat het afhangt van de frequentie t.o.v. de periodetijd van de pwm, maar is daar een vaste regel voor?
Periodetijd is 10kHz, tonen < 2kHz, en er zit een 4th order laagdoorlaat (3kHz) op de pwm.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
Shiptronic

Overleden

10 kHZ , gaat niet Gillen ? niets zo irritant als een fluitenede PWM

Wie de vraag stelt, zal met het antwoord moeten leren leven.
Arco

Special Member

Er zit een 4th order laagdoorlaat achter, dus van die 10kHz blijft weinig over...

[Bericht gewijzigd door Arco op vrijdag 16 oktober 2020 22:27:11 (10%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Je zou ook nog kunnen gaan interpoleren en zo in effect een digitaal filter vormen. Geen idee waar de applicatie voor bedoeld is, en dus of dat problemen gaat geven. Een andere truc is om slechts 1 helling op te slaan en deze in alle 4 kwadranten te gebruiken als het om besparen van geheugen gaat.

Ja... en toen ?

Stel dat de ruis ergens van 20log(1/256) was -48 dB naar 20log(1/64) = -36 dB gaat, dat geeft een gevoel.

Arco

Special Member

Is voor low quality toepassing (telefoonlijn), ik vroeg me alleen af of je dat gaat merken.
(ietsje vervorming is niet zo erg, als het maar niet hoorbaar is. Is o.a. voor DTMF tonen, en die luisteren nogal nauw.)

Voordeel is dat ik 75% minder ruimte nodig heb voor de tabel... ;)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
elmowww

Golden Member

Volgens mij is het sterk afhankelijk van hoe snel je door die tabel loopt, en waarop je filtert.

Oftewel, de grootste stap die je maakt (in amplitude) en de langste tijd tussen twee nieuwe samples zal bepalend zijn. Als je dat nog kan gaan filteren ook zou je best simpel het spectrum kunnen meten. Of simuleren.

Het zou mij verbazen als het een probleem heeft voor dtmf (die zou tenslotte de grondtoon moeten detecteren, die zit er in vanaf een sinus lookup table van twee samples, 1 en -1).

PA0EJE - www.eje-electronics.nl - e.jongerius[aapje]eje-electronics.nl - EJE Electronics - Elektronica/firmware ontwikkeling
EricP

mét CE

Periodetijd is 10kHz, tonen < 2kHz

Hmz... een tijd in Hz, maar goed...

In het achterhoofd: als je uitgaat van een blokgolf, dan tendeert die met wat RC naar een sinus. Derhalve: hoeveel stappen wil je maken?
Daarnaast: ik neem aan dat je zo handig was om slechts een kwart van de table nodig hebt voor een hele sinus - gradtje roept ook al zoiets.
Verder gok ik erop dat je een byte-table hebt. Als het words zijn, dan is daar ook nog wel winst te behalen - ongeveer de helft.
Tenslotte zou je ook nog in 256 stappen kunnen blijven werken, echter - zoals reeds opgemerkt - botweg lineair (dat is rekenkundig makkelijk en dus snel) interpoleren tussen 2 stappen. Dat gezegd hebbende... met 64 entries en 256 steps is die lineaire interpolatie ook niet zo spannend - rekenkundig gezien.

En ja, het kost allemaal 'nauwkeurigheid'. De vraag is hoe spannend dat voor jou is. Gewoon schrijven, scope eraan, op het 2de kanaal een sinus en kijken hoe erg het afwijkt en of je daar nerveus van wordt? Het zou best nog wel eens erg mee kunnen vallen. Immers... met 64 entries is elke entry 1.5o. Dat is niet zo absurd veel.

High met Henk

Special Member

Ik weet niet of je de math library toevallig gebruikt. Maar daar zit een sinus functie in.

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???

Ik neem aan dat je maar een kwart van de sinus-periode in je tabel zet, en de rest dus uitrekent?

Daarnaast, ik heb ooit (vorige eeuw) een DTMF generator gemaakt met een 4 bit DA, dus ik denk eigenlijk dat het wel losloopt met een 64 staps sinus, verwacht eerder dat je met 16 waarden er ook wel komt.

@Henk: als je geen ruimte hebt voor 192 bytes lookuptabel, dan wil je waarschijnlijk ook geen float/math library.

[Bericht gewijzigd door blurp op zaterdag 17 oktober 2020 08:43:18 (16%)

High met Henk

Special Member

@blurp: mee eens, behalve als je hem voor iets anders in je programma toch al nodig hebt...

E = MC^2, dus de magnetische compatibiliteit doet kwadratisch mee???
Arco

Special Member

Bij een 256 stap tabel zou een kwart-sinus tabel veel schelen, ik denk dat 't bij een 64 stap tabel erom zal hangen...
(ik denk dat de benodigde extra code bij een kwart tabel wel eens dicht in de buurt van de 48 bytes kan komen die een hele tabel extra gebruikt)
Ik gebruik nu 'hele' tabellen...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Roman Black heeft ook een oplossing,

https://www.romanblack.com/SG/SG_tutorial.htm#DTMF
Zo te zien met 128 samples.
op de foto staat een filter van 2.7k / 0.1 uF

Guus@Sint-Michielsgestel

Hoe minder stappen hoe meer harmonische vervorming. Dwz je maakt 1kHz maar ook 2, 3, 4 kHz. Dtmf frequenties zijn zo gekozen dat de harmonischen van de ene toets niet de grondfrequentie van een andere toets zijn. Zolang de ontvanger dus maar smalbandig genoeg werkt kan met heel weinig resolutie al worden volstaan.

De ht9200 dtmf generator chip heeft een distortion spec van -30 / -23dB (typ/max).

Met een audio spectrum analyzer (of gewoon de audio line ingang op de pc) kan je jouw signalen meten en vergelijken met de ht9200 datasheet.

Op 17 oktober 2020 10:29:08 schreef Arco:
Bij een 256 stap tabel zou een kwart-sinus tabel veel schelen, ik denk dat 't bij een 64 stap tabel erom zal hangen...

code:


int mysin (int a)
{
  if (a > 180) return (-mysin (360-a));
  if (a > 90) return (mysin (180-a));
  return tabel[a];
}

Het "kwart tabel gebruiken is toch erg simpel?

(Als je compiler tail-recursion goed optimaliseert hoort ie dat op de tweede if te doen. Anders schrijf je a=180-a;)

Als a niet in graden is maar tot 256 loopt voor een complete omwenteling wordt het:

code:


int mysin (int a)
{
  if (a > 128) return (-mysin (256-a));
  if (a > 64) return (mysin (128-a));
  return tabel[a];
}

Effe puzzelen op de randvoorwaarden. Zoals ik het nu schrijf moet je 65 entries in je tabel hebben.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Er zijn ook truucs om een sinus te genereren met een digitaal filter. Ik weet niet meer precies hoe t ging, de wiskunde erachter is lastig, maar je krijgt dan iets in de vorm van: y[n] = a . y[n-1] + b . y[n-2].

Ofwel voor elke sample tel je de 2 vorige samples op, die je hebt vermedigdvuldigd met een factor. A en b zijn berekend met een formule die ik niet meer precies weet, maar zijn afhankelijk van de samplefrequentie en de gewenste frequentie.

Wellicht kun je googlen op iir sine generator.

Het voordeel van deze methode is dat er relatief weinig processortijd voor modig is. Het nadeel is dat het wel even lastig is om te begrijpen

Spanning staat en stroom gaat!
Frederick E. Terman

Honourable Member

Op 16 oktober 2020 21:55:41 schreef Arco:
Om geheugen te besparen wil ik een 64 staps tabel gaan gebruiken, [...]
Periodetijd is 10kHz

Als je bijvoorbeeld de DTMF-toon 1633 Hz wilt opwekken, en je 'klok' is 10 kHz, dan heb je ca. 6 samples per sinus, dus ruwweg één per 60 graden.
Het hele gebied tussen bijvoorbeeld 150 graden (waarvan de sinus +0,5 is) en 210 graden (−0,5) wordt dus samengevat in één sample. Het zal dus relatief onbelangrijk zijn welke waarde dat precies wordt.

Kortweg: met maar 6 samples per sinus zal het niet zoveel uitmaken of je in principe kon kiezen uit 64 of uit 256 mogelijkheden.
Voorbeeld (rood= sinus in 64 stapjes; groen= gesampled met 10 kHz):

(Voor 697 Hz zijn er weliswaar 14 samples per sinus, maar zoveel meer is dat ook weer niet, zodat het verhaal toch blijft opgaan.)

Keramisch, kalibratie, parasitair: woordenlijst.org

@meander Volgens mij noemde ze dat de wortel 2 - 1 methode of zoiets, ik heb het meer dan 35 jaar geleden eens in assembly gemaakt voor een 8086.
Eigenlijk iets van een dds principe.

[Bericht gewijzigd door henri62 op zaterdag 17 oktober 2020 15:39:45 (12%)

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

hier een stukje van Roman Black
De hogere frequenties moeten ook een hogere amplitude hebben ( twist compensated )

(code below is an updated example; 6 Mar 2011, it is "twist compenstaed" to better match telephone system specs.
// 24bit DDS algorithm for dual simultaneous sinewaves on one PWM module
// this is an example for DTMF generation
// 8 MHz xtal (8 MIPS on PIC 18F PLL)
#define Frow0 46775 // 697 Hz DTMF rows
#define Frow1 51674 // 770 Hz
#define Frow2 57177 // 852 Hz
#define Frow3 63149 // 941 Hz
#define Fcol0 81135 // 1209 Hz DTMF columns
#define Fcol1 89657 // 1336 Hz
#define Fcol2 99120 // 1477 Hz
#define Fcol3 109589 // 1633 Hz
unsigned long waveA absolute 0x15; // 32bit accumulator for the sinewaves
unsigned char waveA_2 absolute 0x17; // overload for fast access to byte 2
unsigned long waveB absolute 0x19;
unsigned char waveB_2 absolute 0x1B;
unsigned char pwm;

// This uses dual sinewaves of 28% different amplitudes, to match the spec for "twist" in
// telephone DTMF to ensure the higher freq has a higher amplitude, to cope with line losses.
const unsigned char sine64low[64] = {
39,42,46,50,53,57,60,63,66,68,71,72,74,75,76,77,77,77,76,75,74,72,71,68,66,63,60,57,53,50,46,42
39,35,31,27,24,20,17,14,11,9,6,5,3,2,1,0,0,0,1,2,3,5,6,9,11,14,17,20,24,27,31,35};
const unsigned char sine64high[64] = {
50,54,59,64,68,73,77,81,85,88,91,93,95,97,98,99,99,99,98,97,95,93,91,88,85,81,77,73,68,64,59,54,
50,45,40,35,31,26,22,18,14,11,8,6,4,2,1,0,0,0,1,2,4,6,8,11,14,18,22,26,31,35,40,45};

// loop and generate dual sinewave DTMF tone
PR2 = (128-1); // PWM at period = 128
while(1)
{
while(!PIR1.TMR2IF); // sync to start of PWM cycle
PIR1.TMR2IF = 0;

// calc the A sinewave,
waveA += Frow0; // zero error Accumulation
pwm = sine64low[waveA_2 & 0x3F]; // Binary Divide output (/65536) and keep 6 bits
// calc the B sinewave, and ADD the 2 waves together
waveB += Fcol0;
pwm += sine64high[waveB_2 & 0x3F];
pwm = (pwm >> 1); // scale 0-200 back to 0-100 for PWM
CCPR2L = pwm; // load added sinewaves into PWM module
}

Guus@Sint-Michielsgestel
Frederick E. Terman

Honourable Member

Bedenk wel dat hij met 62 kHz klokt; dat gaat natuurlijk ruim zes keer zo mooi. ;)

Een heel eenvoudige benadering van cos en sin (misschien denkt @meander daaraan) is als volgt (nee, dit is geen programmeertaal :)):

code:


d = 2 pi / aantal stapjes per periode

x(0) = 1                     y(0) = 0

loop
x(n) = x(n-1) - d.y(n-1)     y(n) = y(n-1) + d.x(n-1)

waarin x de cosinus wordt, en y de sinus.
Klik hieronder voor grafiek (kwartperiode in 64 stapjes; d dus 2pi/256 = 0,0245 en het resultaat is nog iets grof, maar toch al erg verrassend).

Keramisch, kalibratie, parasitair: woordenlijst.org
Arco

Special Member

hier een stukje van Roman Black

Da's inderdaad de meest gebruikte methode.
Alleen wordt meestal maar 1 tabel gebruikt (volume kun je aanpassen door een shift van de gevonden tabelwaarde voor 1 van de tonen)

Het LPF wat Black gebruikt is ook wat simplistisch: hierdoor zit er ruim 4dB verschil tussen de hoogste en laagste toon. (en wel de verkeerde kant op... ;) )

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
blackdog

Golden Member

Hi,

Als je zo weinig samples hebt per sinus klopt de frequentie dan wel?
Dus als je filterd is het dan b.v. pecies 1000Hz, de DTMF frequenties moeten vrij precies zijn zover ik het mij kan herrinneren.

Kan iemand mij vertellen of je met b.v. 6 samples per golfvorm wel precis de frequentie in kan stellen?
Ik weet dat twee samples voldoende zou moeten zijn, ik denk b.v. aan de fase van de samples.
Het zal waarschijnlijk wel, maar in mijn brein rammeld het wat dat betreft, ben geen wiskunde wonder :+

Groet,
Bram

You have your way. I have my way. As for the right way, the correct way, and the only way, it does not exist.

Kan wel.

CD's gaan ook tot 20kHz met 44.1 kHz samples. Maar een goed laagdoorlaat filter is dan wel nodig.

En ik krijg een behoorlijk mooie 10 MHz sinus uit een AD9850 op 80 MHz. Dwz geen zichtbare vervorming op de scope.

Edit:
Maar de methode van FET hierboven werkt dan niet meer. Die gaat alleen goed als je veel meer samples hebt binnen een periode.

PS.
Bij een klein aantal samples per periode krijg je telkens bij elke periode een verschuiving van de sample-punten. Zo kun je dus toch exacte frequenties maken. Bijv 5 kHz samples, signaal 1001 Hz geeft toch exact 1001 perioden in 5000 samples.

[Bericht gewijzigd door deKees op zaterdag 17 oktober 2020 17:27:42 (26%)

Frederick E. Terman

Honourable Member

Nou ja, als je iedere keer opnieuw de bijbehorende sinuswaarde uitrekent, ja. Maar hier willen we een beperkt aantal (64) waarden gebruiken, dus bij iedere klokpuls kun je niet een exacte waarde berekenen, maar moet je één van die 64 mogelijkheden kiezen.
Maar over de langere duur komt het inderdaad wel goed.

Maar de methode van FET hierboven werkt dan niet meer.

'Mijn' methode was ook alleen het antwoord op de vraag 'wat was die grappige methode ook weer om sinuswaarden te berekenen met minimale rekenkracht'.

Keramisch, kalibratie, parasitair: woordenlijst.org

Op 17 oktober 2020 08:42:08 schreef blurp:
Ik neem aan dat je maar een kwart van de sinus-periode in je tabel zet, en de rest dus uitrekent?

Dat ik dat gebruikte is zo'n beetje alles dat is blijven hangen van een computertje (80C552) dat ik ooit gemaakt heb (rekende netto snelheid op een zeilboot uit, tweede helft 90'er jaren, had gelukkig hulp bij assembler programmeren). En dat de formule op basis van een sleeplog en een windvaan (waarvan de hoek weer gecorrigeerd werd voor je eigen snelheid) een paar regels aan sinussen en cosinussen was.
Heeft nooit geweldig gewerkt en mocht tijdens wedstrijden toch niet gebruikt worden ;) Dus de GPS module (à 1000 gulden destijds met NMEA0183 protocol iirc, nu heeft een telefoon van 40 euro er al een) is er nooit meer bijgekocht om het verder te ontwikkelen.

Sorry, offtopic maar die kwart tabel is het eerste dat me bij de titel tebinnen schoot maar was al uitgebreid gemeld.