PIC32MXで長時間タイマーを作る(1)

こんにちは。お久しぶりです。

今回はMicrochip社製の32bitマイコンPIC32MX250F128Bを使用して1時間や12時間といった長時間タイマーを作製しようとしました。
負荷を12時間おきにON,OFFしたいというのが目標です。それとなるべくコストをカットすること。
主に備忘録。

ということで、開発環境はMPLAB XとMPLAB Harmonyを使用しました。またデバッカはPICKIT3を使用しました。
また回路エディタはKiCadです。
インストールとプロジェクトファイルの作り方、基本操作は以下のページが分かりやすかったです。
http://www.ys-labo.com/MPLAB%20Harmony/2016/Led%20FreeRun-NOP%20sum.html

今回の大まかな流れです。
1.MPLAB Harmonyプロジェクトを作成し、各種設定を行う。
2.app.cとsystem_interrupt.cにプログラムを追加する。
3.ブレッドボードで試作。
今回はここまで----------------------------------------------------
4.基板設計。
5.フリー基板に実装。
6.Elecrowに発注。


1.MPLAB Harmonyプロジェクトを作成し、各種設定を行う
と、その前に簡単な仕様を決める必要がありますね。
長時間をマイコンでカウントする方法としては
マイコンのシステムクロックを使用したタイマー機能
・外部クロックを用いたRTC
辺りが一般的だと思います。
精度をもっと求める場合は
GPSモジュールの1sパルスをカウントする
・インターネットに接続する(NTP)
が考えられますが、今回はGPSもNTPも使用しません。
よってタイマーモジュールを使うか、RTCを使うかの二択となりましたが、今回実装部品を減らしたいのでマイコンは内部発振及び内部PLLをシステムクロックとしますので、
発振精度が悪いです。そのためカウントをし続けると誤差がどんどん蓄積され、まともな値となりません。

そのため今回は32.768kHzの水晶発振器を外付けし、PICに内蔵されているRTCモジュールを動作させることにしました。

そんなわけでMPLAB HarmonyのClock Diagramは以下のように設定しました。

f:id:TomoC:20200306112947j:plain
Clock Diagram1
f:id:TomoC:20200306112951j:plain
Clock Diagram2

OptionsではMPLAB Harmony&Application Configuration→Harmony Framework Configuration→System Service→RTCCの順に開き、以下のようにしました。

f:id:TomoC:20200306113234j:plain
RTCC設定

Pin SettingsとPin Diagramは次の通り。RTCCピンの設定と、GPIO_OUTを各一つ設定しました。

f:id:TomoC:20200306113412j:plain
Pin settings
f:id:TomoC:20200306113430j:plain
Pin Diagram


2.app.cとsystem_interrupt.cにプログラムを追加する。

Generate Codeボタンを押すとコードが自動的に作製されます。なんかいっぱい出てきますが、編集するのはSource Files→app.cとSource Files→System_config→Default→system_interrupt.cだけです。

ソースファイルが出てきたら、app.cに以下のコードを追加します。以下のページを参考にしました。変数名はそのページのまま使用しております。挿入箇所等もわかりやすく記されているため、
そちらを参照してください。
http://www.ys-labo.com/Shop/Referrence/PIC32MZ/1704/32MZ%20RTCC%20Time%20Alarm%20LCD%20sum.html
またデバックしやすいように12時間ではなく、RTCCアラームを1min、60回アラームを検出したらGPIO反転(60min)というプログラムにしてあります。
データシートを参照し、RTCALRMレジスタのAMASKビットを操作することで時間が変更できます。またそのアラームのカウント回数を変化させれば任意の時間が作製できるかと思います。

#include <stdio.h>
#include "app.h"
#include "peripheral/rtcc/plib_rtcc.h"

extern int AlarmOccurrence;

int date = 0x17022802;//date = 5 March 2017 Monday
int time= 0x23594500;//time = 23h59m45s

void APP_Initialize ( void )に追加

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;

    
    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
    //XXXbits.YY=ZZ //bits select
    PLIB_RTCC_RTCDateSet(RTCC_ID_0, date);  //Defalt set
    PLIB_RTCC_RTCTimeSet(RTCC_ID_0, time);  //Defalt set
    RTCCONbits.RTSECSEL =0b0;//RTCC Alarm Pulse output for the RTCC pin
    RTCALRMbits.ALRMEN  =0b1;//Alarm ON
    RTCALRMbits.CHIME   =0b1;//Alarm Kurikaesi
    //RTCALRMbits.PIV     =0b0;//RTCpin Output Defalt_0
    //RTCALRMbits.AMASK   =0b0101;//1h
    RTCALRMbits.AMASK   =0b0011;//1min
    RTCCONbits.CAL      =0b1111111010;//RTC calibration bits 1111111111=minimum negative djustment
    
    LATBbits.LATB2 = 1;//portB2出力 レジスタ直打ち
}

RTCCONbits.CALに関してはクロック補正用レジスタです。必要に応じて補正値を打ち込みます。1minごとにこのレジスタが読み込まれるそうです。
トライ&エラーで手打ち補正しました。

void APP_Tasks ( void )に追加

void APP_Tasks ( void )
{

    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            bool appInitialized = true;
       
        
            if (appInitialized)
            {
            
                appData.state = APP_STATE_SERVICE_TASKS;
            }
            break;
        }

        case APP_STATE_SERVICE_TASKS:
        {
            if(AlarmOccurrence == 1){
                Hour++;
                AlarmOccurrence = 0;
            }
            if(Hour == 60){
                LATBbits.LATB2 = 0;
            }
            if(Hour == 120){
                LATBbits.LATB2 = 1;
                Hour = 0;
            }
            
            break;
        }

        /* TODO: implement your application state machine.*/
        

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}

1hごとにGPIOピンを反転させるように設定しました。
編集が完了したら、プロジェクトをビルドし、エラーが出ないことを確認します。
これでプログラムの準備はOKです。

3.ブレッドボードで試作
適当にPICKIT3とPIC、水晶発振子そしてLEDをOUTPUTピンに接続し、準備完了です。MPLAB Xの書き込みボタンを押してPICへプログラムを書き込みます。
ここで回路にPICKIT3から電源を供給するように設定ができます。必要であれば画面左下のDashboardウインドウの左上のスパナマークをクリック→出てきたウインドウ左上のPICKIT3→Option categories
→Powerの順に操作し、Power target circuit form PICKit3にチェック、電圧は3.25Vに設定しておけば大丈夫です。
必要に応じて設定します。
書き込み時にターゲットデバイスが見つかりません!とういエラーは配線ミスか、電源供給がされておらず、PICの電源が入っていないことのどちらかが多いように思います。

RTCCピンは指定した時間でHighとLowを繰り返すように設定しました。GPIO_OUTに設定したピンはRTCCのアラーム割込みが60回発生するとピンを反転させるよう設定しました。
これが思った通り動いているか、時間に大きなずれが無いかを確認します。

僕はスマホのタイマーで適当に時間を測定し、ズレていたら1カウントずつCALレジスタを加算/減算し、再度PICに書き込みました。
結果ブレッドボード上では12時間で5秒ほどのズレまで追い込むことが出来ました。
これは基板に実装した場合また変化する可能性があるので、大体で良いと思います。

次回は基板を設計してElecrowへ投げるところまでを書こうと思います。
 

mbedでとりあえずパルス幅計測

こんにちは。

今回はARMのmbedとnucleo F303K8を用いて精度をあまり求めない場合に使用できる、パルス幅測定をしようと思います。

 
使用するモジュールはTimerとInterruptInです。

Timerはこちらを参照してください。
Timer - タイマー時間 | Mbed


InterruptInはピン変化割込みです。こちらを参照してください。
InterruptIn - ピン変化割込み | Mbed


今回想定したパルスは、サーボ信号です。周波数約70Hz、パルスオン幅1500us から 2500us程です。
mbedでは今回のパルスオン幅ではタイマーのオーバーフローを意識しなくとも、コンパイラが勝手に処理して正常な値を返してくれます。(便利すぎる)

以下に割込み処理のコードのみを示します。実際使用する際はご自身でmain関数を書いてください。動作は簡単で、パルスが立ち上がったらタイマースタート、立ち下がったらタイマーストップし、タイマーの値を変数に代入するといった形です。
flip_rise→InterruptIn risng edge mode
flip_fall→InterruptIn falling edge mode
captime→変数
flag→変数

void flip_rise(){             //risng edge interrupt
    t.start();                   //Timer Start
    flag = 0;
    }
    
void flip_fall(){           //falling edge interrupt
    t.stop();                //Timer Stop
    captime = t.read_us();  //captime = pulse on time[us] ,captimeはグローバル変数(任意の変数)
    t.reset();              //reset Timer
    flag = 1;
    }

実際にはタイマーをスタート/ストップするラグがありますので、正確なパルスオン幅が読み取れるわけではないです。しかしパルスオン幅に応じてDCブラシモーターをPWM制御したいといった程度ならば問題ないレベルになります。
適当にggってもそれらしき記事が無かった(このくらい自分で考えつくということでしょうかw)のでノリで作りました。


 

トランジスタやFET等のデータシートにある図

こんにちは。

今回は私がなぜか引っかかってしまったデータシートの図に潜む罠(?)をお伝えしたいと思います。

まずこちらを見てください。

           f:id:TomoC:20180310002755j:plain

http://akizukidenshi.com/download/2sc1815-gr.pdf

にある、2SC1815のデータシートにある図です。これの下の図(足に1,2,3と番号がふってある方)を見てください。これ、上から見た図か、下から見た図か、わかりにくくないですか・・?私はわかりませんでした()

それで普段使用する回路CADは大体が上から見た図を使用して作業を行います。そのためデータシートの図も上から見た図でしょ!と勝手に思い込んでいました。

しかし図を見ると、トランジスタの足の位置が示されています。つまり足が見える方から見ている、よって下側(ボトム側)から見た図なのです!

いや~私はこれに気が付かなくて、結構逆接してしまったことがありました。図の見方は大事ですね・・・

 

トランジスタアレイについて

なんだかんだで便利であろうトランジスタアレイの使い方でも書こうと思いましたハイ

 

今回はTOSHIBAのTD62783とTD62083を例に基本的な使い方を考えていきます。

トランジスタアレイは二つ種類がありまして、シンクドライバとソースドライバというやつですね。まぁ、意味合いとしては引き込むか、取り出すかという感じです。詳細は使用方法を見ればわかると思います。いわゆるトランジスタでいう、P型かN型かというような感じです。

 

まず必要なのはなんといってもデータシートですね。これは秋月電子で検索するとすぐに出てきます。なぜ沢山あるトランジスタアレイからこれを選んだかって?気分です・・

 

さて、データシートを眺めると特徴やら最大定格やら色々出てきますが、これは今回は後回しにします。なにせトランジスタアレイを使おうとして真っ先に引っかかった記述があり、先にこれを紹介したいからです。以下の画像はデータシートから切り抜きました。

f:id:TomoC:20180302211141j:plainf:id:TomoC:20180302211145j:plain

TD62083はシンクドライバ、TD62783はソースドライバです。

ぱっと見、なんや!ただのNOT回路やんけ!!これは電流の取れるロジックICみたいなもんやな!!!とか思いませんか???

僕は思いました()

しかしデータシートの次のページにこんなのが載っています。(画像は見ずらいと思うのでデータシートを参照してくださいすいません)

f:id:TomoC:20180302211549j:plainf:id:TomoC:20180302211552j:plain

基本回路が載っているわけですが、つまりトランジスタアレイはトランジスタ回路なのです!(点線で示されているダイオードはICを作製する過程でできてしまう寄生ダイオードです)

接続の方法もロジックICと同じではありません。

それをやって動かなかったのは僕です!良い子のみんなはマネシナイデネ

まずTD62083のシンクドライバについて考えてみます。

基本回路のOutputの位置に注目するとTD62083のシンクドライバは最終段のトランジスタのコレクタについています。これはオープンコレクタとみることができます。オープンコレクタとは、トランジスタのコレクタが外部ピンとして取り出されていて、トランジスタがON/OFFするとそのピンは電流を吸い取ったり、電流を遮断したりする挙動をするものを指します。

          f:id:TomoC:20180302223025j:plain

つまりこんな感じです。コレクタピンに抵抗R1を外付けすると、Inputに対して反転した信号がOutputから得られることがわかると思います。また、この回路はn型トランジスタのエミッタ接地増幅回路ですので、トランジスタQ1の能力分電流を流すことができます。よってR1の位置にある負荷を駆動することもできます。この回路が8つ入ったICがTD62083、シンクドライバです。電流を引き込んでいくのでシンク(流し台)のようだということらしいです。実際の回路として、TOSHIBAのアプリケーションノートから抜粋した図がこちらです。

        f:id:TomoC:20180302221325j:plain

シンクドライバは以上です。

次はソースドライバです。最終段のみだとこんな感じです。負荷はOutputとGNDの間に挿入します。こちらはエミッタフォロワみたいですね。こちらはInputの信号が反転しません。また電流も先ほどと同じく流すことができます。

           f:id:TomoC:20180302224251j:plain

では応用回路です。シンクドライバとは負荷の位置が逆です。

        f:id:TomoC:20180302221321j:plain

TOSHIBAのアプリケーションノートから抜粋しました。このように接続します。

 

トランジスタアレイには入力電流制限抵抗が内臓されていますのでマイコン等を接続する際は直結で問題ありません。(入力電圧5Vで入力電流約0.2mA)

 

次に使用する際にはもちろんデータシートを読み、定格を超えないように使用する必要があります。データシートには最大電流500mA/chと記載がありますが、どの条件においても全chに500mA連続で流せるわけではありません。連続で流せる電流値は許容損失も兼ねて考えなければICが燃えます。

 

損失は今回のICの場合8ch入りですから全てのchを合計した値が必要です。

 

また、データシートに記載されている許容損失をフルに使うとICが加熱してきます。そのため損失は大きく余裕を持った設計をする必要があります。

 

ぶちゃけLED8個とかなら全く問題ありませんからそのくらいの負荷なら適当で(ry

 

それではまた。

 

 

参考

アプリケーションノート | 東芝 半導体&ストレージ製品

http://akizukidenshi.com/download/ds/toshiba/TD62783AP_TD62783F_TD62783AF_TD62784AP_TD62784F_TD62784AF.pdf

http://akizukidenshi.com/download/ds/toshiba/TD62083APG.pdf