microマックイーンを使ってライントレース機能をプログラムする/第42回アソビワークショップ開催報告

何をやったか

小学3年生は

  • モーターの操作
  • ラインセンサーの使い方
  • 真偽値表を使ったライントレースの理論

小学1年生は

  • とりあえずライントレースできるプログラムを使ってみる
  • 自分なりにライントレースしてみる

振り返り

「どうやったらライントレースできるのか?」を整理して教えようとしたがそれが良くなかった気がする。というのも1年生のmayuchikuwaさんは理屈抜きで「自分の考える最強の動き方」をまず自力で考えていた。その失敗を経て初めて理屈を教えた方が食いつきが良かったのでは?と思った。

当日のPR資料

豆を投げつけたくなる鬼ロボットを作ろう/第41回アソビワークショップ開催報告

明けましておめでとうございます。2022年最初のイベントは報告記事を書き忘れました・・・。

表題のテーマで「鬼ロボット」を作りました。と言っても鬼限定にはせず、各々好きなものをロボットにかぶせてもらいました。発端はmayuchikuwaさんの「亀ロボットを作りたい」から始まりました。

簡単な作り方は以下の記事に書いてますのでよければご覧ください。

https://loochs.org/what-can-make-micro-maqueen-looks-better/

そういえば作品の写真をあまり撮れてなかった・・・。

What can make micro-maqueen looks better?マイクロマックイーンの見栄えをどうにかしたい

これの見た目どうにかならんのか?

https://www.dfrobot.com/product-1783.html

これを見たら閃いた

発砲どんぶり(お椀)で亀を作る:自由工作

上記リンク先の発泡どんぶりそのままだとデコレーションしづらい(油性ペン使えない)ので以下のアイテムを使うことにした。紙製かつ100円で環境にも優しいらしいので工作にはもってこい。

https://iyec.omni7.jp/detail/4973631533420

これだけだとマックイーンとの接着ができないので以下のアイテムを追加購入。

できたのがこちら

作ってみた感想

紙の土台だと工作もしやすいので良き。例えばサーボモータ乗っけて腕をつけるとかできそうかなと。

ArduinoでRFIDモジュール(MFRC522)を使ってタグに名前の書き込み・読み込みをする

今回使うもの

Aruduino UNO

MFRC522

使用する前のセッティング

以下の記事を参考にしてください。

非接触ICタグで遊ぼう!ArduinoでRFIDリーダRC522を使う方法

とりあえず私はこんなかんじ。無駄にマイクロビット繋げてますけど気にしないでください。

コード

ライブラリのサンプルをそのまま使います。

https://github.com/miguelbalboa/rfid/tree/master/examples

まずは書き込みから。

/*
 * Write personal data of a MIFARE RFID card using a RFID-RC522 reader
 * Uses MFRC522 - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT. 
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 *
 * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
 *
 * Hardware required:
 * Arduino
 * PCD (Proximity Coupling Device): NXP MFRC522 Contactless Reader IC
 * PICC (Proximity Integrated Circuit Card): A card or tag using the ISO 14443A interface, eg Mifare or NTAG203.
 * The reader can be found on eBay for around 5 dollars. Search for "mf-rc522" on ebay.com. 
 */

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

void setup() {
  Serial.begin(9600);        // Initialize serial communications with the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card
  Serial.println(F("Write personal data on a MIFARE PICC "));
}

void loop() {

  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  Serial.print(F("Card UID:"));    //Dump UID
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
  }
  Serial.print(F(" PICC type: "));   // Dump PICC type
  MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
  Serial.println(mfrc522.PICC_GetTypeName(piccType));

  byte buffer[34];
  byte block;
  MFRC522::StatusCode status;
  byte len;

  Serial.setTimeout(20000L) ;     // wait until 20 seconds for input from serial
  // Ask personal data: Family name
  Serial.println(F("Type Family name, ending with #"));
  len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
  for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces

  block = 1;
  //Serial.println(F("Authenticating using key A..."));
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("PCD_Authenticate() success: "));

  // Write block
  status = mfrc522.MIFARE_Write(block, buffer, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("MIFARE_Write() success: "));

  block = 2;
  //Serial.println(F("Authenticating using key A..."));
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // Write block
  status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("MIFARE_Write() success: "));

  // Ask personal data: First name
  Serial.println(F("Type First name, ending with #"));
  len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial
  for (byte i = len; i < 20; i++) buffer[i] = ' ';     // pad with spaces

  block = 4;
  //Serial.println(F("Authenticating using key A..."));
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // Write block
  status = mfrc522.MIFARE_Write(block, buffer, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("MIFARE_Write() success: "));

  block = 5;
  //Serial.println(F("Authenticating using key A..."));
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // Write block
  status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }
  else Serial.println(F("MIFARE_Write() success: "));


  Serial.println(" ");
  mfrc522.PICC_HaltA(); // Halt PICC
  mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD

}

すると以下のような出力がシリアルモニターに表示されます。

Type Family name, ending with #

そしたら入力欄にファーストネーム「hoge#」を打ち込みましょう。入力の最後は#で終わらせる必要があります。すると以下の出力が続きます。

PCD_Authenticate() success:
MIFARE_Write() success:
MIFARE_Write() success:
Type First name, ending with #

最後に「taro#」と打ち込めば完了です。

次に読み込み。

/*
 * Initial Author: ryand1011 (https://github.com/ryand1011)
 *
 * Reads data written by a program such as "rfid_write_personal_data.ino"
 *
 * See: https://github.com/miguelbalboa/rfid/tree/master/examples/rfid_write_personal_data
 *
 * Uses MIFARE RFID card using RFID-RC522 reader
 * Uses MFRC522 - Library
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 *
 * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
*/

#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         9           // Configurable, see typical pin layout above
#define SS_PIN          10          // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

//*****************************************************************************************//
void setup() {
  Serial.begin(9600);                                           // Initialize serial communications with the PC
  SPI.begin();                                                  // Init SPI bus
  mfrc522.PCD_Init();                                              // Init MFRC522 card
  Serial.println(F("Read personal data on a MIFARE PICC:"));    //shows in serial that it is ready to read
}

//*****************************************************************************************//
void loop() {

  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  MFRC522::MIFARE_Key key;
  for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

  //some variables we need
  byte block;
  byte len;
  MFRC522::StatusCode status;

  //-------------------------------------------

  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  Serial.println(F("**Card Detected:**"));

  //-------------------------------------------

  mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card

  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex

  //-------------------------------------------

  Serial.print(F("Name: "));

  byte buffer1[18];

  block = 4;
  len = 18;

  //------------------------------------------- GET FIRST NAME
  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Authentication failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  status = mfrc522.MIFARE_Read(block, buffer1, &len);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Reading failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  //PRINT FIRST NAME
  for (uint8_t i = 0; i < 16; i++)
  {
    if (buffer1[i] != 32)
    {
      Serial.write(buffer1[i]);
    }
  }
  Serial.print(" ");

  //---------------------------------------- GET LAST NAME

  byte buffer2[18];
  block = 1;

  status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Authentication failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  status = mfrc522.MIFARE_Read(block, buffer2, &len);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("Reading failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  //PRINT LAST NAME
  for (uint8_t i = 0; i < 16; i++) {
    Serial.write(buffer2[i] );
  }


  //----------------------------------------

  Serial.println(F("\n**End Reading**\n"));

  delay(1000); //change value if you want to read cards faster

  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1();
}
//*****************************************************************************************//

すると以下が出力されます。

**Card Detected:**
Card UID: xxxx
Card SAK: xxxx
PICC type: MIFARE 1KB
Name:
taro hoge
**End Reading**

注意点

一点はまったポイントがあるので記しておきます。書き込み時に以下のような出力が出る場合があります。

PCD_Authenticatie Failed…

MFRC522では各種操作の前に以下リンク先の205行目にあるPICC_CMD_MF_AUTH_KEY_Aを用いてタグの認証を行います。

https://github.com/miguelbalboa/rfid/blob/master/src/MFRC522.h

上記エラーはこの認証が通らなかったことを意味するのですが、事前の鍵情報の書き込みをしてない限りそれはあり得ません。

ではなぜ起こったのか?それは「書き込みが完了する前にタグをリーダから離してしまった」からです。書き込みが完了するまでは以下のようにしっかりとタグを読み込ませておかないと認証が失敗してしまうので気を付けてください。

マイクロビットを使ったクリスマスアクセサリー製作編 最終回/第39回アソビワークショップ開催報告

みなさん明けましておめでとうございます。今年もどうぞよろしくお願いします。

さて新年最初のアソビワークショップ、昨年のやり残しからスタートしました。

去年はどんなことをやってたか?

まずは思い出すところから。確かLEDストリングライトをmicrobitで制御して好みのライトパターンを作っていた。

前回のパターンを再現する

正月明けだけど過去の写真や記憶を辿りながら再現していく。

「さぁ何をしていたか思い出せるかな?」
昔(2021年)の勘を取り戻してきた!?

作品を作り上げる

このわいわい感がたまらない。思い描いたものと違った物になるのもまたよし。失敗から学ぶことの方が多い。新年早々遊びながらも学んでるなー!

「早よせんかい!」
「なかなかいい感じ??」

実際に使ってみる

袋の下まで光らせたかったけどそこは上手くできなかった、とのこと。

光るバッグ

こちらはたくさんのLEDをつけた弊害でどうやらとっても着づらかった模様笑

(内側が)光るジャケット

EDAに使用されるMLモデルの一覧

大まかに4つに分類することができる。

  • 意思決定
  • 性能予測
  • ブラックボックス最適化
  • 自動設計
MLの使い方タスク/活用段階MLアルゴリズムインプットアウトプット参考リンク
意思決定HLS設計空間探索決定木、多項式回帰 などハード指令e.g. 初期状態、終了条件ハイパーパラメータの品質(例:初期状態、終了条件など
ロジック合成DNNRTL記述ワークフローとオプティマイザーの選択
マスク合成CNNレイアウト画像
最適化手法の選択
性能予測アナログトポロジー設計CNN、ファジー などアナログスペック最良トポロジーの選択
HLS線形回帰、SVM、ランダムフォレスト、XGブースト などH LSレポート、ワークロード性質、ハードウェア性質リソース使用、タイミング など
配置とルーティングSVM、CNN、GAN、MARS、ランダムフォレスト などネットリストやレイアウト画像の特徴量ワイヤ長、ルーティング、輻輳 など
物理実装(リソグラフィーホットスポット探知、IR欠落予測)SVM、CNN、XGブースト、GAN などRTL・ゲートレベル記述、技術ライブラリ、物理実装コンフィグリソグラフィーホットスポットの存在、IR欠落、パス遅延バリエーション
検証KNN、ONN、GCN、ルール学習、SVM、CNNテスト仕様セット、低コストスペックブーリアン パス/フェール予測
デバイスサイズ決定ANNデバイスパラメータ制約充足の可能性
ブラックボックス最適化HLS設計空間探索ランダムフォレスト、ガウシアンプロセス、アンサンブルモデル などHLS設計のハード指示品質結果(レイテンシー、エリア など)
3D統合ガウシアンプロセス、NN物理設計コンフィグクロックスキュー、熱性能 など
設計自動化ロジック統合強化学習、GCNロジック関数のゲートレベルDAGエリア、レイテンシー など
配置強化学習、GCNマクロ配置ワイヤ長、輻輳 など
マスク合成GAN、CNN、決定木、辞書学習RTL・ゲートレベル記述、レイアウト画像光学近接補正(OPC)、サブ解像度アシスト機能(SRAF)の生成
デバイスサイズ決定強化学習、GCN、DNN、SVMデバイスパラメータ設計制約の充足性

What is gradient in Gradient Descent? / [勾配降下法]関数の勾配の定義を振り返る

勾配とは?

そもそもの勾配の定義から振り返ろう。以下のような関数fについて考える。

[mathjax]

$$f(x) = 3x_1^2 – 2x_1x_2 + 3x_2^2 -4x_1 -4x_2$$

このときベクトル$latex \nabla f(x)$を点xにおける関数fの勾配(gradient)という。

$$ \nabla f(x) = \left( \frac{\partial f(x)}{\partial x_1}, \frac{\partial f(x)}{\partial x_2}, \cdots, \frac{\partial f(x)}{\partial x_n} \right) \in \mathbb R^n $$

※ただし以下が成り立つ場合(これは2点を結ぶ線分の傾きから求められますよね?)

$$ f(x+d) = f(x) + \nabla f(x)^Td + o(\Vert{d}\Vert), d \in \mathbb R^n$$

この定義に基づくと上式の勾配は以下で表すことができる。

$$\nabla f(x) = \begin{pmatrix}
6x_1-2x_2-4 \\
-2x_1 + 6×2 -4 \\
\end{pmatrix}
$$

ここで勾配の定義をより直感的にするために以下の2点における勾配を考えてみる。

$$a = (0, 0)^T, \nabla f(a) = (-4, -4)^T$$
$$b = (2, 0)^T, \nabla f(b) = (8, -8)^T$$

このようにfにおける各点の勾配は接線に対して垂直なベクトルとして表される。
そして上図の各点において傾きが最大となる方向を表し、勾配と反対になる方向が降下方向となる。

つまり探索方向を勾配$latex \nabla f(x)$の逆(降下)方向に定めて探索することから「勾配降下法」と言われる所以である(と思う。)

勾配降下法の探索イメージ

初期点を(0, 0)とするとたとえばこんな感じ?