●アンドロイド版
音声を利用してスマートフォンからマイコンにFSK方式でデータを送信する実験です。すでにいろいろな方が実施されていますし、BANDAIのスマートドッグという商品にも使われていた方法かと思います。
Baud Rateは630Hzとかなり低速ですが、マイコン側でWiFiやBTの通信手段が不要なのでコスト的には有利です。出力される音声信号は非常に微細なので、LM358でアンプしています。
import android.app.Activity; import android.graphics.Color; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTrack; import android.os.Bundle; import android.view.Gravity; import android.view.View; import android.view.Window; import android.widget.Button; import android.widget.LinearLayout; public class FskTest extends Activity implements View.OnClickListener{ private final static int MP = LinearLayout.LayoutParams.MATCH_PARENT; private final static int WC = LinearLayout.LayoutParams.WRAP_CONTENT; static int SAMPLE_RATE = 44100; //44.1KH static int FREQ_LOW = 3150; static int FREQ_HIGH = 6300; static int BAUD = 630; static int BITS_ALL = 17; private int bufSize; AudioTrack track; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); requestWindowFeature(Window.FEATURE_NO_TITLE); LinearLayout layout = new LinearLayout(this); layout.setBackgroundColor(Color.WHITE); layout.setOrientation(LinearLayout.VERTICAL); layout.setGravity(Gravity.CENTER_VERTICAL); setContentView(layout); layout.addView(makeButton("SEND!")); bufSize = android.media.AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT); track = new AudioTrack( AudioManager.STREAM_MUSIC, //streamType SAMPLE_RATE/2, //sampleRateInHz:サンプリング周波数 AudioFormat.CHANNEL_OUT_MONO, //channelConfig(モノラル指定) AudioFormat.ENCODING_PCM_16BIT, //audioFormat bufSize, //bufferSizeInBytes:バッファサイズ AudioTrack.MODE_STATIC); } private Button makeButton(String text) { Button button = new Button(this); button.setText(text); button.setOnClickListener(this); button.setLayoutParams(new LinearLayout.LayoutParams(MP,WC)); button.setGravity(Gravity.CENTER); return button; } public void onClick(View view) { sendVal('a'); } private void sendVal(int cmd) { if(track.getPlayState()==AudioTrack.PLAYSTATE_PLAYING){ track.stop(); track.reloadStaticData(); } byte[] audioData = createSquareWave(cmd); track.write(audioData, 0, audioData.length); track.play(); } private byte[] createSquareWave(int command) { byte[] b = new byte[SAMPLE_RATE/BAUD*BITS_ALL]; int counter=0; //leader for (int i = 0; i < 8; i++) { // data=low for(int j = 0; j < (FREQ_LOW/BAUD); j++){ b[counter++] = 0; b[counter++] = 56; b[counter++] = 100; b[counter++] = 125; b[counter++] = 125; b[counter++] = 100; b[counter++] = 56; b[counter++] = 0; b[counter++] = -56; b[counter++] = -100; b[counter++] = -125; b[counter++] = -125; b[counter++] = -100; b[counter++] = -56; } } //start bit for(int j = 0; j < (FREQ_HIGH/BAUD); j++){ b[counter++] = 0; b[counter++] = 100; b[counter++] = 125; b[counter++] = 56; b[counter++] = -12; b[counter++] = -125; b[counter++] = -100; } // data for (int i = 6; i >= 0; i--) { if(((1<<i) & command)==0){ for(int j = 0; j < (FREQ_LOW/BAUD); j++){ b[counter++] = 0; b[counter++] = 56; b[counter++] = 100; b[counter++] = 125; b[counter++] = 125; b[counter++] = 100; b[counter++] = 56; b[counter++] = 0; b[counter++] = -56; b[counter++] = -100; b[counter++] = -125; b[counter++] = -125; b[counter++] = -100; b[counter++] = -56; } }else{ for(int j = 0; j < (FREQ_HIGH/BAUD); j++){ b[counter++] = 0; b[counter++] = 100; b[counter++] = 125; b[counter++] = 56; b[counter++] = -12; b[counter++] = -125; b[counter++] = -100; } } } // stop bit for(int j = 0; j < (FREQ_HIGH/BAUD); j++){ b[counter++] = 0; b[counter++] = 100; b[counter++] = 125; b[counter++] = 56; b[counter++] = -12; b[counter++] = -125; b[counter++] = -100; } return b; } }