So-net無料ブログ作成
検索選択

ヤードポイント一括転換 その9 [Arduino]

「どうせなら、終了時の状態のまま再起動出来るといいですね!」って。

確かにその方が自然なことですね。

終了時の各サーボ角度を次回起動時に反映させればいいようです。

ネットで調べてみると、たどり着いた先はEEPROMメモリでした。

Arduinoは3個のメモリを積んでいます。

Arduino MEGA 2560 R3では、スケッチがコンパイルされてCPUが理解出来る.hexファイルを格納するフラッシュメモリが256 KB 。(内8 KBをブートローダーで使用)

パソコンのメインメモリにあたるSRAMが8KB。

そしてEEPROMメモリが4KB

Arduinoを起動すると、最初にフラッシュメモリ内のブートローダー(OSみたいなもの)が読み込まれ、次にフラッシュメモリに格納されている.hexファイル(スケッチ)を、実行していく流れです。

サーボ角度の変数情報はメインメモリにあります。

フラッシュメモリは電源を切ってもスケッチは消えませんが、フラッシュメモリに格納されているスケッチは書き換えることは出来ません。

調べていくと、フラッシュメモリにはデータが保存出来ることが解りましたが、書き換え不可の固定データのみとなってます。

一括転換スケッチの、void loop()の最初に書かれてるスケッチの、

int angle_1 = servo_p1.read();
int angle_2 = servo_p2.read();
int angle_3 = servo_p3.read();

このangle_xが最新の各サーボ角を記憶しています。

この変数値はメインメモリのSRAM内にありますが、SRAMは電源を切ってしまうと消えてしまします。


そこで、EEPROMの登場です。

EEPROMに書き込まれたデータは、スケッチで読み込み、消去、書き込みができ、電源を切っても消えません。

void loop()内で、angle_xの値が変わるたびに、書き換えるようにすればいいわけです。

ArduinoにはEEPROMライブラリもありました。

変数として直接扱うことは出来ませんので1byte単位のデータとして扱います。

初期値、「120120120」をスケッチでEEPROMに書き込んでおき、1番線を選択したとすと、「606060」、2番線選択なら「1206060」と番線選択が変わるたびにEEPROMに書き換えていき、次回起動時に前回終了時のサーボ角度データをセットすればいいのではないでしょうか。

*左右の角度の数値は桁を揃えたほうがいいようです。左角度は99度までに抑えるべきでしょうね。


理屈は解っても、スケッチにするとなるとこれは難儀しそうです。(-_-;)



コメント(4) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その8 [Arduino]

「4線ヤード一括転換 ver.1」の完成で終わりと思っていたら、いまいち動作が気に入らないところがあるようです。

servo_p1.write(servo_p1L);
servo_p2.write(servo_p2L);
servo_p3.write(servo_p3L);

void setup()内で書かれている、各サーボの設定角を決める動きが気になるご様子。

servo_p1.write(120);
servo_p2.write(120);
servo_p3.write(120);

解りやすく書くと、ここで各サーボ角度を一気に120度に動かしています。
(前回終了時に60度にあったサーボのみです。)

決められた角度(120度)になるだけですが、「ギュン!」っていう感じに動きます。

コンデンサ充放電でポイントを切り替えるよりはソフトなのですが、「糸バネ」ありでポイントにサーボを換装した方には精神衛生上よろしくないご様子のようです。

勢い余って、サーボホーン代わりのステンレス棒が受け側から外れる可能性が無きにしも非ずですからね。

そこで、解決方法なのですが、2つばかり考えました。

1の方法は、新たに「終了ボタン」を追加して、「終了スケッチ」で全てのサーボを60~120度に戻すスケッチを書くことです。

遊び終わる最後に「終了ボタン」を押してから電源を切ると、次に起動した時に「ギュン’!」するサーボはありません。

2の方法ですが、た625さんの記事のスケッチをご覧ください。

int pos;
int servo_p1R = 74;
int servo_p1L = 89;
int servo_p2R = 79;
int servo_p2L = 94;
int servo_p3R = 82;
int servo_p3L = 97;
int servo_p4R = 75;
int servo_p4L = 90;

ここで各サーボの左右角度を決めるのは同じです。

servo_p1.write(81);
servo_p2.write(86);
servo_p3.write(89);
servo_p4.write(82);

見慣れない角度を設定していますね。

servo_p1を見ると、

int servo_p1R = 74;
int servo_p1L = 89;

右74度と左89度の真ん中の81度を設定しています。

if(angle_1==81)
for(pos = 81; pos>=servo_p1R; pos-=1)
{
servo_p1.write(pos);
delay(60);

そして、81度から74度へservo_p1をスローアクションで動かしています。

一旦、中立の位置にサーボを動かしてから、設定位置にゆっくり動かしてショックを和らげているわけです。

15度を一気に動かすより、89度から81度と8度動かす方が見た目もわずかですからね。

ただねぇ~、仮にですよ、100個のサーボが全て左を向いていたら、再起動した時にサーボ一個あたり3秒掛かるとしたら3x100=300秒=5分もスタンバイまで掛かってしまいますねぇ。(-_-;)

なんだかなぁ~って感じもしますね。

終了ボタンの方が現実的な気もしますね。


こんなことをやっていたら、更に追い打ちをかけるメールが来ました。

「どうせなら、終了時の状態のまま再起動出来るといいですね!」って。

難しい要望が・・・・(-_-;)

ではでは。


コメント(0) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その7 [Arduino]

頭の中がやっと切り替わりました。(自分かよ)

悲痛な叫びメールの他にもいろいろと要望がありまして、スケッチを書き換え、なんとか使えるスケッチになりました。

<4線ヤード一括転換 ver.1>

#include <Servo.h>

#define SW_p1 22
#define SW_p2 23
#define SW_p3 24
#define SW_p4 25

#define LED_1 30
#define LED_2 31
#define LED_3 32
#define LED_4 33

#define CHIEN 38

Servo servo_p1;
Servo servo_p2;
Servo servo_p3;

int pos;

int servo_p1R = 60;
int servo_p1L = 120;
int servo_p2R = 60;
int servo_p2L = 120;
int servo_p3R = 60;
int servo_p3L = 120;

void setup()
{
pinMode(SW_p1,INPUT);
pinMode(SW_p2,INPUT);
pinMode(SW_p3,INPUT);
pinMode(SW_p4,INPUT);

pinMode(40,OUTPUT);
pinMode(41,OUTPUT);
pinMode(42,OUTPUT);

pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(LED_3, OUTPUT);
pinMode(LED_4, OUTPUT);

pinMode(CHIEN, OUTPUT);

servo_p1.attach(40);
servo_p2.attach(41);
servo_p3.attach(42);

digitalWrite(CHIEN,HIGH);

servo_p1.write(servo_p1L);
servo_p2.write(servo_p2L);
servo_p3.write(servo_p3L);

digitalWrite(LED_4,HIGH);
}

void loop()
{
int angle_1 = servo_p1.read();
int angle_2 = servo_p2.read();
int angle_3 = servo_p3.read();

//1番線開通

if(digitalRead(SW_p1)==HIGH){
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_1,HIGH);

if(angle_1==servo_p1L)
for(pos = servo_p1L; pos>=servo_p1R; pos-=1)
{
servo_p1.write(pos);
delay(60);
}

if(angle_2==servo_p2L)
for(pos = servo_p2L; pos>=servo_p2R; pos-=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==servo_p3L)
for(pos = servo_p3L; pos>=servo_p3R; pos-=1)
{
servo_p3.write(pos);
delay(60);
}
}

//2番線開通

if(digitalRead(SW_p2)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_2,HIGH);

if(angle_1==servo_p1R)
for(pos = servo_p1R; pos<=servo_p1L; pos+=1)
{
servo_p1.write(pos);
delay(60);
}

if(angle_2==servo_p2L)
for(pos = servo_p2L; pos>=servo_p2R; pos-=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==servo_p3L)
for(pos = servo_p3L; pos>=servo_p3R; pos-=1)
{
servo_p3.write(pos);
delay(60);
}
}

//3番線開通

if(digitalRead(SW_p3)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_3,HIGH);

if(angle_2==servo_p2R)
for(pos = servo_p2R; pos<=servo_p2L; pos+=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==servo_p3L)
for(pos = servo_p3L; pos>=servo_p3R; pos-=1)
{
servo_p3.write(pos);
delay(60);
}
}

//4番線開通

if(digitalRead(SW_p4)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,HIGH);

if(angle_3==servo_p3R)
for(pos = servo_p3R; pos<=servo_p3L; pos+=1)
{
servo_p3.write(pos);
delay(60);
}
}
}


変更点は、

int servo_p1R = 60;
int servo_p1L = 120;
int servo_p2R = 60;
int servo_p2L = 120;
int servo_p3R = 60;
int servo_p3L = 120;

ここです。

ここで前記事でメモった各サーボの左右の角度を書きます。

実際サーボ角はサーボの個体差があって綺麗に数字は並びません。

振り角度もせいぜい15度くらいです。

ここだけを変更すれば、各番線スケッチのサーボ角も同期して変更になります。


これにて「4線ヤード一括転換」のスケッチの解説を終わりますって訳にはいきません。

西の方から、更なる要望が届くのでした。(-_-;)


ヤードポイント一括転換 その8に続く。





コメント(0) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その6 [Arduino]

これまではブレッドボードで回路を組んで、サーボをを動かすという、いわば実験ボードの段階でした。

スケッチ自体もまだプロトタイプの段階で、JAM線はこのスケッチを拡張していました。


ここからは実際にPECOポイントにサーボを換装して、レイアウトに配置するわけなのですが、ここで問題が発生したのです。

「逆だ~~!」(-_-;) ←西の方からの悲痛な叫びのメール

逆転2.jpg

サーボを「右」にすると、ポイントは「左」に転換するのです。

現役を離れて1年、まったく気づきませんでした。(-_-;)

頭の中を180度切り替えないといけません。

そこで、ポイント配置図を上下さかさまに見ます。ヾ(-_-;)ぉい!

4線ヤード反転図.jpg


本線側から考えていたものを、番線側から考えるように切り替えます。

4番線(本線)の開通はservo_3が「左」で、1番線の開通は、servo_1、servo_2、servo_3が「右」となります。

あくまでもサーボの向きであって、ポイントの向きは変わりません。


冷却期間を置くために、横道にそれて、サーボをPECOポイントに換装するときの注意点を書きます。

袋から出したサーボは、「90度出し」を実施してください。

ほぼ袋から出したサーボは90度にセットされているのですが、まれに違う場合があるのです。

サーボ付属のカットしたサーボホーンを挿し込んでから、スケッチを実行してください。

//90度出しスケッチ
#include <Servo.h>

Servo servo_p1;

void setup()
{
pinMode(22,OUTPUT);
servo_p1.attach(22);
servo_p1.write(90);
}
void loop()
{
}

デジタル22ピンにサーボの制御線を繋いでスケッチを実行してください。

P1060814.JPG

「90度出し」を実行後、サーボホーンが動かないように注意して、ピンバイスを直角に立てて下穴を開け、穴にステンレス線や真鍮棒を瞬着で接着すると、垂直に立ちます。

この後、サーボをポイントに固定するのですが、トングレールは左右の主レールに触れない位置で(右でも左でもない)真ん中で固定することです。

拘る方はこの方法を取ることをお勧めします。

サーボ換装後、左右の角度調整は上の「90度出しスケッチ」を利用して決めます。

servo_p1.write(90);の「90」を少しずつ変えて、左右の角度を決めたら忘れずにメモしておきます。

さらに、スケッチの初期設定の角度をセットしたまま、レイアウトに固定してください。

本日はここまで。


コメント(9) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その5 [Arduino]

ここで、完成したスケッチをArduinoに書きこみ動かしてみます。

ソネットブログのYouTubu動画の貼り付け方法が変わってしまって解らないのでリンク貼ります。

4線ヤード一括転換動画

この動画はプロジェクトチーム向けにリンクも張らずにYouTubeにアップしてたのですが、いつのまにか再生回数が200近く行ってますね。(-_-;)

この時は「右70度」「左90度」でやっていたと思います。

注意してみて頂きたいのは、4番線選択時で立ち上がった状態から、1番線選択で全てのサーボが「左」に転換、さらに2番線選択をするとservo_p1のみ「右」に転換するだけです。

2番線選択スケッチでは、全てのサーボの動きを書いていますが、1番線選択時にservo_p2とservo_p3はすでに「左」に転換されていたので、2番線開通に必要なservo_p1のみ「右」に転換しています。

「0:12」あたりの3番線選択と「0:26」あたりの3番線選択を見比べてみると、servo_p1の向きが違うのが解ると思いますが、(0:12は「右」0:26は「左」)どちらも3番線開通には同じことです。

4番線選択時のサーボの向きの並びが違うことがありますが、4番線開通には、servo_p3のみ「右」を向けばいいことになります。

ではでは。

次回更新は火曜日になります。







コメント(6) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その4 [Arduino]

さて、スケッチの核心部となる、void loop()内のスケッチを書いていきます。

void loop()
{
int angle_1 = servo_p1.read();
int angle_2 = servo_p2.read();
int angle_3 = servo_p3.read();

あれ?これって変数宣言ですねぇ・・・・

親爺ぃさん、変数宣言はvoid setup()の前に書くって言っていませんでした?

そんなお堅いことは言わずに、ここに書いてあるのですから、ここでいいのです。

void setup()の前に書くのなら、int pos;の次の行に
int angle_1;
int angle_2;
int angle_3;

void loop()内で、
{
angle_1 = servo_p1.read();
angle_2 = servo_p2.read();
angle_3 = servo_p3.read();

と、書けば同じことになります。

void loop()内でも、変数宣言は出来ますよってくらいに考えてください。

意味は「servo_p1.read();の中身の数値を angle_1に代入せよ」となります。

void setup()内でservo_p1.write(60);で60度に初期設定していますので、servo_p1.read();の中身は「60」ってことになり、angle_1もの中身も「60」ってことになります。

他のサーボのangle_2もangle_3も、同じ「60」ですね。


さて、お手元に印刷したポイント配置図をご覧ください?

1番線開通のスケッチから書いていきます。

現在、ポイントは全て「右」の60度になってます。

1番線を開通させるには、各ポイントを「左」の120度に切り替えるわけですね。

if(digitalRead(SW_p1)==HIGH){

もし、1番線選択スイッチを押したとき、SW_p1=デジタル22番ピンが「HIGH」になったら。

digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_1,HIGH);

番線開通表示LEDのLED_2・LED_3・LED_4を「LOW」にして、LED_1を「HIGH」にします。

Arduinoのvoid loop()内では、一度「HIGH」にすると「LOW」命令をしない限り点灯したままになります。

1番線選択スイッチを押されるのは、何番線を選択した後かは解りませんので、1番線開通表示LED以外を消灯させてから、1番線開通表示LEDを点灯させます。

if(angle_1==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p1.write(pos);
delay(60);
}

スローアクション部分です。

もし、angle_1==60ならservo_p1を60度(右)から120度(左)まで1度づつ0.06秒ごとに変化させよってことになります。

for(pos = 60; pos<=120; pos+=1)
{
servo_p1.write(pos);
delay(60);

変数「pos」の値の変化ですが、

pos = 60で、

pos<=120(pos=60から120まで)

pos+=1(pos=60を1ステップずつ)

変化させていくことになります。

1回目で「61」2回目で「62」3回目で「63」と120になるまで繰り返します。

繰り返しの時間ははdelay(60);の0.06秒ごとになりますので、ここをdelay(1000);に変えると右から左にポイントが転換するのに1分掛かることになります。(笑)

servo_p2もservo_p3も同じように書きます。

ここまでのスケッチです。

void loop()
{
int angle_1 = servo_p1.read();
int angle_2 = servo_p2.read();
int angle_3 = servo_p3.read();

if(digitalRead(SW_p1)==HIGH){
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_1,HIGH);

if(angle_1==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p1.write(pos);
delay(60);
}

if(angle_2==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p3.write(pos);
delay(60);
}

}
}

void loop()内は延々と繰り返しスケッチが実行されています。

int angle_1 = servo_p1.read();

このangle_1の変化はどうなるのでしょうか?

最初の読みで、angle_1は「60」でした。

しかし、スローアクションでサーボ角は「60」から「120」に変化しました。

2回目のループで、

int angle_1 = servo_p1.read();

サーボ角を読むと「120」になってますので、angle_1は「120」となります。

すると
if(angle_1==60)は「60」ではないので、以下のスケッチは実行しません。

for(pos = 60; pos<=120; pos+=1)
{
servo_p1.write(pos);
delay(60);

他の番線選択スイッチが押されない限り、servo_p1は120度(左」になったままになります。


1番線開通のスケッチが終わりましたので、次は2番線開通のスケッチです。

if(digitalRead(SW_p2)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_2,HIGH);

if(angle_1==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p1.write(pos);
delay(60);
}

if(angle_2==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p3.write(pos);
delay(60);
}

}

説明の必要はないと思いますが、

if(angle_1==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p1.write(pos);
delay(60);
}

servo_p1を「左」から「右」にするだけで、servo_p2とservo_p3は1番線開通と同じ「右」から「左」にするだけです。

仮に1番線を選択したのちに2番線を選択すると、servo_p2とservo_p3は「左」に向いているので動かないことになります。


3番線開通のスケッチは、

if(digitalRead(SW_p3)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_3,HIGH);

if(angle_2==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p3.write(pos);
delay(60);
}

}

servo_p1はどちらを向いていても関係ないのでスケッチを書く必要はありません。

servo_p2を「左から右」とservo_p3を「右から左」にします。


4番線開通のスケッチは、

if(digitalRead(SW_p4)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,HIGH);

if(angle_3==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p3.write(pos);
delay(60);
}
}

servo_p1とservo_p2は関係なのでスケッチに書く必要はありません。

servo_p3だけ「左から右」にするだけです。

以上で、スケッチが完成しました。



#include <Servo.h>

#define SW_p1 22
#define SW_p2 23
#define SW_p3 24
#define SW_p4 25

#define LED_1 30
#define LED_2 31
#define LED_3 32
#define LED_4 33

#define CHIEN 38

Servo servo_p1;
Servo servo_p2;
Servo servo_p3;

int pos;

void setup()
{
pinMode(SW_p1,INPUT);
pinMode(SW_p2,INPUT);
pinMode(SW_p3,INPUT);
pinMode(SW_p4,INPUT);

pinMode(40,OUTPUT);
pinMode(41,OUTPUT);
pinMode(42,OUTPUT);

pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(LED_3, OUTPUT);
pinMode(LED_4, OUTPUT);

pinMode(CHIEN, OUTPUT);

servo_p1.attach(40);
servo_p2.attach(41);
servo_p3.attach(42);

digitalWrite(CHIEN,HIGH);

servo_p1.write(60);
servo_p2.write(60);
servo_p3.write(60);

digitalWrite(LED_4,HIGH);
}

void loop()
{
int angle_1 = servo_p1.read();
int angle_2 = servo_p2.read();
int angle_3 = servo_p3.read();

//1番線開通 SW(1)ON:サーボ(A)左・サーボ(B)左・サーボ(C)左

if(digitalRead(SW_p1)==HIGH){
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_1,HIGH);

if(angle_1==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p1.write(pos);
delay(60);
}

if(angle_2==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p3.write(pos);
delay(60);
}

}

//2番線開通 SW(2)ON:サーボ(A)右・サーボ(B)左・サーボ(C)左

if(digitalRead(SW_p2)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_2,HIGH);

if(angle_1==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p1.write(pos);
delay(60);
}

if(angle_2==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p3.write(pos);
delay(60);
}

}

//3番線開通 SW(3)ON:サーボ(B)右・サーボ(C)左

if(digitalRead(SW_p3)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_4,LOW);
digitalWrite(LED_3,HIGH);

if(angle_2==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p2.write(pos);
delay(60);
}

if(angle_3==60)
for(pos = 60; pos<=120; pos+=1)
{
servo_p3.write(pos);
delay(60);
}

}
//4番線開通 SW(4)ON:サーボ(C)右

if(digitalRead(SW_p4)==HIGH){
digitalWrite(LED_1,LOW);
digitalWrite(LED_2,LOW);
digitalWrite(LED_3,LOW);
digitalWrite(LED_4,HIGH);

if(angle_3==120)
for(pos = 120; pos>=60; pos-=1)
{
servo_p3.write(pos);
delay(60);
}
}

}


要点は、開通に絶対必要なポイントの向きが反対ならば、向きを変えるスケッチを書くことです。

もう一点は、開通に必要でないポイントのスケッチは書く必要が無いということですね。


以上で、4線ヤードのスケッチの解説を終わりますが、ご理解いただけたでしょうか?

このスケッチはヤード専用ではありません。

複数のポイントを一括で切り替えて、走行ルートを開きたい時とかにも、ボタン一つで操作出来るようになりますので、ご利用してください。


次回は、このスケッチでは実戦では不都合があるので、その辺を修正していきます。

ではまた。


コメント(2) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その3 [Arduino]

ヤードポイント一括転換のスケッチを書いていきます。

と、言われてもプログラミング経験のない方には、どうしたもんだか解りませんよね。

最低限のスケッチの知識として、下記の書籍を読んでみることをお勧めします。

Arduino入門書.jpg
Arduinoをはじめよう 第3版 (Make:PROJECTS)

他にも入門書はありますが、他の書籍はあまり役立ちませんでした。(-_-;)

役に立ったのは、ネットで公開されているスケッチでした。

スケッチをコピペして動かしてみて、何故そうなるのか?スケッチを読み解くことが一番の近道のように思います。

と、言う事で入門書を読んだ方々を対象に解説していきます。

読んだことのない方々は、ちんぷんかんぷんでしょうが、入門書を読んでから見れば理解出来ると思います。

Arduino新規作成.jpg

Arduino IDEの新規ファイル作成画面です。

Arduinoでサーボを扱うには、Servoライブラリを使うのが簡単です。

Arduino IDEのメニューバーにある[スケッチ』→[ライブラリをインクルード]→「Servo]とクリックして、Servoライブラリを使えるようにインクルードします。

ライブラリ.jpg

「//」で始まるコメント行はこの後消しておきましょう。


void setup()の前に 、Arduinoの各ピンの割り当てや変数の宣言を書いていきます。

#include <Servo.h>

#define SW_p1 22
#define SW_p2 23
#define SW_p3 24
#define SW_p4 25

#define LED_1 30
#define LED_2 31
#define LED_3 32
#define LED_4 33

#define CHIEN 38

「#define SW_p1 22」の意味は、Arduinoのデジタル22ピンを「SW_p1」という名前にしますよってことです。

(コンパイル時に「SW_p1」と記述されている部分がすべて22という値に置き換えられます。)

以下、同じように各ピンを割り当てて、名前を付けていきます。

「SW_p*」は、番線選択スイッチ、「LED_*」は、開通番線表示LEDになります。

最後の「#define CHIEN 38」ですが、前記事の「Arduino用電源モジュール」の「CHIEN線」を、デジタル38番ピンに繋ぎます。


Servo servo_p1;
Servo servo_p2;
Servo servo_p3;

次に、サーボの割り当てです。

上から順に割り当てられるので、ポイントAのサーボは「servo_p1」という名前を割り当て、ポイントBのサーボは「 servo_p2」という名前を割り当て、ポイントCのサーボは「servo_p3」という名前を割り当てます。

以降、ポイントAを扱うにはには、 「servo_p1」を扱うことになります。

int pos;

次に「int pos;」ですが、pos(ポジション)という名前の変数は整数ですよって意味です。

(posは後でスローアクション動作のスケッチで使います。)

こういう変数宣言は、void setup()の前に書きます。

ここまでのスケッチです。

#include <Servo.h>

#define SW_p1 22
#define SW_p2 23
#define SW_p3 24
#define SW_p4 25

#define LED_1 30
#define LED_2 31
#define LED_3 32
#define LED_4 33

#define CHIEN 38

Servo servo_p1;
Servo servo_p2;
Servo servo_p3;

int pos;

void setup() {

}

void loop() {

}



次にvoid setup()内のスケッチを書いていきます。

void setup()
{
pinMode(SW_p1,INPUT);
pinMode(SW_p2,INPUT);
pinMode(SW_p3,INPUT);
pinMode(SW_p4,INPUT);

番線選択スイッチの各ピンをインプット(入力)に設定します。

Arduino内臓プルアップ抵抗は使わずに、外部プルダウン抵抗を使ってください。


pinMode(40,OUTPUT);  //servo_p1の制御線を繋ぐ
pinMode(41,OUTPUT); //servo_p2の制御線を繋ぐ
pinMode(42,OUTPUT); //servo_p3の制御線を繋ぐ

この3ピンは各サーボの制御線に繋ぐピンをアウトプット(出力)に設定します。

Arduino内臓プルアップ抵抗は使わずに、外部プルダウン抵抗を使ってください。

pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(LED_3, OUTPUT);
pinMode(LED_4, OUTPUT);

開通番線表示LEDの各ピンをアウトプット(出力)に設定します。

pinMode(CHIEN, OUTPUT);

CHIEN線をアウトプット(出力)に設定します。

servo_p1.attach(40);
servo_p2.attach(41);
servo_p3.attach(42);

servo_p1をデジタル40ピンに、servo_p2をデジタル41ピンに、servo_p3をデジタル42ピンに割り当てます。

digitalWrite(CHIEN,HIGH);

サーボの誤作動防止に為に、ここで初めてサーボの電源をONにします。

servo_p1.write(60);
servo_p2.write(60);
servo_p3.write(60);

各サーボを60(度)に初期設定します。

プログラム起動時は、各サーボの角度を設定しないといけません。(のちの「read() 」で読み取れなくなります。)


前記事のポイント配置図を見てください?

4番線(本線)が開通してるのが自然なので、ポイントCだけを「右」にするだけで、ポイントAとポイントBは「右」にする必要はないのですが、ここは全てのポイントを右に統一することでのちの混乱を防げます。

3基くらいのポイントなら問題はないのですが、これが20基30基となった時、各ポイントがバラバラでは訳わからなくなりますね。

初期設定で向きは統一すべきです。

digitalWrite(LED_4,HIGH);

4番線開通LEDを点灯します。

ここまででvoid setup()内のスケッチを終わります。

これまでのスケッチです。

#include <Servo.h>

#define SW_p1 22
#define SW_p2 23
#define SW_p3 24
#define SW_p4 25

#define LED_1 30
#define LED_2 31
#define LED_3 32
#define LED_4 33

#define CHIEN 38

Servo servo_p1;
Servo servo_p2;
Servo servo_p3;

int pos;

void setup()
{
pinMode(SW_p1,INPUT);
pinMode(SW_p2,INPUT);
pinMode(SW_p3,INPUT);
pinMode(SW_p4,INPUT);

pinMode(40,OUTPUT);
pinMode(41,OUTPUT);
pinMode(42,OUTPUT);

pinMode(LED_1, OUTPUT);
pinMode(LED_2, OUTPUT);
pinMode(LED_3, OUTPUT);
pinMode(LED_4, OUTPUT);

pinMode(CHIEN, OUTPUT);

servo_p1.attach(40);
servo_p2.attach(41);
servo_p3.attach(42);

digitalWrite(CHIEN,HIGH);

servo_p1.write(60);
servo_p2.write(60);
servo_p3.write(60);

digitalWrite(LED_4,HIGH);
}

void loop()
{
}

ここでコンパイルしてみて、Arduinoに書き込んでみます。

起動すると、各サーボの角度が順に60度になり、4番線開通LEDが点灯します。

今日はここまです。







コメント(4) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その2 [Arduino]

た625の工作室」で公開された5線ヤード(以降JAM線)のスケッチは、た625さんの要望をてんこ盛りした特別バージョンです。

元は私がソフトウェア開発に携わった、4線ヤードを拡張したバージョンになります。

JAM線を解説するより、元となった4線ヤードの解説のほうが分かり易いので、こちらでやらせていただきます。

また、Arduinoを使ってサーボ駆動によるポイント転換をやられてる方々も、修正版になりますので是非ご覧ください。


IMG_8666s.jpg
(この画像は印刷してお手元に置いてください。)

4番線が本線の1番線から3番線がヤードという配置です。

ポイント転換用サーボが3個になります。

注)通常ポイントは定位や反位、直進側や分岐側と呼びますが、これらの呼び方は忘れてください。
ポイント「右」、ポイント「左」と呼ばないと混乱いたします。

ポイントAとポイントBは「右開き」、ポイントCは「左開き」となっていますので、これらを定位だの反位だとの言っては、頭の中がこんがらかってしまします。(-_-;)

ポイントはあくまで設置状態のまま、「右」「左」と呼んでいきます。(本線から見た場合)


例)1番線開通は、ポイントA「左」ポイントB「左」ポイントC「左」です。



一括転換スケッチの考え方なのですが、「無駄な動きはさせない!」を基本コンセプトに開発いたしました。


1.番線選択スイッチは「押しボタン」を使う。

た625さんはロータリースイッチとマトリクスを使った転換をおやりになりました。

ロータリースイッチでも一括転換は可能ですが、一発転換が出来ません。

例えば、1番線から4番線に切り替えるには、2番線、3番線とポイントを切り替えてから4番線にやっと切り替わるのです。

一発転換を実現するには「番線選択押しボタン」でダイレクトに切り替えるのが有効と考えました。

押しボタンスイッチも「モーメンタリ」を使えば、いちいち「オルタネイト」のようにOFFにする操作は必要がないので無駄が省けます。


2.サーボに無駄な動きはさせない。

Arduinoのスケッチ(プログラム)は、上から下へ順番に実行して行くため、同時に2個のサーボを動かすことはできませんので、無駄のない転換をさせないといけません。

ポイント配置図を見ながら、動かす必要のないサーボは放っておけばいいと考えました。

本線からの進入目線で見ると、

1番線を開通させるには、ポイントA・B・Cが全て「左」です。

2番線を開通させるには、ポイントAが「右」、ポイントBが「左」、ポイントCが「左」です。

3番線を開通させるには、ポイントBを「右」、ポイントCを「左」、ポイントAはどちらを向いていても関係ないので無視できます。

4番線は、ポイントCのみ「右」で、ポイントAとBは無視できます。


以上の考え方でスケッチを書いていきます。

4線ヤードブログ用.jpg
(この画像も印刷してお手元に置いてください。)

Arduino MEGA 2560 R3のデジタルピンを割り当てた配線図です。

P1060813.JPG

ブレッドボードに組んでみました。


次回は解説を交えながらスケッチを作っていきます。














コメント(0) 
共通テーマ:趣味・カルチャー

ヤードポイント一括転換 その1 [Arduino]

た625の工作室」から飛んできた皆さん、こんにちは。

ソフトウェア開発班の親爺ぃです。

家庭内事情により、1年間もブログを休止していたある日のこと、たまに見るお方のブログ記事に・・・

ポイント一括転換」に苦労しているようです。

最後まで見ると「今回の記事は、こちらを参考にさせていただきましたm(_ _)m」とリンクが貼られていまして、なんと私のブログを参考にしていたではないですか。

確かに、私の記事では、2個のサーボを動かすスケッチは書きましたが、ヤードみたいな各ポイントを個別に切り替えることは出来ません。

書いたことないスケッチに興味を抱き、コメントしたのがソフトウェア開発を担当する事の始まりでした。

同時に、サーボの誤作動に悩まされているご様子で、これまた電子回路に精通しているlofthonsenさんをも巻き込んで、3人タッグでヤード一括ポイントの完成を目指したわけです。

ヤード一括ポイントのスケッチ自体は3日で頭の中では完成していたのですが、難関だったのがサーボの誤作動対策でした。

そこで、ヤードポイント一括転換のスケッチ(プログラム)の解説の前に、サーボの誤作動対策用の周辺回路の紹介から始めますって予定でいたら、た625さんが紹介してしまったのね。(-_-;)

今更記事を変更するのも面倒なので、このままアップしてしまいましょう。

Arduino用電源モジュール(遅延回路付き)5.jpg


このArduino電源モジュールは、「Nゲージレイアウト国鉄露太本線建設記」の管理人のlofthonsenさんが回路設計・推奨されたもので、Arduinoを使ってサーボ駆動によるポイント転換を、サーボの誤作動なく行う上で必須となる回路となります。

サーボでスローアクションポイントにしてる方も必須となります。

この回路は、ACDC12Vアダプターから、12Vと5Vを出力する単一電源になります。

2電源.jpg

上図のように、Arduino用12V、サーボ用5Vと二電源にすると、使用条件によってサーボが誤作動を起こします。

起動時は、Arduino用電源→サーボ用電源と入れ、終了時はサーボ用電源→Arduino用電源と切れば問題は起きませんが、順番を誤ると確実にサーボが誤作動いたします。

決まり事を守ってやればいいことなのですが、人間にミスはつきものです。

電源を二電源から単一電源にすることでミスを回避することが出来ます。

他に「2SA1359」と「2SC1815」のトランジスタで構成する回路や「CHIEN線」がありますが、スケッチの解説のときにご説明いたします。

電源モジュール外部ジャック.jpg
<基板表 >


電源モジュール外部ジャック裏基板.jpg
<基板裏>

上図の基板は、た625さんがJAM2017に出展した時の、基板上に電源スイッチを配置したものです。

実際にご自分で製作する場合は、トグルスイッチや電源表示LEDは外部に引き出して製作されると思います。

余裕のある部品配置.JPG

ケースに収めてみました.JPG

親爺ぃは暇だったので、床に転がっていたケース(タカチ SU-140)に組み込んでみました。
(ケースはPW15-4-11Sを推奨)

使用パーツリストは、製作の仕方によって若干変わりますのでご自分でアレンジされてください。

三端子レギュレーターの熱が気になる方は、ヒートシンクを取り付けてください。

パーツリスト.jpg
<秋月電子通商調べ>

大まかなシステム図です。

システム概略図2.jpg


次回、スケッチの解説になります。



コメント(6) 
共通テーマ:趣味・カルチャー

とりあえず・・・ [Arduino]

前記事の対応策が解りましたので、ご報告です。


1)の起動時のサーボのあばれ現象ですが、入出力ピンに内臓プルアップ抵抗を使わずに、外部プルアップ抵抗を使ってください。

スケッチもそのように変更してください。

確実に起きなくなります。


2)のプルプル現象は、サーボ本体からすぐに電源線と信号線を離してくれればかなり鳴かなくなります。

サーボライブラリのdetach()関数で切り離すのはおやめください。

<追加情報>7/31
サーボ用別電源は必要ありません。
サーボから出ている赤及び茶コードはArduinoの5V及びArduinoのGNDから取ってください。 サーボの動力電流はわずか3mAも流れません。 Arduinoの出力ピンは1ピンあたり最大40mAが流せます。 サーボの1個くらいは余裕で動かせます。 仮に50機のサーボによるスローアクションポイントであっても、全てArduinoから取ってください。 Arduinoのプログラムは同時に数個のサーボは動かせません。
動かせるのは1個だけです。
<追加情報>8/28
と、これでうまく行ったと思ったのですが、問題は根深かったです。
しかし、やっとサーボの暴れを抑えることが出来ました。
その記事は近日公開いたします。
しばし、お待ちください。



コメント(4)  トラックバック(0) 
共通テーマ:趣味・カルチャー