こんばんは!
ゆってぃです。

さっそくですが、前回ご紹介したクラスを使って、DMXでステッピングモータを動かすコードを書きました。
コードはGitHubに置いてあります。

動きは極めてシンプルで、DMXの1ch目でモータが動かすターゲットの目標座標を、2ch目でモータ回転速度をもらい、目標座標に向かってモータを回転させるというものです。
ここで言う目標座標とは、ある基準位置からの距離になります。

Arduinoが起動すると、まずモータ回転させ、ターゲットを基準位置まで移動させます。
(基準位置にはセンサがあることが前提)
ターゲットが基準位置まで来ると、センサが反応しモータが停止します。
その後、DMXで受信した値を元に、基準位置からモータを回転させます。
(DMXでの受信値と基準位置からのステップ数は、DmxStepTable.hで定義しています)

なお、移動中に新しいデータを受信しても無視されます。
簡単なクラスの説明を以下に。
-------------
MainTask:メイン処理です。ステートマシンで動いています。(SystemMain.hにステートの定義があります)

MotorCtrl:モータ制御クラスです。下位モジュールとしてStoppableStepperクラスを持ちます。

ReceiverInterface:ポリモーフィズムの為の抽象クラスです。今回、モータ制御の信号はDMXで受け取りますが、将来的に別の通信(例えば、Artnetなど)になったとしても、具象クラスを入れ替えるだけで移植できるようになっています。

DmxReceiver:ReceiverInterfaceの具象クラスです。下位モジュールとして、Conceptineticsクラスを持ちます。

※Sensorクラスは、現状未使用です。
--------------------
実は人から頼まれてこのコードを書いたのですが、レビューをした結果、どうやら要求と合っていないことが判明しました。
これは要求分析がしっかり出来ていなかったせいです。
そのため、システムが大々的に作り直しになってしまいました。。。
(コードとセットで回路も作ったのですが、幸い、回路のほうはそこまで手直しをしなくてよさそうですが…)
要求分析は大事ですね。依頼側にとっても、出来たものを見て初めてわかることもあるので、要求分析は一緒になってしっかりやっておくべきでした。

で、なんやかんやあって、要求を満たすためには、Stepperクラスの様にモータ制御のために処理をブロッキングする仕組みではダメなことがわかりました。
そこで、次回はL6470を使ってこのシステムを改良します。
幸い、ライブラリがGitHub上にあったので、これを使ってシステムを作りたいと思います。

納期は1ヶ月。間に合うかなぁ。。。
関連記事
おはようございます!
昨日の昼間に寝すぎて、昨夜は4時間しか眠れなかったゆってぃです。

早速、前回の続きを行ってみましょう!
今回の記事では、ArduinoのIDEに付属しているStepperライブラリを拡張し、外部から停止可能な
StoppableStepperクラス
をご紹介します。
(名前がダサいのは僕のセンスが無いからです…)

従来のStepperに対し、拡張して出来ることはひとつだけ。
モータを回転させている時、外部から止めることが出来る!
ただそれだけです…。

githubにコードを上げました。
※このコードのライセンスはLGPLv2.1です。ご注意下さい。

基本的な部分は、スーパークラスであるStepperクラスを流用するのですが、ひとつ問題があります。
README.mdにも書きましたが、Stepperクラスは内部メソッドをprivate宣言しているため、サブクラスからは使用することが出来ないのです。
そのため、Stepperクラス自体に手を入れます。
大した変更ではありませんが、念のため元ファイルのバックアップは取っておいてください。

--- Steppere.h ------------------

void step(int number_of_steps);

int version(void);

// private: <- private宣言をコメントアウトして
protected: // <- protected宣言にします
void stepMotor(int this_step);

int direction; // Direction of rotation
unsigned long step_delay; // delay between steps, in ms, based on speed

------------------

次に、StoppableStepperクラスの説明に入ります。
ヘッダは以下の様になっております。

--- StoppableSteppere.h ------------------

File Edit Options Buffers Tools C Help
#ifndef STOPPABLE_STEPPER_H_
#define STOPPABLE_STEPPER_H_

#include "Sensor.h"
#include <stepper.h>

class StoppableStepper : public Stepper{
public:
StoppableStepper(int steps, int pin1, int pin2, int pin3, int pin4);
virtual ~StoppableStepper(){}
int stepWithStopper(int number_of_steps);
void stop();

private:
StoppableStepper();
void step(int number_of_steps);

private:
volatile bool stop_flag_;
};

#endif // STOPPABLE_STEPPER_H_

------------------

新しいメソッドが2つ追加されています。
stepWithStopper()メソッドstop()メソッドです。
(名前がダ・・・以下略)

stepWithStopper()は、Stepper::step()とほとんど使い方は同じですが、2つだけ違いがあります。
1つ目は、モーター駆動中にstop()メソッドが呼ばれると、モータの駆動を停止してメソッドを抜けるということ
2つ目は、入力に対して何ステップ移動したのかを、戻り値で返すこと

です。
2つ目が必要な理由は単純で、戻り値がvoidだと、stop()によりモータが停止されてしまった場合、どの程度の距離移動したのかが制御側で把握できなくなるためです。
なお、入力に負の数を入れると、負の数として値が戻ります。
StoppableStepper.cppをご覧いただければ、何をしているかはすぐに分かると思います。

また、従来のstep()メソッドと同様に、このメソッドはブロッキングです。
つまり、処理が終了するまでは抜けてきません。
ですので、stop()メソッドは、割り込みハンドラ等でコールしてください。

次回は、このクラスを使って何か出来るのかを見ていきましょう^^
関連記事
こんにちは!
昨日は春一番が吹いてとても暖かく、少し嬉しくなったゆってぃです。
でも、今日からまた寒くなってしまい、ちょっぴりがっかりしています。
なんでこう、春を小出しにするんですかね。

最近はサーバやらAIやらに興味が向いていて、電子工作らしい電子工作はお休みしていたのですが
諸事情により再開いたしました!
作るものは明確になっていて
DMX512という舞台照明用の通信規格を使って、ステッピングモータを動かす装置
です。
「DMXって何?」という人は、タマテックさんのサイトが驚異的に分かりやすいので、是非ご覧になってみてください。

DMXは舞台照明用の規格ですが、物理層はRS485なので、RS485トランシーバを使用すればマイコンで送受信できます。
キャノンケーブルやコネクタも、サウンドハウスさんなどで簡単に手に入るので、回路は簡単に作れそうです。

ただ、DMXのプロトコル自体は公開されているものの、ドライバを書くのは少し骨が折れるのでネットで探したところ、arduino向け拡張ボードarduino向けライブラリを発見しました。
(このライブラリはLGPLv3でライセンスされています。Arduino向けというよりAVRマイコン向けなので、別のプラットフォームへの転用は簡単に出来ますが、商用利用する方はリンクされるコードや開発環境(リバースエンジニアリング環境)も公開対象となる場合があるのでご注意下さい。少なくとも、arduinoで使用する場合は動的リンクではないので、商用利用する場合はリンクされる側のコードも公開対象になります)
今回はプロトタイプなので、ArduinoUnoと、この拡張ボードで、DMXモータ制御装置を作りたいと思います^^

電子工作で使用されるステッピングモータとしてはSM-42BYG011が王道ですが、今回はターゲットが少し大型のものでトルクが不足していたため、高トルクのST-42BYH100にしました。(どなたかこのモータのトルク特性図のありかを知りませんか…涙)
使用するモータードライバ(DRV8835)自体は各相あたり1.5Aを流すことが出来るので、ST-42BYH100(1A/相)でも定格上は問題ありませんが、実際に使用する際は回路にヒートシンクを取り付けるなどして放熱を行ってください。

それでは、さっそく作っていきましょう!!!
まず、簡単な外部仕様から。
DMXのプロトコルにはチャンネルという概念があり、0ch~511chまでの好きなチャンネルを自身に割り当てることが出来ます。
(システムの中で重複してはいけませんが、1つのデバイスで複数のチャンネルを用いることは可能です)
今回はテストですので、開発対象のデバイスでは、0chと1chを使うことにしました。
0chで停止位置を、1chで移動速度を設定することにします。
また、モータは以下の条件で停止します。
(1)停止位置までモータを動かした(従来のstep()と同じ動作)
(2)停止センサが反応した
(3)非常停止スイッチが押下された

arduinoではStepperというステッピングモータ用ライブラリが用意されています。
このライブラリは大変便利なのですが、一度モータを回転させ始めてしまう(回転用API:step()をコールする)と、step()関数が終了するまでモータを停止できないという制約があります。
この制約は、実使用ではそれなりに大きなインパクトを与える場合があります。

通常のモータ制御プログラムでは、停止スイッチが押された場合や、停止センサが反応した場合に、即座にモータを停止したいというシーンが多いです。
例えば、インクジェットプリンタ等でキャリッジをステッピングモータで動かしている場合、キャリッジがガイドシャフトの端まで来たら、モータを停止する必要があります。そうしないと、恐らくプリンタは破損してしまうでしょう。
(余談ですが、ゆってぃは前職ではプリンタの組み込みソフトエンジニアをやっていました)
今回のターゲットはセンサ反応時にモータを停止したいので、この仕様のままではいけません。
そこで、以下の3つの案を検討しました。

(1)step()関数の引数を小さい値にしてループで処理し、ループ毎にセンサ出力ポートを見に行き、停止信号が出ていたらモータを停止する。
(2)Stepperクラスを継承したStepperWithSensorクラスを作り、内部でセンサ出力ポートを見て、センサー反応時にモータを停止する。
(3)Stepperクラスを継承したStoppableStepperクラスを作り、stop()メソッドを新たに実装し、stop()メソッドが呼ばれたらモータを停止する。step()関数は、センサ反応時の割り込みハンドラでコールする。

(1)は最も実装が簡単ですが、設計としてはイマイチです。
センサを見るために定期的にモータを停止するので、モータの励磁タイミングがずれるためスムーズな駆動が難しくなりますし、センサー反応と実際の停止位置にズレが生じる可能性もあります。

(2)も(3)は一長一短ですが、(3)の方が望ましいと言えます。
なぜなら、(2)の場合はモータとセンサが密結合となり、モータ停止の条件がセンサに固定されてしまうからです。(3)はモータ停止の条件がセンサによらないので、例えば緊急停止スイッチを付けた場合などにも対応可能です。
より、今回は(3)で進めることにしました。

※本当にしっかり設計するなら、停止判断クラスを定義し、そのサブクラスのインスタンスをStoppableStepperクラスにコンポジションする、所謂ストラテジパターンにするのが定石です。(2)をより抽象的にした設計ですね。でもあくまでプロトなので、ご勘弁を・・・汗

長くなるので、コードは次の記事で紹介します。
関連記事
こんばんは、ゆってぃです!
昨日から左膝を曲げると痛いのですが、これが間接痛というヤツでしょうか…?

遅ばせながら、最近になってディープラーニングを勉強し始めました。
Amazonでオライリー社の参考書を買って、読んでいます。
非常に読みやすい上、大切な部分はきっちり押さえているので、オススメの一冊です。

この本に書かれた内容でディープラーニングの学習は可能なのですが、環境によっては、この本に書かれた事前準備だけだと上手くpythonが動かない可能性があるので、メモを残します。

OS:ubuntu 16.04(64bit)

○準備
0.Anacondaのインストール
https://www.continuum.io/downloads
上記URLから、Anacondaのインストーラをダウンロードしましょう。
ダウンロードできたら、ダウンロードしたインストーラと同じディレクトリで
$ bash Anaconda3-4.2.0-Linux-x86_64.sh
と入力しましょう。
インストールが成功すると、ホームディレクトリにanaconda3というフォルダが作成されます。

1.pyenvのインストールとPATHの設定
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv

ダウンロード完了後、ホームディレクトリの.bash_profileに以下を追記します。
(.bash_profileが無い場合は、作ってください)

export PATH=$PATH:$HOME/anaconda3/bin
export PATH=$PATH:$HOME/.pvenv/bin
eval "$(pyenv init -)"

因みに、bash_profileに記載せず直接pyenvを叩こうとすると、「なに横着しようとしてるんや。bashrcかbash_profileに書けやコラ」と言われます。。。

ちゃんと書けたら、読み込ませましょう。
$ source ~/.bash_profile

2.python 3.5.0のインストール。
$ pyenv install 3.5.0

もしかしたら、ここで
ERROR: The Python ssl extension was not compiled.
のようなエラーが出るかもしれません。これはlibsslが無いよというエラーです。
その場合は、
$ sudo apt-get install libssl-dev
と打ち、libsslをインストールしてください。

3.pythonの設定
$ pyenv shell 3.5.0

以上で準備は完了です。
バンドでHPを作っているのですが、せっかくだから分散開発しようということで、さくらVPS上にgitを使った開発環境を構築しました。
その時のメモです。

前提:
・gitがインストールされていること
・リポジトリ等は、開発者用のグループでread/write/exec権限があること

①ベースとなるリポジトリを作成(簡単のため、ゆってぃのホームディレクトリ)
cd /home/yutty(ユーザ名)/git_test
git init

②みんながアクセスするリモートリポジトリ(ベアリポジトリ)の作成
cd /var/git(例)
git clone --bare /home/yutty/git_test test.git

③誰かがpushしたら、テスト用サーバーに自動でpullされるように、ベアリポジトリ上にhooks/post-receiveを追加
Qiitaに記事がありました

④テスト用WEBサーバをDigest認証に
参考サイト
httpd.confの設定は、AuthDigestFileではエラーになったので、AuthUserFileとしています。

以上です。
関連記事
ご訪問者様
プロフィール

ゆってぃ

Author:ゆってぃ
経歴7年の組み込み系・制御系エンジニアです。
("ど素人"という文言は取りました…笑)
ソフトウェア開発経験ゼロの状態から、なんとか実務がこなせるようになってきた現在に至るまでの経験を、備忘録代わりに綴っていきたいと思います。
入門者の方、大歓迎!
(上級者の方、ごめんなさい…)

あと、ブログには全然関係ないですが、Bumpy Headというバンドのギターをやっています。
ライブ情報なんかも書いたりすることがあるので、その時に「行ってもいいよ~」といった感じのコメントを戴けると、泣いて喜びます(泣)
ブログ読んでくださってる方なら、チケット代サービスしちゃいます!

最後に…滅多に流用することは無いでしょうが、このブログに書かれているソースは、特に指定の無い限りMITライセンスとします。ただし、一部それ以外のものもございますのでご注意下さい。
※ブログのリンク先にあるコードに関しては、リンク先のポリシーに従ってください。

最新記事
最新コメント
カテゴリ
RSSリンクの表示
メールフォーム

名前:
メール:
件名:
本文:

twitter
リンク
ブロとも申請フォーム
スポンサードリンク