kramann.info
© Guido Kramann

Login: Passwort:










kramann.info
© Guido Kramann

Login: Passwort:




Übertragung der Audio-Datenschnittstelle auf ein Arduino-Micro-Board

(EN google-translate)

(PL google-translate)

Nachfolgend soll das Full-Duplex-Audio-Dateninterface von Javascript nach C/C++ für einen Arduino-Micro übertragen werden.

Zur Tonerzeugung finden sich Hinweise unter:

Kapitel 29 im Kurs "96_Arduino" auf kramann.info: http://www.kramann.info/96_Arduino/29_Tonerzeugung

Um nicht den doppelten PWM-Ausgang von Timer 3 zu belegen und auch nicht den vom Arduino-Grundsystem bereits verwendeten Timer 0, wird Timer 3 für die Tonerzeugung vorgesehen.

Der zu Timer 3 gehörende PWM-Ausgang ist beim Digitalen Ausgang Nr. 3 zu finden.

Es kann jetzt ein Lautsprecher zwischen digitalem Ausgang D4, und digitalem Ausgang D5 angeschlossen werden.

Um die Tonwechsel in einem definierten Abstand vorzunehmen, wird außerdem Timer 1 und ein Software-Interrupt bei Zählerüberlauf verwendet: ISR(TIMER1_COMPA_vect){...}

Die zu sendenden Zeichen können über den seriellen Monitor vom Benutzer eingegeben werden. Sie werden in einem Puffer gespeichert und Zeichen für Zeichen geholt und als Audiosignale gesendet.

Der Hauptloop prüft nun ständig, ob ein neues Zeichen vorliegt. Jedes Bit wird dann als zwei Tonsignale einer festen Dauer gesendet.

audio_daten02.zip - Nachfolgendes Programm als Arduino-Projektordner (gezipt).
#include<avr/interrupt.h> //... um eine "Uhr" zu realisieren
//import processing.serial.*;

//Dauer eines Tonereignisses in Millisekunden
//Beim Javascriptprogramm derzeit dehr langsam:
// 20 Pufferzyklen, ein Pufferzyklus == 1024 Samples
// 1 Sample 1/44100 Sekunden
// => 1000*20*1024/44100 === 464,40 Millisekunden
#define DELAY 12 //12 === ungefähr halbe Sekunde

//Puffergroesse für die zu sendendenden Daten
#define PUFFER 200

int puffer[PUFFER];
int puffer_index_geschrieben = 0; //Pufferposition nach Konsoleneingabe
int puffer_index_gesendet = 0;    //Pufferposition nach abschicken

int SENDEZUSTAND=0; //Phase des Sendevorgangs merken
int zu_sendendes_zeichen = 0;
int RESTZEIT = 0;

ISR(TIMER1_COMPA_vect)
{
     if(RESTZEIT>0) //zyklisch dekrementieren, wenn Zählerüberlauf
         RESTZEIT--;
}

void initUhr() //vergl. Scheduler Arduino
{
  TCCR1B &= ~(1<<WGM13); //Mode 4
  TCCR1B |= (1<<WGM12);
  TCCR1A &= ~(1<<WGM11);
  TCCR1A &= ~(1<<WGM10);
    
  //1024: 15625Hz
  TCCR1B |= (1<<CS12);
  TCCR1B &= ~(1<<CS11);
  TCCR1B |= (1<<CS10);
    
  OCR1A=625;  //25Hz == 25 mal pro Sekunde, Halbe Sekunde ungefähr 12
  
//  TIMSK1 |= (1<<ICIE1); //Mode 12
  TIMSK1 |= (1<<OCIE1A); //Mode 4
  sei();  
}

void initTimer3()
{
  TCCR3B &= ~(1<<WGM33); //Mode 4
  TCCR3B |= (1<<WGM32);
  TCCR3A &= ~(1<<WGM31);
  TCCR3A &= ~(1<<WGM30);

  //Zu erzeugende Töne:
  //700Hz==4*175Hz, 1050Hz==6*175Hz, 1575Hz==9*175Hz. 
    
  //Realisierung:  
  //  f = fclk/(2*N*(OCR3A+1))
  //  N = 1
  //  OCR3A =  fclk/(f*2*N) -1
  //  11427,57 =  16000000/(700*2*1) -1
  //  7618,05  =  16000000/(1050*2*1) -1
  //  5078,37  =  16000000/(1575*2*1) -1
  
  //Außerdem tiefer Ton wie in Javascript-Anwendung:
  //44100/500 == 88Hz
  //Vorteilung 8 nötig:
  //  11362,64  =  16000000/(88*2*8) -1
  
  //Vorteilung 1: 16000000Hz
  //TCCR3B &= ~(1<<CS32);
  //TCCR3B &= ~(1<<CS31);
  //TCCR3B |= (1<<CS30);
    
  //Vorteilung 8: 16000000Hz
  TCCR3B &= ~(1<<CS32);
  TCCR3B |= (1<<CS31);
  TCCR3B &= ~(1<<CS30);
    
  //OCR3A=11428;  //700Hz
  //OCR3A=7618;   //1050Hz
  //OCR3A=5078;   //1575Hz
  OCR3A=11363;    //88Hz mit Vorteilung 8
  
  //Toggle auf OC3A:
  TCCR3A &= ~(1<<COM3A1);
  TCCR3A |=  (1<<COM3A0);
  pinMode(5,OUTPUT);    //OC3A  
  pinMode(4,OUTPUT);          
  digitalWrite(4,0); //Ground für LED
}

void setzeTon(int nr)
{
     if(nr==0) //88Hz
     {
         TCCR3B &= ~(1<<CS32);
         TCCR3B |= (1<<CS31);
         TCCR3B &= ~(1<<CS30);
         OCR3A=11363;
     }
     else if(nr==1) //700Hz
     {
         TCCR3B &= ~(1<<CS32);
         TCCR3B &= ~(1<<CS31);
         TCCR3B |= (1<<CS30);
         OCR3A=11428;
     }
     else if(nr==2) //1050
     {
         TCCR3B &= ~(1<<CS32);
         TCCR3B &= ~(1<<CS31);
         TCCR3B |= (1<<CS30);
         OCR3A=7618;
     }
     else if(nr==3) //1575Hz
     {
         TCCR3B &= ~(1<<CS32);
         TCCR3B &= ~(1<<CS31);
         TCCR3B |= (1<<CS30);
         OCR3A=5078;   
     }
}

void setup() 
{
    initTimer3();
    initUhr();    
    
    //Serielle Schnittstelle aktivieren, um 
    //zu schickende Daten über den seriellen Monitor
    //übergeben zu können:    
    Serial.begin(9600);
}

void loop() 
{
    if(Serial.available())
    {
         puffer[puffer_index_geschrieben] = Serial.read();
         puffer_index_geschrieben++;
         puffer_index_geschrieben%=PUFFER;
    }
    
    if(SENDEZUSTAND==0 && puffer_index_gesendet!=puffer_index_geschrieben) //wenn bereit für neues Zeichen    
    {
         zu_sendendes_zeichen = puffer[puffer_index_gesendet];
         puffer_index_gesendet++;
         puffer_index_gesendet%=PUFFER;
         SENDEZUSTAND=1; //Jetzt bereit für Startton
         RESTZEIT = DELAY;
         setzeTon(1);
    }

    //Höchstwertigstes Bit setzen: Bit 7    
    if(SENDEZUSTAND==1 && RESTZEIT==0)    
    {      
         //erstes Bit senden
         if(zu_sendendes_zeichen/128==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=128;
         }
         SENDEZUSTAND=2; 
         RESTZEIT = DELAY;
    }
    
    //NÄCHSTES BIT #####################################
    //Vorton für Bit 6
    if(SENDEZUSTAND==2 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=3; 
         RESTZEIT = DELAY;
    }
    
    //Bit 6
    if(SENDEZUSTAND==3 && RESTZEIT==0)    
    {      
         //2. Bit senden
         if(zu_sendendes_zeichen/64==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=64;
         }
         SENDEZUSTAND=4; 
         RESTZEIT = DELAY;
    }

    //NÄCHSTES BIT #####################################
    //Vorton für Bit 5
    if(SENDEZUSTAND==4 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=5; 
         RESTZEIT = DELAY;
    }

    //Bit 5
    if(SENDEZUSTAND==5 && RESTZEIT==0)    
    {      
         //3. Bit senden
         if(zu_sendendes_zeichen/32==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=32;
         }
         SENDEZUSTAND=6; 
         RESTZEIT = DELAY;
    }

    //NÄCHSTES BIT #####################################
    //Vorton für Bit 4
    if(SENDEZUSTAND==6 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=7; 
         RESTZEIT = DELAY;
    }

    //Bit 4
    if(SENDEZUSTAND==7 && RESTZEIT==0)    
    {      
         //2. Bit senden
         if(zu_sendendes_zeichen/16==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=16;
         }
         SENDEZUSTAND=8; 
         RESTZEIT = DELAY;
    }

    //NÄCHSTES BIT #####################################
    //Vorton für Bit 3
    if(SENDEZUSTAND==8 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=9; 
         RESTZEIT = DELAY;
    }

    //Bit 3
    if(SENDEZUSTAND==9 && RESTZEIT==0)    
    {      
         //2. Bit senden
         if(zu_sendendes_zeichen/8==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=8;
         }
         SENDEZUSTAND=10; 
         RESTZEIT = DELAY;
    }
     
    //NÄCHSTES BIT #####################################
    //Vorton für Bit 2
    if(SENDEZUSTAND==10 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=11; 
         RESTZEIT = DELAY;
    }

    //Bit 2
    if(SENDEZUSTAND==11 && RESTZEIT==0)    
    {      
         if(zu_sendendes_zeichen/4==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=4;
         }
         SENDEZUSTAND=12; 
         RESTZEIT = DELAY;
    }
     
    //NÄCHSTES BIT #####################################
    //Vorton für Bit 1
    if(SENDEZUSTAND==12 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=13; 
         RESTZEIT = DELAY;
    }

    //Bit 1
    if(SENDEZUSTAND==13 && RESTZEIT==0)    
    {      
         if(zu_sendendes_zeichen/2==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=2;
         }
         SENDEZUSTAND=14; 
         RESTZEIT = DELAY;
    }

    //NÄCHSTES BIT #####################################
    //Vorton für Bit 0
    if(SENDEZUSTAND==14 && RESTZEIT==0)    
    {      
         setzeTon(1); //Vorton ("Jetzt kommt neues Bit")
         SENDEZUSTAND=15; 
         RESTZEIT = DELAY;
    }

    //Bit 0
    if(SENDEZUSTAND==15 && RESTZEIT==0)    
    {      
         if(zu_sendendes_zeichen/1==0)
         {
             setzeTon(2); //0
         }
         else
         {
             setzeTon(3); //1
             zu_sendendes_zeichen-=1;
         }
         SENDEZUSTAND=16; 
         RESTZEIT = DELAY;
    }
     
    //noch mehrmals KEIN TON, dann Zurücksetzen, wenn fertig 
    if(SENDEZUSTAND==16 && RESTZEIT==0)    
    {      
         setzeTon(0); //KEIN TON
         SENDEZUSTAND=17; 
         RESTZEIT = DELAY;
    }
    if(SENDEZUSTAND==17 && RESTZEIT==0)    
    {      
         setzeTon(0); //KEIN TON
         SENDEZUSTAND=18; 
         RESTZEIT = DELAY;
    }
    if(SENDEZUSTAND==18 && RESTZEIT==0)    
    {      
         setzeTon(0); //KEIN TON
         SENDEZUSTAND=0; //Zurücksetzen, dann bereit für nächstes Byte 
         RESTZEIT = DELAY;
    }
    
}

Code 0-1: audio_daten02 - Arduino-Programm, um Daten als Audiosignale zu senden.