べれすく!

素人プログラマによるモノづくりやブログ生活を話すブログ

【スポンサーリンク】

量子コンピュータの仕組みを説明するこの本がとても分かりやすかった話

少し前から、人工知能が話題ですね。
それの影響なのか違うのか、量子コンピュータが注目されています。
私も興味があって、いろいろ調べてみたのですが、イマイチわからん...。
そんなわけで、理解を放棄していたわけなんです。

ところがこの間、本屋をぶらぶらしていたら、見つけてしましました。
わかりやすい本を!

 

いちばんやさしい量子コンピューターの教本

f:id:Veresk:20190728143217j:plain

これ、とってもわかりやすいです。
大雑把に説明してから詳細を書くっていう書き方が理系の人っぽいですね。

内容として、

ざっくりいうとこんな感じでした。
図やイラストが多く、仕組みのわかりやすいです。
各分野の説明も丁寧なので、画像処理や機械学習や深層学習、量子化学計算やセキュリティに関心がある人は一冊持っていて、損がないと思います。

内容に関係ないのですが個人的にうれしかったのがこれ! f:id:Veresk:20190728150935j:plain この本、書籍を買うとPDFがネットからダウンロードできるのでスマホタブレットでも読める!
通学時間が長い僕にとって、スマホで読めるのはとってもありがたいです。 技術書や参考書って電子書籍だけだと実践の時に不便ですが、暇なときに読もうとするには大きすぎてカバンから出すのが面倒なんですよね。
 
冷却装置の点や万能性の点からも、個人的に量子コンピュータを揃えるのはまだまだ無理そうですね。
私も、「いつかめっちゃハイスペックな量子コンピュータ作るぞ!」って思っていたのに残念です。
 
ちなみに、量子コンピュータを知りたいけど本買うほどでもないかなって人はこの動画がおすすめ

www.youtube.com

英語だけど日本語字幕に対応してるから見やすいです。 内容も現在のコンピュータの説明からしてくれるのですっごくわかりやすい。 でも本に比べると詳細さに欠けるので、この動画を見て興味が出れば本を買うといいと思います。  

それでは、また!

【Arduino】Arduino同士をI2C通信でつないでみた話

つなぎ方

いろいろなサイトで調べたけどイマイチわからなかった。
とりあえず、こんな感じで各ArduinoのSDA同士、SCL同士、グラウンド同士をつないでみる。  
f:id:Veresk:20190704011238j:plain  
Arduino IDEには最初からI2Cのライブラリが入っている。
それにはサンプルも付属している。
 

f:id:Veresk:20190704012509p:plain

master_writerとslave_receiverの組み合わせで試したところうまくいったようだ。

ライブラリの解説

ぶっちゃけArduino 日本語リファレンスWireの欄を一つずつ呼んだほうがいいと思う。
 

使用方法関係なく使う関数

Wire.begin(address)

まずはこれ。
基本的にはsetup関数内で動かす。
これがないとWireライブラリは動かない。 引数のaddressは複数機器をI2Cで使わない限りは、適当でいいと思う。
複数使う場合はmaster側とslave側で数値を合わせる必要がある。
 

Wire.write(value)

これは、データを送信をする関数...って考えていい。 正確には送信用に保管するって感じかな。
下で説明するWire.onRequest()やWire.endTransmission();で保管したデータを送信する。  

Wire.read()

これは送られてきたでデータを読み出すもの。
戻り値がデータなので、変数に代入して使う。 送られてきたタイミングで実行しないと受け取れないのでWire.available()をうまく組み合わせるといい。
 

Wire.available()

送られてきたデータが何バイトかを戻り値とする。 送られてきていなければ0。5文字のアルファベットなら5。 こんな感じでバイト数がそのまま帰ってくる。  

マスターからスレーブへのリクエス

f:id:Veresk:20190705015806p:plain

Wire.requestFrom(address, count) 

これは、slave側にリクエストを送る関数。 masterのArduinoのプログラムに記述する。
addressにはbeginのaddressと同じものを書く。
countにはリクエストするバイト数を入れる。
サンプルではcountを6にして、"H" "e" "l" "l" "o" "(改行)"を受け取っていた。
1バイトは数字なら0~255、文字なら一文字だ。
複数バイトをリクエストしても送られてくるのは1バイトずつなので注意したい。
 

Wire.onRequest(handler)

上のrequestFromと対になる関数。
masterからリクエストが来た時に実行する関数を決める。
slaveのArduinoのプログラムに記述する。
handleにはリクエストされたときに実行する関数名を入れる。
リクエストされた瞬間に割り込み実行されるのでslave側で動かしているプログラムがある場合は注意が必要だ。
 
 
 

マスターからスレーブへのリクエス

f:id:Veresk:20190705022238p:plain

Wire.beginTransmission(address);
Wire.write(value);
Wire.endTransmission();

この3つはセットだと考えていいと思う。
それ以外の使い方をしたことがない。
これは、masterからslaveに数値や文字を送るものだ。
使い方は簡単。adressにbeginと同じものを入力。
valueに送りたい数値や文字を入れます。
文字の場合は""(ダブルクォーテーション)でくくる。  

Wire.onReceive(handler)

これはmasterから何らかの値が送られてきた場合に作動する関数だ。
slaveで作用する。
handlerには送られてきた時に実行する関数名を入れる。
onRequest同様、割り込みによる動作なので気を付けたい。
 

ちょっとした応用例

Arduino(master)ーArduino(slave)ーセンサ
 
とつながっているとする。
ところがこのセンサ、値の取得に数秒かかるようだ。(超音波やRGBカラーセンサ)
その間masterには待機させる。 f:id:Veresk:20190707153620p:plain いろいろ書き方があるだろうけど私はこう書いた。

//master

#include <Wire.h>

void setup() {
  Wire.begin();        //I2C通信スタート!
  Serial.begin(9600);
}

void loop() {
  byte value = 0;
  Wire.requestFrom(8, 1, true);//アドレス8(適当)で1バイトのデータをリクエスト!
  while (Wire.available() != 1) {}    //1バイトのデータが帰ってくるまで空ループ
  value = Wire.read();                //空ループ抜けたら値読み込み
  Serial.println(value);
}

 

//slave

#include <Wire.h>

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

void loop() {
  delay(100);
}

void Request() {
  byte value = Senser();
  Wire.write(value);
}

byte Senser(){
    //センサの起動と値の取得
  }

間違ってたらコメントでもください

【Arduino】PID制御でライントレースする話

ロボットの自動走行の一種にライントレースというものがある。
地面に書かれた線に沿ってロボットを走らせるのだ。

それをやってみよう  

  • 必要なもの
    • 光センサー x お好きな数だけ
    • 車体
    • Arduino

今回はこの光センサーを4つ使おう。

akizukidenshi.com

f:id:Veresk:20190629181324j:plain

こんな感じで両方ギリギリ線に乗らないようにはんだ付け。
端の2つはクロスラインっていって十字に貼られたラインを読んだときに挙動を変えられるようにつけた。普通は1から3つでいいかな。マイコンカーとかだともっといっぱいついてるけど。
 
受光側に可変抵抗をつけてアナログ値を揃えられるようにした。 このセンサーをArduinoで使ってる人は結構多いから詳しくはそっち見たほうがいいと思う。
こことかすごくわかりやすい。

deviceplus.jp

車体は転がってたDCモーターとモータードライバつないで片輪ずつPWMで制御できるようにしただけ。

さて、本題のPID制御をしよう。
 

monoist.atmarkit.co.jp

 
ここを参考に理解しながら作ってみる。
結果、こんな感じになった。
 

#define DELTA_T 0.010// FlexiTimer2で決めた周期
#define KP 0.165  //KP、KI、KDは車体の重さとか積んでるモーターで変わるから自分で調整してね。
#define KI 0.013
#define KD 0.0007

//Senser_Value:センサー値、Target_Value:閾値
float PID_LIGHT_L(signed short Senser_Value, signed short Target_Value){   //左車輪のPID制御

   static signed long diff_L[2];
   static float integral_L;

   float p,i,d;

   diff_L[0] = diff_L[1]; //前回の偏差の値を格納
   diff_L[1] = Senser_Value  - Target_Value; //ターゲットとの差を格納
   integral_L  += ( diff_L[1] + diff_L[0])/ 2.0 * DELTA_T ; //積分はグラフの面積なので平均値取って長方形にして値x時間

   p = KP * diff_L[1] ;   //差に比例して上昇
   i = KI * integral_L ;   //積分値
   d = KD * ( diff_L[1] - diff_L[0] )/DELTA_T ; //秒数がmsなので"偏差の差"を繰り返すだけで十分きれいな"偏差の微分"になる

   return math_limit(p+i+d);


}


float PID_LIGHT_R(signed short Senser_Value, signed short Target_Value){   //右車輪のPID制御(右車輪とアルゴリズムは一緒)

   static signed long diff_R[2];
   static float integral_R;
   
   float p,i,d;

   diff_R[0] = diff_R[1]; 
   diff_R[1] = Senser_Value  - Target_Value; 
   integral_R  += ( diff_R[1] + diff_R[0])/ 2.0 * DELTA_T ; 

   p = KP * diff_R[1] ;
   i = KI * integral_R ;
   d = KD * ( diff_R[1] - diff_R[0] )/DELTA_T ; 

   return math_limit(p+i+d);


}

//////////////////PID値の制限//////////////////
float math_limit(float pid) {
  pid = constrain(pid, -255 , 255); //定義域-255 <= pid <= 255

  return pid;
}

 
もしかしたらグローバルの関数使ってるかもしれん。エラー出たらちょこっといじって対処して。
ここで出た値をこんな感じで車輪のPWM値に足し引きしてやれば線に追従するはず。

#include <FlexiTimer2.h>

void setup() {

  /*********モーター*********/
  pinMode(PIN_IN1_R, OUTPUT);
  pinMode(PIN_IN2_R, OUTPUT);
  pinMode(PIN_IN1_L, OUTPUT);
  pinMode(PIN_IN2_L, OUTPUT);

  /*********モニタ出力設定********/
  Serial.begin(9600);// 9600bpsでシリアル通信のポートを開きます

  /*********FlexiTimer********/
  FlexiTimer2::set(10, FLASH); //タイマー割り込み入れたほうが正確になる。面倒ならFLASH()の中身をloop()の中に入れてもいいよ。詳しくは FlexiTimer2で調べてみて。
  FlexiTimer2::start();

}

void loop() {
   RUN_RIGHT(1, Power_R);
   RUN_LEFT(1, Power_L);
}



void FLASH(){

  int sensor_RIGHT = analogRead(A5) ;        //センサーから読込む//右センサ値
  int sensor_LEFT = analogRead(A7) ;         //センサーから読込む//左のセンサ値

  Pid_val_R = PID_LIGHT_R(sensor_RIGHT, 830);
  Pid_val_L = PID_LIGHT_L(sensor_LEFT, 830);

  Power_R = constrain((80 + Pid_val_R - Pid_val_L), 0 , 255);//走り出しはPWM=80。ここを速度制御すれば安い低トルクモータでもなんとかなるかも。
  Power_L = constrain((80 + Pid_val_L - Pid_val_R), 0 , 255);
}

loop文の中に入ってるモータ動かす関数の中身はこんな感じ。いらないと思うけど一応ね。

/***右車輪***/
#define PIN_IN1_L 9 //DIGITAL_pin 9番
#define PIN_IN2_L 8 //DIGITAL_pin 8番
#define PIN_VREF_L 11 //DIGITAL_pin 11番 //※PWM用
/***左車輪***/
#define PIN_IN1_R 5 //DIGITAL_pin 5番
#define PIN_IN2_R 4 //DIGITAL_pin 4番
#define PIN_VREF_R 6 //DIGITAL_pin 6番 //※PWM用


//////////////////右側モータ//////////////////
void RUN_RIGHT(short int n , short int power) {

  switch (n) {
    case 0://後進方向
      digitalWrite(PIN_IN1_R , LOW);
      digitalWrite(PIN_IN2_R , HIGH);
      break;

    case 1://前進方向
      digitalWrite(PIN_IN1_R , HIGH);
      digitalWrite(PIN_IN2_R , LOW);
      break;

    case 2://ブレーキ
      digitalWrite(PIN_IN1_R , HIGH);
      digitalWrite(PIN_IN2_R , HIGH);
      break;

  }
  analogWrite(PIN_VREF_R , power);//出力調整
}



/////////////////左側モータ////////////////
void RUN_LEFT(short int n , short int power) {

  switch (n) {
    case 0://後進方向
      digitalWrite(PIN_IN1_L , HIGH);
      digitalWrite(PIN_IN2_L , LOW);
      break;

    case 1://前進方向
      digitalWrite(PIN_IN1_L , LOW);
      digitalWrite(PIN_IN2_L , HIGH);
      break;

    case 2://ブレーキ
      digitalWrite(PIN_IN1_L , HIGH);
      digitalWrite(PIN_IN2_L , HIGH);
      break;

  }
  analogWrite(PIN_VREF_L , power);//出力調整
}

読みづらいソースコードで申し訳ない。
ブログに上げるつもりもなかったから、きれいに書いてないんだ。
ゲインの調整がかなり過剰だが、動かすとこんな感じになる。

www.youtube.com

 
徐々に線に向かって収束しているのがわかると思う。
こんな記事でも何かの参考になれば幸いだ。

初心者サバゲーマーな私にぴったりな電動ガンの話

突然だが、持ってる電動ガンの話をしよう。

 

私が持っているのはG&GのRK74 CQBだ。

クリンコフ(AKS74U)が元?のスポーツ用架空銃だ。

 

サバゲがしてみたいと友人に相談したら、取り回しがしやすくお勧めだといわれたので購入。

 

f:id:Veresk:20190620233245j:plain

これは買ってきてすぐぐらいの写真

今はいろいろパーツがついてる。

 

感想としては”わからん”

他の銃を使ったこともないしね。仕方ないね。

 

ただ、弾はまっすぐに飛んでるし、フルメタルでかっこいい。

初めてのサバゲでもそこそこヒット取れた。

 

ポジティブな記事はいっぱいあるし、ここではネガティブに説明していこう。

 

まず先っちょ。ハイダーから。

これうるさい。超うるさい。

クリンコフのハイダーとは似ても似つかない。

前方に拡声器つけてるみたいな感覚。

今は自作のサプレッサーつけてる。消音効果があるかどうかは微妙だけど、元のハイダーよりはいいかな。

 

次、前のレール周り。

剛性は高い。

気になるのは他のRKシリーズではそこにバッテリーを入れるはずのところがあかないこと。

ロック機構はついているのに。まぁ、あかなくても支障ないけどね。

Key-Modは使ってない。でもかっこいい。

 

サイトはひどい。

まずアイアンじゃ見えにくい。精度は「ないよりはまし」ぐらい。

なにが悪いかってこれ取れないんだけど。

レシーバーカバーがこのサイトで本体とリンクしてる。

おかげで大型スコープが干渉する。

邪魔すぎる…

 

マガジンは給弾不良がたまにある。

いざという時「あれ、弾が出ねぇ」ってことがある。

あと、今はなじんできたけどマガジン装填が固すぎる。

買う時の試射で店員も苦労する固さ。

マルイのマガジンと互換性あるらしいし給弾不良考えるとそっちのがいいかもね。

 

チャージングハンドルは好き。

これ、電動なのに最後まで下がるんだよ。

最高かよ。

ところがどっこい、ここにはバッテリーが入ってる。

小さめのバッテリーにすれば入れながらでも最後までハンドル引けるよ。

 アンビである必要はなかったかな。

寝かせられないのがきつい。

 

レシーバーカバーもよくないねぇ。

細いサイトで本体とリンクしてるのもそうだけど、留め具が固すぎる。

AKのレシーバーを留めるギザギザの留め具の色がハゲかけてる。
これってAKシリーズあるあるなのかな?

バッテリーも大きいのはいらないね。

 

グリップもトリガーも文句なし。

発射はキレがあるしグリップも程よい太さ。

 

ストックも悪くない。

折りたためればもっとよかった。

頬あてつけたい。

 

 

 

余談だけどこの架空銃、ロシアの銃器メーカ、ORSIS社のP-18 ShARifっていう銃に結構似ていて、最近は気に入ってる。

f:id:Veresk:20190620235809j:plain

 

今日はこんなとこかな。

自己紹介する話

こんにちは。Vereskです。

 

これから、できるだけ多くの記事を書いていこうと思います。

まぁ、基本自分飽き性なんでいつまで続くかわからないですけどね。

 

興味のあること、やってみたこといろいろ載せていく予定ではありますが、HTMLとか面倒なんで、しばらくは見たまま編集になるかと思います。

 

どうぞ、よろしく。