スタートアップエンジニアの作ってみた日記

ものづくりが下手な横好きなエンジニアによる作ってみた的なブログです。

ESP32を使ってIoTデバイスを作ってみた。その3(赤外線LEDにて家電の操作)

ESP32を使っての第3弾ということで、今回は赤外LEDを発光させて家のエアコンを操作してみたいと思います。

 

家電によって赤外の信号は異なるので、信号を受信して学習するところもやっていきます。

 

■必要なもの

・赤外LED

秋月電子で購入できます。  http://LED(http://akizukidenshi.com/catalog/g/gI-03261/

・フォトトランジスタ

こちらも秋月電子で購入可能です。 http://LED(http://akizukidenshi.com/catalog/g/gI-03261/

・抵抗 20KΩ

・その1、その2で作った回路

 

■赤外信号の学習

まずは家にあるリモコンの信号を学習するところを作ります。

フォトトランジスタを使って以下の回路を作ってください。

f:id:goengine:20190623135811p:plain

フォトトランジスタは、トランジスタのベースが光になったもので、光(今回は赤外光)を受けると電気が流れます。(詳細を知りたい方は各自フォトトランジスタの原理を参照してください。)

 

これによって光を受けると、35ピンに5Vが入力されます。

 

 

 では次にESP32に以下のコードを書き込みましょう。

#define READ_PIN 35
#define LOW_STATE 0
#define HIGH_STATE 1

void setup() {
  Serial.begin(115200);
  pinMode(READ_PIN, INPUT);
  //pinMode(4, OUTPUT);

  Serial.println("Ready to receive");
}

void waitLow() {
  while (digitalRead(READ_PIN) == LOW) {
    ;
  }
}

int waitHigh() {
  unsigned long start = micros();
  while (digitalRead(READ_PIN) == HIGH) {
    if (micros() - start > 5000000) {
      return 1;
    }
  }
  return 0;
}

unsigned long now = micros();
unsigned long lastStateChangedMicros = micros();
int state = HIGH_STATE;

void loop() {
  if (state == LOW_STATE) {
    waitLow();
  } else {
    int ret = waitHigh();
    if (ret == 1) {
      Serial.print("\n");
      return;
    }
  }

  now = micros();
  Serial.print((now - lastStateChangedMicros) / 10, DEC);
  Serial.print(",");
  lastStateChangedMicros = now;
  if (state == HIGH_STATE) {
    state = LOW_STATE;
  } else {
    state = HIGH_STATE;
  }
}

 

上記のコードは35ピンのHigh,Low状態の変化を受けると、それまでの時間を計算して表示するというものです。

 

では、Arduinoのシリアルモニタを出した状態でフォトトランジスタに向かって手持ちのリモコンを向けて、何かボタンを押してみましょう。

f:id:goengine:20190623144720p:plain

 

するとシリアルモニタに以下のような数字が出てきます。

f:id:goengine:20190623144906p:plain

これの一番初めの大きい数字を除いた数字をメモ帳などにコピペして保存しておきましょう。

この数字は後程の赤外信号を生成するところで使います。

 

これでリモコンの信号の学習は完了です。

 

■赤外線信号の生成

次にさきほどの取得した信号をESP32と赤外LEDを使って生成し、家の家電を操作してみましょう。

回路はその1の記事をご参照ください。

こちらの記事に書かれている回路のLEDのところを今回用意した赤外LEDにするだけです。 

https://goengine.hatenablog.com/entry/2019/05/26/141312

 

それでは、ESP32にコードを書き込みましょう。

#include <WiFi.h>

const char* ssid = "******"; //ご自分のルーターのSSIDに書き換えてください。
const char* password = "******"; //ご自分のルーターのパスワードに書き換えてください。

//先ほど学習した信号情報をコピーする
int data_on[] = {337,143,58,21,58,102,58,21,58,21,58,102,57,21,58,102,57,21,58,21,58,102,54,102,55,102,54,21,58,102,54,21,58,102,54,102,54,102,54,22,58,22,58,22,57,22,57,104,55,104,55,22,58,104,55,22,57,104,55,104,55,22,57,22,57,22,57,104,55,22,57,104,55,22,58,22,58,104,55,102,54,102,54,21,58,102,54,102,54,21,58,102,54,102,54,102,54,102,54,102,57,21,58,21,58,102,54,21,58,21,58,21,58,21,58,102,57,102,57,102,57,21,58,102,57,102,58,102,58,101,58,21,58,21,58,21,58,102,58,21,58,21,58,21,58,21,58,102,57,21,58,102,58,102,58,101,58,101,58,101,58,101,58,19,57,102,58,19,57,19,57,19,57,21,58,21,58,19,57,101,58,101,58,101,58,101,58,101,58,101,58,101,58,101,58,19,60,19,60,19,60,19,60,19,60,19,60,19,60,19,61,101,58,101,58,101,59,18,61,101,59,100,59,100,59,101,58,18,61,18,61,18,62,100,59,18,61,18,61,18,61,18,61,100,59,100,59,100,59,98,58,98,58,98,61,18,61,98,58,19,61,18,61,18,61,18,61,18,61,18,61,98,58,18,61,98,61,98,61,18,61,98,61,98,61,98,61,98,61,18,61,18,61,18,61,98,61,18,61,18,61,18,61,18,61,98,58};
int data_off[] = {314, 166, 34, 45, 34, 125, 34, 45, 34, 46, 34, 125, 34, 45, 34, 125, 34, 45, 34, 46, 34, 125, 34, 125, 34, 126, 34, 45, 34, 125, 34, 45, 34, 125, 34, 126, 34, 125, 34, 45, 34, 45, 34, 45, 34, 45, 34, 125, 34, 125, 34, 45, 34, 125, 34, 45, 34, 125, 34, 126, 34, 45, 34, 46, 33, 45, 34, 126, 34, 45, 34, 125, 34, 45, 34, 45, 34, 125, 34, 126, 34, 126, 34, 125, 34, 126, 34, 45, 34, 125, 34, 125, 34, 126, 34, 126, 34, 125, 34, 45, 34, 46, 33, 126, 34, 45, 34, 46, 34, 45, 34, 46, 33, 45, 34, 126, 34, 126, 34, 126, 34, 45, 33, 125, 35, 124, 34, 125, 34, 125, 34, 46, 33, 46, 33, 45, 34, 125, 34, 45, 34, 45, 34, 45, 34, 45, 34, 125, 34, 45, 34, 126, 34, 126, 34, 125, 34, 125, 34, 125, 34, 128, 31, 45, 34, 126, 34, 45, 34, 46, 33, 46, 33, 46, 33, 46, 33, 46, 34, 125, 34, 125, 34, 125, 34, 124, 34, 125, 34, 125, 34, 125, 34, 125, 34, 45, 34, 45, 34, 45, 34, 45, 34, 46, 34, 46, 34, 45, 34, 45, 34, 125, 34, 125, 34, 125, 34, 46, 34, 125, 34, 125, 34, 125, 34, 125, 34, 45, 34, 45, 34, 46, 33, 125, 34, 45, 34, 46, 34, 45, 34, 45, 34, 125, 34, 125, 34, 127, 32, 125, 34, 126, 34, 124, 34, 46, 41, 118, 34, 46, 34, 46, 33, 46, 34, 45, 34, 45, 34, 46, 34, 125, 34, 46, 34, 125, 34, 125, 34, 45, 34, 125, 34, 126, 34, 126, 34, 125, 34, 45, 34, 46, 34, 45, 34, 125, 34, 45, 34, 45, 34, 46, 33, 45, 34, 126, 34};

int IR_SEND_PIN = 27; // 赤外線LEDのピン

const char* host = "******";//作成したサイトのURLを入れる。http://は不要

int on_off_flag = 2;

void setup() {
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // 出力に設定
  pinMode(IR_SEND_PIN, OUTPUT);
}

void loop() {
  delay(100);

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }

  // We now create a URL for the request
  String url = "/stateGet.php";

  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  int timeout = millis() + 5000;
  while (client.available() == 0) {
    if (timeout - millis() < 0) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  // Read all the lines of the reply from server and print them to Serial
  int i = 0;
  int flag_temp = on_off_flag;
  while (client.available()) {
    String line = client.readStringUntil('\r');
    if (i == 8) {
      if (line.lastIndexOf("OFF") == -1) {
        Serial.println("on");
        on_off_flag = 0;
      } else {
        Serial.println("off");
        on_off_flag = 1;
      }
      break;
    }
    i++;
  }
  if (flag_temp != on_off_flag) {
    if (on_off_flag == 0) {
      sendSignal(data_on, sizeof(data_on) / sizeof(data_on[0]));
    } else {
      sendSignal(data_off, sizeof(data_off) / sizeof(data_off[0]));
    }
  }

  Serial.println();
  Serial.println("closing connection");
}

void sendSignal(int data1[], int num) {
  int dataSize = num;
  int j = 0;
  for (int cnt = 0; cnt < dataSize; cnt++) {
    unsigned long len = data1[cnt] * 10;
    unsigned long us = micros();
    //Serial.println(len);
    do {
      digitalWrite(IR_SEND_PIN, 1 - (cnt & 1));
      delayMicroseconds(8.8);
      digitalWrite(IR_SEND_PIN, 0);
      delayMicroseconds(17.5);
      //Serial.println(j);
    } while (long(us + len - micros()) > 0); // 送信時間に達するまでループ
    //digitalWrite(IR_SEND_PIN, 0);
  }
}

こちらの配列data_onやdata_offのところに先ほどメモ帳にコピーした数列を入力してください。

 

また、Wifiの設定やサイトのURLなどは適宜、変更してください。

 

こちらのコードはその2で作ったwebサイトからon,offのボタンを押すと押された時だけ、on,offの信号を出力するコードになっています。

 

これで以下のようにブラウザから家電を操作できるようになります。

 

 

今回はこちらのサイトを参考にさせて頂きました。

ありがとうございました。

https://www.erestage.com/arduino/remo_recv/

https://www.erestage.com/arduino/arduino-send-remo/

 

以上です。

 

 

平成元年生まれの音楽ファンが選ぶ勝手に平成の名曲10選

本日はいつものブログの内容とは異なります。
私の好きな音楽についてです。

名曲10選みたいに書いてますが、私の中でこれまでブームになってきた曲を
私の年齢別に10曲紹介していきたいと思います。
ですので、選曲がめちゃくちゃ偏っていると思いますが、ご了承ください。

年代が近い人で、好きな音楽のジャンルが近い人にはそこそこ共感してもらえるかなーと思っています。
(動画は公式から出ているものだけ載せています。)

ー小学校低学年ー
松任谷由実 春よ、来い(平成6年10月)
言わずと知れた超名曲。ユーミンこと松任谷由実の代表曲ですね。
老若男女知っている名曲でしょう。
最近の若手のシティポップバンドらに大きな影響を与えた方です。
後に紹介するYogee New Wavesもユーミンを聞いて育ったと公言しています。

ー小学校高学年ー
サザンオールスターズ TSUNAMI(平成12年1月)
これも言わずと知れた超名曲。
親の影響でサザンオールスターズ桑田佳祐をよく聞いていました。
当時はミスチルバンプなどが僕の周りでは流行っており、サザンを聴いていた僕は周りの友達にはなんでそんなオヤジ臭い曲聴いてるんだよ。と少しバカにされていましたが、

ー中学生時代ー
スーパーカー YUMEGIWA LAST BOY(平成13年11月発売)
これも音楽好きの人には説明は不要でしょう。
日本のロックシーンを変えたとも言われている97の世代のSUPERCAR
ギターをひずませながら、けだるそうに歌う。
これまでのロックとは一線を書くスタイルでロックシーンを席巻しました。

ー高校時代ー
■銀杏ボーイズ 援助交際(平成17年1月)
中学~高校時代の私の青春そのものです。
銀杏BOYZのアルバムを初めて聞いたときはすごく衝撃でした。Going Steadyを聞いていたので、峯田さんの作る音楽をある程度は知っているつもりだったのですが、それでもすごい衝撃でした。
アルバム「DOOR」「 君と僕の第三次世界大戦的恋愛革命」は本当に聴き倒しました。
バンドを組んで「夢で逢えたら」をカバーしたのも今では本当に良い思い出です。

www.youtube.com



フジファブリック 銀河(平成17年2月)
フジファブリックを最初聴いた時は正直よくわからない曲だなーと思っていました。
しかし、繰り返し聴いていくと「あら、不思議。」むちゃくちゃハマってしまいました。
今はなき志村正彦さんが作り出す変態的な名曲は今でも色褪せることはありません。

www.youtube.com



チャットモンチー 恋の煙(平成18年3月)
2018年を持って解散したチャットモンチー。日本のガールズロックバンドの歴史に間違いなくその名を刻まれているでしょう。
えっちゃんのかわいらしい声とかっこいいギターサウンドのアンマッチ感にはまります。
また、深い歌詞が多く聞いていて全く飽きがきません。

www.youtube.com


ー大学時代ー
相対性理論 スマトラ警備隊(平成20年5月)
初めて聞いたときは本当に衝撃が走りました。
このなんとも言えないメロディと不思議な歌詞。そしてやくしまるえつこさんの声。
何かわからないけど非常に引き込まれました。
ライブも何度か行きましたが、他のロックバンドなどのライブとは全く異なり独自の世界観で非常に楽しめます。

andymori すごい速さ(平成20年10月)
このバンドもロックファンの中ではおなじみのバンドですね。
UK的なロックンロール調に日本語歌詞。
歌詞はナショナリズム的な要素を含めた考えさせる歌詞。
こんな音楽やってくれるバンドまた現れてほしいですね。 

www.youtube.com

 
■OKAMOTO’s dance with you(平成27年5月)
ロックンロールのかっこよさと日本語歌詞をしっかりと融合させているバンドです。
ライブでも、飛んで踊れるバンドですね。
聴いていると本当に楽しく踊りたくなる曲です。

www.youtube.com



■Yogee New Waves HOW DO YOU FEEL?(平成29年5月)
最近のシティポップブームの立役者でもあるバンドのひとつです。
80年代や90年代の日本のポップの良さを受け継いだ現代のシティポップ。
この曲はYogeeの良いところが全て詰まった名曲です。
歌詞、メロディ、MVどれをとっても最高です。

www.youtube.com

以上、10曲が平成元年生まれが勝手に選んだ平成の名曲10選でした。

ESP32を使ってIoTデバイスを作ってみた。その2

ESP32を使ってIoTデバイスを作ってみた第2弾です。

その1では、ESP32を使えるようにライブラリを導入してLEDを光らせるところまでやりました。

その2では、ESP32をネットワークに接続し、ブラウザからLEDを光らせるところまで行きたいと思います。

 

■まずはwebサイトの準備です。

webサイトに作成については今回は詳しく書きません。

 

無料でサーバを借りられるサービスなどがありますのでそちらで借りてください。

私は以下のxfreeというサイトで無料のサーバーを準備しました。

https://www.xfree.ne.jp/

 

そのサーバーに置くファイルは以下のgitから落としてきましょう。

https://github.com/MassSkt/IoT_Airconditioner_webInterface_and_API/tree/master/html

こちらのhtml以下にあるファイルたちををサーバにおいてください。

 

ただしhtml\js\index.jsファイルだけ少し書きかえる必要があります。

index.jsを適当なソフトで開きましょう。

開くと以下のようなコードになっています。

この3行目と4行目の部分(赤枠の白字部分)のURLを自分のサイトのURLに変更してください。

f:id:goengine:20190616211130p:plain

 

(Temperatureの部分文字化けして、変なのが表示されているかもしれませんが、気にしないでください。)

とりあえずこれで、サイト側の準備は完了です。

 

■ESP32をネットワークにつながるようにしましょう。

 

回路については前のブログをご参照ください。

https://goengine.hatenablog.com/entry/2019/05/26/141312


早速ですが、以下のコードをesp32に書き込みましょう。

#include <WiFi.h>

const char* ssid = "************"; //ご自分のルーターのSSIDに書き換えてください。
const char* password = "************"; //ご自分のルーターのパスワードに書き換えてください。

const char* host = "************";

int IR_SEND_PIN = 27; // LEDのピン


void setup() {
  Serial.begin(115200);
  delay(10);

  // We start by connecting to a WiFi network

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // 出力に設定
  pinMode(IR_SEND_PIN, OUTPUT);
}

void loop() {
  delay(100);

  Serial.print("connecting to ");
  Serial.println(host);

  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  
  
    if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
    }

  // We now create a URL for the request
  String url = "/stateGet.php";

  Serial.print("Requesting URL: ");
  Serial.println(url);

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  int timeout = millis() + 5000;
  while (client.available() == 0) {
    if (timeout - millis() < 0) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }

  // Read all the lines of the reply from server and print them to Serial
  int i = 0;
  while (client.available()) {
    String line = client.readStringUntil('\r');
    if (i == 8) {
      if (line.lastIndexOf("OFF") == -1) {
        Serial.println("on");
        digitalWrite(IR_SEND_PIN, 1);

      } else {
        Serial.println("off");
        digitalWrite(IR_SEND_PIN, 0);
      }
      break;
    }
    i++;
  }
  Serial.println("closing connection");
}

 

3行目、4行目、6行目はそれぞれ環境自分の環境にあったものをご使用ください。

 

これでESP32に書き込めば、サーバー上のphpファイルからon,offの情報を取ってきてLEDが光るはずです。

 

ちなみに完成は品はこんな感じで、web上でon,offボタンを押すとLEDがそれに対応して光ります。

こちらは温度センサも付属させており、部屋の温度も表示するようになっています。

 

 

次回はこのLEDを赤外線LEDに変更して部屋のエアコンを操作できるようにしていきたいと思います。

ESP32を使ってIoTデバイスを作ってみた。その1

題名の通り、ESP32を使って家電をIoT化してみました。

 

この記事はその1ということで、ESP32を使ってLEDを光らせるところまで説明していきます。

まず使うものは以下になります。

・ESP-WROOM-32開発ボード(秋月電子にて購入、以下のURL参照)

http://akizukidenshi.com/catalog/g/gM-11819/

・ブレッドボード

・ジャンパピン

・LED

・抵抗100Ω

 

ESP-WROOM-32開発ボードはESP-WROOM-32のWifiモジュールが実装されており、開発ボードを購入するだけでPCとUSBケーブルで接続するし、ArduinoIDEを使ってすぐに開発することができる優れものです。

はじめ私はESP-WROOM-32のモジュールとArduinoを接続して動かそうと思ったのですが、接続やら電力供給やらがめんどくさそうっだった(←コラ)ので、開発ボードを購入しました。笑

 

では、実際に作り方について説明していきます。

■ESP-WROOM-32開発ボードをArduinoIDEでいじれるようにする。

まずはArduinoにESP32のライブラリをインストールします。

図のようにファイル→環境設定で環境設定画面を開きます。

f:id:goengine:20190526125013p:plain

環境設定の画面の「追加のボードマネージャーのURL」のところに以下のURLを入力します。

https://dl.espressif.com/dl/package_esp32_index.json

こうすることで次にライブラリをインストールする際にここのURLを参照にするようになり、ライブラリを見つけることができるようになります。

f:id:goengine:20190526125252p:plain

 

次に「ツール→ボード→ボードマネージャ」を選びます。

f:id:goengine:20190526125703p:plain

 

以下の図の赤枠内にESP32と入力して検索すると1つヒットするので、それをインストールしてください。バージョンは最新(2019年5月の時点では1.0.2)で問題ないでしょう。

f:id:goengine:20190526130305p:plain

これでESP32のライブラリにインストールは完了です。

■次にプログラムを書き込めるように設定を変更していきます。

「ツール→ボード」からボードを「ESP32 Dev Module」に変更してください。

その下にもいろいろ設定がありますが、そこは変えなくても大丈夫です。

f:id:goengine:20190526131106p:plain

これでArduino IDEからESP32にプログラムを書き込めるようになりました。

■次にLEDを光らせるための回路を組んでいきます。

図のように27のピンとGND間をLEDと抵抗100オームで直列に接続します。

f:id:goengine:20190526133209p:plain

 

■次に書き込むためのプログラムを書きます。

以下のコードをコピーしちゃってください。

内容は0.5秒ごとに点灯と点滅を繰り替えすプログラムです。

#define LED_PIN 27

void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_PIN, 1);
  delay(500);
  
  digitalWrite(LED_PIN, 0);
  delay(500);
}

これでArduino IDEからESP32にプログラムを書き込めるようになりました。

 

これをESP32に書き込めば完成です。

動画のように点灯しているはずです。

 

以上で、ESP32を使ったLEDの点灯は完了です。

次回は実際にネットワークにつなげてブラウザからLEDの点灯について書きたいと思います。 

 

今回のブログは以下のサイトを参考にさせて頂きました。ありがとうございました。

https://www.mgo-tec.com/arduino-core-esp32-install/2

 

 

 

 

金額が表示される貯金箱を作ってみた。

これまで作ってきたものを元に投入されたコインを判別しLCDに金額が表示される貯金箱を作ってみました。

できたものはこれです。


■これまでのブログは以下の二つです。
Arduinoで重さを計測してみた
https://goengine.hatenablog.com/entry/2019/03/24/235058
Arduinoと液晶(1602A)を使って文字を簡単に表示させてみた。
https://goengine.hatenablog.com/entry/2019/03/17/211934


使うものはこれまで作ってきたものと同じです。
Arduino uno
Amazonで購入したロードセル(Arduinoと接続するためのモジュール付き)
Amazonで購入したLCD液晶

Arduinoとロードセル、LCDの接続についてはこれまでのブログを参照お願いします。

入れたコインの判別はロードセルの質量計測で行います。

コインと質量の関係は以下です。

硬貨 重さ
1円玉 1
5円玉 3.75
10円玉 4.5
50円玉 4
100円玉 4.8
500円玉 7

参考:http://honkawa2.sakura.ne.jp/5094.html

これを元に重さを計測して投入されたコインを判別します。

しかし、今回使用するロードセルだと時間が経つだけで少しずつ計測値が変化していくので、
単純に計測値が変わるとコインの種類を判別するようにしてしまうと、
コインを入れていないのにコインを入れたことになってしまいます。

なので、計測値が大きく変化したときだけ、コインが入れられたと判定するようにします。
また、コインが入った瞬間は値が大きくなってしまうので、
一度、変化しその計測値が落ち着いたときにコインを判別するようにしています。

Arduinoのコードは以下です。
(雑なコードですみません。動けばいいという精神です。。)

#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Arduino.h>

void AE_HX711_Init(void);
void AE_HX711_Reset(void);
long AE_HX711_Read(void);
long AE_HX711_Averaging(long adc, char num);
float AE_HX711_getGram(char num);

//---------------------------------------------------//
// ピンの設定
//---------------------------------------------------//
#define pin_dout  8
#define pin_slk   9

//---------------------------------------------------//
// ロードセル S字型 SC301A 100kG [P-12036]
//---------------------------------------------------//
//#define OUT_VOL   0.002f      //定格出力 [V]
//#define LOAD      100000.0f   //定格容量 [g]

//---------------------------------------------------//
// ロードセル シングルポイント( ビーム型) SC601 120kG [P-12035]
//---------------------------------------------------//
//#define OUT_VOL   0.001f      //定格出力 [V]
//#define LOAD      120000.0f   //定格容量 [g]

//---------------------------------------------------//
// ロードセル シングルポイント( ビーム型) SC133 20kG [P-12034]
//---------------------------------------------------//
//#define OUT_VOL   0.002f      //定格出力 [V]
//#define LOAD      20000.0f    //定格容量 [g]

//---------------------------------------------------//
// ロードセル シングルポイント(ビーム型) SC616C 500g[P-12532]
//---------------------------------------------------//
//#define OUT_VOL   0.0007f   //定格出力 [V]
//#define LOAD      500.0f    //定格容量 [g]

#define OUT_VOL   0.0008f   //定格出力 [V]
#define LOAD      2000.0f    //定格容量 [g]

float offset;

int count = 0;

double gram[5]; //gram記憶用

int total;
int coin;
int rep  = 3;

int display_count = 0;

double sabun[2];

double gram_ave[2];//重量が落ち着ているときの値を記憶しておく

double coin_sabun;

double gosa = 0.3;

int total_amount = 0;

boolean situation = true;//tureが定常、falseが非定常

boolean coin_in = false;//tureがコインを入れられたと判別、falseはコイン入れられていない

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup() {
  Serial.begin(9600);
  Serial.println("AE_HX711 test");
  AE_HX711_Init();
  AE_HX711_Reset();
  offset = AE_HX711_getGram(30);

  //LCD用のsetup
  lcd.init();                      // initialize the lcd

  // Print a message to the LCD.
  lcd.backlight();
  //lcd.setCursor(0, 0);
  //lcd.print("Savings amount");
  //lcd.setCursor(0, 1);
  //lcd.print("Arduino!");
}

void loop()
{
  float data;
  char S1[20];
  char s[20];

  double gram0;

  data = AE_HX711_getGram(5);

  for (int i = 0; i  < rep - 1; i++) {
    gram[rep - i - 1] = gram[rep - i - 2];
  }
  sabun[1] = sabun[0];

  gram0 = (data - offset) * 4.5 /4.75;
  gram[0] = gram0;
  //sprintf(S1, "%s [g] (0x%4x)", dtostrf((data - offset), 5, 3, s), AE_HX711_Read());
  Serial.println(gram0);
  sabun[0] = gram[0] - gram[1];

  if (sabun[1] < 0.7 && sabun[0] < 0.7) {
    if(situation == false){
      gram_ave[1] = gram_ave[0];
      coin_in = true;
    }
    situation = true;
    gram_ave[0] = (gram[0] + gram[1] + gram[2]) / 3.0;
  } else {
    situation = false;
    //Serial.println("test");
  }
  if (coin_in) {
    coin_sabun = gram_ave[0] - gram_ave[1];
    coin = coin_hantei(coin_sabun);
    coin_in = false;
    //Serial.println("coin in");
    //Serial.println(coin);
    total_amount = total_amount + coin;
    lcd.setCursor(0, 1);
    lcd.print("insert coin");
    lcd.setCursor(12, 1);
    lcd.print(coin);

    display_count = 0;
  }
  
  lcd.setCursor(0, 0);
  lcd.print("Total");
  lcd.setCursor(6, 0);
  lcd.print(total_amount);
  display_count++;
  if(display_count == 6){
    lcd.setCursor(0, 1);
    lcd.print("                      ");
  }
  //delay(500);
  count++;
}

int coin_hantei(double g){
  if(coin_hantei2(1.0,g) == true){
    return  1;
  }
  if(coin_hantei2(3.75,g) == true){
    return  5;
  }
  if(coin_hantei2(4.5,g) == true){
    return  10;
  }
    if(coin_hantei2(4.0,g) == true){
    return  50;
  }
  if(coin_hantei2(4.8,g) == true){
    return  100;
  }
  if(coin_hantei2(7.0,g) == true){
    return  500;
  }
  return 0;
  
}

boolean coin_hantei2(double g , double h){
  if(g - gosa < h && g + gosa > h){
    return true;
  }
  return false;
}


void AE_HX711_Init(void)
{
  pinMode(pin_slk, OUTPUT);
  pinMode(pin_dout, INPUT);
}

void AE_HX711_Reset(void)
{
  digitalWrite(pin_slk, 1);
  delayMicroseconds(100);
  digitalWrite(pin_slk, 0);
  delayMicroseconds(100);
}

long AE_HX711_Read(void)
{
  long data = 0;
  while (digitalRead(pin_dout) != 0);
  delayMicroseconds(10);
  for (int i = 0; i < 24; i++)
  {
    digitalWrite(pin_slk, 1);
    delayMicroseconds(5);
    digitalWrite(pin_slk, 0);
    delayMicroseconds(5);
    data = (data << 1) | (digitalRead(pin_dout));
  }
  //Serial.println(data,HEX);
  digitalWrite(pin_slk, 1);
  delayMicroseconds(10);
  digitalWrite(pin_slk, 0);
  delayMicroseconds(10);
  return data ^ 0x800000;
}


long AE_HX711_Averaging(long adc, char num)
{
  long sum = 0;
  for (int i = 0; i < num; i++) sum += AE_HX711_Read();
  return sum / num;
}

float AE_HX711_getGram(char num)
{
#define HX711_R1  20000.0f
#define HX711_R2  8200.0f
#define HX711_VBG 1.25f
#define HX711_AVDD      4.2987f//(HX711_VBG*((HX711_R1+HX711_R2)/HX711_R2))
#define HX711_ADC1bit   HX711_AVDD/16777216 //16777216=(2^24)
#define HX711_PGA 128
#define HX711_SCALE     (OUT_VOL * HX711_AVDD / LOAD *HX711_PGA)

  float data;

  data = AE_HX711_Averaging(AE_HX711_Read(), num) * HX711_ADC1bit;
  data =  data / HX711_SCALE;


  return data;

Arduinoで重さ計測してみた(ロードセルを使ってみた)

重さを計測したいと思い、簡単に手に入るロードセルを使って重さ計測してみました。

要求スペックとしては
最大計測重量 2kg
分解能 0.1g

使ったのは以下の二つです。
Arduino uno
Amazonで購入したロードセル(Arduinoと接続するためのモジュール付き)
購入したロードセルはこちらです。

www.amazon.co.jp



こちらの商品はロードセルとArduinoの通信(アンプ+AD変換)を行うためのモジュールがついているので、便利です。
これがないとArduinoにて使えません。
ただし、モジュールはピンがハンダづけされていないので、ハンダ付けする必要があります。
ハンダ付けができない方はもともとピンがハンダ付けされているものを選んで購入しましょう。


購入して届いたロードセルがこちら

f:id:goengine:20190324230904j:plain

(手前のねじ穴に青い物体がつまっているのは、固定用に3Dプリンタの部品を詰め込んだら折れてしまったものです。当然、買ったときにはねじ穴が空いています。)

使い方は、奥側のねじ穴の部分をベースに固定して、手前の矢印のシールが貼ってあるほうに重量物を載せるための皿などを固定して計測をします。

f:id:goengine:20190324231359p:plain

このロードセルは写真の白い樹脂が塗ってあるところに歪みを計測する歪みセンサーが入っており、その歪みを計測することで重量を計測しています。なので、重量に対して正しく金属歪ませることが正確に測定するコツになります。なので、固定をしっかりと行うことが重要になります。
きちんと固定しないとロードセル自体が傾いたりしてしまい正しく計測できません。(かくいう僕もネジが手元になかったので、適当に固定して計測しました。。そして苦戦しました、、)

次に接続についてです。
以下のようにArduino、モジュール、ロードセルを接続してください。

 ■ロードセル - モジュール

 赤線    - E+

 黒線    - Eー

 白線    - A-

 緑線    - A+ 

■モジュール - Arduino

 GND    - GND

 DT     - Digital 8

 SCK     - Digital 9

 VCC     - 5Vf:id:goengine:20190324232432p:plain


このように接続したらArduinoに以下のコードを書き込みましょう。
(サンプルコードは以下の秋月電子のサイトにあったものを参考にしました。)
http://akizukidenshi.com/catalog/g/gK-12370/

#include <Arduino.h>

void AE_HX711_Init(void);
void AE_HX711_Reset(void);
long AE_HX711_Read(void);
long AE_HX711_Averaging(long adc,char num);
float AE_HX711_getGram(char num);

//---------------------------------------------------//
// ピンの設定
//---------------------------------------------------//
#define pin_dout  8
#define pin_slk   9

//---------------------------------------------------//
// ロードセル S字型 SC301A 100kG [P-12036]
//---------------------------------------------------//
//#define OUT_VOL   0.002f      //定格出力 [V]
//#define LOAD      100000.0f   //定格容量 [g]

//---------------------------------------------------//
// ロードセル シングルポイント( ビーム型) SC601 120kG [P-12035]
//---------------------------------------------------//
//#define OUT_VOL   0.001f      //定格出力 [V]
//#define LOAD      120000.0f   //定格容量 [g]

//---------------------------------------------------//
// ロードセル シングルポイント( ビーム型) SC133 20kG [P-12034]
//---------------------------------------------------//
//#define OUT_VOL   0.002f      //定格出力 [V]
//#define LOAD      20000.0f    //定格容量 [g]

//---------------------------------------------------//
// ロードセル シングルポイント(ビーム型) SC616C 500g[P-12532]
//---------------------------------------------------//
//#define OUT_VOL   0.0007f   //定格出力 [V]
//#define LOAD      500.0f    //定格容量 [g]

#define OUT_VOL   0.001f   //定格出力 [V]
#define LOAD      2000.0f    //定格容量 [g]

float offset;

void setup() {
  Serial.begin(9600);
  Serial.println("AE_HX711 test");
  AE_HX711_Init();
  AE_HX711_Reset();
  offset = AE_HX711_getGram(30); 
}

void loop() 
{ 
  float data;
  char S1[20];
  char s[20];
  data = AE_HX711_getGram(5);

//data = 55.0 / 50.0; //ここで校正を行う
sprintf(S1,"%s [g] (0x%4x)",dtostrf((data-offset), 5, 3, s),AE_HX711_Read()); Serial.println(S1); } void AE_HX711_Init(void) { pinMode(pin_slk, OUTPUT); pinMode(pin_dout, INPUT); } void AE_HX711_Reset(void) { digitalWrite(pin_slk,1); delayMicroseconds(100); digitalWrite(pin_slk,0); delayMicroseconds(100); } long AE_HX711_Read(void) { long data=0; while(digitalRead(pin_dout)!=0); delayMicroseconds(10); for(int i=0;i<24;i++) { digitalWrite(pin_slk,1); delayMicroseconds(5); digitalWrite(pin_slk,0); delayMicroseconds(5); data = (data<<1)|(digitalRead(pin_dout)); } //Serial.println(data,HEX); digitalWrite(pin_slk,1); delayMicroseconds(10); digitalWrite(pin_slk,0); delayMicroseconds(10); return data^0x800000; } long AE_HX711_Averaging(long adc,char num) { long sum = 0; for (int i = 0; i < num; i++) sum += AE_HX711_Read(); return sum / num; } float AE_HX711_getGram(char num) { #define HX711_R1 20000.0f #define HX711_R2 8200.0f #define HX711_VBG 1.25f #define HX711_AVDD 4.2987f//(HX711_VBG*((HX711_R1+HX711_R2)/HX711_R2)) #define HX711_ADC1bit HX711_AVDD/16777216 //16777216=(2^24) #define HX711_PGA 128 #define HX711_SCALE (OUT_VOL * HX711_AVDD / LOAD *HX711_PGA) float data; data = AE_HX711_Averaging(AE_HX711_Read(),num)*HX711_ADC1bit; //Serial.println( HX711_AVDD); //Serial.println( HX711_ADC1bit); //Serial.println( HX711_SCALE); //Serial.println( data); data = data / HX711_SCALE; return data; }

こちらのコードでは、上のほうに書かれているところでロードセルの最大可測重量と分解能を設定しています。
今回のロードセルでは定格出力1mV、定格重量2Kgなので以下のように書き加えています。
#define OUT_VOL 0.001f //定格出力 [V]
#define LOAD 2000.0f //定格容量 [g]

あとはArduinoに書き込めばOKです。

シリアルモニタを開いてみるとこんな感じに表示されると思います。

f:id:goengine:20190324235850p:plain
これだけでも簡単には重量計測はできますが、ロードセルの個体差や計測環境などによって多少ずれがありそうです。

なので、スケールを校正しましょう。
重量が分かっているもの(小銭などが便利かと思います。)を使って校正していきます。
なるべく、可測重量内で大きなものがいいかと思います。

校正用に用意した物をロードセルに載せます。
ロードセルで計測した値とその用意した物の本来の値を以下のようにdataにかけ合わせます。
data * 本来の重量 / ロードセルで計測した値

これを
AE_HX711_getGram関数内か
loop関数内に書きましょう。

どちらに描いても機能としては同じですが、
今回はloop関数内に書きます。以下のように書きます。

 

この例では 本来の重量が50gのモノを計測したときに55gと計測された場合の例を示しています。

f:id:goengine:20190324234911p:plain


これでスケーリングも正しくできて正確な値を計測できると思います。

以上です。

Arduinoと液晶(1602A)を使って文字を簡単に表示させてみた。

 Arduinoamazonで売っていた液晶を使って文字を液晶に表示してみました。
原理や仕組みについての説明は省いてやり方をメインに初心者の方でもわかるように書いていきたいと思います。

必要なものは以下です。

Arduino uno
Amazonで購入したLCD液晶

ちなみに僕はこのLCDを買いました。 

https://www.amazon.co.jp/gp/product/B07BJ5PW3R/ref=ppx_yo_dt_b_asin_title_o03_s00?ie=UTF8&psc=1


上で紹介したLCD液晶は始めからI2C通信用のアダプターが半田づけされているので、アダプターの端子4本(電源、GND、SCL、SDA)をArduinoに接続すればよいだけなので非常に楽です。

このように配線してください。

LCD  Arduino

GND ー GND

VCC ー 5V

SDA ー Analog 4

SCL ー Analog 5

f:id:goengine:20190317210123p:plain

次にI2C通信用のライブラリが必要なので落とします。
ここのgithubのサイトより落としてください。
 

GitHub - johnrickman/LiquidCrystal_I2C: LiquidCrystal Arduino library for the DFRobot I2C LCD displays

 
Githubのサイトにいったらここからzip形式をダウンロードしてください。
ダウンロードしたらarduinoのlibrararyフォルダにzipをまるまる入れてください。

f:id:goengine:20190317210311p:plain
そしたら、arduinoのツールの画面でzipをライブラリとして取り込むように指定していきます。
ArduinoIDE上でスケッチ→ライブラリをインクルード→.ZIP形式のライブラリをインストールを選びます。
そしたら先ほどダウンロードしたzipファイルを指定しましょう。

f:id:goengine:20190317210349p:plain


これでokです。

次に以下のようにコードを書いてください。
コピペできるので、コピペしちゃいましょう。

#include <LiquidCrystal_I2C.h>

int count = 0;

LiquidCrystal_I2C lcd(0x27,16,2);

void setup()
{
  lcd.init();                      
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Hello, world!");
}

void loop()
{
  lcd.setCursor(0, 1);
  lcd.print(count);
  delay(500);
  count++;
}


基本はこのままで大丈夫ですが、以下の部分だけ異なる可能性があります。

f:id:goengine:20190317211358p:plain


私の場合は0x27でした。(素子の品番(以下の図参照)がPCF8574Aのときは0x3FでPCF8574のときは0x27っぽい)

f:id:goengine:20190317211544p:plain

*参考 

[I2C] 1602 LCD ディスプレイ (HD44780 + PCF8574A)


以上のようにコードを書いて、arduinoに書き込めば、液晶に図のように表示されるはずです。
1行目に“Hello world”、
2行目にカウント数が表示されます。(0.5秒ずつに1増加する)

f:id:goengine:20190317211801j:plain

 

以上で、LCDの表示方法でした。