情弱でもNimでLチカしたい!on Nucleo-F401RE
この記事はstm32 Advent Calendar 2017の7日目の投稿です.間に合ったぜ.
動機
わたしの近況なのですが,最近はマウスのモチベが下がって研究室配属などがあり,マイコンプログラミングから離れてPythonばかり書いています.なので久しぶりにCを書こうとするととても辛い.そこでCの資産が使えて書きやすい言語がないかなーと探していたところ,Nimという言語に行き当たりました.
Nimについて
詳しくは以下の記事などを読んでください.
インストールに関しては
公式から落としてくるか,Githubを参照してください.
簡単にいうとPythonっぽい記法でC並の速度が出るモダンな感じの静的言語です.
下準備
前回の記事にしたがって準備を進めます.
一点,前回とは違い,今回は話を簡単にするために.c/.hを別ファイルにするチェックを外します.
生成形式は前回の記事と同じくmakefile形式です.
これで初期化コードを生成します.
手段
自分は全体的な作業の流れとして,以下のようなやり方を考えました.
Nimの公式から提供されている変換ツール「c2nim」を用いてmain.cに依存するヘッダーファイルをNimファイルに変換してライブラリごとバインドするというやり方です.
このやり方は結果として失敗に終わるので詳細は割愛しますが,まずc2nimのビルドに失敗します.ソースのバージョンを落とし,中身をコメントアウトしてビルド成功,実際に使ってみるとマクロがうまく変換されず無限にエラーが出ます.楽しいですね.
次に考えたのが,cファイルで関数をラップしてnimファイルに渡し,それをcファイルにコンパイルし(Nimは一旦cファイルに変換してからgccでコンパイルしてるっぽい)他のファイルとリンクさせてビルドするというやり方です.
実装
基本的にProjectName/Srcの中にファイルを置いていきます.まずはビルドに必要になるnimファイルを作成していきましょう.nimファイルは--os:standaloneオプションをつけてコンパイルするときpanicoverride.nimというファイルが必要になります.
proc printf(frmt: cstring) {.varargs, importc, header: "<stdio.h>", cdecl.} proc exit(code: int) {.importc, header: "<stdlib.h>", cdecl.} {.push stack_trace: off, profiler:off.} proc rawoutput(s: string) = printf("%s\n", s) proc panic(s: string) = rawoutput(s) exit(1) {.pop.}
このコードの必要性がよくわからないんですがないとビルドできないので置きましょう.偉い人はなんでこのコードがいるのか僕に教えてください.
STM32CubeMXから吐き出されたコードをいじっていきます.makefileをビルドに用いる都合上,同名のファイルがあった場合一番上の階層のコードをコンパイルする&main関数が複数あるとよろしくないのでmain.cをmain_.cなど別の名前に変えましょう.main_.cの中身ですが,自分はこう書きました.
#include "main.h" #include "stm32f4xx_hal.h" void SystemClock_Config(void); static void MX_GPIO_Init(void); void main_init(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); } void LED1_tick(void){ HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); } void SystemClock_Config(void) { /*************以下略**************/
簡単に説明すると,上で書いた通り,main関数はnimファイルの中に書くので消去,とりあえずLチカだけしたいので初期設定用の関数をmain_initという名前でまとめ,Nucleoの緑LEDをトグルする関数をLED1_tickという関数でラップしました.それ以外はそのままです.
main.nimの中身はこんな感じで実装します.
{.compile: "./main_.c".} proc main_init(): void {.importc.} proc LED1_tick(): void {.importc.} proc HAL_Delay(ms: uint32){.header: "stm32f4xx_hal.h", importc: "HAL_Delay", varargs.} when isMainModule: main_init() while true: LED1_tick() HAL_Delay(1000)
nimファイルにcの関数を渡す方法は何通りかあって,このファイルではcファイルでラップされた関数をインポートするやり方とヘッダーファイルから関数をインポートするやり方の2通りを実装しています.
前者のやり方ですが,1行目でインポートしたい関数がある.cファイルを指定します.この文法はcompile pragmaと言ってコンパイル時に実行されます.
2,3行目で関数を宣言します.この時,右に.cファイルからインポートされたファイルであるということを示すimport pragmaを追加します.
4行目では,ヘッダーファイルから関数を読み込んでいます.1行目とは違い、nimコマンドでcファイルに変換する時には読み込まれず間違っていても変換されてしまうので注意が必要です.パスですが,makefileに記述されているのに従い指定します.
それ以降はmain関数内に読み込んだ関数を使いLチカのコードを書いています.
ビルド
まず,main.nimをビルドします.projectディレクトリで,
nim cc -c --cpu=arm --d:release --gc:none --os:standalone --deadCodeElim:on src/main.nim
を実行します.
実行するとnimcacheなるディレクトリが作成されます.nimcacheの中のファイル構造は次のようになっていると思われます.
main.cとstdlib_system.cの中身はみてはいけません,目が死にますmain.nimからcファイルに変換された結果が入っています.
main_.sha1はこの場合main_.cが変更された時のみ新しくファイルを生成するためのファイルらしいです.
main.jsonにはcファイルをビルドする手順が書かれていますが今回は無視します.
nimコマンドで生成されたcファイルをビルドする前に,生成されたcファイルで読み込んでいるnimbase.hというファイルをnimcacheの中に置きます.
このファイルは本来ならnim/nim_version/nim/libの中にあってそれを呼び出したいんだろうな〜というファイルなのですが残念ながら呼び出してくれないので同じものを作成します.公式をコピペして持ってくるのが早いです.
最後にmakefileを書き換えます.
前回の記事のようにBINPATHにgcc-arm-none-eabiのパスを入力します.
C_SOURCES= 以下のmain.cをmain_.cに変更し,Src/nimcache/main.cとSrc/nimcache/stdlib_system.cを追加します.
これで
make all
を実行するとめでたくバイナリが生成されます.おめでとうございます.(以下のツイートは多分ソースコードの中身が少し違います)
Lチカできました!!! #はじめてのLチカ pic.twitter.com/Cpl2EBvfnT
— tattaka (@tattaka_sun) 2017年12月6日
まとめ
とりあえずNimを使ってLチカすることはできました.しかし,わざわざラップしなくてはいけなかったり,ヘッダファイルから読み込む場合でも引数の型が他のファイルに依存していたりすると面倒なので使い勝手がいいとは言えないです.ただ,Cではマクロを使って無理やり書くしかなかったテンプレートなどメタプログラミングに強い面もあるので(どうせ後でCに変換されるんだけどな)有用な場面も出てくるのではないでしょうか.
おまけ
上に書いたmakefileの仕様で同名のファイルは上の階層のものがビルドされることを知らずに改変前のmain.cをビルドして喜んでいるわたしの様子です.
— tattaka (@tattaka_sun) 2017年12月6日
追記
githubにもあげています.makefileのパスは各自対応お願いします.
github.com
STM32CubeMXのMakefile出力機能でSTM32お手軽開発環境構築
最近というほど最近ではないのですが,STM32の初期化コード自動生成ツールであるCubeMXにMakefileを出力する機能が追加され,ソフト文鎮EclipseなどのIDEを使わないで開発することが容易になりました.自分のための備忘録も兼ねて開発環境のセットアップから書き込みまでの手順をまとめておこうと思います.
開発環境のインストール
必要なソフトウェアは以下の通り
- gcc-arm-none-eabi
インストールに関しては以下のページの通り
- STM32CubeMX
本来ならここからインストールできるはず(10/11日現在リンクが消えてるので復活するまで待ちましょう......)※追記(11/11) インストールできるようになってました
- stm32flashやstlinkなどの書き込みツール
stm32flashは以下のリンクから自分のOSに応じてダウンロードしインストールする
stlinkは以下のページを参考にOSに応じてインストール
- 好きなエディタ
自分はAtomで開発してます.
プロジェクト作成
STM32CubeMXを起動しNew Projectを選択
以下の画面になったら使用したいボード・CPUを選ぶ
今回はNucleoF446ボードを例にやっていきます.
ProjectタブのSettingsを開いて
以下のようにします(プロジェクトの場所は任意で)
設定が終わったらOKを押し,Generateボタン(歯車っぽいボタン)を押してコードを生成します.
先に設定した場所を見るとプロジェクトが生成されていることがわかります.
コンパイル
このままだとコンパイルが通らないので生成されたMakefileの中のBINPATHにgcc-arm-none-eabiのPATHを入力します.
#######################################
# binaries
#######################################
BINPATH = /PATH/gcc-arm-none-eabi/bin/
#gcc-arm-none-eabiのバージョンや場所は各々の環境に応じて変更する
また,自分で新しく.cファイルを作った場合は
######################################
# source
######################################
以下に作った.cファイルを追記しなければいけません.
修正が終わったら
make all
してコンパイルができるはずです.
書き込み
コンパイル後のバイナリファイルは新しく作られたbuildディレクトリの中に生成されます.
たくさんファイルが出来ていますがデフォルトだとプロジェクト名と同じ名前のファイル(.bin,.elf,.hex,.map)があると思います.
生成されたバイナリファイルを書き込みツールを用いてマイコンに書き込めれば成功です!
まとめ
これで一通りSTM32の開発環境が整ったと思います.
自分の使いやすいエディタで良きSTM32ライフを!
今年度機体バグ備忘録(順次追加予定)
-
モータ・モータドライバ発熱
いらないクソデカコンデンサを撤去して解決
-
右側エンコーダが読めない
未解決
手で回すと正しい値が取れるが直進方向に制御をかけると読み取れなくなりおおよそ値が1/4.5くらいになる
全然わからん
-
stm32に書き込めない
参照:OpenSTM32 Community Site | Connect to custom board STM32L053 - STLINK-V2 - SWD
/open-ocd/0.9.0/share/openocd/scripts/board/st_nucleo_f4.cfgの最終行の
reset_config srst_only srst_nogate を reset_config srst_nogate に書き換えたら書き込めるようになった
再出現は警戒
-
if文の挙動がおかしい
if(角度 < M_PI){
— tattaka (@tattaka_sun) May 3, 2017
target_speed=0.0;
target_omega=500.0;
target_accel=0.0;
}
else{
target_speed=0.0;
target_omega=0.0;
target_accel=0.0;
}
正しく動くなら半周回転して止まるはず
これをループで回してるけど1回目の処理で角度(ジャイロで積分されている値)にM_PI(任意の数字)が代入されてるっぽい
機体をマイナス方向に回すと初期位置に戻る力が加わる
わけわかんね
この機体の中では180°(3.14[rad])が360という数値に近いらしい
ifの条件文を(角度<360)にすると意図通りの挙動をする
おそらくターン速が決まらなかったのもこれが原因
ただしモータに制御をかけず半周機体を回すと180°は3.14[rad]という正しい値を出力する
わけわかんね
-
減速が明らかにおかしい
減速が明らかに強い
距離を読み違えている?
加速は(おそらく)問題なし
4区画加速10m/s2減速-10m/s2
— tattaka (@tattaka_sun) May 4, 2017
減速がびみょい……? pic.twitter.com/4AcoStyH62
総括
覚えてろ謎挙動……地べたを這いドロ水すすってでももどってきてやる…...
— tattaka (@tattaka_sun) May 4, 2017
2017予定とか雑感とか
新年明けましておめでとうございます
今年は研究室配属などもあり単位も危ういしそろそろ正課に本気出さないとなーと思ったりしてます.(テスト前・レポート締め切り直前にブログ書いてる時点で......)
今年の予定としてはまともに走るクラシックサイズマウスを作る(フレッシュマンなりエキスパートなりまともな公式記録を残す)というのをひとまずの目標としたいと思います.
進捗は回路はほぼ完成といったところ,試験が終われば部品集めと去年のソフトウェアの改修をする予定です.7月の関西大会に間に合えばいいなあ......
後余裕があったらハーフやりたい,まともに動作させるのは来年だろうけど(CADは一日でできた).とりあえず今年はクラシックに注力する感じでやりたいですね.
アリュージョニストとの馴れ初めとか思い出とか自分的イメージソングとか
これはゆらぎの神話・アリュージョニスト・アリスピ Advent Calendar 2016 - Adventarの参加記事です.
幻想再帰のアリュージョニストに出会って2年半,色々なものが変わったり変わらなかったりしましたが思い出とかイメソンとか書いていこうと思います.
はじめに〜アリュ界隈以外の方へ:幻想再帰のアリュージョニストってなんぞ?〜
↑これ
人殺しが異世界に行ったり師弟な百合が出てきたりみんなでカラテやったりする話です.
広い性癖をカバーしてるので読んで
あ、一応R15なので15歳未満は読んではだめらしいです.
私とアリュージョニストの出会い
おおよそ2年半前の2014年4月末ごろ,私はいつものように朝から小説を読もう!のページを開いてスコップ作業*1に勤しんでいました.当時はすることが熱帯魚を見ることと本を読むことくらいしかなかったのです.*2その日もいつもと同じように小説を読もう! || 小説検索を開き,選定作業をしていました.*3
そんな時1話あたり3万文字越え*4,連載開始してから1ヶ月足らずで50万字を超えているという小説を見つけてしまったのです.
それから1週間,その小説を読むこと以外のことが碌に手をつけられなくなりました.食事が終われば読みふけり,水槽の水換えの間の水を貯めている時でさえiPod touchを手放すことができませんでした.
そして選定をした当時最新話だった話に辿りついた私は恐ろしいことに気がつきました.
あれ、20万文字増えてね?
これがアリュージョニスト七不思議の1つ,「最新話に辿りつけない」です,はい.当時は前述の1話3万文字越え,ほぼ毎日更新のため,いくら読んでも読み終わらない><という状況でした.結局読み終わったのが5月の半ば,レビューをまとめて某オープンな掲示板に投稿したのが6月の初めになります.探したら簡単に見つかると思うのですがこっ恥ずかしいので興味のある方は探してみてはいかがでしょう.
影響力のあるまとめサイトにも転載され,面白いと言ってくれる人もいて(自分が書いたわけでもないのに)ニヤニヤしながらエゴサ(誤用)したりしながら日々を過ごしていました.
アリュージョニストの思い出
イェツィラー(テステス)
— tattaka (@tattaka_sun) 2015年3月22日
2015年3月にTwitterのアカウントを作ってはじめてのツイートはこれですね、今となっては懐かしい.
サイバーカラテ道場botとかWikiが出てきたのもこの時期*5,というかそれを見てTwitterを始めたと言っても過言ではない.もともとtattaka (@tattaka_sun) | Twitterはアリュージョニスト用のアカウントであって,何か間違って情報系の学部に進んだりサークルでロボットを始めたりしてしまってカオスになってますが本来はアリュージョニストな人たちを観察するために生まれたアカウントでした.
気づいたら多くの知り合いができ,オフ会などやったりして色んな人のアリュージョニスト観に触れることができる快適なインターネットを構築することができました.
章ごとのイメソン
自分は物語にハマると自分的世界観と照らし合わせてテーマソング的なのを作ってしまう人間なのですが例に漏れずアリュージョニストにもそういう曲があるので紹介.
2章~3章
[Official Video] ZAQ - Alteration -
イメージとしてはアニメのオープニングみたいな感じで脳内再生してる.
ついでにこの記事書いてる時に上のアレンジを見つけてしまってこれも良い.
上がOPとするならばこっちはED
どちらも2章の魔女姉妹の自分のイメージにぴったりくる.
この曲のせい(?)でハルの歌声がこれになってしまった.
4章前半(死人の森の女王編)
死人の森の断章の暗い雰囲気によく合う.
loop, shareという曲名がもうこの編の主題とマッチしすぎてる.
歌詞も偶然とは思えないほどマッチしていて
大きな時間まで そっと 飲み込まれてしまうような カード合わせの渦に 負けてしまう
予感は記憶から染み出すように襲う
のあたりとか,
今 見ているものも 自分一人だけのものではなくて 誰かの持ちものや 心を 貰っただけだとしたら ひどくやるせない
これとかはコルセスカやトリシューラの相互参照性を想起させるし,
息を吐き出そうとして引っかかっていたのは 言葉ではなかった 体の半分は 言い訳や 偽善や そんなので出来ていると思う
くだらない強調も 理由も 確証も 過去も必要ないのに
ただ 素直に心は流れていかない 選んでいけない
この辺はアキラくんだし
灰色の夜と融け合う 冷たさに混じり合うために 柔らかくなっていく 細い糸で世界まで吊り上げようとしている 夢に似ている 虚ろに見るような 青
終盤のこれとかは完全にラクルラールだしでやばい,4章読んでるなら聞いて
4章中盤(樵さんのとこあたり)
これは自分でもよく分からない,雰囲気的には合ってるとは思うけど......
終わりに
Twitterとかでアリュージョニストを読んでる人と交流するとやっぱり一人で読んでた時と世界観の広がりというか,尊いってだけの感想でも言い合うのが大事なんだなあってのを感じることができた1年でした.来年もよろしく,アリュージョニスト.
明日は宗谷織衛さんです.
マイクロマウス全日本大会に参加してきた
マイクロマウス全日本大会に参加してきました.
結果
マイクロマウスクラシックサイズ フレッシュマン予選
第1走 R
第2走 R
第3走 R
見てのとおり、記念受験的な感じになりました.
探索用のプログラムもできてなかったので当然ですが......
来年はちゃんと走ろうと思いました.
その他
棄権という制度があるのに受付終わってから気づく
— tattaka (@tattaka_sun) November 19, 2016
・Twitterでしか見たことない人が現実で動いてる......すごい......!
・AUTODESKの人からTシャツをもらった
fusion360のTシャツもらったマン pic.twitter.com/BNsuK3CnYF
— tattaka (@tattaka_sun) November 19, 2016
・MiceフレッシュマンはやっぱりMiceだった
#マウス・トレースプロジェクト東京観光の旅 pic.twitter.com/JKDw7aYrla
— tattaka (@tattaka_sun) November 18, 2016
300km/hで走行するマウス pic.twitter.com/jWH5m5oIzY
— tattaka (@tattaka_sun) November 18, 2016
遠足は家に着くまでが遠足です#マウス・トレースプロジェクト東京観光の旅 pic.twitter.com/P6PJA8wLEZ
— tattaka (@tattaka_sun) November 20, 2016
追記
・某 FNDさんに顔覚えられてた(一方特定してると思ってたのに......)
・あとMiceのFF外の人にもtattakaって名乗ったらああ......って顔された
マウスパーティでは酔った勢いでいろんな人に絡みに行ってしまったけど色々と話聞けたし結果オーライかな(迷惑かけた方々すみませんでした......)
通常時より積極性が5割り増しくらいになってたはずです
マイクロマウス全日本大会直前
進捗
前回記事から現在までの進捗です.
今日の進捗動画です pic.twitter.com/rvjbY1cWJe
— tattaka (@tattaka_sun) November 5, 2016
この機体で1番やりたかったことです pic.twitter.com/4Sd22889GO
— tattaka (@tattaka_sun) November 10, 2016
マイクロマウス楽Cィィィィィィィィ!!!(ドレミファソラシド) pic.twitter.com/vpjBxYn7lX
— tattaka (@tattaka_sun) November 11, 2016
エレクトリカルパレード(のつもり) pic.twitter.com/4J34pjbghq
— tattaka (@tattaka_sun) November 12, 2016
直進です(微妙にできてない) pic.twitter.com/7ugeTuZq0R
— tattaka (@tattaka_sun) November 18, 2016
バッテリ電圧を簡単に監視できるようにした
— tattaka (@tattaka_sun) November 18, 2016
お気づきだろうか......前日まで競技成績に関わることを全くしていないことに......
ちなみに最後2つの進捗は2単位を犠牲にして産みました.
これからは金曜1限に無理して出席しなくても良くなったよ!やったね!
こんな感じなのでおそらく来年もフレッシュマンクラスにお邪魔することになると思います.来年はちゃんと走行できるようになりたいですね.まだモータの制御とかわかってないですけど.
P.S. マウスを始めて人間不信になってしまったのでTwitterのTL上の「探索走行できない><」って言葉を信じられなくなりました.訴えてやる.