8ピンSTM32で温湿度表示に挑戦!AQM1602+DHT20を3ステップで動かす方法

黄色背景の上にSTM32G031、AQM1602 LCD、DHT20温湿度センサ、抵抗が配置され、LCDに温度25.3℃・湿度60.1%と表示されたブログ用アイキャッチ画像8ピンSTM32で温湿度表示に挑戦!AQM1602+DHT20を3ステップで動かす方法
スポンサーリンク

前回STM32G031J6をArduino IDEでLチカをしましたが、今回も同じ構成ですが、i2c接続で液晶表示と温湿度センサを同時に動かしててみることにしました。
でもいきなり全部つなぐと、
「どこが原因で動かないのか分からない…」
という状態になりがちです。
そこで今回は、

① まずはLCDだけ動かす
② 次にセンサだけ確認する
③ 最後に組み合わせる

という3段階で進めます。
初心者の方でも確実に動作確認できる構成です。

スポンサーリンク

使用部品

【図①:部品一覧】
STM32G031(8ピン)(数年前に秋月電子で120円で購入したものです)
AQM1602(I2C液晶)
DHT20(I2C温湿度センサ)
470Ω前後の抵抗
3.3V電源 (St-Link) (nucleo-Stlink)(アマゾンの安いものでも書き込めるようです) 
ブレッドボード ジャンパーワイヤー

配線

配線図

aqm1602  go31j6  dht20 stlink 接続図
  • PB6(ピン8)── 470Ω ── SCL(SWCLKとSCLを同時有効にす為470Ωの抵抗を入れます)
  • PB7(ピン1)──────── SDA
  • 3.3V → VDD
  • GND → GND
  • I2Cは2本の線で複数機器を接続できます。
  • NRST は接続しなくても書き込めます。

I2Cは2本の線で複数機器を接続できます。
注意:必ずSCLとSDAラインに10KΩ程度のプルアップ抵抗を入れてください私はAQM16022内のプルアップ抵抗を有効にしてありますので省略してあります。

まずはAQM1602だけ動かす

いきなり全部を動かすのではなく、まずはLCD単体で動作確認します。
ArduinoIDEの設定の仕方についてはこちらの私の記事で確認してくだ。
プログラム(LCD単体)

#include <Wire.h>

#define AQM_ADDR 0x3E

void cmd(uint8_t c){
  Wire.beginTransmission(AQM_ADDR);
  Wire.write(0x00);
  Wire.write(c);
  Wire.endTransmission();
}

void data(uint8_t d){
  Wire.beginTransmission(AQM_ADDR);
  Wire.write(0x40);
  Wire.write(d);
  Wire.endTransmission();
}

void init_lcd(){
  delay(40);
  cmd(0x38);
  cmd(0x39);
  cmd(0x14);
  cmd(0x70);
  cmd(0x56);
  cmd(0x6C);
  delay(200);
  cmd(0x38);
  cmd(0x0C);
  cmd(0x01);
  delay(2);
}

void print_str(const char *s){
  while(*s) data(*s++);
}

void setup(){
  Wire.setSCL(PB6);
  Wire.setSDA(PB7);
  Wire.begin();
  init_lcd();
  print_str("Hello STM32");
}

void loop(){}

LCDに文字が表示されれば成功です。
表示されない場合:

  • 電源は3.3Vか?
  • SCL/SDAは正しいか?
  • 抵抗は正しく接続されているか?

DHT20測定開始するプログラム

ここではまだLCDに表示しません。

プログラム

#include <Wire.h>

#define DHT20_ADDR 0x38

void setup(){    //こちらの部分はAQM1602と共通のセットアップ項目です
  Wire.setSCL(PB6);
  Wire.setSDA(PB7);
  Wire.begin();
}

void loop(){
  Wire.beginTransmission(DHT20_ADDR);
  Wire.write(0xAC);
  Wire.write(0x33);
  Wire.write(0x00);
  Wire.endTransmission();
  delay(80);
}

LCD+DHT20を組み合わせる

いよいよ完成形です。
やることはシンプル:

  • センサから値を取得
  • LCDに表示

最終プログラム

#include <Wire.h>

#define AQM_ADDR 0x3E
#define DHT20_ADDR 0x38

//--------------------------------
// AQM1602 基本関数
//--------------------------------
void aqm_cmd(uint8_t cmd)
{
  Wire.beginTransmission(AQM_ADDR);
  Wire.write(0x00);
  Wire.write(cmd);
  Wire.endTransmission();
}

void aqm_data(uint8_t data)
{
  Wire.beginTransmission(AQM_ADDR);
  Wire.write(0x40);
  Wire.write(data);
  Wire.endTransmission();
}

void aqm_init()
{
  delay(40);
uint8_t initComs[] = {0x38, 0x39, 0x14, 0x70, 0x56, 0x6C, 0x38, 0x0C, 0x01};  //初期化コマンドを配列にまとめる場合
  uint16_t delays[]  = {2, 2, 2, 2, 2, 150, 2, 2, 2};
  for (uint8_t i = 0; i < sizeof(initComs); i++) {
       aqm_cmd(initComs[i]);
       delay(delays[i]);
  } 
}

void aqm_setCursor(uint8_t col, uint8_t row)
{
  uint8_t addr = (row == 0) ? 0x00 : 0x40;
  aqm_cmd(0x80 | (addr + col));
}

void aqm_print(const char *str)
{
  while (*str) {
    aqm_data(*str++);
  }
}

//--------------------------------
// DHT20 読み取り
//--------------------------------
bool dht20_read(float &temp, float &hum)
{
  uint8_t buf[7];

  // 測定開始
  Wire.beginTransmission(DHT20_ADDR);
  Wire.write(0xAC);
  Wire.write(0x33);
  Wire.write(0x00);
  if (Wire.endTransmission() != 0) return false;

  delay(80);

  // データ取得
  Wire.requestFrom(DHT20_ADDR, 7);
  for (int i = 0; i < 7; i++) {
    if (Wire.available()) buf[i] = Wire.read();
    else return false;
  }

  // 生データ変換
  uint32_t h_raw =
      ((uint32_t)buf[1] << 12) |
      ((uint32_t)buf[2] << 4)  |
      (buf[3] >> 4);

  uint32_t t_raw =
      ((uint32_t)(buf[3] & 0x0F) << 16) |
      ((uint32_t)buf[4] << 8) |
      buf[5];

  hum  = (h_raw * 100.0f) / 1048576.0f;
  temp = (t_raw * 200.0f) / 1048576.0f - 50.0f;

  return true;
}

//--------------------------------
// 数値を簡単表示(軽量版)
//--------------------------------
void print_float(float v)
{
  char buf[8];
  int i = (int)v;
  int d = (int)((v - i) * 10);

  if (d < 0) d = -d;

  snprintf(buf, sizeof(buf), "%d.%d", i, d);
  aqm_print(buf);
}

//--------------------------------
// setup
//--------------------------------
void setup()
{
  Wire.setSCL(PB6);
  Wire.setSDA(PB7);
  Wire.begin();
  Wire.setClock(100000);

  aqm_init();

  aqm_setCursor(0,0);
  aqm_print("STM32 + DHT20");
}

//--------------------------------
// loop
//--------------------------------
void loop()
{
  float t, h;

  if (dht20_read(t, h)) {

    aqm_setCursor(0,1);

    aqm_print("T:");
    print_float(t);

    aqm_print(" H:");
    print_float(h);
  }

  delay(2000);
}

コンパイルした時のメモリーは下記ようになりました。

出力結果

LCDに2秒間隔で

aqm1602動作確認画像

のように表示されれば成功です。

実際にやってみた感想

8ピンという制限の中でも、
I2Cを使えば複数デバイスを扱えます。

最初は不安でしたが、
動いた瞬間の達成感は大きいです。

まとめ

小型STM32でも、

✔ LCD表示できる
✔ 温湿度を取得できる
✔ I2Cで拡張できる

ということが分かりました。

初心者の方はぜひ
「まずはSTEP1から」試してみてください。
また秋月電子で販売されているこのチップSTM32F303K8T6もメモリー64k vscode pltformIOにも対応していますので魅力的です。

タイトルとURLをコピーしました