Sin/Cos table revisited

Arco

Special Member

Ik weet dat ik er al vaker mee bezig was, maar zaken als cos/sin tabellen blijven (voor mij) toch lastig.
(meetkunde heeft me vroeger op school helaas nooit erg kunnen boeien)

Voor toondetectie heb ik een cos/sin tabel nodig, die ik nu als volgt bereken. (voorbeeld is op PC, maar wordt in een PIC gebruikt en berekend)

pic basic code:


#COMPILE EXE "test.exe"
#DIM ALL
#INCLUDE "win32api.inc"

FUNCTION PBMAIN () AS LONG
  Local lCnt As word, flResult As Single, dStr As String
  '-------------------------------------------------------------------
  dStr = ""
  FOR lCnt = 1 TO 255
    flResult = Sin(2 * 3.14159 * 697.0 * (1 / 10000 * lCnt))
    If flResult >= 0 Then dStr = dStr + " 1"  Else dStr = dStr + " 0"
    If (lCnt Mod 16) = 0 Then dStr = dStr + $Cr
  NEXT i
  Msgbox dStr,, "Sin table:"
  '-------------------------------------------------------------------   
  dStr = ""
  FOR lCnt = 1 TO 255
    flResult = Cos(2 * 3.14159 * 697.0 * (1 / 10000 * lCnt))
    If flResult >= 0 Then dStr = dStr + " 1"  Else dStr = dStr + " 0"
    If (lCnt Mod 16) = 0 Then dStr = dStr + $Cr
  NEXT i
  Msgbox dStr,, "Cos table:"
  '-------------------------------------------------------------------
END FUNCTION

Geeft netjes deze 2 tabellen:

Het nadeel is dat ik veel (te veel) berekeningen doe, omdat ik cos en sin helemaal niet nodig heb, ik moet alleen
weten of de waarde 1 of 0 is tijdens een sample. Voorbeeld is 255 samples op 10kHz en een toon van 697 Hz.

In de PIC gebruik ik dit 14x, zodat de cos/sin functie 7140 keer aangeroepen wordt.
Daar doet de arme PIC meer als 20 sec. over op 16MHz... ;)
Op zich niet zo erg (tabellen worden alleen de eerste keer na programmeren berekend), maar mooi is anders...

Ik heb het gevoel dat dit veel sneller moet kunnen...
Heb ik de Cos tabel eigenlijk wel nodig? (is volges mij identiek aan de Sin tabel, alleen met een offset)

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

Golden Member

Op 23 oktober 2020 13:17:02 schreef Arco:
Heb ik de Cos tabel eigenlijk wel nodig? (is volges mij identiek aan de Sin tabel, alleen met een offset)

Klopt. Een cosinus is een sinus met een faseverschuiving, dus je kunt inderdaad dezelfde tabel gebruiken met een offset op het adres.

Eluke.nl | De mens onderscheid zich van (andere) dieren door o.a. complexe gereedschappen en bouwwerken te maken. Mens zijn is nerd zijn. Blijf Maken. (Of wordt, bijvoorbeeld, cultuurhistoricus)
Arco

Special Member

De offset zou dan in dit geval dus 10000/697/4 = 3.586 zijn?

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

Wil je die 697hz (voorbeeld) detecteren en moet dat analoog de PIC in?

Arco

Special Member

Nee, signaal gaat via een comparator de pic in: is dus 1 of 0

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

Honourable Member

Dan ben je dus een simpele periodemeting aan het doen: geen trigoniometrie voor nodig....

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.
Arco

Special Member

Ik meet meerdere frequenties tegelijk (bijv. dtmf), dus een simpele periodemeting werkt niet.
De detectie werkt trouwens goed, alleen de tabellen maken duurt veel te lang...

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

Je berekent de sinus (cosinus), en kijkt dan alleen maar of ie groter of kleiner dan 0 is.

Dat kan wel simpeler:

c code:


for (int i= 0; i<256; i++) {
   if ((697*i*256)%10000 < 5000) {
      printf ("1");
   }
   else {
     printf("0");
   }
}

Edit: modulo toegevoegd :) Geen garantie of ie nu klopt, of dat je er een factor 256 naast zit.

[Bericht gewijzigd door blurp op vrijdag 23 oktober 2020 15:25:05 (10%)

Arco

Special Member

Ik begrijp wat je bedoelt, en het werkt ook, alleen mist er een modulo... (werkt anders maar 1 loop... ;) )

pic basic code:


  If (697 * i) Mod 10000 < 5000 Then....

Ik heb nog eens gekeken of ik met 1 tabel af kan, maar er zitten natuurlijk wel minieme verschillen tussen beide.
(dit doordat de samplefrequentie niet netjes door de frequentie kan worden gedeeld)

Dus een vaste offset zou kleine verschillen geven. Is dat aanvaardbaar, of toch beter 2 tabellen gebruiken?

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

Als je de tabelwaarde kunt bepalen met een simpele multiply-modulo-compare, is het dan nog de moeite waard een tabel te maken en iedere keer een lookup te doen?

Zeker als je de tabelwaarde sequentieel nodig hebt (en ik vermoed dat je een convolutie doet...) dan kun je de volgende waarde ook uitrekenen met optellen en aftrekken.

Arco

Special Member

Ik ga eens kijken hoeveel overhead dat oplevert en of het in de interrupt rourine past.
(moet iedere interrupt 14x worden uitgevoerd; voor 14 frequenties)

De Sin tabel heb ik nu en die klopt exact, ik moet alleen nog kijken hoe ik de Cos tabel zo kan maken (90 graden verschoven)

Edit:
Cos tabel simpel te maken met:

pic basic code:


If (2500 + 697 * i) Mod 10000 < 5000 Then....

[Bericht gewijzigd door Arco op vrijdag 23 oktober 2020 15:53:43 (17%)

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

Special Member

Scheelt veel!
Tijd voor tabellen maken is nu van 23 seconden terug naar 1.45 seconden... ;)

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