当初かわロボ用にM5Stackを使うつもりで、そのメリットのひとつとしてSBUSを読んで従来の4chから10chに増やすことがありました(プロポも6EXから10J+SBUS受信器に)
しかしM5Stackを諦めた今、折角新しく買った10J+SBUS受信器が活かせないのは勿体無いので、従来のPIC24FでもなんとかSBUSを読めるようにする必要がありました(性能としてはほぼ上がらないけれど)
ネットでPIC24Fを使ってSBUSを読んでる人は見つけられなかったので、M5Stackで使ったArduino用のコードを参考に移植しましたが、多少ハマった所もあったので、参考までに末尾にソースコード載せておきます
一応累計で数時間以上試運転やら操縦練習してますが、SBUS関係が原因と思われる怪しい挙動はありませんでしたが、決して自信がある訳ではないので何かもっとスマートな方法があったら教えて下さいませ
先にM5Stackで上手くいったお陰で諦めずにトライできたので(逃げ道を潰せたのと、結果を比較したり)、これもM5Stack投資回収と言えなくもないかな?
M5StackはPIC24Fと通信してログや現在値を表示するモニタとして使用しようと検討してます
この前の練習会でもトラブルありPCと接続して不具合調査しており、変数をさくっと一覧orグラフ化できると便利なので本大会までには作ろうかなと思います
以下詳細です
10chの内訳は以下の通りです(一部は予定)
ch | 割当 | 用途 |
---|---|---|
1ch | 右スティック左右 | アームモード変更、攻撃 |
2ch | 左スティック上下 | 左脚スロットル |
3ch | 右スティック上下 | 右脚スロットル |
4ch | 左スティック左右 | 長押しでスタート姿勢など |
5ch | ボリューム | 移動時アーム上げ高さ変更 |
6ch | 左トグルスイッチ小 | 緊急停止 |
7ch | 左3点トグルスイッチ | ログ記録・停止・再生 |
8ch | 右3点トグルスイッチ | 攻撃時のゲイン大中小 |
9ch | 左スライドスイッチ | 左アーム原点トリム |
10ch | 右スライドスイッチ | 右アーム原点トリム |
個人的には緊急停止スイッチの位置は共通化したら良さそうかなと思いますが、取敢えずはプロポ側で目立つようにしとくべきですね
参考させてもらったサイト
SBUS関係
https://github.com/zendes/SBUS/blob/master/SBUS.cpp
http://www.hoihoido.com/blog/wp/?tag=s-bus
http://forum.autoquad.org/download/file.php?id=2319
PIC24F uart関係
http://cyberworks.cocolog-nifty.com/blog/2013/07/pic24f-ab7e.html
http://blog.livedoor.jp/mplab/archives/1016032279.html
http://nanoappli.com/blog/archives/5041
http://ww1.microchip.com/downloads/en/DeviceDoc/DS39708A_JP%20PIC24F%20Ref.Manual%20Section%2021.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/39881e.pdf
http://anarchy.hatenablog.com/entry/2014/12/07/181853
https://neo-sahara.com/wp/2016/02/20/pic24fj64gb002-uart%E3%82%92%EF%BC%92%E3%81%A4%E4%BD%BF%E3%81%A3%E3%81%A6tera-term%E3%81%A8%E9%80%9A%E4%BF%A1%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/
サンプルコード
タイマーなど、SBUSと無関係な部分は省略しているので適宜追加して下さい
//初期化部分 #define SBUS_DATA_MAX 25 #define SBUS_CH_MAX 19 #define SBUS_START_BYTE 0x0F #define SBUS_END_BYTE 0x00 unsigned int sbus_error=0, sbus_startbyte_flag=0, sbus_data[SBUS_DATA_MAX], sbus_ch[SBUS_CH_MAX]; RPOR0bits.RP0R = 3; // UART1Tx RP0 RPINR18bits.U1RXR = 1; // UART1Rx RP1 RPINR19bits.U2RXR = 20; // UART2Rx RP20 U1BRG = 103; // 9600bps@16MHz for PC U1MODE = 0x8800; U1STA = 0x0400; U2BRG = 9; // 100kbps@16MHz for S.BUS U2MODE = 0x8813; // data8bit even stop2bit 毎回割込み 信号反転=インバータ不要 U2STA = 0x0040; IEC1bits.U2RXIE = 1; IPC7bits.U2RXIP = 1; // 最優先 //Timer1は14msec周期が良さそうだが、自分は都合上10msec周期の為、省略 //1byte読込部分 読込時割込み void __attribute__((interrupt, no_auto_psv)) _U2RXInterrupt(void) { unsigned int buf = U2RXREG; if( sbus_startbyte_flag == 0 && buf == SBUS_START_BYTE ) sbus_cntr = 0, sbus_startbyte_flag = 1; if( sbus_cntr < SBUS_DATA_MAX ) sbus_data[sbus_cntr++] = buf; if( U2STAbits.OERR ) U2STAbits.OERR = 0; IFS1bits.U2RXIF = 0; } //変換部分 タイマー割込み void __attribute__((interrupt, no_auto_psv)) _T1Interrupt(void) { if( sbus_cntr >= SBUS_DATA_MAX ) { sbus_cntr = 0, sbus_startbyte_flag = 0; if( sbus_data[24] == SBUS_END_BYTE ) { sbus_ch[0] =((sbus_data[1] & 0xff)<<0) + ((sbus_data[2] & 0x07)<<8); sbus_ch[1] =((sbus_data[2] & 0xf8)>>3) + ((sbus_data[3] & 0x3f)<<5); sbus_ch[2] =((sbus_data[3] & 0xc0)>>6) + ((sbus_data[4] & 0xff)<<2) + ((sbus_data[5] & 0x01)<<10); sbus_ch[3] =((sbus_data[5] & 0xfe)>>1) + ((sbus_data[6] & 0x0f)<<7); sbus_ch[4] =((sbus_data[6] & 0x0f)>>4) + ((sbus_data[7] & 0x7f)<<4); sbus_ch[5] =((sbus_data[7] & 0x80)>>7) + ((sbus_data[8] & 0xff)<<1) + ((sbus_data[9] & 0x03) <<9); sbus_ch[6] =((sbus_data[9] & 0x7c)>>2) + ((sbus_data[10] & 0x1f)<<6); sbus_ch[7] =((sbus_data[10] & 0xe0)>>5) + ((sbus_data[11] & 0xff)<<3); sbus_ch[8] =((sbus_data[12] & 0xff)<<0) + ((sbus_data[13] & 0x07)<<8); sbus_ch[9] =((sbus_data[13] & 0xf8)>>3) + ((sbus_data[14] & 0x3f)<<5); sbus_ch[10]=((sbus_data[14] & 0xc0)>>6) + ((sbus_data[15] & 0xff)<<2) + ((sbus_data[16] & 0x01)<<10); sbus_ch[11]=((sbus_data[16] & 0xfe)>>1) + ((sbus_data[17] & 0x0f)<<7); sbus_ch[12]=((sbus_data[17] & 0x0f)>>4) + ((sbus_data[18] & 0x7f)<<4); sbus_ch[13]=((sbus_data[18] & 0x80)>>7) + ((sbus_data[19] & 0xff)<<1) + ((sbus_data[20] & 0x03) <<9); sbus_ch[14]=((sbus_data[20] & 0x7c)>>2) + ((sbus_data[21] & 0x1f)<<6); sbus_ch[15]=((sbus_data[21] & 0xe0)>>5) + ((sbus_data[22] & 0xff)<<3); sbus_ch[16] = (sbus_data[23] & 0x1) ? 0x7ff : 0 ; sbus_ch[17] = (sbus_data[23] & 0x2) ? 0x7ff : 0 ; sbus_ch[18] = (sbus_data[23] & 0x8) ? 0x7ff : 0 ; // Failsafe sbus_error = 0; } else sbus_error++; } else sbus_error++; IFS0bits.T1IF = 0; }購入前は10ch余るなとか言ってましたが足りなくて悩んでます隣の部屋から操縦したり練習会で数時間動かしましたが、今の所ノーコンにはなってないです