DTMF tonu üretme

Başlatan Mucit23, 25 Ekim 2019, 00:19:19

Mucit23

Selamlar

STM32 ile daha önce DTMF tonu üreten oldu mu? Nasıl bir mantık yürütmek gerekiyor? Şurda küçük bir örnek buldum ama olayı kafamda canlandıramadım.
https://github.com/robots/STM32/tree/master/dtmf

Basitçe anlatabilecek olan var mı?


OptimusPrime

Dtmf biri yuksek digeri dusuk 2 farkli frekansin toplamindan olusan bir kodlama. Cevirmeli telefondan (darbeli aramadan) sonraki muhtesem bulus. :D

Yuksek ve alcak frekanslara ait lookup table larin olsa bunlari cikista toplayip fs ye kurdugun bir timer uzerinden dac a versen dtmf kodlu sinyali dac cikisinda gorursun.

Dtmf cozmesi biriz sikintili bir is. Ne556 nin datasina bakarsan az cok bir fikir elde edersin.
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

mufitsozen

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

LukeSkywalker

Bir kaç farklı yöntem var ama ben her tuşa ait sinyali 8KHz ile örnekleyip tablosunu çıkarttım. Örneklediğim frekansa denk gelecek şekilde kurduğum timer ile her tuşa karşılık gelen tablolardaki değerleri toplayıp ikiye bölerek PWM çıkışına bir alçak geçiren filtre uygulayarak hoparlöre aktardım. Daha sonra çıkan sinyali android telefon ile test ettim. Bire bir sonuç aldım.

Mucit23

#4
Yöntemi anladım. Şöyle birşey yapsam nasıl olur? 128 elemanlı bir sinüs tablosu kullanarak sinüs değerlerini elde edeceğim. Tek bir sinüs üretmek basit. İki farklı sinüs'ü de iki farklı timer ile elde ederim. Timer Update rutinlerini F1 ve F2 frekanslarını üretecek şekilde kurarım. Daha sonra Update rutinlerinde İki farklı sinyalin toplanması ve DAC'ye gönderilmesi işlemini yaparım. Akşam mutlaka deneyeceğim

Edit: Yalnız faz farkını nasıl oluşturacam? Pek mantıklı gelmedi şimdi. Daha Efektif bir yöntem düşünüyorum. @LukeSkywalker Senin yöntemde güzel. Toplama ve Bölme işlemini neden yaptın onu anlayamadım. Eğer 8Khz'de örneklediysen Örneklediğin değerleri yine 8Khz de çıkışa aktarsan aynı değer çıkması lazım. Zaten sinyaller periyodik. Aslında aynı yöntemi yapabilirim. Her tuş işin ayrı bir lookup tablosu olması gerekecek. Belki hafıza açısından dezavantaj ama işlevsellik açısından daha uygun olur. 

fide

Amacınız yazılımsal dtmf üretmek ise kolay gelsin, basit bir şekilde kullanmak ise mt8870 entegresini tavsiye ederim. 3.579khz kristal ile basit şekilde dtmf üretebilirsiniz.
Her birimiz, geride bıraktığımız eserler kadar ölümsüzüz. Evlat gibi, talebe gibi, icatlar gibi...   http://fidenetgaraj.blogspot.com

LukeSkywalker

Alıntı yapılan: Mucit23 - 25 Ekim 2019, 10:03:06Yöntemi anladım. Şöyle birşey yapsam nasıl olur? 128 elemanlı bir sinüs tablosu kullanarak sinüs değerlerini elde edeceğim. Tek bir sinüs üretmek basit. İki farklı sinüs'ü de iki farklı timer ile elde ederim. Timer Update rutinlerini F1 ve F2 frekanslarını üretecek şekilde kurarım. Daha sonra Update rutinlerinde İki farklı sinyalin toplanması ve DAC'ye gönderilmesi işlemini yaparım. Akşam mutlaka deneyeceğim

Edit: Yalnız faz farkını nasıl oluşturacam? Pek mantıklı gelmedi şimdi. Daha Efektif bir yöntem düşünüyorum. @LukeSkywalker Senin yöntemde güzel. Toplama ve Bölme işlemini neden yaptın onu anlayamadım. Eğer 8Khz'de örneklediysen Örneklediğin değerleri yine 8Khz de çıkışa aktarsan aynı değer çıkması lazım. Zaten sinyaller periyodik. Aslında aynı yöntemi yapabilirim. Her tuş işin ayrı bir lookup tablosu olması gerekecek. Belki hafıza açısından dezavantaj ama işlevsellik açısından daha uygun olur. 

Toplama isleminin sebebi ayni anda iki farkli degerin tek cikisa aktarilmasi. İki farkli sinyal seviyesini ayni anda cikisa aktarmak icin bu sekilde bir islem gerceklestirdim.

z

Her tusa basip ornek alinca zaten iki sinyalin toplaminin ornegini almis oluyorsun.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

LukeSkywalker

Aslında yanlış söylemişim. Tuşların örneğini almamışım. Sadece DTMF frekanslarını excelde üretip değerlerini almışım.


extern const char w697[];
extern const char w770[];
extern const char w852[];
extern const char w941[];
extern const char w1209[];
extern const char w1336[];
extern const char w1477[];
extern const char w1663[];

char i=0,j=0,key=0;
 
//Place/Copy this part in declaration section
void InitTimer0(){
  T0CON	 = 0x88;
  TMR0H	 = 0xFA;
  TMR0L	 = 0x24;
  GIE_bit	 = 1;
}


void kurulum()
{
 InitTimer0();
 PWM1_Init(80000);
 PWM1_Start();
 //PWM1_Set_Duty(127);
}

void main() {
kurulum();
TMR0IE_bit	 = 1;
while(1)
{
i=0,j=0;
TMR0IE_bit	 = 1;
key=0;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=1;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=2;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=3;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=4;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=5;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=6;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

TMR0IE_bit	 = 1;
key=7;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=8;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(200);

i=0,j=0;
TMR0IE_bit	 = 1;
key=9;
delay_ms(200);
TMR0IE_bit	 = 0;
delay_ms(2000);
}
//TMR0IE_bit	 = 0;
}


void Interrupt(){
  if (TMR0IF_bit){
    TMR0IF_bit = 0;

  TMR0H	 = 0xFA;
  TMR0L	 = 0x24;
    i++;
    j++;

    switch(key)
               {
                case 0: if(i==25)i=0; if(j==36)j=0; PWM1_Set_Duty(((int)w941[i]+(int)w1336[j])/2);break;
                case 1: if(i==35)i=0; if(j==33)j=0; PWM1_Set_Duty(((int)w697[i]+(int)w1209[j])/2);break;
                case 2: if(i==35)i=0; if(j==36)j=0; PWM1_Set_Duty(((int)w697[i]+(int)w1336[j])/2);break;
                case 3: if(i==35)i=0; if(j==32)j=0; PWM1_Set_Duty(((int)w697[i]+(int)w1477[j])/2);break;
                case 4: if(i==32)i=0; if(j==33)j=0; PWM1_Set_Duty(((int)w770[i]+(int)w1209[j])/2);break;
                case 5: if(i==32)i=0; if(j==36)j=0; PWM1_Set_Duty(((int)w770[i]+(int)w1336[j])/2);break;
                case 6: if(i==32)i=0; if(j==32)j=0; PWM1_Set_Duty(((int)w770[i]+(int)w1477[j])/2);break;
                case 7: if(i==28)i=0; if(j==33)j=0; PWM1_Set_Duty(((int)w852[i]+(int)w1209[j])/2);break;
                case 8: if(i==28)i=0; if(j==36)j=0; PWM1_Set_Duty(((int)w852[i]+(int)w1336[j])/2);break;
                case 9: if(i==28)i=0; if(j==32)j=0; PWM1_Set_Duty(((int)w852[i]+(int)w1477[j])/2);break;
               }

  }
}

OptimusPrime

@Mucit23

Tek tablodan sinus uretmek ile birden fazla tablodan tek bir isaret uretmek arasinda cokda bir fark yok.  ;)

4 satir ve 4 sutun oldugunu dusun @mufitsozen hocamin verdigi tablodaki gibi. Bu durumda 8 farkli tablon var. Diyelimki 5 e basildi. 1336Hz ve 570Hz lik tablolardan birer deger cekip bunlari toplayacaksin. DAC cozunurlugune uygun olarak bolme islemi yapabilirsin. Sonra bu degerle DAC i fs ye uygun olarak ayarladigin bir timer esliginde besleyeceksin.

Zor degil. 1 saatte yaparsin  :)
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

Mucit23

Dediğiniz gibi çok zor bir şey değilmiş. Akşam birkaç deneme yapacağım.

mufitsozen

Alıntı yapılan: Mucit23 - 25 Ekim 2019, 17:04:10Dediğiniz gibi çok zor bir şey değilmiş. Akşam birkaç deneme yapacağım.

biraz gayretle daha "bilimsel" bir uygulama yapabilirsiniz. Bu uygulamada size 8-bit resolution yetecektir diye dusunuyorum.

Kisitli hafiza/hiza sahip gomulu bilgisayar uygulamalarinda CORDIC algorithmasi kullanilir diye ogretilmisti bize 45 sene once.

"implementing fixed integer cordic sine function" diye google'larsaniz bir cok kaynak bulabileceginize eminim. (denedim About 26,800 results (0.75 seconds) dedi!  ;) )

kolay gelsin.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

Mucit23

İlk mesajda verdiğim örneği biraz ayrıntılı inceleyince çalışmasını anladım. Aynısını Temize çekerek STM32F4'e uyarladım ve çalıştırdım.

PWM çıkışına 1K ve 100nF ile RC filtreden geçirip çıkan sinyali gözlemledim. Sonuç aşağıdaki gibi.


RC filtreden kaynaklı oldukça fazla gürültü var sinyal üzerinde.  Bundan dolayı PWM yerine DAC kullanmak istedim Fakat DAC'yi düzgün bir şekilde çalıştıramadım. Çıkışta ya sabit sabit gerilim oluyor yada hiçbir şey alamıyorum.

DAC ayarlarım bu şekilde
void DAC_Configuration(void)
{
   // Enable clocks for PORTA and DAC
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  
   RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
   
   // Set up PA.4 as DAC channel 1 output
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   
   /* DAC channel 1 Configuration */
   DAC_InitTypeDef DAC_InitStructure;
   DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
   DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
   DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
   DAC_Init(DAC_Channel_1, &DAC_InitStructure);

   /* Enable DAC Channel 1 */
   DAC_Cmd(DAC_Channel_1, ENABLE);
}

Bu şekilde sabit değer gönderiyorum
DAC_SetChannel1Data(DAC_Align_12b_R,2048);

Vref 3V civarı dolayısıyla çıkışta Vref/2 görmeyi bekliyorum ama çıkış ya VDD ya da sıfır. Ne etkiliyor anlamıyorum. Bilgisi olan var mı?
 


OptimusPrime

#13
Isaretinde bir gariplik var. Tabloya bakarsan en kotu ihtimal bir isaret digerinin 2.3 kati. Ama senin cikisinda baya yuksek frekansda birseyler var gorunen  sinyalin uzerinde  ???

Fft ile bak bakalim senin frekanslar ordami. RC nin sucu gibi durmuyor bu. Veya sadece tum tablolari teker teker dene.
https://donanimveyazilim.wordpress.com || Cihân-ârâ cihân içredir ârâyı bilmezler, O mâhîler ki deryâ içredir deryâyı bilmezler ||

z

#14
Alıntı YapPWM çıkışına 1K ve 100nF ile RC filtreden geçirip çıkan sinyali gözlemledim. Sonuç aşağıdaki gibi.

Ripili azaltmak icin Ikinci bir 1K 100nF den daha gecir.

Ya da ornekleme frekansini daha da yukselt. Bu durumda tablo boylarin da artar ama Sin fonskiyonlarini tablo olarak tutmak zorunda degilsin. Gercek zamanli da hesaplayabilirsin.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com