Baumkuchen’s Workshop

バイオリンと電子工作、DIY、ジョギングなど。

【バイオリン】初めての発表会 ~主よ、人の望みの喜びよ~

先週、初めての発表会を経験しました。(バイオリンの話題を殆どアップしていないので、たまには書いてみます。)

 

2019年にバイオリン教室に通い出して、本来なら2020年に初発表会の予定でしたが、残念ながらのコロナ禍で、結局、二年遅れの発表会体験となりなした。

 

演奏曲は、テキストの中から昨年に一応合格になった曲からということで、「主よ、人の望みの喜びよ」のアンサンブルです。

発表の順番は、トリもオオトリの、3部構成の3部目の最後の順番に決定。最後まで、緊張するじゃないか!

 

本番までは、結構練習したつもり。土日は、夕食の後の1時間位は欠かさず練習。最近は、在宅勤務もしているので、通勤時間が無くなった分、平日もできるだけ練習。

レイトスターターなので頑張ってみんなについていかないと。

 

また、バイオリンを買ってから一度も弓の毛替えしてなかったので、今の技術レベルでは大差はないだろうなと思いつつも、良い機会なので交換。でも、7月末に頼んでから、結局、8月の盆休み明けになったので、1ヵ月弱も掛かってしまって、発表会に間に合わないんじゃないかと心配でした。

 

本場までは、緊張感は全くありませんでしたが、いざ、本番直前の音出しで、さすがに緊張してきました。全員でちょっと合わせの練習をしていたら、もう、出番待ちですとの案内。舞台裏で、徐々に緊張が高まるのを、平静をよそいながらの待ち時間。

本番も、譜面台に楽譜を置いたら、ひと呼吸置く間もなく、伴奏がスタートです。全然余裕がないです。もう、本番と腹をくくって演奏するしかないです。

頑張りました。で、結構、ガタガタ震えてしまいました。でも、弾きました。

前半は何とかミスなく演奏。最後の方の少し難しいところ、ソシレ・ソレシ、ソシレ・ファレシ~(といって分かんないかな。分かる人には分かる)をどうにかクリアしたあたりで、気が緩んだのか、1小節飛んでしまいました。ヤバいと思いましたが、ボーイングが何とか同じ調子で動けていたので(多分変な音が出ていた)、直ぐに復活できて、あとは夢中で最後まで演奏しきりました。

 

久々の緊張でしたが、最後まで演奏しきることができ、初めての発表会としては上出来と思いたいです。 これからも、もっと良い音、もっと難しい曲を目指して頑張ります。

 

最後に、おまけ。

今まで、自分の技術を棚に上げ、他人のYouTube動画を見て、音がずれてるとか偉そうなことを言っておりましたが、直前に自分の演奏をiPhoneで録音して聞いたところ酷いもんでした。(それでも発表会は頑張りましたが)

懺悔の意味も込めて、リンクを貼らせて頂きます。1年9か月でこの出来は、関心します。ぜひ、チャンネル登録してあげてください。


www.youtube.com

 

 

 

バイオリン教室の前日、Violinの弦が切れました【Pirastro Tonicaへの弦張り替え】

バイオリン教室の前日、弦が切れて焦りました。

写真は、切れた弦(E線)です。

E線が切れた(切ってしまった)のは、2回目です。

baum-kuchen.hatenablog.com

弦が切れた原因

原因は、単に張力の掛けすぎとしか言えません。言い訳できません。

写真は、今使っているKorgのクリップチューナです。練習前にチューニングしようと、A線、D線、G線と進め、E線をチューニングしましたが、全然針が振れません。音も聞いた感じでも特におかしくはなかったのですが、テールピースの微調整のネジを回しても、針がピクリともしなかったので、ペグ回してチューニングを。ところが一向、針が動かないな~。と思っていたら、

ブチッ

という音と共にE線が切れました。

で、何でか?というと、よく見たら次の写真の様に、チューナのモードが、”VIOLA”になっているではありませんか。

Korgのチューナは、本体左端のスイッチで、電源オンとチューニングモード選択ができる様になっているんですが、どうも、電源オンの時に誤ってモードも”VIOLIN”から変えてしまった様でした。

Violaには、E線があるわけがなく、いっくらチューニングしようが針が動かないわけです。

実は、1回目に弦を切ってしまった時も同じ間違いを犯していました。人間、学習しないもんですね。と、悠長なことは言っていられず、何とかせねばということで、いざというときのためにバックアップでとっておいた使い古しの弦を取り出して、明日のバイオリン教室はしのぐことにしました。

新しい弦の注文

早速、新しい弦を注文せねば。

今使っている弦は、ドミナントですが、次には別のものも使って見たいな(どんだけ違いがあるのかも試してみたい)といことで、PIRASTRO当たりを考えていました。

値段も手ごろなもので、下記のサイトなどを参考にPIRASTRO TONICAを選択。EVAH PIRRZZIとか良く聞いて(見て)いましたが、ちょっと高めなので、今回はTONICAで。

www.yamano-music.co.jpで、翌日には届きました。

新しい弦の張替え

早速、新しい弦に張替えです。PIRASTROは、ペグ側の方が色分けしてあるんですね。

テールピース側は、基本、赤白(E線のみ赤)です。

結果

弦を張り替える前に、練習音をiPhoneで録音し、PRASTROに張り替えた後、同じく録音して比較してみました。最終的には耳で聞いた音ですが、古い弦の音を思い出すのが難しいと思ったので。

が、あんまり差がない感じです。よく良く聞くと、音量は確実に大きく響いているようですが。

前回、ドミナント弦に変えたときは、すごく差があったんですが、腕前の問題なのかもしれません。ただ、練習あるのみですね。

 

 

 

バイオリンタイマーの製作#16-状態遷移ロジックのデバッグ

フラッシュメモリの問題は無事解決?しました。

baum-kuchen.hatenablog.com

時計ICのメモリ

そもそもフラッシュメモリを使おうと思った動機は、バッテリー寿命の計測のためです。なので、余り記憶するデータも多くないことから、時計ICにあるバッテリーバックアップされた31バイトのメモリを使うことで、解決です。

毎秒、作動タイマー(1秒カウントのlong int)を書き込めば、最大5万年もカウント出来ます。

じゃあ、フラッシュメモリは何に使うかと言うと、練習時間の履歴データの保管に使うつもり。これなら、バッテリーの電圧がある時に1時間に1回程度記録すれば、書き込み回数上限も気にしないで行けそうです。

状態遷移ロジックのデバッグ

その後は、ずっと状態遷移ロジックのトラブルシュートを行っていました。LCD画面に内部データを表示させて、細かい遷移条件のチューニングやバグ取などです。写真は、①で音検知と練習音検知の条件確認。②で音無し1分間や練習なし10分間のタイマー確認。③が、システムモード(4=通常モード)、バックライトモード(1=DIMモード)、Oが操作後1分のフラグ確認などといった感じです。

f:id:Baum_kuchen:20220408205414j:plain

状態遷移ロジックは、割り込み処理で、音検知はバックグランドタスクで実施になっているので、処理タイミングなどの調整が微妙だったり、状態が直ぐ、次に移ってしまったりと、結構、大変です。

また、スタンバイモードとなるとCPUクロックが1MHzになるので、作動速度がとても遅くなりデバッグ表示自体にかなり時間を取られ、確認が遅々として進まないといった感じです。

不可解な問題

その中で、問題が更に起きました。

デバッグのため、しばらく放置しておくと、画面が真っ白になっていることが多々発生。不思議なことに時計モードとかでは発生しません。

f:id:Baum_kuchen:20220408204336j:plain

何だかんだで、1ヵ月位この問題と取り組んでいました。

症状としては、LCDの初期化が失敗したときの様な表示であるところから、それを手がかりにトラブルシュートです。

まず、分かったのは、画面が真っ白な状態でも、輝度コントロールができること。これは、つまりは、処理(割り込み)は動いているということです。更に、それを確認するため、特定のモードの時に、LCDを初期化する様にしたところ、画面が正常に復帰することが確認できました。ここまで分るだけでも結構掛かりました。

また、この事象は、時計モードでは起きたことが無く、練習時間タイマーモードのみ発生しています。単に頻度の問題なのかもしれませんが。

要因を考えてみましたが、多分、LCDコマンド送信途中に割り込みが入って、おかしくなるのかなと想定。コマンド送信の本体機能はSPIハードインターフェースを使っているので割り込みが入っても大丈夫だと思うんですが。

割り込み自体は、各モードでも同じ様に発生する作りですが、練習時間タイマーモードと時計モードの差ということを考えれば、マイク入力のADサンプルをするかしないかです(正確には、時計モードは、サンプルしたデータがいっぱいのまま使わない状態を保持)。

バックグランドタスクのプログラム構造として、

 1.マイクADサンプル完了を待つ

 2.音声関連処理(音検出、練習音検知など)

 3.マイクADサンプルスタート

 4.デバッグ表示 

 5.練習時間積算処理

となっています。どこで、問題が発生しているか特定するため、上の各行の処理が終わったところで後はスキップするようにしていったところ、3.でスキップすると問題が発生せず、4.まで進むと問題が発生することを突き止めました。あとは、デバッグ表示のどこが問題なのかを調べていくと、下の写真の矢印の表示(音の大きさ)を表示するとダメというこが分かりました。つまりは、ADサンプルをスタートした直後のデバッグ表示で、割り込みがかかると問題の様でした。右下の〇印のところの数字は、矢印表示直後のADサンプル数(HEX値;10進で104)を表示させたもので、2文字表示で256サンプルの半分近くの割り込みが掛かっていることになります。これが、1MHzクロックだと、完全に256サンプルしてしまいます。

つまり、原因は良く分かりませんが、LCDへの表示コマンドを送っているときに、ADサンプルが行われると表示異常になることは確かなようです。

f:id:Baum_kuchen:20220408205433j:plain

なので、暫定処置として、4.デバッグ表示の前に、ADサンプリングを256点完了させてしまうことにしました。約50ms待つことになりますが、不可解な動きをするよりは良いです。

今後の計画

ということで、大分道草を食ってしまいました(と言っても、その間は作業机更新とかが出来ました)が、状態遷移の細部条件を確認していき、物として完成させていきます。

まだ、まだ、先は長いですが、よろしかった、お付き合い願います。

バイオリンタイマーの製作#15-低消費電力化(課題が後から次々)

低消費電力化の実装に手こずっています。

baum-kuchen.hatenablog.com

タスク構成の見直し

まず、システムモード、バックライトモードの状態遷移を割り込み処理で行うことにしました。通常処理で、表示と各モード処理などを行うと、表示に1秒とか掛かる場合は、反応が遅くて使い物になりません。ただ反応が遅いだけならまだしも、タイムアウト処理(スイッチ操作後30秒とか、音無し1分とか)が規定時間通りうまく働かず、状態遷移が機能しないことに(デバッグでも何を確認しているか分からない状態)。

なので、タスク構造を大きく見直して、基本のモード処理を全て割り込みベースにすることしました。

ただし、表示処理は時間が掛かるので、バックグラウンドタスク化して、表示自体は出来るまで待つという方法にしました。

ここで、懸案はフレームオーバーしないかどうかということ。現状の処理時間を測ったところ、システムモードとバックライトモード判定処理は、100μS以下だったのて、3KHzサンプリングでも行けそうです。一方、スタンバイモードの時1MHzクロックでどうかと言うと単純に8倍の時間が掛かるので3KHzはとても無理、よって、1KHzサンプリングとする事に。というのも、スタンバイモードでは、音色判定としてFFTは不要だからです。

タスク構成を図に表すと、こんな感じです。

f:id:Baum_kuchen:20220308185611p:plain

有音判定

次いで、音判定も割り込み化できないかトライ。まず、音判定自体がどの位時間が掛かっているか調べると、最初500msも、rms計算でfloat演算を全部intとlong int処理に変更しても(1024の二乗の256サンプルでLong intに収まるはず)、25msが限度。判定だけなら、閾値を二乗にしておけばいいので、平方根も取ってみたけど大差なしです。なので分りやすい様に、平方根計算は残すことに。25msも掛かるので、割り込み内ででの処理は無理なので、バックブランド処理のまま残すことにしました。割り込みでのモード判定処理との間で、フラグによるやり取りが必要になります。

バックグラウンド側で、割り込みによるAD変換が256データ完了するのを待って、音判定処理開始、終わったら音判定完了フラグを立て、今度は、割り込み側でモード判定処理に使いと言った構造です。

結構、ややこしいタスク構造になってしまいました。

SLEEP時の問題

10分間、音が無いと判断したらスリープモードに遷移します。これは、単にsleep命令(MLAでは、SLEEP()関数)でOKです。

で、問題はスリープからどうやって復活するかです。PICにはいくつかの方法がありますが、ウォッチドッグタイマの使用が一番シンプルでしょうね。タイマからの割り込みと言う手もありますが。以下が、スリープモードを選んだ時の処理です。

            case CPU_SLEEP:
//prepare for sleep
            TFTCS = TFTCD = 0;  //0 for LCD
            TFTRST = 0
            RC0 = RC1 = RC2 = 0;  //0 for CLOCK
//WDT
            di();
            CLRWDT();
            WDTCON = 0x01;           //SWDTEN = 1 for wake up          
            SLEEP();
//wake up sequence
            WDTCON = 0x00;           //SWDTEN = 0    
            ei();
            
            TFTRST = 1;
            break;    

最初の部分は、IO出力を0にして消費電力を抑えるための処理。

あとで、タイマ割り込みが入らないように割り込み禁止とし、ウッチドッグタイマをクリアするために、WDTCLRを行った後、SWDTEN=1でウォッチドッグタイマを有効にしてから、スリープに入ります。

そうすると、予め設定したウォッチドッグタイマの時間経過後に、スリープのコマンドの次からプログラムが再開するという段取りです。

ここまで、出来るようになるまで、結構、試行錯誤をしてます。今のタスク構成上は、この処理が走るのが1KHzのタイマ割り込み中なので、本当は割り込み禁止、許可は不要のハズです。

ウォッチドッグタイマの時間は、CONFIGレジスタのWDTPSで512(=約2秒)に設定する必要があります。

ここまでは、まあ、いろいろ試行錯誤はしたものの、何とかなりましたが、そこからが結構やらしいです。

まず、簡単なところからいうと、スリープ中に一旦、IO=0としたことで、LCDが初期化されます。なので、スリープから復活してもLCDに何も表示されないという問題が。ま、これは、もう一度LCD初期化ルーチンを呼べば済む話なので、単純な話ですが、そうは問屋が卸さずです。割り込みの中で、LCD初期化ルーチンを呼ぶとその中でLCDへのコマンドライト関数を呼びと、どんどん関数のネストが深くなり、ついにはスタックオーバーフローが発生してしまいました。最初は何が起こったか全くわかりませんでしたが、STKPTRレジスタの値を表示させてみて分かりました。原因が分かったのでとりあえずLCDのリセットを発生させないようにして、LCD初期はしないでデバッグしてます。いずれは、改善が必須です。

次の問題は、スタンバイ時そのものの問題です。

スタンバイ時の問題

問題というか、必然というか。低消費電力化のため、8MHz作動を1MHz作動に切り替えると、いろいろ影響が出ます。まずは、処理スピードが1/8になるので、ソフト的に作っていた1msカウンタ、50msカウンタ、1秒カウンタなどが、ことごとくずれます。AD変換のパラメータが変ります。LCD描画速度が激遅になります。等々。

LCD描画は、SPIの速度が律速なのでどうしようもないです。ソフトタイマとAD変換パラメータは、2つの定数を切り替える様にソフト処理をそれぞれ追加しました。

最初にも書いた通り、ADサンプリングも3KHzを1KHzに変更します。なので、256サンプルに、256mSかかり、有音判定も25msだったものが、200ms必要になるので、トータル0.5秒近く必要になります。なので、当初、スリープ中は、実際には2秒スリープ、0.2秒スタンバイの繰り返しのハズが、2秒スリープ、0.5秒スタンバイとなって、低消費電力化の効果激減してしまいます。実際には、0.5秒では終わらないので、効果はもっと落ちます。単純計算で、稼働日数が約5日減少の影響になりそうです。(実測は、まだできてません)

フラッシュメモリ活用

低消費電力化と直接関係は無いですが、どの位バッテリが持つかを測るため、フラッシュメモリに作動時間を記録するように考えました。

使っているPICがプログラムメモリをプログラムから書き込みできるタイプです。

フラッシュメモリのイレーズ、ライト、リードの基本的関数を作ってみました。リードは直ぐできましたが、ライトが動くまで、結構悩みました。

最初は、フラッシュメモリのプロテクト設定です。これも、CONFIGレジスタの設定になりますが、0xF000からの4Kbyte分を書き込み可能とする設定は次の通りで、プログラムが間違っているのか設定が間違っているのか何回もトライしてます。

#pragma config WPFP = PAGE_59       //Write Protect Program Flash Page 59
#pragma config WPEND = PAGE_0       //Start protection at page 0
#pragma config WPCFG = OFF           //Configuration Words page erase/write-protected
#pragma config WPDIS = ON           //WPFP<5:0>/WPEND region erase/write protected

とりあえず、何か書けるようになってからも、何故か、0しか書けません。ちょうど、1Hz毎にタイマ値を書いて、直ぐに読み出して表示するテストプログラムで確認しましたが、全て0です。アドレス設定とか型の不整合なども、何度も見直しましたが、分かりません。で分ったきっかけが、テストプログラムを起動直後から、ずっと表示を見ていると、最初だけ何か数値があり、あとは必ず0になるという動きを発見。最初の数回だけ正しくてあとは動かなくなるモードも考えましたが、ちょっと思いつきません。数字が出るのは、テストプログラムを書き込んだ直後のみ。

で、分かりました。フラッシュメモリの”書く”=”0にする”だからです。イレーズをすると0xFFになり、値を1回書くと、0のbitが0になり値が書き込まれます。全てのbitに0を書いたら、それ以降は1にならない。です。

値を書く前に、イレーズ処理が必要なんでした。

確かに、データシートを良く読めべば書き込みの前にイレーズがされている場合・・とあります。ワード書き込みモードを使ったんですが、これは新しいモードなので、事前のイレーズはいらないのかなと勝手に勘違していました。

ということで、以下の関数が無事動くことが確認できました。ほっ。

/* flash memory */
union {
    unsigned int iw;
    struct {
        unsigned char il,ih;
    };
} fd;

void flash_erase1()
{
    TBLPTRU = 0x00;
    TBLPTRH = 0xF0;
    TBLPTRL = 0x00;
   
    EECON1 = 0b00010100;    //FREE = 1,WREN=1,WR=0  
    di();
    EECON2 = 0x55;
    EECON2 = 0xAA; 
    WR = 1;                 //WR=1
    ei();
    EECON1 = 0b00000000;    //WPROG =0,WREN=0,WR=0
}

void flash_write_word(unsigned char adrs,unsigned int data)
{
    TBLPTRU = 0x00;
    TBLPTRH = 0xF0;
    TBLPTRL = 0x00 + adrs+ adrs;
    fd.iw = data;
    
    TABLAT = fd.il;         //LSB
    __asm("TBLWT*+");
    TABLAT = fd.ih;         //MSB
    __asm("TBLWT*");
    
    EECON1 = 0b00100100;    //WPROG = 1,WREN=1,WR=0  
    di();
    EECON2 = 0x55;
    EECON2 = 0xAA; 
    WR = 1;                 //WR=1
    ei();
    EECON1 = 0b00000000;    //WPROG =0,WREN=0,WR=0
}

unsigned int flash_read_word(unsigned char adrs)
{
    TBLPTRU = 0x00;
    TBLPTRH = 0xF0;
    TBLPTRL = 0x00 + adrs + adrs;   
    
    __asm("TBLRD*+");
    fd.il = TABLAT;
    __asm("TBLRD*+");
    fd.ih = TABLAT;
      
    return fd.iw;
}


ただ、フラッシュメモリの本質的問題は避けて通れません。書き込み回数制限があります。データシートを見ると、10,000回以上とあるではないですか。
ダメです。バッテリ電圧低下時に作動時間が記録されてないとけないので、1秒毎に作動時間をフラッシュメモリに書くつもりでいましたが、そんなことしたら、3時間も経つと書けなくなってしまうということ。書き込み間隔を広げても、実際の運用までに消耗してしまいそう。10,000時間以上の練習時間を記録(そんなに練習できるか!!)しようとすると、1時間に1回しか記録できない勘定です。
ということは、解決策は一つ。バッテリOFFのタイミグで1回のみ、それまでの作動時間を記録するし無い、と考えた次第。
で、Brouwn Out Resetの機能をトライすることになりました。

BOR(Brown Out Reset)活用

バッテリ電圧が下がりBORになったとき、結局はリセットなので、プログラムは最初から動くことになります。そこで、通常のPOR(Power On Reset)と区別をして、フラッシュメモリにデータを書き込むことを行えばいいはずです。

PORかBORかの区別は、RCONレジスタのPOR bit、BOR bitを使えば判別でき、コードとしては次の様になります。これで、PORの時は、フラッシュメモリーから値を復活し作動し、BORの時は、フラッシュメモリーに値を書いたあと、バッテリが死ぬまで無限ループで終了となるはずです。

    if((POR == 0) && (BOR == 0)) {//PORの時
        POR = 1;            //for detetc BOR
        isBOR = 0;
    }
    else {//BORの時
        if(BOR == 0)
            isBOR = 1;  
    }
  
//
    if( isBOR == 1)  {
        stat_to_flash();
        while(1);
    }
    flash_to_stat();

ところが、これもうまくいきません。実際、プログラムがこれでいいのかを確認するのが、なかなか難しいですが、強制的にreset命令をデバッグ用に入れるなどしてみると、ロジックとしては動いているようですが、フラッシュメモリーの値が正しく書けてません。MPLAB Xでメモリを読み出しても、やはり0になっています。今回は、ちゃんとイレーズを入れているのですが。

困ったときは、まず、データシートを良く読めということで、いろいろ読みました。原因はまだ特定できていない状態ですが、ちょっと致命的なことに気づいてしまいました。

データシート上、フラッシュメモリのイレーズ(1Block分)に掛かる時間TIE=33msとあります。つまり、BOR後、最低33ms立たないと、データを書ける状態にならないということです。バッテリが死にかけている状態で、そんなに作動できるのか微妙です。

(2022.3.9追記)実際、DC電源をつないで、だんだん電圧を落としていって、VDDCOREの電圧がどうなるか確認してみました。2.2Vを切ってからVDDCOREが2.0Vとなるまでの時間は、約1.1msでした。やっぱり時間的にも無理ですね。実際には電池の電圧はもっと滑らかに落ちるでしょうが。

もう一つは、フラッシュメモリの書き込み電圧です。VPEW=2.25V(min)とあります。一方、BOR判定の電圧は、VBOR=1.9~2.2Vです。つまり、BORが発生した時の電圧では、フラッシュメモリには書き込みできないということです。

なんと。

構想が見事に破綻しました。

う~ん。

今後の計画

ということで、少し疲れ感、満載です。(いろいろ、勉強にはなりましたが)

さて、どうしようかな。

消費電流低減がどこまでできるかは結果次第ということで、Violin Timer機能本体の仕上げをしますか。バッテリ交換の頻度が上がっても、使えるもの作って、なんぼですからね。

まだ、完成まで、とっ~ても長そうですが、よろしかった、お付き合い願います。

バイオリンタイマーの製作#14-低消費電力化&システム作動設計

相変わらず、USBのデバイス認識はうまくいっていませんが、アドレス設定までは何とか出来ているようですが、コンフィグレーション設定でコケている様。なかなか、手ごわいのでで、低消費電力化と合わせて、全体のシステム動作の設計を進めます。

baum-kuchen.hatenablog.com

システム動作の設計

消費電流の低減をある程度想定したうえで、まず、全体の作動シーケンスを考えます。大きくは、システムモード(CPUの作動周波数)と、LCDバックライト輝度の制御になります。練習時を通常時として、バイオリンの音を検知しなくなったら、スタンバイモードにて消費電流を低減し、さらに、そこから時間がたったら極低消費電流のSLEEPモードに遷移するという考えです。これをまとめると次の様になります。

f:id:Baum_kuchen:20220220114758p:plain

f:id:Baum_kuchen:20220220114844p:plain

SLEEPモードからの復帰は、割り込みや、WDTをトリガとしますが、ここでは、WDTによる復帰を考え、2秒周期で、通常モードへの復帰を判断することにしました。間隔をあまり長くすると反応が遅くなるし、逆に、短くすると消費電流の低減効果が減ってしまうため、2秒にしています。

一方、LCDのバックライト制御は、システムモードと基本的には独立していて、必要最小限の点灯とするため、練習中でもLED消灯とできるように考えました。

状態遷移図

プログラムを実装するにあたり、シーケンスを状態遷移図の形に書き表しました。システムモードは大きく分けて4つ(通常、スタンバイ、SLEEP、USB)ありますが、状態としては、更に2つ増やした6つの状態で実装することにしました。

f:id:Baum_kuchen:20220220115311p:plain

バックライトの方も同じく状態遷移図に表すと、こうなります。

f:id:Baum_kuchen:20220220115332p:plain

状態遷移図では、他の作動モード(時計とか)に遷移したときの条件も一部追加していますが、ここは、実装を行いながら少し手直しをしていこうと考えています。

消費電力測定

肝心の消費電流低減ですが、方法としては、

・電源電圧を下げる

・CPUクロックを下げる

・内臓モジュールを停止

・DIOからの電流を下げる

・バックライトの電流を下げる

と言った方法があります(詳しくは、こちら)。最初のものは電源3.3V作動で、これ以上は難しいので取れません。バックライトは既に実験済みなので、CPUクロックを下げる手法で確認をしていない、CPUクロック1MHz動作と停止(内臓モジュール停止、DIO電流低減)を確認してみました。

結果は次の様になり、1MHzで2.1mA、クロック停止(SLEEP)で、0.5mAとなりました。クロック停止で0.5mAとあるのは、主にオペアンプと時計ICの電流になります。

f:id:Baum_kuchen:20220220120726j:plainf:id:Baum_kuchen:20220220120750j:plain

ちなみに、USB作動用に24MHzとすると、9.5mAにもなっていました。
f:id:Baum_kuchen:20220220120808j:plain

稼働時間予測

システム作動シーケンスと実測消費電流が分かりましたので、稼働時間の予測をしてみます。一応、平日は1時間、土日は3時間の練習をするとした場合(年間573時間ですね。1万時間には17.5年も掛かってします)、

f:id:Baum_kuchen:20220220115425p:plain

f:id:Baum_kuchen:20220220121624p:plain

稼働時間は、32.5日と出ました。
最初、電池だけで1ヵ月持たせたいと考えていましたが、計算上は、何とか持ちそうです。

今後の計画

消費電流低減の目途が立ちました(計算上は)。あとは、ソフトの実装と確認です。

Violin Timer機能本体の仕上げもまだなので、それと合わせて進めていきます。

まだ、完成までいろいろありますが、よろしかった、お付き合い願います。

バイオリンタイマーの製作#13-USBのトラブルシュート

USBのトラブルシュートをした結果、原因が分かりました。

f:id:Baum_kuchen:20220215205406j:plain

baum-kuchen.hatenablog.com

USBイネーブル信号

前回で、USBモードが動かないと書きましたが、以前からプログラムには、MLAからCDC-Serial Emulatorを持ってきて組み込んでありましたが、回路もちゃんと組んでない状態でしたので、一部コメントアウトしているところがありました。具体的には、下のUSBDeviceAttch()です。ここをコメントアウトしないと、プログラムが止まってしまうからでした。

MAIN_RETURN main(void)
{
/* Initialize I/O and Peripherals for application */
    SYSTEM_Initialize(SYSTEM_STATE_USB_START);

    USBDeviceInit();
//deug
//    USBDeviceAttach();
   
    while(1)
    {
        SYSTEM_Tasks();
    ・・・    

今回、詳しく調べていくと関数内の次の行で、USBENが1(enable)にならず、ずっと止まっていることが分かりました。これは、USBを使うときの一番基本の設定なのに何故止まってしまうのか不思議でした。

void USBDeviceAttach(void)
{
・・中略・・
//debug
    while(!U1CONbits.USBEN){U1CONbits.USBEN = 1;}

 

クロック設定

マニュアルを見ると、

f:id:Baum_kuchen:20220218211705p:plain

f:id:Baum_kuchen:20220218211638p:plain

とあるので、RC発振器(INTOSC)8MHzを2分周してをPLLに食わせて48MHzを作り、それを8分周することで、LOW Speed USBに必要な6MHz設定しましたが、動きません。

f:id:Baum_kuchen:20220218235722p:plain

(Microchip DataSheet DS39931Dより)


USBのD-、D+端子もプルアップされるはずなのに、0.5Vぐらいの電圧が出て(多分浮遊電圧か)いているという状況です。

解決しないまま、FFTの高速化のため、この48MHzが使えるんじゃないかと思って、設定を変えてみたことがきっかけで原因が分りました。

f:id:Baum_kuchen:20220219000051p:plain(Microchip DataSheet DS39931Dより)

 

48MHzは、CPDIVで2分周して24MHzを使うことになりますが、その後の切替スイッチのところにある注記(4)です。

f:id:Baum_kuchen:20220219000349p:plain

このスイッチをPrimary Clock側にしないとUSBは動かないってあります!なんと。

でも、USBのクロックとCPUのクロックって別でいいと思うじゃないですか。
で、その通り設定してみたら、ちゃんとD-,D+端子もプルアップされるし、USBENは1になって、PCに刺すとちゃんと認識してくれました。まずは、第一段階クリアです。

ただ、残念ながら、PCのデバイス認識としてはエラーが出ているので、まだ完全ではないですが、ハード的にはつながった様です。

副作用として、FFTの処理速度は3倍になりました。また、消費電流も大幅増加。

なので、結論としては、通常作動とUSB接続状態でクロックを可変とする必要があるため、USB接続の判別ハードは必要ということも分かりました。

 

今後の計画

原因が分かって、がっくりと言う感じですが、要は”マニュアルをしっかり読め”ということに尽きるんですかね。

USBのソフトは完全にできてませんが、目途が立ったということで、電池寿命延長のための消費電流低減について、いくつかトライアルをしてみます。

まだ、完成までいろいろありますが、よろしかった、お付き合い願います。

バイオリンタイマーの製作#12-ハード改善(USB回り+α)

ソフトウエアも大体形になって来て、改善すべき事項は大体把握できたので、ハード回りで残っていたUSBコネクタの実装と、いままで気づいたハードの改善点を盛り込みます。

baum-kuchen.hatenablog.com

USBコネクタの実装

マイクロUSB端子に、ピンヘッダを付けて、デバッグ時に分解し易い様に工夫。

f:id:Baum_kuchen:20220215205345j:plain

ケースに装着したところ。

f:id:Baum_kuchen:20220215205406j:plain

ピンヘッダからの配線(写真は仮配線)もしてみた所。かなり、きつきつになってしましましたが、ちゃんと裏蓋もしまるので、これが、ハードの完成形になります。

ちなみに、USBのソフトはなぜか動きません(CDCデバイスとして認識せず。)

f:id:Baum_kuchen:20220215235334j:plain

USBコネクタへの配線が仮なのは、USB接続の判定用の回路を追加するか否かで迷っているためです。PICマニュアルによれば推奨回路としての記述があり、一方、MLA*1のUSB用サンプルプログラムのコメントには、なくても動くような記述があるし。ただ、実際にUSBソフトが動いていない状態なので、判断できないでいます。

ADCアンチエイリアシングフィルタ変更

ADCのサンプリングを3000Hzとした事で、アンプのカットオフ周波数を見直します。今は、1MΩ・100pFで、約1590Hzですが、さすがにエイリアシング周波数と同じという訳にも行かないで、手持ちの部品と相談して、1MΩ・220pFで、約720Hzとしました。エイリアンシング周波数で、約6dBと未だ減衰は少ないですが仕方ないです。2次フィルタにするにも実装スペースがないので。

720Hz、3Vppの信号を入れた結果です。理論上は、2.1Vppの出力(グラフ上は3.8DIV)になるはずですが、大体のところはあっているので、これで良しとします。

f:id:Baum_kuchen:20220215232239j:plain

ちなみ、1440Hz信号のサンプリングでは、エイリアシングの影響が出ています。振幅が大きくなったり、小さくなったりしてます。

f:id:Baum_kuchen:20220215235031j:plain

LCD輝度調整用抵抗の変更

テスト中もバッテリーで動作させてますが、意外と消耗が速いです。現時点での消費電流を測って見ました。消費電流の多くを占めるLCDのバックライトLEDも個別に測りました。やはり、LEDの消費は大きいです。消灯時の小電力化は、別途考えるとしても最低輝度のところを手当てします。

f:id:Baum_kuchen:20220215211658p:plain

f:id:Baum_kuchen:20220215211724p:plain

過電圧で壊してしまったLCDを実験台としてどの位の輝度が有れば良いかを確認したところ、半分の2mA以下でも、室内で有れば見える事が確認出来たので、PIC出力で約2mA程度になる様に100Ω抵抗を220Ωに変えるとこにしました。

f:id:Baum_kuchen:20220215211747p:plain

見た目は、写真では、ほぼ分からないので、消費電流の測定結果です。Dim時のLEDバックライト電流が2.6mAに低減しました。副作用として、見た目、MiddleとBrightの差が余り無くなった感じです。

f:id:Baum_kuchen:20220216010353p:plain

ちなみに、これで、平日1時間、土日3時間練習とし、表示以外のスタンバイ時は電流を1mAに抑えるとしても、20日しか電池が持たない試算になりました(750mAhの電池を使っても)。それも、スタンバイ電流の1mAが全体の約半分を占める結果となり、LEDバックライト電流の低減の効果は限定的です。

これは、あくまで試算なので、それぞれの状態で消費電流が少ないことは決して無駄ではないでしょう。また、スタンバイ時の電流低減は、いろいろ手があるようですが、もう少し後に回して考えていきます。

省電力化ノウハウ

http://www.picfun.com/lowpower/lowpowerframe.html

 

バッテリ残量表示用ハード追加

消費電流のこともあり、単四Ni-MH電池×2の出力電圧(公称2.4V)を計測し、バッテリ残量の表示ができるようにします。IOは、RA3がデバッグ用にとってあったので、ここに入力して表示します。

とりあえず、テスト用に作ったデバッグ画面で電圧を確認できるようにしました。3行めのBAT:がそれで、充電したてなので、2.65Vもあります。

f:id:Baum_kuchen:20220216012215j:plain

最終的な回路図

USB回りはまだ予定のところがありますが、現時点における最終回路図です。USB回りを少しいじっていますので、以前のものとLED電源供給が変っています。これは、USB接続検出を5V入力可能なPC6に変更したためです。

f:id:Baum_kuchen:20220216003619p:plain

今後の計画

今回はここまで。一番の課題は、使うかどうかもまだ決めていないUSBのソフト。次いで、電池寿命延長のための消費電流低減、本体機能の練習時間積算タイマーも、一旦、使える形に仕上げて行きます。できたら、FFTのさらなる高速化もです。

まだ、完成までいろいろありますが、よろしかった、お付き合い願います。

*1:Microchip Libraries for Applications v2017-03-06