[C] Pulsecodemodulation

RebellDerSonne

Cadet 2nd Year
Registriert
Sep. 2004
Beiträge
17
Wir müssen in de Schule einen PCM machen.
Dieser soll über ein in C geschriebenes Programm den Com-Port ansprechen,an dem ein Tiefpass aus Kondensator und Lautsprecher hängt.
Entsprechend der Frequenz soll ein Ton ausgegeben werden. Das Programm und die Schaltung haben wir schon,aber irgendwie funktioniert es nicht.
Vielleicht habt ihr eine Idee... Hier ist das Programm:

Code:
#include <math.h>
#include <windows.h>
#include <stdio.h>
int main ()
{
   /* Definitionen*/

	DWORD wb;
	HANDLE hCom;
   DCB dcb;
   FILE *handle;
   int Data[115200], n, p, nr, frequenz, perioden;
   double sinwert;

   /* Einstellung f. File & COM */

   handle = fopen("sin.txt","w");
	hCom = CreateFile("COM1",
					  		GENERIC_READ|GENERIC_WRITE,
					  		0, NULL, OPEN_EXISTING, 0, NULL);

   dcb.BaudRate = CBR_115200;     // set the baud rate
   dcb.ByteSize = 8;             // data size, xmit, and rcv
   dcb.Parity = NOPARITY;        // no parity bit
   dcb.StopBits = ONESTOPBIT;    // one stop bit


   perioden = pow(10,6);
	frequenz = 100000;
   nr = 115200/frequenz;

   /* Berechnung der Sinuswerte */

	for (n=0; n < nr; n=n+1)
	{
		sinwert = sin (2*M_PI * n/(double)nr);
		Data[n] = 128 + floor(100 * sinwert + 0.5);
      fprintf(handle,"%d\t%g\t%d\n",n,sinwert,Data[n]);
	}

   /* Ausgabe in File & COM */

	for(p=0; p<perioden; p+=1)
	{
		unsigned char wert;
		for (n=0; n < nr; n=n+1)
		{
			wert = Data[n];
			WriteFile(hCom, &wert , sizeof(wert), &wb, 0);
		}
	}
   printf("Ende!");
	getchar();
	return 0;
}

Danke im Vorraus, Rebell der Sonne
 
was ist denn der genaue fehler? kommt ein ton, kommt keiner, kommt überhaupt was am com-port an? lässt sich das programm nicht kompilieren?
 
Kann es sein, dass dein Data-Array nicht ganz gefüllt wird? Du deklarierst es mit 115200, aber beim füllen zählst du nur bis nr und das ist ja 115200/100000, also ist nur ein sehr kleiner Teil von Data gefüllt.

Bin mir nicht sicher ob das folgende noch eine Fehlerquelle sein kann, aber du deklarierst Data als int-Array und weist das dann einem unsigned char zu. int is glaube ich signed.
 
Es kommt ein ziemlich konstanter "Ton" (eher ein Rauschen) aus dem Lautsprecher, egal ob der Wert frequenz verändert wird.

pilso schrieb:
Kann es sein, dass dein Data-Array nicht ganz gefüllt wird? Du deklarierst es mit 115200, aber beim füllen zählst du nur bis nr und das ist ja 115200/100000, also ist nur ein sehr kleiner Teil von Data gefüllt.

Bin mir nicht sicher ob das folgende noch eine Fehlerquelle sein kann, aber du deklarierst Data als int-Array und weist das dann einem unsigned char zu. int is glaube ich signed.

Und womit bzw. wie sollen wir das Data-Array füllen?
Und wie löst man das int-problem?
 
Zuletzt bearbeitet:
also nachdem ich gerade das hier überflogen habe, denke ich, dass das so nicht klappt, wie du das da versuchst!

soweit ich das verstanden habe, erstellst du einen haufen ints, die die frequenz repräsentieren, und schickst sie über die com-file-write-funktion über die leitung, jedoch werden die dabei anders kodiert. deswegen bekommst du auch dieses rauschen!
wenn ich du wäre würde ich versuchen, eine leitung direkt anzusprechen, also direkt auf hardware zu coden, wenn es geht!
 
Also auf jeden Fall musst du beim Füllen des Data-Arrays auch so weit zählen, wie das Array lang ist.

Wenn mich nicht alles täuscht ist COM doch eine serielle Schnittstelle. Also gibst du ein Bit nach dem anderen aus. Somit wird die Frequenz über das Bitmuster bestimmt. Bei der BAUD-Rate von 115200 dürfte man doch nur jedes achte Bit setzen, damit es im hörbaren Frequenzbereich bleibt?
 
also ich hab mir da nochmal kurz ein paar gedanken drüber gemacht:
1. erstelle ein char-array
2. rechne aus, ob der sin von deiner frequenz an der stelle n größer oder kleiner 0 ist
3. wenn größer, dann schicke 1 ins array und verschiebe bitweise (<<) weiter, wenn kleiner, dann eben 0
4. schicke das array durch die leitung

du solltest versuchen, eine frequenz zu wählen, die du gut nachprüfen kannst, da sie nicht zu tief ist (lautsprecher summt nur) und nicht zu hoch (krächz-gefahr) :D
 
Die Pulscodemodulation wird, wenn ich den Versuchsaufbau richtig verstanden habe, ganz kläglich scheitern. Dabei wird nämlich unbedingt ein D/A-Wandler benötigt, um etwas herauszuholen, was für den Lautsprecher einigermaßen verwertbar ist.

Etwas anderes wäre die Pulsweitenmodulation. Mit ihr kann man digital "analoge" Signale formen.

Z. B. wäre ein einzelner Sinuston genau das, was wolf beschrieben hat: ist der Sinus größer Null, gib eine 1 aus (Spannung), ist er kleiner Null eine Null.

Die Sache hat aber noch zwei Haken: das Spektrum dieses Rechtecksignals besteht aus der Grundwelle und ganzzahligen Vielfachen derselben, bei 1kHz Basisfrequenz also noch bei 2, 3, 4, usw. kHz. Du benötigst also einen Tiefpass, um diese unerwünschten Spektralanteile herauszufiltern.

Weiter enthält das Spektrum noch einen Gleichspannungsanteil. Da gibt es zwei Möglichkeiten, den Fehler zu beheben (der auch ziemlich schlecht für die Schwingspule des LS ist; die mögen keine Gleichspannung): entweder mit einem Kondensator in Reihe zum LS oder Du ziehst den LS auf ein höheres Potential als den Com-Port.

Beides ist ziemlich bescheiden. Um das Potential zu verändern benötigst Du weitere Elektronik, sonst wird das nüscht. Und der Kondensator in Reihe bildet mit dem LS einen Hochpass mit einer ziemlich hohen Eckfrequenz, es sei denn Du nimmst einen Kondensator im Wassereimerformat.

Gruß
Morgoth
 
jetzt wüsste ich ja gerne, ob das dein lehrer hinbekommen hat ;)
 
Unser Lehrer hats gar ned probiert.... find ich jetzt sehr :freak:

Er hat die Schaltung in einem Buch gehabt und da war auch das Proggi in Visual Basic dabei und die Schaltung war eben ein 47µF-Elko parallel zu einem Lautsprecher. (das ganze zw. TXD und GND). kA wie das Buch heißt (ich glaub "elektronik mit visual basic",aber nach dem Buch müsste es funzen...

liegt das daran,dass es in C ist,oder müsste es generell nicht funzen?
 
Zuletzt bearbeitet: (doppelpost - sorry)
Sorry 4 doppelpost bitte löschen
 
wenn du den code richtig von vb nach c portiert hast müsste es schon gehen. Poste doch mal den code in vb aus dem buch.
 
also:
Code:
Private Sub Command1_Click()
    Dim Dat(10000)
    pi = 3.1415
    freq = Val(Text1.Text)
    Nr = Int(11520 / freq)
    For n = 1 To 10 * Nr
        Dat(n) = 128 + Int(100 * Sin(2 * pi * n / Nr))
    Next n
    out = 128
    For n = 1 To 10 * Nr
        out = out + 5
        Data = Dat(n)
        Bit = 1
        send = 0
        For i = 1 To 8
            If Data < out Then
                send = send + Bit
                out = out - 5
            Else
                out = out + 5
            End If
            Bit = Bit * 2
        Next i
        out = out - 5
        Dat(n) = send
    Next n
    REALTIME
    For n = 1 To 100
        For i = 1 To 10 * Nr
            SENDBYTE 2, Dat(i)
        Next i
    Next n
    NORMALTIME
            
End Sub

Private Sub Form_Load()
OPENCOM 2, 115200, 0, 8, 1, 100, 100
DTR 2, 1
RTS 2, 1
End Sub

Private Sub Form_Unload(Cancel As Integer)
CLOSECOM 2
End Sub

Hauptprogramm fehlt oder? :D

Ach ja,...es sollte bis nächsten Freitag fwertig sein (*loooooooooooooooooooooool*)
 
Zuletzt bearbeitet:
Im Basic-Code wird nr auf 11520/frequenz gesetzt, im c++-code auf 115200/frequenz, also das 10-fache im c++-code. Bei der Berechnung des Sinus teilst du durch nr, was im c++ code aber 10 mal grösser als im BASIC code ist.

Ich würde erst mal versuchen den Code Eins zu Eins zu portieren, bevor ich dran schraube. Für die frequenz-variable nimmst du natürlich den Wert, den du im VB-Programm eingibst, den man hört. Wenn mich nicht alles täuscht kann man 100000 Hertz garnicht hören, sondern nur so von 20 bis 20000, also probier mal was dazwischen.
 
Zurück
Oben