家にあった謎のステッピングモーターを使ってみた話

こんかいは、家にあった謎のステッピングモーターを動かしました。

 前にも謎のLCDを使ったことがありますが、今回のモーターもその時のLCDとセットになってたやつだと思われます。
 何年か前に、中国からArduino周辺機器セット?みたいなものを買ったことがあってそれに入ってたものだと思うのですが、このセットはすごく不親切でデータシートはおろか型番の一覧すら入っていません。それなので、型番を本体から読んでネットから関連情報を持ってくるまで謎の部品になるのです。

 そんなわけで、今回のステッピングモーターはこれです。
DSC01159
DSC01158
 裏に「STEP MOTOR」と書いてあります。また、書いてあることが正しければ5V耐圧のようです。

 また、付属していたドライバー基板はこんな感じです。
DSC01160
 これ、左にあるピン4本が入力ピンで、下にあるピンが電源の+と-なのですが、5~12Vと書いてあります。ICはトランジスタアレイで、電源平滑用のコンデンサは入っていますが、レギュレータのようなものはどう考えてもありません。モーターの耐圧は5Vと書いてあったのですが、果たして12Vもかけて大丈夫なんでしょうか?

 まあ、そんなことは置いといて配線です。
 今回はドライバとArduino双方の電源を共通の5Vにしました。また、ドライバの1,2,3,4番ピンをArduinoの8,9,10,11番ピンにさします。

 コードですが、今回はArduinoのAtepperライブラリを使います。
#include <Stepper.h>

const int number_of_steps = 32;
const int steps_output_rev = 32 * 64; // 2048
const int CW = 1;
const int CCW = -1;

Stepper stepper(number_of_steps, 8, 10, 9, 11);

void setup() {
  stepper.setSpeed(1000);
}

void loop() {
  int steps;

  steps = get_step_by_rev(CW, 1);
  stepper.step(steps);
  delay(3000);

  steps = get_step_by_rev(CCW, 1);
  stepper.step(steps);
  delay(3000);  
}

int get_step_by_rev(int dir, float rev){
  return dir * (steps_output_rev * rev);  
}

 このようにすると回ります。Stepperの解説はまた違う機会に。気になる人はArduino公式リファレンスを見てください。


 実際に動かすとこんな感じです。
 そこそこトルクは強いようです。


 今回はここまでです。次回はまたなんか作りたいと思います。それではまた今度。

パズルゲームを作った話

今回はProcessingでパズルを作ってみました。

 動作はこんな感じです。一列揃えると消えて、消えたマス分の得点が入ります。
 まず詰むことはないのでゲームオーバーの処理がありません。タイムアタックで得点を競えばいいんじゃないですかね? もしくはちゃんと詰む状態になるようにブロックを追加するかですね。

 10*10の配列に入れているだけなので難しいことは何もやっていません。for,switch-case,ifだけで書いているので、大学の授業の三回目ぐらいの知識があればできると思います。

 ダウンロードしたい人はここからダウンロードしてください。

 今回はここまでです。最近はバイトで月給15万円を超していて忙しいですが、そのうち何かやると思います。それではまた今度。

Processingで遊んだ話

やることもなかったのでProcessingで遊んでみました。

①ただバウンドさせるだけ
 何も難しいことはしていなく、y座標が画面外になったら速度のy方向成分を反転させているだけです。

②x方向にも動くようにする
 速度のx方向成分にランダムに生成した初速を与えています。

③当たり判定みたいなのを作ってみる 運動量保存則とか、運動エネルギー保存則とか、考えるのめんどくさいのでこの辺で終了しました。


 今回はここまでです。次回はパズルゲームでも作ろうと思います。それではまた今度。

ArduinoでTETRiSっぽい何かを作った話

 なんとなくテトリスっぽい何かを作ってみました。

 いろいろなソフトをつなげるのはめんどくさいのでArduinoIDEにいろいろ表示します。
 こんな感じの実行画面にしました。

tetris

 まあそこそこ見やすいのではないでしょうか?

・回路
tetris_ブレッドボード

 回路というか入力インターフェースですね。スイッチは左から「回転」「落下」「左」「右」です。

・コード
 コードはここからダウンロードできます。

 まあ一応解説でも、
loop() メインでいろいろ処理をしています。
f5() ブロックの落下とゲームオーバーの判定を行っています。
freeze() 落下できないブロックを硬直させています。
rot() ブロックの回転をします。動作不良があるかもしれません。
set() 新しいブロックの配置を行っています。
GO() ゲームオーバーの判定と初期化を行っています。
del() そろった列の消去とそれより上の列のブロックの落下を行っています。
right() 移動中のブロックを右に動かします。
left() 移動中のブロックを左に動かします。



 結局途中で飽きちゃったので動作が怪しいですが、まあいいでしょう。
 今回はここまでです。次回は何か適当にやろうと思います。それではまた今度。

ミニマップを追加した話

 最近ずっと作っているメーターにミニマップをつけてみました。

 流れは以下の通りです。

 me-ta-

 Arduino-Arduino間でI2Cをしても、なぜかGPSのデータを送ることができません。それなので、座標のデータを演算するときにStringで出てくるのでそのまま一文字ずつmasterに送っています。
 そのデータとセンサーの値を一定周期でProsessingに送りそれを表示します。

 このような感じで動作します。

 今回はここまでです。プログラムがまだ不安定なのでそこを改良したいと思います。それではまた今度。

Arduino-Arduino間でI2Cをした話

 前にもやった気がしなくもないですが、自分が完全に忘れていたので今回はi2cをします。

 まず、勘違いしていたのですが、SoftwareSerialや普通のシリアル通信はI2Cとは関係ありません。なんでこれを間違えていたのかわからないのですが、なぜかRX,TXピンで通信しようとしていました。正しくはSDA(A4),SCL(A5)ピンですね。

 とりあえず今回はArduino同士でI2Cをします。

・配線

Untitled Sketch_ブレッドボード
 SDAとSDA、SCLとSCL、GNDとGNDをつなぎます。

・プログラム

①master
5秒おきにリクエスト送っているだけです。
#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  Wire.requestFrom(8, 6);

  while (Wire.available()) {
    char c = Wire.read();
    Serial.print(c);
  }
  Serial.println("");
  delay(500);
}

②slave
リクエストが来た時にセンサーの値を返します。
#include <Wire.h>

void setup() {
  Wire.begin(8);
  Wire.onRequest(requestEvent);
}

void loop() {
  delay(100);
}

void requestEvent() {
  Wire.write("hello ");
}

 これを二台のArduinoに入れて動かすとmasterのシリアルモニタにhelloと表示されます。


 今回はここまでです。次回はどうにかします。それではまた今度。

メーターの改良をした話

 今回も開発していくメーターですが、去年使ったデータはすべて表示できるようになりました。今になって時計を表示するのを忘れてることを思い出しましたが、そのうち追加したいと思います。


 今回行ったことはほとんど前回前々回のコピペなのでプログラムは載せませんが、一つ不具合が出ました。
1
 これはArduinoからシリアル通信で送られてくるデータなのですが、二つしかデータが格納されていません。Arduinoから送られてきたデータを、一つの配列に格納して使うようなプログラムにしているので、データが格納されていないところがあるとエラーを吐かれます。それなので、読み取るかどうか判断する部分部分のプログラムを"
if (inString != null && split(trim(inString),',').length==4) {
のようにすることで解決しました。

 そんなわけで出力は下のようになります。
me-ta-
 それっぽくなってきているんじゃないでしょうか?

 今回はここまでです。次回はまたちょっと改良しようと思います。それではまた今度。

Processingで複数のデータをいっぺんに送った話

 今回もProccessingをやっていきます。今回は、いくつかのデータをArduinoからProcessingに送っていこうと思います。

 前々回やった方法でまとめて送ることもできるとは思いますが、めんどくさかったのでStringを使うことにしました。


・Arduino
 今回は3つにデータを1秒おきに送ろうと思います。
void setup() {
  Serial.begin(9600);
}

void loop() {
  int valueh = analogRead(0);
  int values = analogRead(1);
  int valuev = analogRead(2);
  Serial.print(valueh);
  Serial.print(",");
  Serial.print(values);
  Serial.print(",");
  Serial.print(valuev);
  Serial.print("\n");

  delay(1000);
}


・Processing
 Processingのコードは以下のようになります。
import processing.serial.*;
Serial myPort;

int []data = new int [3];

void setup() {
  myPort = new Serial(this, Serial.list()[1], 9600);
}

void draw() {
}

void serialEvent(Serial p) {  
  String inString = myPort.readStringUntil('\n');

  if (inString != null) {
    inString = trim(inString);
    data = int(split(inString, ','));
    println(data);
  }
}
 このプログラムの大事なところは以下の通りです。
① String inString = myPort.readStringUntil('\n');
 ここで改行(\n)までをいっぺんに読み取ります。例:"valueh,values,valuev\n"
② inString = trim(inString);
 trim()で改行(\n)を削除します。例:"valueh,values,valuec"
③ data = int(split(inString, ','));
 split()で区切られた文字列を配列に直し、int()でint型に直します。例:{valueh,values,valuec}

 このようにすることでArduinoからProcessingにint型の複数の値を簡単に渡すことができます。

キャプチャ
 出力はこのような感じで出てきます。

 今回はここまでです。次回は前回作ったメーターを改良し、スピード、温度、電圧を表示できるようなものを作りたいです。それではまた今度。

Processingでメーターを作った話

 前回に引き続き開発をしていきたいと思います。今回は各種メーターの基礎を作っていきたいと思っています。


 Arduinoのプログラムはそのままでセンサーの値を1バイトずつ出力します。

・Processing
import  processing.serial.*;

Serial  serial;
int[]   data;
int recv_dataH;

void setup() {
  size(800, 600);
  smooth();
  background(0,0,0);
  data = new int [width];
  serial = new Serial( this, Serial.list()[1], 9600 );
  speedmeter();
}

void speedmeter(){
  strokeWeight(3);
  stroke(255,0,0);
  fill(30,30,30);
  arc(200, 200, 220, 220, PI, PI*2.000, PIE);
  arc(200, 200, 220, 220, PI, PI*1.875, PIE);
  arc(200, 200, 220, 220, PI, PI*1.750, PIE);
  arc(200, 200, 220, 220, PI, PI*1.625, PIE);
  arc(200, 200, 220, 220, PI, PI*1.500, PIE);
  arc(200, 200, 220, 220, PI, PI*1.375, PIE);
  arc(200, 200, 220, 220, PI, PI*1.250, PIE);
  arc(200, 200, 220, 220, PI, PI*1.125, PIE);
}

void draw() {
  speed();
}

void speed(){
  strokeWeight(4);
  fill(30,30,30);
  stroke(100,50,0);
  arc(200, 200, 201, 201, PI, PI*2, PIE);
  strokeWeight(3);
  stroke(255,0,0);
  arc(200, 200, 200, 200, PI, PI+recv_dataH*0.002, PIE);
  fill(255);
  textSize(32);
  text(recv_dataH, 220, 200);
}

int serialEvent(Serial port) {  
  if ( port.available() >= 3 ) {
    if ( port.read() == 'H' ) {
      int high = port.read();      
      int low = port.read();
      recv_dataH = high*256 + low;
      println(recv_dataH);
    }
  }
  return(recv_dataH);
}

 ゴリ押しで図形を表示しています。特に開設することもないでしょう。改善点はそれぞれの図形のxy座標を変数にしていじりやすくするとかですかね。
キャプチャ

 出力してみるとこのような感じ。そこそこいい感じになっていると思います。

 動かしてみるとこんな感じです。結構それっぽくなったと思います。


 今回はここまでです。次回はいろいろなデータをいっぺんに表示できるようにしたいと思います。それではまた今度。

ProcessingでArduinoからのデータをグラフ化した話

前回の続きとして、今回はセンサーの値をArduinoで読み取り、それをProcessingでグラフにします。

 
 まず、int型は2バイトです。しかし、シリアル通信は1バイトずつデータを送るので、センサーの値を送るのにはひと手間かかります。


・Arduino側のプログラム

  1. void setup() {
  2.   Serial.begin(9600);
  3. }

  4. void loop() {
  5.   int value = analogRead(0);
  6.   Serial.write('H');             // ヘッダの送信
  7.   Serial.write(highByte(value)); // 上位バイトの送信
  8.   Serial.write(lowByte(value));  // 下位バイトの送信
  9. }
ヘッダーをつけて二つに分割して送ります。


・Processing側のプログラム

  1. import  processing.serial.*;

  2. Serial  serial;
  3. int[]   data;

  4. void setup() {  
  5.   size(400, 250);
  6.   data = new int [width];
  7.   serial = new Serial( this, Serial.list()[1], 9600 );
  8. }

  9. void draw() {
  10.   background(10);
  11.   strokeWeight(2); 
  12.   stroke(0, 255, 0);

  13. //グラフの描画
  14.   for (int i=0; i<data.length-1; i++) {
  15.     line( i, convToGraphPoint(data[i]), i+1, convToGraphPoint(data[i+1]) );
  16.   }
  17. }

  18. void serialEvent(Serial port) {  
  19.   if ( port.available() >= 3 ) {
  20.     if ( port.read() == 'H' ) {
  21.       int high = port.read();      
  22.       int low = port.read();
  23.       int recv_data = high*256 + low;
  24.       
  25. //時系列データを更新
  26.       for (int i=0; i<data.length-1; i++) {
  27.         data[i] = data[i+1];
  28.       }
  29.       data[data.length-1] = recv_data;
  30.     }
  31.   }
  32. }

  33. float convToGraphPoint(int value) {
  34.   return (height - value*height/1024.0);
  35. }

 このようにするとできます。まあそもそも、データをそのままグラフにして表示するのならArduino IDEのシリアルプロッタを使えばいいのですが...
 一応出力はこのようになります。シリアルプロッタと違うところは背景や線の色を自由に変えられるところでしょうか...
キャプチャ



 この中で大事なのは以下に抜き出した部分です。

  1. void serialEvent(Serial port) {  
  2.   if ( port.available() >= 3 ) {
  3.     if ( port.read() == 'H' ) {
  4.       int high = port.read();      
  5.       int low = port.read();
  6.       int recv_data = high*256 + low;

 この部分はたびたび使いますが、大量のデータをいっぺんに送るときの方法です。このブログでは、GPSを使ったときに似たようなことをやっていて、センサーから送られてきた様々なデータから必要なデータを持ってくるときに使っていました。このような処理はよく使うので、プログラムがちょっとできる人なら見たことがあると思います。

 今回はここまでです。次回はメーター類の基礎をできればいいと思います。それではまた今度。

2020/10/13更新 プログラムがたぶん読みやすくなったはずです。
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

読者登録
LINE読者登録QRコード