PIC24FでUARTのDMA転送

やりたいこと

PIC24FでUARTの送受信をDMA転送をします。開発環境はMPLABで、MCC (MPLAB Code Configurator) によるコード生成を用います。

MCCでUARTの設定

まず、MCCでUARTの設定します。MCCはUIがゴチャゴチャして分かりにくいツールなので、大きいモニタで作業したほうが良いです。ノートPCだとつらいです。直感的でないUIなので、使い方は「MPLAB Code Configurator v3.xx ユーザガイド」を読んで確認しましょう。

ここではUART3を用いるものとします。Easy Setupで設定します。

  • Enable UART にチェック。
  • Baud Rate, Parity, Data Bits, Stop Bits, Flow Controlを適宜設定します。
  • Enable UART Interrupts はチェックしません。 ←ここポイント
  • Redirect Printf to UART はチェックしません。

あと、ピン割り当てもMCCで別途設定します。ここでは説明を省略します。

MCCでDMAの設定

続いてDMAもMCCで設定します。ここではChannel 0を送信に、Channel 1を受信に割り当てます。こちらもEasy Setupで設定します。

  • Enable DMA にチェック。
  • Low Address Limit, High Address Limitは0x800, 0xFFFFのままでもOK。
Channel 0 (送信用)の設定
  • Enable Channel 0 をチェック。
  • Enable Reloadはチェックしない。
  • Transfer Mode は One Shot を選択。 ←ここポイント
  • Trigger Source は UART3 TX を選択。
  • Source Address Mode は Incremented を選択。
  • Destination Address Mode は Unchanged を選択。
  • Source Address, Destination Address, Transfer Count はここでは0のままにしておく。
  • Data Size は 8bit を選択。 ←ここポイント
Channel 1 (受信用)の設定
  • Enable Channel 1 をチェック。
  • Enable Reloadはチェックしない。
  • Transfer Mode は One Shot を選択。 ←ここポイント
  • Trigger Source は UART3 RX を選択。
  • Source Address Mode は Unchanged を選択。
  • Destination Address Mode は Incremented を選択。
  • Source Address, Destination Address, Transfer Count はここでは0のままにしておく。
  • Data Size は 8bit を選択。 ←ここポイント

設定が終われば「Generate」ボタンを押してコードを生成します。

初期化処理

UAR3とDMAの初期化は、UART3_Initialize() と DMA_Initialize() ですが、これらは SYSTEM_Initialize() の中で呼ばれます。

送信処理

ここでは特にDMA割り込みは使用せず、送信完了、送信バイト数はポーリングすることにします。

static uint16_t s_sendSize; // 送信サイズをおぼえておく

// 送信開始
// data: 送信データ
// size: 送信サイズ
void Uart_send(uint8_t *data, uint16_t size)
{
    s_sendSize = size;
    
    // UART送信いったん無効
    U3STAbits.UTXEN = 0; 
    // DMAチャンネルをいったん無効
    DMA_ChannelDisable(DMA_CHANNEL_0);
    // 転送サイズ、転送元 (メモリ)、転送先 (UART)の設定
    DMA_TransferCountSet(DMA_CHANNEL_0, size);
    DMA_SourceAddressSet(DMA_CHANNEL_0, (uint16_t)data);
    DMA_DestinationAddressSet(DMA_CHANNEL_0, (uint16_t)&U3TXREG);
    // DMAチャンネルを有効
    DMA_ChannelEnable(DMA_CHANNEL_0);
    // UART送信を有効(送信開始)
    U3STAbits.UTXEN = 1; 
}

// 送信完了したか?
bool Uart_sendComplete(void)
{
    return DMA_IsOperationDone(DMA_CHANNEL_0);
}

// 送信したデータサイズ
uint16_t Uart_sendSize(void)
{
    // 送信したサイズ = 送信すべきサイズ - 残りサイズ
    uint16_t size = s_sendSize - DMA_TransferCountGet(DMA_CHANNEL_0);
    return size;
}

受信処理

ここでは特にDMA割り込みは使用せず、受信バイト数はポーリングすることにします。

static uint16_t s_recvSize; // 受信サイズをおぼえておく

// 受信開始
// data: 受信データの格納先
// size: 受信最大サイズ
void Uart_recv(uint8_t *data, uint16_t size)
{
    s_recvSize = size;
    
    // DMAチャンネルをいったん無効
    DMA_ChannelDisable(DMA_CHANNEL_1);
    // UART受信バッファオーバーランクリア
    U3STAbits.OERR = 0;
    // UART受信バッファ読み捨て
    volatile uint16_t rx = U3RXREG; rx = U3RXREG; rx = U3RXREG; rx = U3RXREG;
    // 転送サイズ、転送元 (UART)、転送先 (メモリ)の設定
    DMA_TransferCountSet(DMA_CHANNEL_1, size);
    DMA_SourceAddressSet(DMA_CHANNEL_1, (uint16_t)&U3RXREG);
    DMA_DestinationAddressSet(DMA_CHANNEL_1, (uint16_t)data);
    // DMAチャンネルを有効
    DMA_ChannelEnable(DMA_CHANNEL_1);
}

// 受信したデータサイズ
uint16_t Uart_recvSize(void)
{
    // 受信したサイズ = 受信最大サイズ - 残りサイズ
    uint16_t size = s_recvSize - DMA_TransferCountGet(DMA_CHANNEL_1);
    return size;
}

メモ:ESP32のOTA

ESP32でOTA(Over The Air)、つまり無線経由のプログラム書き込みは下記の記事が詳しい。

lang-ship.com

そもそもOTAの動機としては大きく二通りがある。

  1. 開発時のプログラム書き込みの便宜のため
  2. 運用時のプログラム更新の便宜のため

1.の目的に適しているのがArduinoOTA方式であり、2.の目的に適しているのがUpdate方式である。

そしてArduinoOTA方式のもっとも基本的なサンプルコード(スケッチ例)が BasicOTA である。ArduinoOTAに対応する場合には、このスケッチを参考にしてスケッチにArduinoOTA機能を抱き込めばよい。ArduinoOTAに対応したスケッチを実行しているESP32デバイスがローカルエリア内に存在するとき、Arduino IDEからシリアルポートのかわりにESP32デバイスのホスト名を選択できるようになり、プログラムの書き込みができる。

6月のまとめ

進捗

  • SOEMのchipKIT Max32対応
  • SOEMのNucleo-F446RE対応
  • ミニ四駆ラジコンのRumiCar化 / GPduinoによるRumiCar製作
  • マイRumiCar試走会@大阪 開催

イベント等

動画


所感

今月は、SOEMの移植に一区切りをつけ、RumiCarという新しいテーマに取り組みはじめた。今月の成果物は少なめだが、RumiCarは今後の展開が楽しくなりそうな予感。

RumiCar用簡易コースの壁の作り方

先日のRumiCar試走会の大阪会場で設営した簡易コースの壁の作り方を紹介します。

  • 材料のやすさ
  • 作りやすさ
  • 設営しやすさ
  • 持ち運びやすさ

がモットーです。

f:id:licheng:20200624203905j:plain:w480

(1) 材料

工作用紙

100円ショップなどで売ってる30cm×40cmの方眼入りのボール紙です。ダイソーだと5枚入りで100円です。
f:id:licheng:20200624200226j:plain:w480

塩ビアングル (20mm×20mm)

ホームセンターなどで売ってる塩化ビニル(PVC)のアングル材です。20mm×20mmのものがちょうどよいでしょう。長さ1メートルで1本160円ほどです。
f:id:licheng:20200619163145j:plain:w480

両面テープ

15mm幅で薄手のものが良いでしょう。
f:id:licheng:20200623201909j:plain

マスキングテープ

設営に使います。養生テープだと工作用紙から剥がしにくいのでマスキングテープのほうが良いです。
f:id:licheng:20200623201959j:plain

(2) 作り方

工作用紙を切る

短手方向 (30cmの方向) に幅5cmの短冊状に切っていきます。工作用紙は5cmごとに太い線が入っているのでこれに合わせると切りやすいでしょう。大量に切る必要がありますが、気を抜いてケガをしないように注意しましょう。
f:id:licheng:20200623202352j:plain:w480

アングルを切る

アングルも幅5cmに切っていきます。そんなにきれいに切る必要はないので、電工ニッパーで切ります。(まちがっても精密ニッパーを使わないように。) 一度には切れないので、いったん歯形を入れておいて隅からチョビチョビ切っていきます。歯形を入れるのにけっこう握力が要ります。作り方に改善の余地ありかも?
f:id:licheng:20200623204205j:plain:w320
f:id:licheng:20200623204226j:plain:w320
f:id:licheng:20200623204246j:plain:w320
f:id:licheng:20200623204302j:plain:w320

f:id:licheng:20200624075359j:plain:w320

アングルを工作用紙に貼る

両面テープでアングルを工作用紙に貼ります。工作用紙の方眼に合わせるとよいでしょう。
f:id:licheng:20200623202635j:plain:w480

(3) 設営

マスキングテープで床に固定したり、となりの壁とつないだりします。曲線にも対応できます。簡単に剥がせて簡単に組み替えることができます。
f:id:licheng:20200624203905j:plain:w480

(4) 持ち運び

重ねて輪ゴムでしばればこの通り。持ち運ぶにも大荷物になりません。
f:id:licheng:20200624075712j:plain:w480

マイRumiCar試走会@大阪 レポート

RumiCar試走会東西同時開催

6月20日に関東で開催されたマイRumiCar試走会に合わせ、大阪の本町デジもく会でもRumiCar試走会を開催しました。オンラインで東西両会場の様子をお互いに中継し、とても楽しい試走会となりました。

関東会場に比べ小さなコースながら、大阪会場には製作途中のものも含めユニークなマシンがたくさん集結しました。(なんかぜんぜんRumiCar関係ないのも混ざってますがw)

f:id:licheng:20200620164619j:plain:w560

大阪会場では最終的に3台のマシンでのレースとなりました。狭いコースなのでコーナーで詰まって切り返しが多発するのはご愛嬌。

関東会場の様子はこちら↓

大阪会場のユニークなマシンの数々

@InatamaSさんのミニ四駆。ステアリングはありませんが、ガチのモータ制御にプロのコダワリを感じます。ミニ四駆らしく乾電池2本で動くのも素晴らしい。マイコンはM5Stick-Cで、モータドライバ基板は独自設計です (→こちらの資料)。

f:id:licheng:20200620142154j:plain:w560

@nakkyiさんが開発中のラズパイカーとobnizカー。ベース車両はダイソーの600円ラジコンですが、ステアリングをサーボに改造されてます (→こちらの記事)。今後の展開が楽しみです。

f:id:licheng:20200620143243j:plain:w560
f:id:licheng:20200620143340j:plain:w560

@igiyさんが今回の試走会のために急遽作ってくれたマシン。電装系は標準的なRumiCarですが、さすがに車がデカすぎやろw

f:id:licheng:20200620141339j:plain:w560

私が昔作ったミニ四駆ラジコンのRumiCar化と、今回作った1/32 GT-RベースのRumiCar。ともに回路は標準的なRumiCarのものではなく、昔作ったミニ四駆ラジコンの基板を流用してます。

f:id:licheng:20200621154631j:plain:w560

RumiCarではありませんが、同様に距離センサで壁をよけて進むキャタビラロボット。これも@nakkyiさんのです。マイコンIchigoJamですね。センサの位置が高すぎて残念ながらRumiCarのコースでは走れませんでした。

f:id:licheng:20200620151023j:plain:w560

RumiCar関係ないですが、筋電車椅子でおなじみの@naranaviさんの車椅子ラジコン。小型ギヤードモータによる対向二輪駆動でスマホからコントロールできます。ベース車両はギルティクラウン篠宮綾瀬の車椅子だそうですw

f:id:licheng:20200620150719j:plain:w560

今後の展開

今回は関西では初めての試みでコースも小さく、周回できたマシンも3台のみでしたが、これは面白くなりそうという手ごたえを感じました。本町デジもく会では今後もRumiCarに取り組んでいきたいと思ってますし、次回はもっと広いコースでやりたいなと思います。

PSoC Creatorの .gitignore

*.cywrk.*
*.cydsn/codegentemp/
*.cydsn/CortexM0p/
*.cydsn/CortexM3/
*.cydsn/CortexM4/
*.cydsn/Export/
*.cydsn/Generated_Source/
*.cydsn/*.cyprj.*
*.cydsn/*.cycdx
*.cydsn/*.cyfit
*.cydsn/*.rpt
*.cydsn/*.svd
*.cydsn/*_datasheet.pdf
*.cydsn/*_timing.html
*.cydsn/*.log