Arduino IDEでボードマネージャーがエラーを吐くようになった時の対応 [ATmarquino Arduino]
Arduino IDEでボードマネージャーがエラーを吐くようになった時の対応
downloads.arduino/packages/package_index.jsonがダウンロードできない!ってエラーの時の対応、、、
以下のリンク先を参照。
https://github.com/arduino/Arduino/issues/5188
オレの場合は"package_index.json.tmp"が該当した。クソゥ、、、
downloads.arduino/packages/package_index.jsonがダウンロードできない!ってエラーの時の対応、、、
以下のリンク先を参照。
https://github.com/arduino/Arduino/issues/5188
オレの場合は"package_index.json.tmp"が該当した。クソゥ、、、
Arduino AVRでマルチタスクしてみない [ATmarquino Arduino]

折角なのでPWMで2相出力してみる。
/**********************************************************/ /* AVR Atmega328P PWM generator */ /**********************************************************/ #include <avr/io.h> #include <FlexiTimer2.h> extern "C" { } /**********************************************************/ /* prototypes */ /**********************************************************/ /**********************************************************/ /* valiables */ /**********************************************************/ #define PWMA_PIN 9 // PB1:OC1A #define PWMB_PIN 10 // PB2:OC1B #define TIMER_COUNTER_CLOCK (1000000) #define FREQUENCY (50.0f) #define RESOLUTION (32) #define PHASE_SHIFT (-60.0f) int scale = (256 / 2) - 1; /**/ int offset = (256 / 2) - 0; /* center position */ int waveTableCounter; float channelPhase = (2 * M_PI * PHASE_SHIFT / 360.0f); unsigned int waveTableA[ RESOLUTION ]; unsigned int waveTableB[ RESOLUTION ]; /**********************************************************/ /* setup */ /**********************************************************/ void setup() { Serial.begin( 115200UL ); Serial.println( "AVR Atmega328P PWM generator." ); pinMode( PWMA_PIN, OUTPUT ); pinMode( PWMB_PIN, OUTPUT ); /* generate wave data */ for( int i = 0; i < RESOLUTION; i++ ) { int tempI = (int)(sin(2 * M_PI * i / RESOLUTION) * scale); waveTableA[ i ] = (unsigned int)tempI + offset; tempI = (int)(sin((2 * M_PI * i / RESOLUTION) + channelPhase) * scale); waveTableB[ i ] = (unsigned int)tempI + offset; } /* display wave data A */ Serial.println( "WAVE DATA A" ); for( int i = 0; i < RESOLUTION; i++ ) { Serial.print( waveTableA[ i ], DEC ); Serial.print( "," ); if( (i % 10) == 9 ) Serial.println(); } Serial.println(); /* display wave data B */ Serial.println( "WAVE DATA B" ); for( int i = 0; i < RESOLUTION; i++ ) { Serial.print( waveTableB[ i ], DEC ); Serial.print( "," ); if( (i % 10) == 9 ) Serial.println(); } Serial.println(); /* timer counter initialize. */ TCCR1B = 0x00; // timer1 stop TCNT1 = 0x0000; // 16bit counter clear TIMSK1 = 0x00; // interrupt disable TCCR1A = 0b10100001; // 0b10 10 00 01 // OC1A : compare match goes OC1A to clear and top goes OC1A to set. // OC1B : compare match goes OC1B to clear and top goes OC1B to set. // fast 8bit PWM and top is 0x00FF. WGM = 0b0101 TCCR1B = 0b00001010; // 0b0 0 0 01 010 // fast 8bit PWM and top is 0x00FF. // clkIO / 8 priscaller. OCR1A = waveTableA[ 0 ]; OCR1B = waveTableB[ 0 ]; TIMSK1 = 0x00; // interrupt disable waveTableCounter = 1; FlexiTimer2::set( 1, 1.0f / (FREQUENCY * RESOLUTION), pwmUpdateHandler ); FlexiTimer2::start(); /* Infinite loop */ while(1) {} } /**********************************************************/ /* loop ※使われない */ /**********************************************************/ void loop() { } /**********************************************************/ /* pwm update handler */ /**********************************************************/ void pwmUpdateHandler() { OCR1A = waveTableA[ waveTableCounter ]; OCR1B = waveTableB[ waveTableCounter ]; if( ++waveTableCounter >= RESOLUTION ) { waveTableCounter = 0; } }
Arduino AVRでマルチタスクしてみる タスク2 [ATmarquino Arduino]

ファイル名を変えずに中身を書き換えちゃったのは、まずかったかなぁ、、、
マルチタスクのサンプルとして、PWMで50Hzのサイン波を出力するデモ。
別途用意したスイッチを押す度に別途用意したLPFを通してサイン波が出力される。ただし10秒間掛けて波形はフェードアウトする。
/**********************************************************/ /* マルチタスクやってみる */ /* PWMで50hzのサイン波を出力する。10秒掛けてフェードアウト。 */ /**********************************************************/ #include <avr/io.h> #include <FlexiTimer2.h> #include "delivertive.h" extern "C" { #include "mul_tsk.h" } /**********************************************************/ /* prototypes */ /**********************************************************/ void tsk_ini( void ); void stackMonitor( void ); void switchScanTask( void ); void pwmGenerateTask( void ); /**********************************************************/ /* valiables */ /**********************************************************/ SYSTIM systim; // 1msでインクリメントする変数 uint8_t tsk0_stk[ 128 * 1 ]; uint8_t tsk1_stk[ 128 * 1 ]; uint8_t tsk2_stk[ 128 * 1 ]; #define PWM_PIN 10 #define TRIGGER_PIN 2 #define LED_PIN 13 #define TIMER_COUNTER_CLOCK (8 * 1000000UL) #define PWM_FREQUENCY (10 * 1000) #define RESOLUTION (40) /* 50hz * 40 over sampling. */ #define DELTA_SLOPE (1.0f / 500) int scale = TIMER_COUNTER_CLOCK / PWM_FREQUENCY / 2; /* 1000000 is timer clock */ int offset = TIMER_COUNTER_CLOCK / PWM_FREQUENCY / 2; /* center position */ int waveTableCounter; float slope = 1.0f - DELTA_SLOPE; /* 10s = 20ms * 500 */ int originalWaveTable[ RESOLUTION ]; unsigned int waveTable[ RESOLUTION ]; unsigned char switchScanUpdate; unsigned long timer1CompbIsrCounter; bool conversionStart = false; /**********************************************************/ /* setup */ /**********************************************************/ void setup() { Serial.begin( 115200UL ); Serial.println( "AVR Multi Task Demo." ); /* ststem and pwm update timer start. */ FlexiTimer2::set( 5, 1.0f / 10000, pwmUpdateHandler ); FlexiTimer2::start(); tsk_ini(); //タスクの初期化 sta_rdq( ID_monitor ); //ラウンドロビン開始。ここからタスクが開始される } /**********************************************************/ /* loop ※使われない */ /**********************************************************/ void loop() { } /**********************************************************/ /* タスク初期化 */ /**********************************************************/ void tsk_ini( void ) { reg_tsk( ID_monitor, (void *)stackMonitor, (void *)tsk0_stk, sizeof(tsk0_stk), 0,0,0,0 ); reg_tsk( ID_switchScan, (void *)switchScanTask, (void *)tsk1_stk, sizeof(tsk1_stk), 0,0,0,0 ); reg_tsk( ID_pwmGenerate, (void *)pwmGenerateTask, (void *)tsk2_stk, sizeof(tsk2_stk), 0,0,0,0 ); sta_tsk( ID_monitor ); // sta_tsk( ID_switchScan ); // sta_tsk( ID_pwmGenerate ); } /**********************************************************/ /* stack monitor task */ /**********************************************************/ static unsigned int RemainStack( void *stk, unsigned int sz ); static void stackPrint( const char *msg, void *stk, unsigned int sz ); void stackMonitor( void ) { sta_tsk( ID_pwmGenerate ); while( 1 ) { dly_tsk( 10 * 1000UL ); stackPrint( "task1 stack : ", tsk1_stk, sizeof(tsk1_stk) ); stackPrint( "task2 stack : ", tsk2_stk, sizeof(tsk2_stk) ); stackPrint( "monitor stack : ", tsk0_stk, sizeof(tsk0_stk) ); } } static void stackPrint( const char *msg, void *stk, unsigned int sz ) { Serial.print( msg ); Serial.print( RemainStack( stk, sz ), DEC ); Serial.print( "/" ); Serial.println( sz, DEC ); } static unsigned int RemainStack( void *stk, unsigned int sz ) { unsigned int i; char *ptr = (char *)stk; for( i = 0; i < sz; i++ ) { if( *ptr++ != 0 ) break; } return sz - i; // return i; } /**********************************************************/ /* switchScanTask */ /**********************************************************/ void switchScanTask( void ) { pinMode( TRIGGER_PIN, INPUT_PULLUP ); unsigned char sw = 0x00; while( 1 ) { sw <<= 1; if( digitalRead( TRIGGER_PIN ) == LOW ) sw |= 1; if( (sw & 0x0f) == 0x07 ) { switchScanUpdate++; } dly_tsk( 50UL ); } } /**********************************************************/ /* PWM Generate Task */ /**********************************************************/ void pwmGenerateTask( void ) { pinMode( PWM_PIN, OUTPUT ); digitalWrite( LED_PIN, LOW ); pinMode( LED_PIN, OUTPUT ); /* wave table generate. */ for( int i = 0; i < RESOLUTION; i++ ) { int tempI = (int)(sin( 2 * M_PI * i / RESOLUTION) * scale); originalWaveTable[ i ] = tempI; waveTable[ i ] = (unsigned int)tempI + offset; Serial.print( waveTable[ i ], DEC ); Serial.print( "," ); if( (i % 10) == 9 ) Serial.println(); } /* start switch scan task. */ sta_tsk( ID_switchScan ); while( 1 ) { /* wait for switch pushed. */ unsigned char switchScanUpdateBase = switchScanUpdate; while( switchScanUpdateBase == switchScanUpdate ) dly_tsk( 50UL ); switchScanUpdateBase = switchScanUpdate; Serial.println( "pwmGenerateTask PWM start." ); /* timer counter initialize. */ TCCR1B = 0x00; // timer1 stop TCNT1 = 0x0000; // 16bit counter clear TIMSK1 = 0x00; // interrupt disable TCCR1A = 0b00100011; // 0b00 10 00 11 // OC1A : normal port and not connected OC1A. // OC1B : compare match goes OC1B to clear and top goes OC1B to set. // fast PWM and top is OCR1A. TCCR1B = 0b00011001; // 0b0 0 0 11 001 // fast PWM and top is OCR1A. // clkIO / 1 priscaller. OCR1A = (unsigned int)(TIMER_COUNTER_CLOCK / PWM_FREQUENCY); OCR1B = waveTable[ 0 ]; TIMSK1 = 0x00; /* interrupt timer start. */ slope = 1.0f - DELTA_SLOPE; waveTableCounter = 1; conversionStart = true; digitalWrite( LED_PIN, HIGH ); /* wait 10s. */ dly_tsk( 11 * 1000UL ); conversionStart = false; for( int i = 0; i < RESOLUTION; i++ ) { int tempI = originalWaveTable[ i ]; waveTable[ i ] = (unsigned int)tempI + offset; } Serial.println( "pwmGenerateTask PWM stop." ); digitalWrite( LED_PIN, LOW ); } } /**********************************************************/ /* pwm update handler */ /**********************************************************/ void pwmUpdateHandler() { static int count = 0; /* system timer update */ if( count & 1 ) systim += 1UL; count++; if( conversionStart == true && slope >= 0.0f ) { OCR1B = waveTable[ waveTableCounter ]; float tempF = (float)originalWaveTable[ waveTableCounter ] * slope; waveTable[ waveTableCounter ] = (unsigned int)tempF + offset; if( ++waveTableCounter >= RESOLUTION ) { waveTableCounter = 0; slope -= DELTA_SLOPE; } } }
Arduino AVRでマルチタスクしてみる タスク1 [ATmarquino Arduino]

gitHubで公開と言う慣れない事をやっているので、良かったら教えてね!
https://github.com/chobichan/avrMultiTask_001
※ちょっとだけ修正入れています。ダウンロード実績1件、わらった!
サンプルINOは3つのタスクが起動しています。
1.stackMonitor
2.task1
3.task2
ライブラリの非依存部のサービスコールは従来からこのblogで公開している物。
AVRに依存するライブラリを今回新たに作成している。
AVR依存部を作成するにあたって考慮するところ!
※AVR GCCの破壊レジスタ : r0,r18-r27(X register),r30-r31(Z register)
※;AVR GCCの非破壊レジスタ : r2-r17,r28-r29(Y register)
※関数から戻る時は必ずr1レジスタを0にする r1=0
※AVR GCCの最初の引数 : r25:r24、AVR GCCの2番目の引数 : r23:r22、AVR GCCの3番目の引数 : r21:r20、AVR GCCの4番目の引数 : r19:r18
※AVR GCCの戻り値 : r25:r24
コンテキストをスタックに積むところは以下の様にした。
スタックポインタからのオフセット | レジスタ |
---|---|
0 | r29 |
1 | r28 |
2 | r17 |
3 | r16 |
4 | r15 |
5 | r14 |
6 | r13 |
7 | r12 |
8 | r11 |
9 | r10 |
10 | r9 |
11 | r8 |
12 | r7 |
13 | r6 |
14 | r5 |
15 | r4 |
16 | r3 |
17 | r2 |
18 | ステータスレジスタ |
19 | 空き |
20 | プログラム・カウンタ 上位 |
21 | プログラム・カウンタ 下位 |
スタックにプログラム・カウンタを積むところで結構嵌った(笑)。
Marudinoサポートページを立ち上げました [ATmarquino Arduino]

http://maruduino.blog.so-net.ne.jp/
是非ご利用ください。

Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
Arduino互換テストボードのMaruduinoでMIDI演奏にチャレンジ [ATmarquino Arduino]
※著作権表記及び署名の改竄以外はご自由にお使いください。
※ところでヘッダー情報の4分音符の分解能とデルタタイムを使っての時間指定の計算ってどうすればいいのでしょう?。
※デルタタイムを引数としてdelay関数を使って次のイベントまでの待ち時間を生成していますが、この為delayの引数の時間とそれ以外の処理時間の累積となって、実はテンポがいい加減です。さて、どうしたものかね。
※スケッチ改良しました。多分大体テンポは合っているかと思う。

前からMIDIをやってみたいとは思っていたんです。
ただMIDIに関すると言うか音楽全般に関する知識は皆無、音符とか読めませんし、そんな状態なので結構苦労しています。Arduinoの例題をベースにスケッチを書いてみましたが、まだまだバグバグで、しかも複数トラックを持つフォーマットには対応していません。
ですが、楽器を鳴らせるのは楽しいですな。
現状はキーを押すとMIDI出力するとかそう言ったものではなく、MIDIファイルをROM化して、それを流しています。
本当はMIDIファイルをそのまま垂れ流す程度で済むかと思っていましたが、そうではないんですね。データを送るタイミングとかはこちらでコントロールする必要が有るみたい。
あ、ちなみに物理的な接続はやけに簡単です。
スケッチとバイナリーデータをCソースに変換するプログラムも一応。
※MIDIのフォーマット0のみに対応



※ところでヘッダー情報の4分音符の分解能とデルタタイムを使っての時間指定の計算ってどうすればいいのでしょう?。
※デルタタイムを引数としてdelay関数を使って次のイベントまでの待ち時間を生成していますが、この為delayの引数の時間とそれ以外の処理時間の累積となって、
※スケッチ改良しました。多分大体テンポは合っているかと思う。

前からMIDIをやってみたいとは思っていたんです。
ただMIDIに関すると言うか音楽全般に関する知識は皆無、音符とか読めませんし、そんな状態なので結構苦労しています。Arduinoの例題をベースにスケッチを書いてみましたが、まだまだバグバグで、しかも複数トラックを持つフォーマットには対応していません。
ですが、楽器を鳴らせるのは楽しいですな。
現状はキーを押すとMIDI出力するとかそう言ったものではなく、MIDIファイルをROM化して、それを流しています。
本当はMIDIファイルをそのまま垂れ流す程度で済むかと思っていましたが、そうではないんですね。データを送るタイミングとかはこちらでコントロールする必要が有るみたい。
あ、ちなみに物理的な接続はやけに簡単です。
スケッチとバイナリーデータをCソースに変換するプログラムも一応。
※MIDIのフォーマット0のみに対応

Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本

新 裏口からのMIDI入門―「楽器が弾けない」「楽譜が読めない」初心者必見! (I・O BOOKS)
- 作者: 御池 鮎樹
- 出版社/メーカー: 工学社
- 発売日: 2009/11
- メディア: 単行本

SANWA SUPPLY KB-MID01-18 MIDIケーブル
- 出版社/メーカー: サンワサプライ
- メディア: エレクトロニクス
/* MIDI player The circuit: * digital in 1 connected to MIDI jack pin 5 * MIDI jack pin 2 connected to ground * MIDI jack pin 4 connected to +5V through 220-ohm resistor Attach a MIDI cable to the jack, then to a MIDI synth, and play music. created 13 Jun 2006 modified 2 Jul 2009 by Tom Igoe http://www.arduino.cc/en/Tutorial/MIDI */ #include <LiquidCrystal.h> #include <avr/pgmspace.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #define DI13 13 #define DI12 12 #define DI11 11 #define DI10 10 #define DI9 9 #define DI8 8 #define DI7 7 #define DI6 6 #define DI5 5 #define DI4 4 #define DI3 3 #define DI2 2 #define DI1 1 #define DI0 0 #define AN0 14 #define AN1 15 #define AN2 16 #define AN3 17 #define AN4 18 #define AN5 19 #define PWM11 DI11 #define PWM10 DI10 #define PWM9 DI9 #define PWM6 DI6 #define PWM5 DI5 #define PWM3 DI3 typedef struct { struct { unsigned char chunk[4]; unsigned char len[4]; unsigned char format[2]; unsigned char tracks[2]; unsigned char period[2]; } header; struct { unsigned char type[4]; unsigned char len[4]; unsigned char data[4]; } track; } MIDI; static unsigned long swap_l( unsigned char src[] ); static unsigned short swap_w( unsigned char src[] ); extern const unsigned char PROGMEM midi_data[]; LiquidCrystal lcd(DI2,DI3,DI4,DI5,DI6,DI7); unsigned long data_len; unsigned short period; PGM_P ptr; void setup() { MIDI *midi = (MIDI *)malloc( sizeof(MIDI) ); memcpy_P( midi, midi_data, sizeof(MIDI) ); data_len = swap_l(midi->track.len); period = swap_w(midi->header.period); lcd.begin(16,2); lcd.clear(); lcd.setCursor(0,1); lcd.print( period ); // Set MIDI baud rate: Serial.begin(31250); // Serial.begin(38400); free( midi ); } void loop() { unsigned char c; unsigned long temp,delta_time,old_time,new_time; ptr = (PGM_P)(((MIDI *)midi_data)->track.data); old_time = 0; while( 1 ) { delta_time = 0; c = pgm_read_byte_near(ptr++); if( c == 0x00 ) {} else { while( 1 ) { delta_time <<= 7; delta_time |= c & 0x7f; if( c & 0x80 ) c = pgm_read_byte_near(ptr++); else break; } } #if 1 lcd.setCursor(4,1); lcd.print( " " ); lcd.setCursor(4,1); lcd.print( delta_time ); #endif if( old_time == 0 ) new_time = 0; else new_time = millis(); temp = (delta_time * 1000 * 10) / period / 35; if( temp <= (new_time - old_time) ) temp = 0; else temp -= new_time - old_time; delay( temp ); old_time = new_time; if( event() == (-1) ) { delay( 10000UL ); break; } } } int event() { unsigned char c; int ret = 0; c = pgm_read_byte_near(ptr++); // switch( c & 0xf0 ) { case 0xf0 : if( c == 0xff ) ret = meta(); else { if( c == 0xf0 ) { c = pgm_read_byte_near(ptr++); // for( int i = c; i > 0; i-- ) { c = pgm_read_byte_near(ptr++); // } } else { c = pgm_read_byte_near(ptr++); // for( int i = c; i > 0; i-- ) { c = pgm_read_byte_near(ptr++); // } } } break; case 0x80 : // 3bytes pattern case 0x90 : // 3bytes pattern case 0xa0 : // 3bytes pattern case 0xb0 : // 3bytes pattern case 0xe0 : // 3bytes pattern lcd.setCursor(8,1); lcd.print( " " ); lcd.setCursor(8,1); Serial.print(c,BYTE); lcd.print( c,HEX ); lcd.print( ":" ); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); lcd.print( c,HEX ); lcd.print( ":" ); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); lcd.print( c,HEX ); break; default : // 2bytes pattern lcd.setCursor(8,1); lcd.print( " " ); lcd.setCursor(8,1); Serial.print(c,BYTE); lcd.print( c,HEX ); lcd.print( ":" ); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); lcd.print( c,HEX ); break; } return ret; } int meta() { unsigned char c,len; int ret = 0; c = pgm_read_byte_near(ptr++); switch( c ) { case 0x00 : Serial.print(0xff,BYTE);Serial.print(c,BYTE); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); break; case 0x01 : case 0x02 : case 0x03 : case 0x04 : case 0x05 : case 0x06 : Serial.print(0xff,BYTE);Serial.print(c,BYTE); len = pgm_read_byte_near(ptr++); Serial.print(len,BYTE); lcd.setCursor(0,0); lcd.print( " " ); lcd.setCursor(0,0); for( ;len > 0; len-- ) { c = pgm_read_byte_near(ptr++); Serial.print(c, BYTE); lcd.print( c ); } break; case 0x2f : Serial.print(0xff,BYTE);Serial.print(c,BYTE); c = pgm_read_byte_near(ptr++); Serial.print(c,BYTE); ret = (-1); break; case 0x51 : case 0x58 : case 0x59 : Serial.print(0xff,BYTE);Serial.print(c,BYTE); len = pgm_read_byte_near(ptr++); Serial.print(len,BYTE); for( ;len > 0; len-- ) { c = pgm_read_byte_near(ptr++); Serial.print(c, BYTE); } break; default : break; } return ret; } static unsigned long swap_l( unsigned char src[] ) { unsigned long temp = 0; temp += src[0]; temp <<= 8; temp += src[1]; temp <<= 8; temp += src[2]; temp <<= 8; temp += src[3]; return temp; } static unsigned short swap_w( unsigned char src[] ) { unsigned short temp = 0; temp += src[0]; temp <<= 8; temp += src[1]; return temp; }
/* ------------------------------------------------------------------------ */ /* バイナリファイルをCソースファイルに変換するプログラム */ /* */ /* Copyright (C) 2004- by hamayan */ /* ------------------------------------------------------------------------ */ #include <stdio.h> #include <string.h> #include <time.h> /* ------------------------------------------------------------------------ */ /* メインね! */ /* ------------------------------------------------------------------------ */ int main( int argc, char *argv[] ) { char str[32]; int i,c; long length; FILE *in,*out; time_t timer; struct tm *tblock; if( argc != 3 ) { fprintf( stderr, "Argument Missmatch.\r\n" ); return EOF; } if( (in = fopen( argv[1], "rb" )) == NULL ) { fprintf( stderr, "Image File Open Error.\r\n" ); return EOF; } if( (out = fopen( argv[2], "wb" )) == NULL ) { fprintf( stderr, "Output File Open Error.\r\n" ); fclose( in ); return EOF; } /*ヘッダー部の出力*/ fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); fprintf( out, "/* Binary data file convert to C source file program. */\r\n" ); fprintf( out, "/* designed by hamayan */\r\n" ); fprintf( out, "/* Copyright(C) hamayan */\r\n" ); fprintf( out, "/* since 2004 - */\r\n" ); fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); /*ヘッダーファイルの取り込み*/ fprintf( out, "#include\t<avr/pgmspace.h>\r\n" ); /*変換後のデータ表現*/ fprintf( out, "const unsigned char PROGMEM midi_data[] =\r\n" ); fprintf( out, "{\r\n" ); do { fprintf( out, "\t" ); for( i = 0; i < 16; i++ ) { if( (c = fgetc( in )) == EOF ) break; fprintf( out, "0x%02X,", c ); } fprintf( out, "\r\n" ); } while( c != EOF ); fprintf( out, "};\r\n\r\n" ); /*フッター部の出力*/ fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); fprintf( out, "/* designed by hamayan */\r\n" ); fprintf( out, "/* Copyright(C) hamayan */\r\n" ); fprintf( out, "/* since 2004 - */\r\n" ); fprintf( out, "/* ------------------------------------------------------------------------ */\r\n" ); fclose( in ); fclose( out ); return 0; } /* ------------------------------------------------------------------------ */ /* Copyright (C) 2004- by hamayan */ /* ------------------------------------------------------------------------ */
Japaninoで超音波距離計を作ってみる。Maruduinoまたは(◎)の回路図公開 [ATmarquino Arduino]

例によってローカルにダウンロード後、拡張子をpdfに修正してお使いください。
※スケッチと動作している様子は以下のリンク先をご覧ください。
http://hamayan.blog.so-net.ne.jp/2010-05-19
Arduinoのtoneライブラリを使って40KHzの搬送波を生成します。生成した搬送波はArduinoからの出力のままでは5Vpしかありませんので、増幅する為にRS232CドライバーICを利用します。これだと10Vp以上の振幅にする事ができますので、その出力を送信モジュールに入力します。
この振幅を大きくする回路は、トランジスタ技術2010年3月号別冊付録の中の回路を参考とさせていただきました。
受信センサーは2つのアンプで増幅された後、ダイオードで検波されます。超音波を受信するとコンパレータの非反転入力端子に入力する信号がGNDレベルから山が立ち上がりますので、それをオペアンプで構成したコンパレータで検出します。
と、この検出した変化点をArduino側でポーリングで見付け、送信時間から往復の距離を算出する訳ですね。
ソフトウエア的には、40KHzを搬送波とする送信パルスを短時間だけ送出します。※あまり長いと送出している間に反射して戻ってきてしまう為。但し、短すぎると到達距離自体も短くなってしまう。
この送信の時にも受信センサー側はそのパルスを拾ってしまい誤検出しますので、送信の間だけコンパレータの出力をキャンセルするのがD1のダイオードを通したポートの出力です。HIGHを出力している間、コンパレータはLOWを出力し続けます。
送信パルス送出後は、D1に接続されているDIGITAL5をLOWに落として置きます。
その後ポーリングで立ち上がりを検出し、経過時間を求めます。
但し反射波が検出できないと無限ループとなりかねないので、適当なタイミングでループを抜ける処理も必要ですね。大体3m先の往復時間が約18msなので、それよりちょっと多目の時間で抜けると良いでしょう。

Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本
Japaninoで超音波距離計を作ってみる。Maruduinoまたは(◎)の応用編 [ATmarquino Arduino]
![]() |
![]() |
![]() |
計測した対象物までの距離はLCDにて表示を行っています。
電源電圧は5Vです。送信側の振幅をより大きくする為にRS232ドライバーICを流用しています。
40KHzの発振はArduinoのtoneライブラリを使用して発生しています。これを搬送波とする短いパルスを発し、帰って来るまでの時間を計測し、音速≒340m/sから対象物までの距離を計算しています。
音速は周囲温度に依存しますので、実際には温度を計測しながら距離の計算を行うと、もっと良いでしょう。
という訳で簡単なコードを書いておきます。あまり深く考えて記述した物ではないのでご注意を。
#include <LiquidCrystal.h> #include <avr/io.h> #include <avr/interrupt.h> /*************************************************************************/ /* defines */ /*************************************************************************/ #define AREF 0 #define NOT_GND 1 #define DI13 2 #define DI12 3 #define DI11 4 #define DI10 5 #define DI9 6 #define DI8 7 #define DI7 8 #define DI6 9 #define DI5 10 #define DI4 11 #define DI3 12 #define DI2 13 #define DI1 #define DI0 #define AN0 14 #define AN1 15 #define AN2 16 #define AN3 17 #define AN4 18 #define AN5 19 #define PWM11 DI4 #define PWM10 DI5 #define PWM9 DI6 #define PWM6 DI9 #define PWM5 DI10 #define PWM3 DI12 /*************************************************************************/ /* global parameter */ /*************************************************************************/ #define UltraSonicPin PWM6 LiquidCrystal lcd(DI2, DI3, DI4, DI5, DI6, DI7); /*************************************************************************/ /* prototype */ /*************************************************************************/ /*************************************************************************/ /* timer1 output compare match a int handler */ /*************************************************************************/ SIGNAL( TIMER1_COMPA_vect ) { } /*************************************************************************/ /* setup */ /*************************************************************************/ void setup() { lcd.begin(16,2); lcd.clear(); lcd.print( "designed by" ); lcd.setCursor(0,1); lcd.print( " hamayan." ); pinMode( DI8, INPUT ); pinMode( DI10, OUTPUT ); digitalWrite( DI10, LOW ); } /*************************************************************************/ /* main loop */ /*************************************************************************/ void loop() { digitalWrite( DI10, HIGH ); tone( UltraSonicPin, 40000 ); unsigned long startMicro = micros(); delayMicroseconds( 500 / 8 ); noTone( UltraSonicPin ); delayMicroseconds( 500 / 8 ); digitalWrite( DI10, LOW ); unsigned long endMicro = startMicro; while( digitalRead( DI8 ) == LOW ) { endMicro = micros(); if( (endMicro - startMicro) > 20 * 1000UL ) break; } unsigned long distance; if( (endMicro - startMicro) < 20 * 1000UL ) { distance = ((340 * (endMicro - startMicro)) / 10000UL) / 2; } else { distance = 999; } lcd.clear(); lcd.print( distance ); lcd.print( "cm" ); delay( 500 ); }

Prototyping Lab ―「作りながら考える」ためのArduino実践レシピ
- 作者: 小林 茂
- 出版社/メーカー: オライリージャパン
- 発売日: 2010/05/27
- メディア: 大型本