制御工学博士の日常+備忘録

ようやく制御工学で博士を手に入れたので真っ当な人間になるべく研究以外の事とか色々と備忘録的にやっていく。そんな感じ

無料でできる勉強を効率的に行うための環境作り5選

※実験中です。 勉強を効率的に行うための無料でできる環境作りについて、以下の5つの方法をランキング形式で説明します。

1. 静かな学習スペースの確保

勉強に集中するためには、静かな環境が重要です。家の中であれば、個室や閑静な場所を利用しましょう。周囲の騒音や人の声が少ないことで、集中力が向上します。

2. 自己管理をサポートするアプリの活用

スマートフォンやコンピューターには、タスク管理や時間管理をサポートする無料のアプリが豊富にあります。例えば、TodoistやTrelloはタスクの整理に便利であり、ForestやPomodoro Timerは集中力を高めるのに役立ちます。

3. インターネットの制限

誘惑に負けて勉強の妨げにならないよう、インターネットの使用を制限することが重要です。無料のウェブサイトブロッカーやアプリを使用して、学習時間中に特定のサイトへのアクセスをブロックすることができます。

4. 整理整頓された学習環境の構築

学習環境が整理整頓されていると、無駄な時間を減らし、学習に没頭しやすくなります。机の上や周辺を整理し、必要な教材やノートがすぐに手に取れるように整えましょう。

5. 自然光の活用

できるだけ自然光の入る場所で学習すると、目の疲れを軽減し、集中力を持続させることができます。カーテンを開けて日中の自然光を取り入れるように心掛けると良いでしょう。

これらの方法を組み合わせて、効率的な学習環境を整えることで、より効果的な学習が可能となります。

さらに詳細を見たい場合は以下を進んでください。

この続きを読むには
購入して全文を読む

昔と今の指導方針について何となく違いが分かったのでまとめておく


目的

これまでの研究室での後輩指導を元に今とのギャップについて一つ問題点が分かったのでメモっておきたい。 今回の内容は研究指導をベースに考えてみたい。

これまでの指導スタイルと現在のギャップ

これまでの自分のスタイルからやる気がある人、あるいはコツコツ出来る人に対しての直接指導はうまくいってきた。 特に指導方法としては、 進捗どうですかアタックを細目にやっていたし、持っている技術や知識をとりあえず話す。 特にその場面に来たときに何パターンも繰り返し話すことで印象を与えておく。 これで結果的に後輩指導ではうまく回っていて、良い成果が研究で得られた。 これは現在も元職の研究室との連携で好循環が続いている。このスタイルはポスドクだったり博士学生だったから割と時間を気にせず後輩と話す機会(時間)に恵まれていたからだと思う。 (単純にコアタイムは有ったが定時で帰るという概念が無いということが大きい)

一方で教員として今の職場に来てから学生指導は理想と現実とのギャップが大きい。 その結果として多少なりともイラついたりする時が増えてきた気がする。

イラつきの要因はわかっていて、時間的な余裕がない。無能教員がいる。出世は年功序列(今の成果では全然足りない。もっとぶっ飛んだ成果を出さないとダメらしい)。家庭と仕事・研究のバランスが難しく思い通りにならない。

人間の感情で、「怒り」というのは理想と現実のギャップ、自分ではどうにもならない要素による影響に対して感情が「怒り」「イラ立ち」に変わると思う。 人間は面白いセンサを持っていて感情が伝搬するのでそういう点を出さないようにするのが重要だと思う(、が自分も全然できていないと思う)。 もっと意識のコントロールを覚えていきたい。。。

という訳で、今分かっている範囲で自分の中での指導スタイル・考えを以降に書いておきたい。 こんなことをここで書いておいて問題になりそうだが、その時は誰か説教してください。

自分で積極的に手を動かすタイプ

このタイプはこれまで通りのスタイルで良いので指導が簡単。一緒に遊べばいいだけ。

やりたいことがあるという割には行動が伴わないタイプ

このタイプは今厄介だと思っている。ある程度頭が良い人にありがちなタイプで、頭が良い分余計なメリットデメリットが 沢山考えついてしまって結果的に行動に起こすまでものすごいエネルギーが必要になる。 受験勉強とかはやらないと死活問題なのでこのレベルになるまで行動するエネルギーギャップが大きい。 いざやり始めたら結構凄いが、とりあえず行動しながら考えることが出来ないのでこのマインドを変えることが出来たら 相当伸びるはず。おそらく昔の俺はこっちのタイプだったかもしれない。

やる前からうまくいくか行かないかを考えることが一番時間の無駄なのでまずはやってから、またはやりながら考えれば良いと思っているが現実はうまくいかないな。。。

何からやれば良いか分からなくてやる気をなくすタイプ

何か課題を与えた時に、すぐ行動できない要因としては解決までのフローがイメージできていない。 そもそも知識が無くて何も分からない⇒行動できないという風になるんだろうと思う。

このタイプは恐らく一緒にやるのが良いんだろう。

難しく考えすぎていて実際は簡単なはずなのにめちゃくちゃ難しそうっていう風に感情が動く。 その結果行動ができなくなる人が多い。 それか知識が無くて行動できないって人もいるはず。

このタイプは一緒にやれば、案外簡単なんだということを肌で感じることになるのでその後の行動が積極的になってくれるのかもしれない。 分からないことを調べる方法についても一緒にやってどう調べればいいかという例を体験できれば変わるかもしれない。 結局は一緒にやってみないとダメだと思う。

分からないものを難しいと勘違いして手を出さないタイプ

このタイプも上と同じタイプなので一緒にやってみるってのが良いんだろう。

ここまでのタイプに対して、とりあえず行動してみるというマインドを植え付ける方法は、一緒にちょっとだけやってみてやる気エンジンを回してあげる、行動のハードルを下げてあげるという方法を取るのが良いと現状の自分では結論付けた。

教員としての問題点

問題点:会議や研究、研究費獲得のための研究費申請書作成、事務作業、授業準備、部活動

これだけの仕事がある影響で学生と直接接する時間がない。あと学生が卒研時間に来ないという問題もあるのでこれが加速する。 完全に負の循環が現在の学校教育の問題点になっていると思う。

というわけで問題はシンプルで、学生と直接接する時間が減っているのが根本な問題になる。 卒研という話で言えば、卒研時間で接する時間がない。雑談や進路相談というのは別途取っているがそれは教員の卒研に対する願望ではなく、 学生の死活問題から来る願望に教員が答えている形を取っているので、実質give and giveになっている。 学校教育ではgive and takeという概念はほぼほぼ無いはずなので、自分の研究成果を卒研で出したければ学生と接する機会を強制的に増やすしか方法はないんだろう。

研究室の回し方:検討案

今年の目標:卒研時間に来た学生で一緒にできそうなものがあれば一緒にやってみる。 卒研時間以外でも卒研をやっているなら時間がとれなそうな場合は相談に乗ったりアドバイスや方針について考えを話しておく。

来ない人:研究室に来るように呼び掛けるべきか否か。対応が難しい。とりあえず今年はギリギリまで放置しておく。 定期的な進捗だけは合った時に聞いて、進捗が出るようなマインドに変わることを祈っておく。

M5Stackを使ってステッピングモータを回したい(L6740ドライバ使用)

目的

ステッピングモータをモータドライバから回したい。 これができれば、ステッピングモータで位置制御、速度制御をしてみたい その内、ターンテーブルを作るまでいけると嬉しい

参考にしたリンク

http://spinelify.blog.fc2.com/blog-entry-80.html ↑これが一番参考にした

http://sheep-me.me/2019/11/22/geidai_19/ https://qiita.com/BotanicFields/items/fff644f408c291e5a5f0 https://energy-note.hatenablog.com/entry/2020/09/20/090719

使用物品

  • L6470:ステッピングモータドライバ
  • ST-42BYH1004: バイポーラステッピングモータ
  • M5Stack Gray(Basic+IMU9軸センサの一体型)
  • KX-100L: 直流安定化電源(直流リンク供給用)

配線等は後で確認する。

実行手順

実行手順は以下のとおりである。 1. http://spinelify.blog.fc2.com/blog-entry-80.html こちらのリンクを参考にM5Stack gray用のSPI通信を実装 2. L6740とM5Stackの各種PINを配線 3. プログラムを実行

参考リンクにあったプログラムではSPIポートの設定が異なっているようだった。 M5Stack grayはM5stack Basicに9軸IMUセンサが内蔵されたタイプでどうやらチャンネルが微妙に異なることが分かった。 https://energy-note.hatenablog.com/entry/2020/09/20/090719 のリンクを見るとSPI通信用のPIN対応は

#define CK 5
#define MI 17
#define MO 16
#define SS 22

となっている。 ここで、理解する必要のある信号名として、

CK:SCK

MI:MISO

MO:MOSI

SS:GPIOからディジタルIOを設定

https://qiita.com/BotanicFields/items/fff644f408c291e5a5f0 こちらのリンクを参考にしてみると

SCLK(Serial CLocK)

MISO(Mater In Slave Out)

MOSI(Master Out Slave In)

SS(Slave Select)

LCD(Liquid Crystal Display)

TF(TransFlash)

という意味があるらしい。(M5Stack Basicの対応)

アルゴリズムについて

以降は理解していないのでアルゴリズムについての説明は省略する。 こちらは理解できるようになったら少しずつ加筆する。 理解できるようになった時にSPI通信の感覚が掴めるようになるのではないかと思われる。 ※あくまでArduino IDEで使えるマイコンに関してだけ

プログラムは一番下に貼っておく。

配線状況と実験風景

配線の対応や設定について https://strawberry-linux.com/catalog/items?code=12023 こちらのリンクにl6470r2-manual.pdfがある。

このPDFによるとM5Stackから5Vを制御IC用に供給できるので左のジャンパー設定をする。 このインターフェースとマイコンとの通信にはSPI通信を行うわけだが、SPI通信の各社インターフェースはこのマイコンに依存することなく利用できるらしい。 詳しいことはPDFに書いてある。

L6740_PIN設定.PNG (347.7 kB) L6740_PIN設定1.PNG (182.5 kB)

実際の実験装置と配線状況

DSC_1155.JPG (4.0 MB)

DSC_1160.JPG (4.0 MB)

DSC_1157.JPG (4.2 MB)

写真より、各ピン設定についてまとめておく。

PIN 2:Slave Select

これは複数台になった時に色々使えるらしいがよくわかっていない。

PIN 5:BUSY

これはL6740ボードから処理が終わったら来る信号?まだわからない。 詳しいことは(http://spinelify.blog.fc2.com/blog-entry-41.html )に説明があるので要勉強

PIN 18:SCK

これはSPI用の基準クロック(Serial Clock)

PIN 19:MISO

これはMaster In Slave Outという意味なのでSlave機側からのデータが来る。ここで言うMaster機はM5Stack grayの事である。

PIN 23:MOSI

これはMaster Out Slave Inという意味。これが今回L6740側に送るシリアルデータ送信端子になる。

さらなる理解にはSPI.hを理解する必要がある。 https://blog.goo.ne.jp/namva/e/2733bdfc3ab15105cf3efabfb36ea29f http://www.musashinodenpa.com/arduino/ref/index.php?f=1&pos=539 https://stupiddog.jp/note/archives/976 これが参考になりそうである。

まとめ

とりあえずサンプルをコピペしてステッピングモータを回すことができた。 しかしSPI.h内やサンプルプログラムも全て理解できていない。

これを理解せずして先へは進めないのでよく調査する必要がある。 これが今後の大きな課題である。 解決後は回転位置の指定(位置制御)や速度制御を行い、ターンテーブルが作れたら最高である。

ビットの補足

0xFFとかあるが、これは16進数なので、

0b11111111 = 0xFFになる。 16進数の1byteが0b1111になるので0b1111=0xFになる。

つまり0xFFは2byteデータである。 ちなみに28=256である。

つまり8bitは10進数で28=256である。

10bit=1024, 12bit=4096

世の中のエンコーダでは17bit, 20bit, 30bit+2bitのような物もある。 これは多摩川精機のエンコーダ(シングルシン)が該当。あとはNICONあたり? 参考リンク https://haselab.net/class/literacy/note/2/0xff.html

プログラム(100%コピペ)

#include <SPI.h>
//#include <MsTimer2.h>

// ピン定義。
#define PIN_SPI_MOSI 23
#define PIN_SPI_MISO 19
#define PIN_SPI_SCK 18
#define PIN_SPI_SS 2
#define PIN_BUSY 5

void setup()
{
  delay(1000);
  pinMode(PIN_SPI_MOSI, OUTPUT);
  pinMode(PIN_SPI_MISO, INPUT);
  pinMode(PIN_SPI_SCK, OUTPUT);
  pinMode(PIN_SPI_SS, OUTPUT);
  pinMode(PIN_BUSY, INPUT);
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  SPI.setBitOrder(MSBFIRST);
  Serial.begin(9600);
  digitalWrite(PIN_SPI_SS, HIGH);
 
  L6470_resetdevice(); //L6470リセット
  L6470_setup();  //L6470を設定
  
//  MsTimer2::set(50, fulash);//シリアルモニター用のタイマー割り込み
//  MsTimer2::start();
//  delay(4000);
  
  L6470_move(1,1600);//指定方向に指定数ステップする 
  L6470_busydelay(5000); //busyフラグがHIGHになってから、指定ミリ秒待つ。
  L6470_run(0,10000);//指定方向に連続回転
  delay(6000);
  L6470_softstop();//回転停止、保持トルクあり
  L6470_busydelay(5000);
  L6470_goto(0x6789);//指定座標に最短でいける回転方向で移動
  L6470_busydelay(5000);
  L6470_run(0,0x4567);
  delay(6000);
  L6470_hardhiz();//回転急停止、保持トルクなし
}

void loop(){
}

void L6470_setup(){
L6470_setparam_acc(0x40); //[R, WS] 加速度default 0x08A (12bit) (14.55*val+14.55[step/s^2])
L6470_setparam_dec(0x40); //[R, WS] 減速度default 0x08A (12bit) (14.55*val+14.55[step/s^2])
L6470_setparam_maxspeed(0x40); //[R, WR]最大速度default 0x041 (10bit) (15.25*val+15.25[step/s])
L6470_setparam_minspeed(0x01); //[R, WS]最小速度default 0x000 (1+12bit) (0.238*val[step/s])
L6470_setparam_fsspd(0x3ff); //[R, WR]μステップからフルステップへの切替点速度default 0x027 (10bit) (15.25*val+7.63[step/s])
L6470_setparam_kvalhold(0x50); //[R, WR]停止時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
L6470_setparam_kvalrun(0x50); //[R, WR]定速回転時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
L6470_setparam_kvalacc(0x50); //[R, WR]加速時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
L6470_setparam_kvaldec(0x50); //[R, WR]減速時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)

L6470_setparam_stepmood(0x03); //ステップモードdefault 0x07 (1+3+1+3bit)
}

void fulash(){
  Serial.print("0x");
  Serial.print( L6470_getparam_abspos(),HEX);
  Serial.print("  ");
  Serial.print("0x");
  Serial.println( L6470_getparam_speed(),HEX);
}


/*ver 1.00 2013/4/24*/
/*ver 1.01 2013/12/14 コメント追記*/

/*L6470 コントロール コマンド
 引数-----------------------
 dia   1:正転 0:逆転,
 spd  (20bit)(0.015*spd[step/s])
 pos  (22bit)
 n_step (22bit)
 act   1:絶対座標をマーク  0:絶対座標リセット
 mssec ミリ秒
 val 各レジスタに書き込む値
 ---------------------------
 L6470_run(dia,spd); //指定方向に連続回転
 L6470_stepclock(dia); //指定方向にstepピンのクロックで回転
 L6470_move(dia,n_step); //指定方向に指定数ステップする 
 L6470_goto(pos); //指定座標に最短でいける回転方向で移動
 L6470_gotodia(dia,pos); //回転方向を指定して指定座標に移動
 L6470_gountil(act,dia,spd); //指定した回転方向に指定した速度で回転し、スイッチのONで急停止と座標処理
 L6470_relesesw(act,dia); //スイッチがOFFに戻るまで最低速度で回転し、停止と座標処理
 L6470_gohome(); //座標原点に移動
 L6470_gomark(); //マーク座標に移動
 L6470_resetpos(); //絶対座標リセット
 L6470_resetdevice(); //L6470リセット
 L6470_softstop(); //回転停止、保持トルクあり
 L6470_hardstop(); //回転急停止、保持トルクあり
 L6470_softhiz(); //回転停止、保持トルクなし
 L6470_hardhiz(); //回転急停止、保持トルクなし
 L6470_getstatus(); //statusレジスタの値を返す (L6470_getparam_status();と同じ)
 
 L6470_busydelay(msec); //busyフラグがHIGHになってから、指定ミリ秒待つ。
 
 レジスタ書き込みコマンド
 L6470_setparam_abspos(val); //[R, WS]現在座標default 0x000000 (22bit)
 L6470_setparam_elpos(val); //[R, WS]コイル励磁の電気的位置default 0x000 (2+7bit)
 L6470_setparam_mark(val); //[R, WR]マーク座標default 0x000000 (22bit)
 //ありませんL6470_spped //[R] 現在速度read onry  (20bit)
 L6470_setparam_acc(val); //[R, WS] 加速度default 0x08A (12bit) (14.55*val+14.55[step/s^2])
 L6470_setparam_dec(val); //[R, WS] 減速度default 0x08A (12bit) (14.55*val+14.55[step/s^2])
 L6470_setparam_maxspeed(val); //[R, WR]最大速度default 0x041 (10bit) (15.25*val+15.25[step/s])
 L6470_setparam_minspeed(val); //[R, WS]最小速度default 0x000 (1+12bit) (0.238*val+[step/s])
 L6470_setparam_fsspd(val); //[R, WR]μステップからフルステップへの切替点速度default 0x027 (10bit) (15.25*val+7.63[step/s])
 L6470_setparam_kvalhold(val); //[R, WR]停止時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
 L6470_setparam_kvalrun(val); //[R, WR]定速回転時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
 L6470_setparam_kvalacc(val); //[R, WR]加速時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
 L6470_setparam_kvaldec(val); //[R, WR]減速時励磁電圧default 0x29 (8bit) (Vs[V]*val/256)
 L6470_setparam_intspd(val); //[R, WH]逆起電力補償切替点速度default 0x0408 (14bit) (0.238*val[step/s])
 L6470_setparam_stslp(val); //[R, WH]逆起電力補償低速時勾配default 0x19 (8bit) (0.000015*val[% s/step])
 L6470_setparam_fnslpacc(val); //[R, WH]逆起電力補償高速時加速勾配default 0x29 (8bit) (0.000015*val[% s/step])
 L6470_setparam_fnslpdec(val); //[R, WH]逆起電力補償高速時減速勾配default 0x29 (8bit) (0.000015*val[% s/step])
 L6470_setparam_ktherm(val); //[R, WR]不明default 0x0 (4bit) (0.03125*val+1)
 //ありませんL6470_adcout //[R] read onry (5bit) ADCによる逆起電力補償の大きさかな?
 L6470_setparam_ocdth(val); //[R, WR]過電流しきい値default 0x8 (4bit) (375*val+375[mA])
 L6470_setparam_stallth(val); //[R, WR]失速電流しきい値?default 0x40 (7bit) (31.25*val+31.25[mA])
 L6470_setparam_stepmood(val); //[R, WH]ステップモードdefault 0x07 (1+3+1+3bit)
 L6470_setparam_alareen(val); //[R, WS]有効アラームdefault 0xff (1+1+1+1+1+1+1+1bit)
 L6470_setparam_config(val); //[R, WH]各種設定default 0x2e88 (3+3+2+1+1+1+1+1+3bit)
 //L6470_status //[R]状態read onry (16bit)

 [R]:読み取り専用
 [WR]:いつでも書き換え可
 [WH]:書き込みは出力がハイインピーダンスの時のみ可
 [WS]:書き換えはモータが停止している時のみ可
 
 
 レジスタ読み込みコマンド(返り値 long型)
 L6470_getparam_abspos();
 L6470_getparam_elpos();
 L6470_getparam_mark();
 L6470_getparam_speed();
 L6470_getparam_acc();
 L6470_getparam_dec();
 L6470_getparam_maxspeed();
 L6470_getparam_minspeed();
 L6470_getparam_fsspd();
 L6470_getparam_kvalhold();
 L6470_getparam_kvalrun();
 L6470_getparam_kvalacc();
 L6470_getparam_kvaldec();
 L6470_getparam_intspd();
 L6470_getparam_stslp();
 L6470_getparam_fnslpacc();
 L6470_getparam_fnslpdec();
 L6470_getparam_ktherm();
 L6470_getparam_adcout();
 L6470_getparam_ocdth();
 L6470_getparam_stallth();
 L6470_getparam_stepmood();
 L6470_getparam_alareen();
 L6470_getparam_config();
 L6470_getparam_status();
 */



void L6470_setparam_abspos(long val){L6470_transfer(0x01,3,val);}
void L6470_setparam_elpos(long val){L6470_transfer(0x02,2,val);}
void L6470_setparam_mark(long val){L6470_transfer(0x03,3,val);}
void L6470_setparam_acc(long val){L6470_transfer(0x05,2,val);}
void L6470_setparam_dec(long val){L6470_transfer(0x06,2,val);}
void L6470_setparam_maxspeed(long val){L6470_transfer(0x07,2,val);}
void L6470_setparam_minspeed(long val){L6470_transfer(0x08,2,val);}
void L6470_setparam_fsspd(long val){L6470_transfer(0x15,2,val);}
void L6470_setparam_kvalhold(long val){L6470_transfer(0x09,1,val);}
void L6470_setparam_kvalrun(long val){L6470_transfer(0x0a,1,val);}
void L6470_setparam_kvalacc(long val){L6470_transfer(0x0b,1,val);}
void L6470_setparam_kvaldec(long val){L6470_transfer(0x0c,1,val);}
void L6470_setparam_intspd(long val){L6470_transfer(0x0d,2,val);}
void L6470_setparam_stslp(long val){L6470_transfer(0x0e,1,val);}
void L6470_setparam_fnslpacc(long val){L6470_transfer(0x0f,1,val);}
void L6470_setparam_fnslpdec(long val){L6470_transfer(0x10,1,val);}
void L6470_setparam_ktherm(long val){L6470_transfer(0x11,1,val);}
void L6470_setparam_ocdth(long val){L6470_transfer(0x13,1,val);}
void L6470_setparam_stallth(long val){L6470_transfer(0x14,1,val);}
void L6470_setparam_stepmood(long val){L6470_transfer(0x16,1,val);}
void L6470_setparam_alareen(long val){L6470_transfer(0x17,1,val);}
void L6470_setparam_config(long val){L6470_transfer(0x18,2,val);}

long L6470_getparam_abspos(){return L6470_getparam(0x01,3);}
long L6470_getparam_elpos(){return L6470_getparam(0x02,2);}
long L6470_getparam_mark(){return L6470_getparam(0x03,3);}
long L6470_getparam_speed(){return L6470_getparam(0x04,3);}
long L6470_getparam_acc(){return L6470_getparam(0x05,2);}
long L6470_getparam_dec(){return L6470_getparam(0x06,2);}
long L6470_getparam_maxspeed(){return L6470_getparam(0x07,2);}
long L6470_getparam_minspeed(){return L6470_getparam(0x08,2);}
long L6470_getparam_fsspd(){return L6470_getparam(0x15,2);}
long L6470_getparam_kvalhold(){return L6470_getparam(0x09,1);}
long L6470_getparam_kvalrun(){return L6470_getparam(0x0a,1);}
long L6470_getparam_kvalacc(){return L6470_getparam(0x0b,1);}
long L6470_getparam_kvaldec(){return L6470_getparam(0x0c,1);}
long L6470_getparam_intspd(){return L6470_getparam(0x0d,2);}
long L6470_getparam_stslp(){return L6470_getparam(0x0e,1);}
long L6470_getparam_fnslpacc(){return L6470_getparam(0x0f,1);}
long L6470_getparam_fnslpdec(){return L6470_getparam(0x10,1);}
long L6470_getparam_ktherm(){return L6470_getparam(0x11,1);}
long L6470_getparam_adcout(){return L6470_getparam(0x12,1);}
long L6470_getparam_ocdth(){return L6470_getparam(0x13,1);}
long L6470_getparam_stallth(){return L6470_getparam(0x14,1);}
long L6470_getparam_stepmood(){return L6470_getparam(0x16,1);}
long L6470_getparam_alareen(){return L6470_getparam(0x17,1);}
long L6470_getparam_config(){return L6470_getparam(0x18,2);}
long L6470_getparam_status(){return L6470_getparam(0x19,2);}


void L6470_run(int dia,long spd){
  if(dia==1)
    L6470_transfer(0x51,3,spd);
  else
    L6470_transfer(0x50,3,spd);
}
void L6470_stepclock(int dia){
  if(dia==1)
    L6470_transfer(0x59,0,0);    
  else
    L6470_transfer(0x58,0,0);
}
void L6470_move(int dia,long n_step){
  if(dia==1)
    L6470_transfer(0x41,3,n_step);
  else
    L6470_transfer(0x40,3,n_step);
}
void L6470_goto(long pos){
  L6470_transfer(0x60,3,pos);
}
void L6470_gotodia(int dia,int pos){
  if(dia==1)    
    L6470_transfer(0x69,3,pos);
  else    
    L6470_transfer(0x68,3,pos);
}
void L6470_gountil(int act,int dia,long spd){
  if(act==1)
    if(dia==1)
      L6470_transfer(0x8b,3,spd);
    else
      L6470_transfer(0x8a,3,spd);
  else
    if(dia==1)
      L6470_transfer(0x83,3,spd);
    else
      L6470_transfer(0x82,3,spd);
}  
void L6470_relesesw(int act,int dia){
  if(act==1)
    if(dia==1)
      L6470_transfer(0x9b,0,0);
    else
      L6470_transfer(0x9a,0,0);
  else
    if(dia==1)
      L6470_transfer(0x93,0,0);
    else
      L6470_transfer(0x92,0,0);
}
void L6470_gohome(){
  L6470_transfer(0x70,0,0);
}
void L6470_gomark(){
  L6470_transfer(0x78,0,0);
}
void L6470_resetpos(){
  L6470_transfer(0xd8,0,0);
}
void L6470_resetdevice(){
  L6470_send_u(0x00);//nop命令
  L6470_send_u(0x00);
  L6470_send_u(0x00);
  L6470_send_u(0x00);
  L6470_send_u(0xc0);
}
void L6470_softstop(){
  L6470_transfer(0xb0,0,0);
}
void L6470_hardstop(){
  L6470_transfer(0xb8,0,0);
}
void L6470_softhiz(){
  L6470_transfer(0xa0,0,0);
}
void L6470_hardhiz(){
  L6470_transfer(0xa8,0,0);
}
long L6470_getstatus(){
  long val=0;
  L6470_send_u(0xd0);
  for(int i=0;i<=1;i++){
    val = val << 8;
    digitalWrite(PIN_SPI_SS, LOW); // ~SSイネーブル。
    val = val | SPI.transfer(0x00); // アドレスもしくはデータ送信。
    digitalWrite(PIN_SPI_SS, HIGH); // ~SSディスエーブル 
  }
  return val;
}

void L6470_transfer(int add,int bytes,long val){
  int data[3];
  L6470_send(add);
  for(int i=0;i<=bytes-1;i++){
    data[i] = val & 0xff;  
    val = val >> 8;
  }
  if(bytes==3){
    L6470_send(data[2]);
  }
  if(bytes>=2){
    L6470_send(data[1]);
  }
  if(bytes>=1){
    L6470_send(data[0]);
  }  
}
void L6470_send(unsigned char add_or_val){
  while(!digitalRead(PIN_BUSY)){
  } //BESYが解除されるまで待機
  digitalWrite(PIN_SPI_SS, LOW); // ~SSイネーブル。
  SPI.transfer(add_or_val); // アドレスもしくはデータ送信。
  digitalWrite(PIN_SPI_SS, HIGH); // ~SSディスエーブル。
}
void L6470_send_u(unsigned char add_or_val){//busyを確認せず送信するため用
  digitalWrite(PIN_SPI_SS, LOW); // ~SSイネーブル。
  SPI.transfer(add_or_val); // アドレスもしくはデータ送信。
  digitalWrite(PIN_SPI_SS, HIGH); // ~SSディスエーブル。
}
void L6470_busydelay(long time){//BESYが解除されるまで待機
  while(!digitalRead(PIN_BUSY)){
  }
  delay(time);
}
long L6470_getparam(int add,int bytes){
  long val=0;
  int send_add = add | 0x20;
  L6470_send_u(send_add);
  for(int i=0;i<=bytes-1;i++){
    val = val << 8;
    digitalWrite(PIN_SPI_SS, LOW); // ~SSイネーブル。
    val = val | SPI.transfer(0x00); // アドレスもしくはデータ送信。
    digitalWrite(PIN_SPI_SS, HIGH); // ~SSディスエーブル 
  }
  return val;
}

M5Stackを使って温湿度センサーで遊ぶ

目的 

温湿度センサーの原理の理解と実際に使いかたを学ぶ

仕様物と参考にしたリンク

M5stackで温湿度センサーを動かす adafruit/DHT-sensor-library Arduinoで温湿度センサ(DHT11)を使う

使用したもの

  • DHT11
  • M5Stack Gray

今回はDHT11という温湿度センサーを試す。上記リンクを参考に実装することにした。 DHT11を使用するにはDHT11に関連するセンサーライブラリのインストールをする必要がある。

そこで、下記画像のようにライブラリの管理からインストールを行った。 この時、Adafruit Unified SensorやDHT Unified Sensorライブラリもインストールするか聞かれるが、特に気にせず全部インストールを選択した。 (どうやら加速度センサ等のライブラリも同時にインストールされたらしい。ADXL343のやつ)

ライブラリインストール.png (33.0 kB)

サンプルプログラムを開く

というわけで、まず何も考えずにスケッチ例からDHTtesterを開く

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor

#include "DHT.h"

#define DHTPIN 2     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 3 (on the right) of the sensor to GROUND (if your sensor has 3 pins)
// Connect pin 4 (on the right) of the sensor to GROUND and leave the pin 3 EMPTY (if your sensor has 4 pins)
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  Serial.println(F("DHTxx test!"));

  dht.begin();
}

void loop() {
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("°C "));
  Serial.print(f);
  Serial.print(F("°F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("°C "));
  Serial.print(hif);
  Serial.println(F("°F"));
}

このプログラムはArduinoようになっているようで、Serial.printはArduino IDEのシリアルモニタ用の設定?になっていると思われる。 そこで、Serial.printはすべて削除し、M5.Lcd.printへ置き換えて出力することにする。

#include <M5Stack.h>
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor

#include "DHT.h" //センサ信号受信

#define DHTPIN 2     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// NOTE: If using a board with 3.3V logic like an Arduino Due connect pin 1
// to 3.3V instead of 5V!
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 3 (on the right) of the sensor to GROUND (if your sensor has 3 pins)
// Connect pin 4 (on the right) of the sensor to GROUND and leave the pin 3 EMPTY (if your sensor has 4 pins)
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  M5.begin();

  dht.begin();
}

void loop() {
  // 画面を黒くする
  M5.Lcd.fillScreen(BLACK);
  // 文字サイズ
  M5.Lcd.setTextSize(2);
  // Wait a few seconds between measurements.
  delay(2000);

  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
   // Serial.println(F("Failed to read from DHT sensor!"));
    M5.Lcd.print(F("Failed to read from DHT sensor!"));
    delay(2000);
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  M5.Lcd.setCursor(0, 0);
  M5.Lcd.print("Humidity=");
  M5.Lcd.print(h);
  M5.Lcd.print("%\n");
  M5.Lcd.print("Temperature=");
  M5.Lcd.print(t);
  M5.Lcd.print("deg. Celsius\n");
  M5.Lcd.print(f);
  M5.Lcd.print("deg. Fahrenheit\n");
  M5.Lcd.print("Heat Index={hic,hif}={");
  M5.Lcd.print(hic);
  M5.Lcd.print("deg.C,");
  M5.Lcd.print(hif);
  M5.Lcd.print("deg.F}");
  delay(5000);
}

というわけで出力した結果が下記画像のとおりである。 無事出力できた。

DSC_0858.JPG (3.9 MB)

まとめ

今回はDHT11という温湿度センサーを使用してみた。 サンプルプログラムでデータを取得し、M5stackのLcdに出力する簡単な実験ができた。 ライブラリがあるということがとても助かるが、中身のプログラム(DHT.h)を理解していないので、どういう処理をしているのかは別途理解したいところ。とりあえず、Arduino IDEがあれば、ライブラリが揃っているので実験がすぐできるという点でとてもありがたいのでこういう開発は簡単に進みそうである。

FPGAやLinuxPC等で同様に取得する場合にはライブラリの中身を理解してプログラムを書き直せば行けると思うので必要になったらそういうこともやってみたい。

M5Stackを使って超音波センサで遊ぶ

目的

超音波センサで距離を測りたい。 今回は下記リンクを参考にそのままやってみることにする。

【初心者向け電子工作】超音波センサーで距離を測ってみる

超音波センサを使ってみる

使用した物品

  • M5stack gray
  • HC-SR04(超音波センサ)

この超音波センサは最近では突然データ取得できなくなる問題が発生しているため、生産が中止になった商品らしい

細かい式の意味については下記リンク 超音波距離センサーの使い方(HC-SR04)

次節でプログラムを示すが、0.017は1/58.8からきている。 ちゃんとやるなら計算式をしっかり書いた方が良い。

計算式は

距離[m] = 超音波の送信から受信までの往復時間[s]×音速[m/s]×1/2

1/2は片道分の計算にするため。

実際は2cm から 400 cmなのでcm単位で表示した方が分かりやすい。

丸パクリしたプログラム

#include <M5Stack.h>

#define TRIG 2
#define ECHO 5

int times;
int distance;

void setup() {
  M5.begin();

  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);

  // 文字サイズ
  M5.Lcd.setTextSize(10);
}

void loop() {
  // 画面を黒くする
  M5.Lcd.fillScreen(BLACK);

  // 超音波を発生させる
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG, LOW);

  // 超音波を受け取る
  times = pulseIn(ECHO, HIGH);
  distance = (int)(times * 0.017);

  // ディスプレイに表示させる
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.print(distance);
  delay(500);
}

pulseIn関数の意味はこちら

結果

写真は取っていないが、うまく実行できた。

コメントと改良を加えた実験

プログラムを下記に示すようにコメントを加えて、さらにLCD表示をわかりやすく変更した。

#include <M5Stack.h>

#define TRIG 2
#define ECHO 5

float times;  //超音波の往復時間 [us]
float distance; //物体距離[cm]
float sound_Vel = 340;  //音速 340 [m/s]

void setup() {
  M5.begin();

  pinMode(TRIG, OUTPUT);
  pinMode(ECHO, INPUT);

  // 文字サイズ
  M5.Lcd.setTextSize(2);
}

void loop() {
  // 画面を黒くする
  M5.Lcd.fillScreen(BLACK);

  // 超音波を発生させる
  digitalWrite(TRIG, HIGH);
  delayMicroseconds(10);  //Triggerを10usの間High Levelに設定, 基本はLow Level
  digitalWrite(TRIG, LOW); //この後に超音波モジュールから勝手に40kHzで8パルスが送出される
  
  // 超音波を受け取る
  times = pulseIn(ECHO, HIGH); //超音波を送信終了後から受信するまでの時間
  distance = times * 0.017; //times*340/2*(1/1000000)*100でcmに変換: [us]*[m/s]*[s/us]*[cm/m]=[cm]

  // ディスプレイに表示させる
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.print("distance=");
  M5.Lcd.print(distance);
  M5.Lcd.print("cm\n");
  M5.Lcd.print("ReflectingTime=");
  M5.Lcd.print(times);
  M5.Lcd.print("us");
  delay(1000);
}

そして実験の様子が下記画像。 お酒の缶に向けて超音波を送出し、距離を測ってみた。

DSC_0842.JPG (3.7 MB)

下画像にあるようにいい感じに8.24cmの距離が測定された。 この時の超音波の送受信した時間は485usになっている。

DSC_0843.JPG (3.8 MB)

ここで、実際に測定データから音速を求めなおしてみる。

音速[m/s] = 8.24*2*0.01/(485*1e-6) = **339.79**

すなわち、音速340 m/sが得られていることが分かる。 (データから逆算しているだけなので合っていて当然だが一応確認。)

まとめ

今回は超音波センサを使ってみました。 これも参考リンク丸パクリで実行できたので、これから原理について理解していきたいと思う。 うまいこと利用して追跡ロボット?みたいなものができないかな。。。

他気になるリンクは以下の通り。 参考リンク1 参考リンク2 等を参考に計算式の確認やモータとの組み合わせなども試してみたい。

今後の目標

mycobot-pi上で超音波センサを制御できるようにする。 そして、mycobot-piに取り付けて制御をやりたい。 Ex) - 超音波で人の手の距離を測り、ある範囲まで来たらmycobotが遠のく動きをする。 - ある距離内で反応を始めたらそれに追尾するみたいなやつ。(上の参考リンクのパクリ)

M5Stack GrayでSG90のサーボモータを回す

目的

シリアルサーボを使いこなせるようになりたい。 これができると、mycobot-piに内蔵されているシリアルサーボが自由に制御できるようになると思う。他にも自由に遊び倒せるようになるはず。。。

使用するシリアルサーボについて

SG90の仕様など 上記リンクは秋月電商のリンクだがこのページにデータシートがあるので、こちらをDLして確認することをお勧めする。

サーボ仕様.PNG (419.7 kB)

仕様は上図に示す通り、オレンジ色がPWM信号(回転角指定)、赤がVcc、茶色がGNDである。 色々と参考リンクがあるようだが、今回はこちらのリンクに従って進めていく。

m5stack+SG90のリンク

接続対応

今回はM5stackの16PINのGPIOと5V, GNDPINの3本を使用する。 PWMの分解能を16bit=216-1=65535とする。 ※ビット計算は2n - 1で最大bit数が計算できる。 SG90のデータシートより

  • 0.5ms: -90度

  • 1.45ms: 0度

  • 2.4ms: +90度

となることとPWM周期50Hzと考えると、必要なビットデータは

X = 0.5ms/20ms*65535 = 1638.375 = 1638

となる。つまり、1638が90deg回転に必要なPulse数となるわけである。

配線対応は以下の通りにすればよい。 DSC_0838.JPG (4.3 MB)

ただし、後述するがプログラムの書き込みの最中はピンをすべて外すことに注意。

実際に動かしてみる

とりあえずプログラムを丸々コピーして試してみる。 プログラムを新規作成して、コンパイルから書き込みをしてみると以下のようなエラーが出た。

A fatal error occurred: Failed to connect to ESP32: Invalid head of packet (0x4F)

この原因は色々とあるようだが、下記リンクが参考になった。

ESP32 ( ESP-WROOM-32 , M5Stack )自分的 トラブルシューティング まとめ

このリンクによると、書き込み時にGPIO端子に何かしらピンが接続していると失敗するらしい。

ということで、全部のPINを外してもう一度書き込みをしたら無事できた。 参考リンクによる色々と指定するパルス数に問題はあるようではあるが、とりあえず動いたので一旦放置。

プログラムコード

下記プログラムコードは色々と遊んでわかったことをそのままコメント付きで残している。

#include <M5Stack.h>

int led1 = 16;

//PWMの設定
const double PWM_Hz = 50;   //PWM周波数
const uint8_t PWM_level = 16; // PWM 16bit(0~65535)

void setup() {
  Serial.begin(115200);
  m5.begin();
  pinMode(led1, OUTPUT);
  //モータのPWMのチャンネル、周波数の設定
  ledcSetup((uint8_t)1, PWM_Hz, PWM_level);

  //モータのピンとチャンネルの設定
  ledcAttachPin(led1, 1);
}
void loop() {
  // 1600から9000の間で回転するように指令。
  // i=i+10は更新ごとに10パルス増やすので(9000-1600)/10=740回
  // 740*10ms=7.4sに-90degから90degまで回転、逆回転も7.4sでいく
  for (int i = 1600; i <= 9000; i=i+10) {
    ledcWrite(1, i);
    delay(10);  //20msの遅延
    Serial.printf("%d\n", i);
  }
  for (int i = 9000; i > 1600; i=i-10) {
    ledcWrite(1, i);
    delay(10);
    Serial.printf("%d\n", i);
  }
  // ひたすら-90deg⇔0deg⇔90degまでを1秒ごとに繰り返す動作
  /*
  int deg=1638;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg = 4751;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg = 7864;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg=4751;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg = 1638;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg = 4751;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg = 7864;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  deg = 4751;
  ledcWrite(1, deg);
  Serial.printf("%d\n", deg);
  delay(1000);
  */
}

まとめ

今回はm5stack grayでシリアルサーボを動かしてみた。 後程シリアルサーボ制御用のパルス数の計算について厳密にまとめておきたいと思う。 とりあえず動いてよかった。

WokwiによるESP32のLチカ

目的

物があればそれでやればいいが、実験は手間がかかる。 ということでパソコンで出来るとラク

そういうわけでWokwiを使ってESP32のLチカをやってみたい。

参考にしたLチカリンク

https://zenn.dev/slowhand/articles/20c6ba543f5e74

Wokwiの使い方

まずはページへ飛ぶ https://wokwi.com/

飛んだらGitHubgmailなどでSIGN INする。今回はGitHubSIGN INすることにした。

まずWokwiは既に作ってあるサンプルをそのまま実行して確認することもできる。 これは有志の誰かが作ってくれている。当然自分たちでもアップロードできる。

それは置いておいて今回は新規プロジェクトで作ってみたい。

< >My projectsをクリックして実際に作っていく。

+New Projectをクリックして好きなマイコンを選ぶ。今回はESP32

すると以下の画像のようになる。

右画面の再生マークはシミュレーション開始。 +マークは素子などの部品を選択できる。

左画面はプログラミング画面である。ここまでくればあとはやるだけ。

Lチカしてみる

PINアサイ

https://omoroya.com/esp32-lesson01/

Lチカプログラム

int led = 5;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Hello, ESP32!");
  pinMode(led, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(10); // this speeds up the simulation
  digitalWrite(led, HIGH);
  delay(500);
  digitalWrite(led, LOW);
  delay(500);
}

再生ボタンを押せばあとはプログラムが動作する。

Ltika_ESP32_gif.gif (270.6 kB)

実際のプログラムはZIPでダウンロードできる。 ダウンロードした中身はこちら。 Ltika_ESP32_4.png (7.0 kB)

まとめ

今回は実際にWokwiでESP32のLチカをやってみた。

色々とできるようなので、一般的にやるような温度センサや超音波センサをシミュレーションしてみたい。