Forum: Digitale Signalverarbeitung / DSP / Machine Learning Frequenzerkennung 125-140kHz mit dsPIC machbar?


von oli (Gast)


Lesenswert?

Guten Morgen!

Habe folgende Aufgabenstellung:

Es soll erkannt werden ob 2 Frequenzen im Bereich von 125-140kHz (ja eh 
klar - Powerline) anwesend sind und je nachdem ein Portpin high oder low 
sein. Nebenbei ist noch ein wenig UART Kommunikation zu erledigen 
(19200bps, ca. alle 100ms) und je nachdem was dort gekommen ist ein PWM 
Signal verändert werden.
Mit einem ARM7@60Mhz komme ich wenn ich wenn ich 2 IIR Filter 1.Ordnung 
berechne gerade mal auf max. 25kHz Samplerate bzw. "Berechnungsrate".
Selbst wenn ich dort noch Codeoptimierungen machen könnte auf die nötige 
Samplerate komme ich mit diesem Prozessor wohl nicht - für was hat der 
dann eigentlich einen ADC der 400kS/s schafft?)

Ich hab zwar schon recht erfolgreiche Versuche mit 
"Bandpassunterabtastung" gemacht wo ich die Anwesenheit der Frequenzen 
recht gut festgestellt habe, jedoch brauche ich dann wohl einen recht 
guten Bandpass am Eingang. Das würde aber wahrscheinlich auf Spulen 
hinauslaufen und die benötigen Platz den ich nicht habe. Für mehr als 
einen nicht allzuaufwändigen Tiefpass wird kaum Platz sein (Platine max 
2x3cm).

Nun meine Frage: Was brauche ich an Rechenpower um eben mit ca. 
350-400kHz Abzutasten und 2 IIR Filter 2.Ordnung zu berechnen? Schaft 
ein dsPIC das?
Ehrlich gesagt war ich von der Langsamkeit des ARMs schon sehr 
überrascht.
"richtige" DSP scheiden wohl aus da das Programmierequipment dafür wohl 
richtig Geld kostet (mehr als Bastlerbudget gibts leider nicht). 
Außerdem sollen die Bauteile pro Platine nicht mehr als 5-7€ kosten 
(dsPIC ist recht günstig und vorallem beschaffbar).
Gibts bessere Methoden als IIR um die Anwesenheit einer bestimmten 
Frequenz festzustellen? Analogtechnik ist nicht grundsätzlich verboten, 
da ich aber ohnehin etwas uC Artiges benötige wärs ideal wenn dieser 
dies erledigen könnte.

Danke im Voraus

Oli

von Zacc (Gast)


Lesenswert?

Was soll denn ein IIR 2.Ordnung ? Wenn die Frequenzen ja bekannt sind 
ist es viel einfacher. Das Signal gleichzeitig mit Sin & Cos der 
gesuchten Frequenz multiplizieren und integrieren. Die 
Frequenzunschaerfe bekommt man mit der weniger als unendlichen Laenge

von Detlef _. (detlef_a)


Lesenswert?

>>Mit einem ARM7@60Mhz komme ich wenn ich wenn ich 2 IIR Filter 1.Ordnung
>>berechne gerade mal auf max. 25kHz Samplerate bzw. "Berechnungsrate".

Die IIRs in integer implementieren, auf Overflows achten!

Es schadet ja auch nicht, wenn Du die beiden Frequenzen unterabtastest, 
die spiegeln sich dann runter, z.B. 100kHz mit 90ks/s abgetastet sieht 
aus wie 80kHz. Die kannst Du dann prima erkennen.

Cheers
Detlef

von Detlef _. (detlef_a)


Lesenswert?

> Es schadet ja auch nicht, wenn Du die beiden Frequenzen unterabtastest,
> die spiegeln sich dann runter, z.B. 100kHz mit 90ks/s abgetastet sieht
> aus wie 80kHz. Die kannst Du dann prima erkennen.

Ähm, ne, 100kHz mit 90kHs/s abgetastet sieht aus wie 10kHz: 100kHz 
gespiegelt um 90khz ist 80kHz, 80kHz gespiegelt an Nyquist 45kHz zeigt 
10khz.

Cheers
Detlef

von oli (Gast)


Lesenswert?

@Detlef_a: ja genau sowas ähnliches mach ich gerade. Ich Taste mit z.B. 
12,5kHz ab und sehe jetzt den Bereich von 125-130kHz als 0-5kHz.
Nur muß da ein recht steiler Bandpass vor den ADC damit keine Aliases 
von anderen Frequenzen reinkommen. Den will ich eigentlich irgendwie 
vermeiden. Mehr als ein Tiefpass 3-4.Ordnung sollte es nicht werden 
(Platzprobleme).

Bin jetzt auf den Goertzel-Algorithmus gestossen der für meine Anwendung 
ggenau das richtige sein soll. Mal sehen ob ich überhaupt verstehe um 
was es da geht.


MfG Oli

von Zacc (Gast)


Lesenswert?

Der Goertzel ? War nicht die Frage nach der Anwesenheit von Frequenzen ? 
Deswegen muss man die ja noch nicht bestimmen. Eine komplex 
multiplikation mit einem oder zwei sinussen ist viel einfacher.

von oli (Gast)


Lesenswert?

Hallo Zacc

Der Ansatz klingt interessant (und recht einfach und schnell)

Bin leider recht neu in dem Thema deswegen nochmal nachgefragt:

Versteh ich das richtig: Sinus- und Cosinuswerte (von welcher Frequenz? 
Signalfrequenz? )in Tabelle und Eingangswerte damit multiplizieren 
(jeden Wert mit jeden oder wie?), dann die Ergebnisse aufaddieren und 
wenn Ergebniss Grenze übersteigt ist die Frequenz "da"?
Hat das ganze eine offiziellen Namen?


Trotzdem mal danke für alle Antworten

MfG
Oli

von Detlef _. (detlef_a)


Lesenswert?

Einen komplizierten Bandpaß/Tiefpaß würde ich nicht dazu aufbauen. Dann 
lieber nochmal auf die digitale Seite kucken: ARM7 braucht doch 3 Takte 
oder so für ne Multiplikation, also 20e6 Multiplikationen @60MHz. Für 
zwei IIRs brauchst Du 10Multiplikationen, also 4e6 bei 400ks/s 
samplerate. Damit ist der ARM doch 5mal schneller als Du brauchst!

@Zacc: Für den Sinus brauchst Du tabellierte Werte. Falls Du die sin/cos 
on the fly erzeugst ist das dergleiche hack wie nen IIR.

Cheers
Detlef

von oli (Gast)


Lesenswert?

Das mag schon sein das der so schnell ist aber ich hab in meiner 
Sample/Berechnung ISR einen Portpin gesetzt den ich mit dem Oszi 
beobachte um zu schauen wie lang er in der ISR ist und irgendwie braucht 
mein IIR 1.Ordnung mit dem Sampling (braucht angeblich 11 Takte) und ein 
wenig Speicher umladen so lang das sich max. 30kHz (entspricht kSmpls/S) 
ausgehen.
Wie gesagt ich hab noch nix optimiert (Compiler gcc-C).
Werd mal den Assembler anschmeißen.

Seltsam ist - selbst wenn ich in der ISR einfach nur einen Wert aus 
einer Tabelle auf den DAC schreibe und dann einmal index++ mache dauert 
das so lang das max. 100kHz Interruptrate gehen. Ich glaub ich mach was 
falsch.
(Die ISR wird übrigends vom Timer getriggert)


MfG Oli

von oli (Gast)


Lesenswert?

Guten Morgen

Hab gestern noch etwas mit dem ARM herumexperimentiert.

1.)
Mal rein in einer Endlosschleife Portpins getoggelt.
Ergebniss:
C Code mit gcc kompiliert: 2,4MHz Toggelrate,
Assembler: etwas über 8 Mhz Toggelrate.
Da ist sicher noch was drinn wo dann auch diverse Signalverarbeitung am 
ARM möglich ist.

2.)
Wenn ich jetzt rechne: 60Mhz, 400kSmpls/s -> 150 Takte Rechenzeit pro 
Sample

27Takte braucht er mind. bis er in der ISR ist,
143!!! Takte (hab mich gestern verlesen) braucht der ADC bis er fertig 
ist (da ergeben sich dann so ziemlich genau die angegebenen 400kSmpls/s 
bei 60Mhz Systemtakt)
Man kann während diesen 143 Takten zwar was anderes machen aber 
irgendwann brauch ich den Wert um zu rechnen. Wenn das dann auch noch 
100Takte braucht bin ich sowieso jenseits von gut und böse.

Mal sehen ob es geht den ADC direkt vom Timer zu triggern und die ISR 
dann vom "ADC fertig Interrupt". Da sollte sich das dann mit ASM 
Programmierung mal grade so ausgehen.

Das Problem ist dann nur das für die Hauptschleife dann genau garkeine 
Zeit mehr überbleibt

3.)
Deswegen ja meine Frage ob der dsPIC da nicht vielleicht die bessere 
Wahl wäre (richtigen TI oder Analog DSP kann ich mir vermutlich nicht 
leisten).
ARM7 hat den Vorteil das ich da Board und Programmierequipment schon 
habe. Aber wenn mir jetzt jemand sagt das das mit dsPIC locker von der 
Hand geht (oder der gar noch unterfordert ist) dann würd ich mir sogar 
die Mühe machen auf diesen umzustellen.


MfG
Oli


P.S.: Juhu Freitag - noch wenige Stunden und dann ab ins Wochenende

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Wenn dein ARM DMA hat könntest du längere Blöcke vom ADC einlesen und 
danach verarbeiten, das spart den Interrupt-Overhead. Aber muss die 
Verarbeitung überhaupt kontinuierlich sein? Reicht es nicht "ab und zu 
mal" einen Block zu speichern und in diesem die Detektion durchzuführen? 
Dann würde das auch ein AVR schaffen (falls der ADC mitkommt).

von Zacc (Gast)


Lesenswert?

Mein Ansatz mit Sinus und cosinus zu multiplizieren ist der Ansatz den 
man fuer Fourierkoeffizienten im Allgemeinen nimmt. Die Sin/ Cos We\rte 
nimmt man natuerlich aus einer Tabelle.

von Sebastian (Gast)


Lesenswert?

Primitiv-Vorschlag.

Auf einen analogen Tiefpass (Spannungsteiler) Signal draufgeben. Die 
Spannung muss sich dann über die Frequenz am ADC-Eingang einstellen. Nur 
noch ADC auslesen und Fenster kontrollieren. Mit einer hohen 
ADC-Auflösung wird das Ergebnis recht scharf.

Sebastian

von oli (Gast)


Lesenswert?

Hallo

@andreas:
DMA hat er leider nur für USB (LPC2148).
Ich hätte bisjetzt nicht entdeckt das der auch für was anderes zu 
gebrauchen ist.

Das mit dem "ab und zu" verarbeiten klingt aber interessant. Ich möchte 
halt gern mind. 4800bps über dieses "Powerline" System (nur hat die Line 
über die es geht kaum Power :-) ) schaufeln. Dh. wenn ich mind. doppelt 
so schnell berechnen kann sollts eigentlich passen. Werd am Abend 
Versuche machen.

Wenn wirklich mit AVR oder MSP430 machbar dann wär das natürlich ein 
Traum, nur dürften die ADCs zu langsam sein.

@Sebastian:
Das mit dem analogen FM Demodulator funktioniert aber wahrscheinlich nur 
wenn der Betrag der Eingagsspannung bekannt ist bzw. mit einer 
automatischen Verstärkungsregelung (siehe Radio).
Außerdem will ich auf Analogtechnik so weit wie möglich verzichten, für 
viel mehr als die CPU ist eigentlich nicht Platz


MfG Oli

von n!x (Gast)


Lesenswert?

>27Takte braucht er mind. bis er in der ISR ist,
>143!!! Takte (hab mich gestern verlesen) braucht der ADC bis er fertig
>ist (da ergeben sich dann so ziemlich genau die angegebenen 400kSmpls/s
>bei 60Mhz Systemtakt)
>Man kann während diesen 143 Takten zwar was anderes machen aber
>irgendwann brauch ich den Wert um zu rechnen. Wenn das dann auch noch
>100Takte braucht bin ich sowieso jenseits von gut und böse.
was haelst du davon:
1
volatile int oldval;
2
3
isr(){
4
  start_adc():
5
  calculate_iir(oldval);
6
  wait_for_adc();
7
  oldval = adcval;
8
}
dann hast du keine probleme mit den mind. 143 takten ;)

von oli (Gast)


Lesenswert?

Hallo n!x

Ja so ähnlich passiert das jetzt auch.
Der ADC ist jetzt so eingestellt das er ca. 200Takte für ein Sample 
braucht. Immer wenn er fertig ist triggert er die ISR und sampled gleich 
weiter.

Also von der Verarbeitungsgeeschwindigkeit ist das jetzt durchaus OK. 
Hab etwas mit Assembler optimiert. Das was der gcc produziert ist 
sowieso irgendwie recht müllig wenns schnell sein muß: z.B. verwendet er 
kaum einmal andere Register als r2 und r3. Und er fügt "sinnlose" 
Registerkopierbefehle ein nur damit z.B. immer r2 (oder halt r3) 
Zielregister ist.
Und so Sachen wie banked Register (bei FIQ) kennt scheint er auch nicht 
zu kennen.

MfG Oli

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.