2015年03月07日

dsPIC内部プルアップ

先日、ある試作機を作る際に遭遇したトラブルについて、
解決方法をご紹介します。


試作機の概要としてはdsPICのUARTモジュールで数MHzの高速通信をさせ、
RS485ドライバを介してデバイスと通信するものです。


遭遇した問題はUARTの受信がなかなか安定しないということです。
低速なUARTではこのような問題に遭遇したことがありませんでした。



時々、全く通信ができなかったり(受信割り込みが発生しない)、
通信できても、意図しないデータも一緒に受信したりという状況でした。


RS485とdsPICの間にオシロで計測すると、
波形には問題なく、通信も安定するという状況でした。


RS485ドライバは半二重通信なので送信モードと受信モードの切り替えに
問題があるのか、受信バッファ処理に問題があるのかなど色々検討しました。




結論は、UARTのdsPICの入力ポートの電圧が不安定だったようです。
オシロをつなぐと、プローブの微小なキャパシタンスで安定したようです。
電圧が不安定なため、ノイズの影響をもろに受けているようです。




対策は、
RS485のRO受信ポートからdsPICのUART入力ポートへ直接つないでいる
配線に対してプルアップ抵抗を間に入れました。


追加回路を作成するのは面倒なため、
dsPICのメインプログラム内で内部プルアップを有効にさせました。


dsPICリセット時のデフォルトではCN**ピンの内部プルアップは
すべて無効になっています。
CNPU1=0x0000;
CNPU2=0x0000;



今回、UARTの送受信ポートはRB10,11のため、
ピンアサイン図からCN15,16に該当します。



CN15,16の内部プルアップを有効にさせるため、
下記のように変更しました。
CNPU1=0x8000;
CNPU2=0x0001;




内部プルアップは外付けでプルアップさせるよりも、
弱いプルアップとなっていますが、
今回内部プルアップを有効にさせるだけで
遥かにUARTの通信が安定するようになりました。



内部プルアップ恐るべし。




内部プルアップを有効にすると、
スイッチ入力を使用する際の回路の簡素化にも貢献できます。
スイッチ入力の際に入力ポートに直接スイッチを接続し、
一方をGNDに落として、内部プルアップでプルアップさせれば、
入力ポート部分の抵抗やVDDなどのプルアップ回路が不要になります。


ぜひ、内部プルアップを活用してみてください。
posted by Crescent at 00:00| Comment(0) | TrackBack(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2015年02月19日

dsPIC33FでのI2C LCD初期化トラブル

dsPIC33FJ64GP802で不思議な事象に遭遇したため、メモ書き。


マイコンのデータ表示に使うLCDで秋月やaitendoで販売されているI2C接続のものをよく使用しています。


LCDの価格に差がなく、4ビットや8ビットピンを配置する必要がなく、配線が楽だからです。


好んで使用しているのは
ACM1602NI-FLW-FBW-M01
です。

白い綺麗なバックライトが特徴で他の省エネ薄型I2CのLCDに比べ、
プルアップ抵抗の制限を受けない感じです。

省エネ薄型I2CのLCDはI2Cの駆動電流が少なく、
プルアップ抵抗が小さくても大きくてもうまく通信できない感じがします。
特にスレーブのデバイスを複数繋げるとプルアップ抵抗の制限が顕著でした。






今回はI2CのLCDでdsPIC30FやPIC16F等で使用していたライブラリを
dsPIC33F用に少し修正して利用しようとしたところ、あるトラブルに遭遇しました。


プログラムとしては、
main関数内で
クロックの設定やポートの設定の後、
I2Cモジュールの初期化を行い、
LCDの初期化という流れです。



dsPIC30FやPIC16F等でも使えていたにも関わらず、
うまくLCDの初期化ができないという問題に遭遇しました。


オシロで波形を見るとI2Cのデータやクロックが出ているようですが、
うまく初期化ができていないようです。


送信やACKのタイミングなど調整してみましたが、
うまくいかず・・・



結局、
ポートの初期化の際にI2CでSDAとして使用するRB9を
"input"として初期化するとうまくいきました。


つまり、
TRISB=0b0000000000000000;
から
TRISB=0b0000001000000000;
にすると解決。


データシートにはI2Cモジュール有効と共にIOの設定が上書きされるとありましたが、
他の何かが悪さしているのか上書きされなかったようです。
それでLCDからのACKが無視されてしまったようです。

タイミングが変わるのか、IO設定が上手くいっていないのか、
真因は不明ですが、同じような事象で苦労している方に役立てればと思います。
posted by Crescent at 00:00| Comment(0) | TrackBack(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2015年01月27日

PICマイコンデバッグ裏技

今回はPICマイコンでデバッグする際に役立つ裏技?をご紹介します。

デバッグの方法としてデバッガー使ったり、LEDで確認したり、
LCDを接続して表示させたり・・・


ご存じな方もいらっしゃると思いますが、
おススメな方法としてマイコンでもprintfでデバッグです。


PIC16FやdsPICで簡単にprintfが使えてしまいます。
といってもデフォルトではマイコンに画面なんてありません。
画面の代わりにUartとして出力されます。







メモリを多く消費してしまうという問題点はありますが、
Uartの初期化だけ済ませればそのままprintfが使えます。


また、秋月やaitendoでUart<->USB変換モジュールがあるため、
そのままUartをRS232Cの電圧レベルに変換なしにTTLレベルで変換できます。


USB-UART変換モジュール [USB2UART-CP2102]
http://www.aitendo.com/product/2890




マイコンのUARTのTXをUSB変換モジュールのRXに接続。
またGNDを接続すればケーブル2本でパソコンに接続できます。

パソコン側にはTeraTerm等のターミナルソフトを用いて表示させます。


debug_image_tt.jpg
実際にプロジェクションボールのマイコン処理情報をPC上に表示させた例

Uartの表示が通信として間に合うように0.2秒ごとに
割り込みを入れて必要な情報を表示させています。


マイコン側とパソコン側でボーレートを合わせる必要がありますが、
初期化だけで簡単にprintfが使えるのはなかなか便利です。



以下に参考プログラム例を示します。

_____________________________
PIC16等の8bitPICの場合
_____________________________
//グローバル関数として宣言しておく
void putch(char data) {
while( ! TXIF) // check buffer
continue; // wait till ready
TXREG = data; // send data
}


//Main関数内で初期化する
    //Uart Initialize
    SYNC = 0;
    BRGH = 0;
    BRG16 = 0;
    SPBRG = 51;//ボーレートはマイコンのクロックに応じて変更

    //TXSTA
    CSRC = 1;
    TX9 = 0;
    TXEN = 1;
    SYNC = 0;
    BRGH = 0;

    //RCSTA

    SPEN = 1;    
    RX9 = 0;        
    SREN = 0;    
    CREN = 1;    
    ADDEN = 0;    
    
_____________________________
dsPIC30F等の16bitPICの場合
_____________________________

//UART 初期化 Main関数の初期化時にinit_uart()を実行させる
 void init_uart(void)
{
 
 unsigned int config1 = UART_EN & UART_IDLE_CON & 0xFFE7 & UART_NO_PAR_8BIT & UART_1STOPBIT
                     & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD;
 
 unsigned int config2 = UART_INT_TX_BUF_EMPTY & UART_TX_PIN_NORMAL & UART_TX_ENABLE & UART_INT_RX_CHAR
                     & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
 
//ボーレートはマイコンのクロックに応じて変更
 OpenUART1(config1,config2,191);
}

_____________________________
dsPIC33F等の16bitPICの場合(ピン配置の設定を追加)
_____________________________

 //UART 初期化 Main関数の初期化時にinit_uart()を実行させる
 void init_uart(void)
{
 
 unsigned int config1 = UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE & UART_MODE_FLOW &
 UART_UEN_00 & UART_DIS_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD &
 UART_UXRX_IDLE_ONE & UART_BRGH_SIXTEEN & UART_NO_PAR_8BIT & UART_1STOPBIT;
 
 unsigned int config2 = UART_INT_TX & UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED &
 UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR;
 

    //UART1の設定    PIC33FのI/Oピン割付 初期化 割込設定
    TRISB = TRISB & 0xFF7F;//RB7-U1RX RB6-U1TX    
    RPINR18 = 7;// RP7をU1RXに設定 入力マップ
    RPOR3bits.RP6R = 3;// RP6をU1TXに設定 出力マップ
    //ボーレートはマイコンのクロックに応じて変更
    OpenUART1(config1,config2, 246);

 }

Crescentは上記のプログラムに対していかなる責任も負いません。
posted by Crescent at 00:00| Comment(0) | TrackBack(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2015年01月11日

PIC fgets関数


今回は大量のデータをマイコンに入れたい場合の手法をご紹介します。

マイコンでロギングする際にSDカードに情報を書き込む方法がよく使われています。

一方で座標情報やパラメータ設定など大量のデータを読み込みたい場合にも
SDカードを用いて実現することができます。

特にプロジェクションボールで用いる描画の座標情報や
ロボット等のパラメータ情報をそのままマイコンの変数に
1つ1つ代入するのは面倒なのでこの方法がおススメです。


SDカードを使えばPC上で入力したエクセルCSVファイルを
読み込んで簡単に変数に代入することが可能となります。


SDカードに書き込むロギングの情報がネット上にいくらでもありますが
逆のSDカードから読み込むという方法の情報が非常に少ないです。




C言語でファイル操作をしたことがあれば、fgetcやfgets関数はお馴染みなはず。
ここで問題なのはマイクロチップから配布されているSD書き込みMDDFileSystem
スタックにはfread関数と同じ動きをするFSfread関数、fwrite関数と同じ動きをする
FSfwrite関数はありますが、fgetcやfgets関数がないということです。

PICで使用可能なfgetcやfgets関数を作ったのでご紹介します。
既に先人で公開されている方http://www.freeml.com/bl/9519095/55560/がおられましたが、
一部コードが化けていたため、再度作りなおしてみました。


以下に参考としてソースを記述。
char *FSfgets(volatile char *s,volatile int n,FSFILE * stream){
          char *const head = s;        // 先頭ポインタを保存
          for (; n > 1; n--) {

             int c =FSfgetc(stream);    // 1文字入力
             if(c == EOF)break;
                *s = c;                    // 配列に代入
                s++;                    // sを進める
             if (c == '\n')break;
          }
          // 入力失敗のとき
          if (s == head || FSerror()){
               return NULL;
        }
          *s = NULL;
          return head;
         //return s;
}

int FSfgetc(FSFILE *fp){
   volatile char c;
   if(FSfread(&c,1,1,fp) != 1){
            //while(1);
   }
   return (int)c;
}

コメントアウト部分は必要に応じて変更してください。


また、実際に以下のCSVデータをintで読み込む関数をご紹介します。
データ例
 1,23,34
 1,24,25
 1,25,26
    ・
    ・
    ・


以下に参考としてソースを記述。

void setpath(struct path* pR, char* str) {
    int i = 0;
    // 最初の","を探す
    char* pStr = strtok(&str[0], "\",\"");
    while (pStr) {
      switch (i) {
                 case 0:
                       pR->pow = atoi(pStr);
                       break;
         case 1:
                       pR->x = atoi(pStr);
                       break;
         case 2:
                       pR->y = atoi(pStr);
                       break;
                  default:
                       break;
               }
       i++;
            // ","を探す
            pStr = strtok(NULL, "\",\"");
            if (pStr == NULL ) {
              // ","がない場合、最後の"を探す
                pStr = strtok(NULL, "\"\n");
            }
        }
 
}

これらの関数を組み合わせることでCSVファイルからマイコン上の変数に代入できます。
ただ、最後に残る問題はマイコンのRAM容量が限られるため、
dsPIC33Fでもint型400個以上の変数だと容量オーバーしてコンパイルできないんです...
そこをどう回避するかが今後の課題かもしれません。
【ソースに間違い等あっても何もCrescentは責任は負いません】



posted by Crescent at 00:00| Comment(0) | TrackBack(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2015年01月05日

モータードライバ裏技

前回はおススメなモータドライバL298Nをご紹介しました。

今回はモータドライバ回路を作成する際の裏技?をご紹介します。



L298Nを使う際やモータドライバを自作する際に地味に面倒なのが

フライホイールダイオードの回路です。


MOSFETやトランジスタに内蔵している場合でも一応、

外付けでフライホイールダイオードを付けとく場合も多いと思います。


SBD_fixed.jpg

図はモータドライバからの出力回路の抜粋です。

1つのHブリッジに対して4つもダイオードが必要なためなかなか面倒です。



L298N_diode2.jpg

実際にチマチマ、ショットキーバリアダイオード(SBD)を

4つ付けた例(白枠に4つSBDがあります)


チップSBDだと場合によって半田にミスって短絡していることもしばしば...笑





そこで、今回おススメな裏技!!

【4つのフライホイールダイオードをダイオードブリッジ1つで代用!】

です。





回路をご覧ください。

L298N_diode3.jpg


先ほど示したHブリッジのスイッチング素子部分に4つダイオードを付ける場合と

回路が等価になります。



ダイオードブリッジの交流側をモータ出力の2端子へ接続。

一方の+をモータ電源のVCC、-をモータ電源のGNDに接続して使用します。


特に秋月ではSBDのダイオードブリッジも販売されているため、

そのまま置き換えが可能です。


ショットキーバリアダイオードブリッジ(60V2A) SDI260




値段の高いSBDを4つ必要な費用とチマチマ付ける手間を考えると、

ワンチップで済む安さと素晴らしさ!


知ってる人はなかなか少ないと思います。


これを思いついたとき、

モータドライバの回路パターンがかなり簡単になるので

自分でちょっと感動しちゃいました(*^^)
posted by Crescent at 00:00| Comment(2) | TrackBack(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする