備忘録 ラズパイ5 ROS2 ⑨ Ubuntu Desktop 24.04LTSでROS2環境 C++ その5 bme280_3.cpp 温度、湿度、気圧 

　前回、BME280センサで測定した温度をPublishしました。BME280は三つのデータを同時に取得できるので、温度、湿度、気圧を全部Pubulishします。

### 環境
- Raspberry Pi 5 8GB
- 追加ボード；NVMe Base for Raspberry Pi 5 (NVMe Base by Pimoroni)
- Crucial クルーシャル P2シリーズ 500GB 3D NAND NVMe PCIe M.2 SSD CT500P2SSD8
- 初期；RaspberryPi OS Desktop 64bit (Debian version: 12 (bookworm) Release date: March 15th 2024)
- 現在；Ubuntu Desktop 24.04LTS(64-bit)
- ROS2 HumbleではなくJazzy

 　Windows10で、検索窓にcmdと入れ、コマンドプロンプトを起動します。
　sshでログインします（第１回参照）。必要ならupdateします。
```
C:\Users\yoshi>ssh yoshi.local
```
 ### 温度、湿度、気圧を取得するプログラム
 ```
 yoshi@yoshi:~/ros2_ws$ nano  works/src/bme280/read3data.cpp
 ```

```read3data.cpp
#include <iostream>
#include <fstream>       //  ファイル入出力用
#include <cstdlib>       //  exit()用
using namespace std;

std::tuple<float, float, float>  read3data(){
   ifstream ifs;            //  ifstream の変数（インスタンス）を生成．

    ifs.open("/sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_temp_input");
    //  ファイルを開く．fopen() に相当
    if( ! ifs ) {            //  ファイルが開けない場合の処理
        cerr << "File open error ! " << endl;
        exit(1);
    }
    char dataT[32];       //  データを読み込むバッファ
    ifs >> dataT;          //  ifs から入力
    float temp = stof(dataT);
    ifs.close();

    ifs.open("/sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_pressure_input");
    if( ! ifs ) {
        cerr << "File open error ! " << endl;
        exit(1);
    }
    char dataP[32];
    ifs >> dataP;
     float press = stof(dataP);
    ifs.close();

    ifs.open("/sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_humidityrelative_input");
    if( ! ifs ) {
        cerr << "File open error ! " << endl;
        exit(1);
    }
    char dataH[32];
    ifs >> dataH;
    float humi = stof(dataH);
    ifs.close();

    return  std::make_tuple((float)(temp/1000.0), (float)(press*10.0), (float)(humi/1000.0));
}

int main(void)
{
    auto [temp, press, humi] = read3data();
    cout << temp;
    cout << "\n" << press;
    cout << "\n" << humi;
auto datas = read3data();
cout << std::get<0>(datas);
    cout << "\n";
cout << std::get<1>(datas);
    cout << "\n";
cout << std::get<2>(datas);
    cout << "\n";
    return 0;
}
```

　コンパイルします。実行すると、温度、気圧、湿度を表示します。出力の方法は二通りを試しています。
 
```
yoshi@yoshi:~/ros2_ws$ g++ -o out works/src/bme280/read3data.cpp
yoshi@yoshi:~/ros2_ws$ ./out
27.78
1007.58
55.206
27.78
1007.58
55.206
```


 ### 温度、気圧、湿度をpublishする
 
 　ディレクトリ構造です。srcのなかに、bme280ディレクトリを作り、bme280.cppでプログラムを保存されています。新しいプログラムは、前回のbmp280.cppに、read3data()関数を組み込んだ形にし、ファイル名はbmp280_3.cppにしました。
  
```
$ cd ros2_ws
  tree
└── works
    ├── CMakeLists.txt
    ├── include
    │   └── works
    ├── package.xml
    └── src
        ├── bme280
        │   ├── bme280.cpp
        │   ├── read3data.cpp
        │   └── readTemp.cpp
        ├── exec_sample
        │   └── main.c
        ├── pub
        │   └── pub.cpp
        └── sub
            └── sub.cpp
yoshi@yoshi:~/ros2_ws$ mkdir works/src/bme280
yoshi@yoshi:~/ros2_ws$ nano  works/src/bme280/bme280_3.cpp
```

```bme280_3.cpp
#include "rclcpp/rclcpp.hpp"
#include "std_msgs/msg/string.hpp"
#include <stdio.h>
#include <iostream>
#include <fstream>       //  ファイル入出力用
#include <cstdlib>       //  exit()用
using namespace std;

std::tuple<float, float, float>  read3data(){
   ifstream ifs;            //  ifstream の変数（インスタンス）を生成．

    ifs.open("/sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_temp_input");
    //  ファイルを開く．fopen() に相当
    if( ! ifs ) {            //  ファイルが開けない場合の処理
        cerr << "File open error ! " << endl;
        exit(1);
    }
    char dataT[32];       //  データを読み込むバッファ
    ifs >> dataT;          //  ifs から入力
    float temp = stof(dataT);
    ifs.close();

    ifs.open("/sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_pressure_input");
    if( ! ifs ) {
        cerr << "File open error ! " << endl;
        exit(1);
    }
    char dataP[32];
    ifs >> dataP;
     float press = stof(dataP);
    ifs.close();

    ifs.open("/sys/bus/i2c/devices/i2c-1/1-0077/iio:device0/in_humidityrelative_input");
    if( ! ifs ) {
        cerr << "File open error ! " << endl;
        exit(1);
    }
    char dataH[32];
    ifs >> dataH;
    float humi = stof(dataH);
    ifs.close();

    return  std::make_tuple((float)(temp/1000.0), (float)(press*10.0), (float)(humi/1000.0));
}

int main(int argc, char **argv)
{
  printf("start publish bme280_3\n");
  rclcpp::init(argc, argv);
  auto node = rclcpp::Node::make_shared("publish_bme280_3data");
  auto publisher = node->create_publisher<std_msgs::msg::String>("greeting", 1);

  rclcpp::WallRate loop(1);
  while (rclcpp::ok()) {
    auto msg = std_msgs::msg::String();
    auto datas = read3data();
    msg.data = "Temp, Press, Humi " + std::to_string(std::get<0>(datas)) + ","+ std::to_string(std::get<1>(datas))+ ","+ std::to_string(std::get<2>(datas));
    publisher->publish(msg);
    loop.sleep();
  }

  rclcpp::shutdown();
  return 0;
}
```

　CMakeLists.txtを修正します。

```
 yoshi@yoshi:~/ros2_ws$ nano works/CMakeLists.txt
 ```
 
 ```CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
project(works)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rclcpp_components REQUIRED)
find_package(std_msgs REQUIRED)

add_executable(sub src/sub/sub.cpp)

ament_target_dependencies(sub rclcpp std_msgs)

install(
  TARGETS sub
  DESTINATION lib/${PROJECT_NAME}
  )

add_executable(bme280_3 src/bme280/bme280_3.cpp)

ament_target_dependencies(bme280_3 rclcpp std_msgs)

install(
  TARGETS bme280_3
  DESTINATION lib/${PROJECT_NAME}
  )

ament_package()
 ```

```
source /opt/ros/jazzy/setup.bash
```

 　``colcon build``でビルドしたものを登録します。subscriberのsubを起動します。
```
yoshi@yoshi:~/ros2_ws$ source ~/ros2_ws/install/setup.bash
yoshi@yoshi:~/ros2_ws$ ros2 run works sub
```

　もう一つターミナル（Windows10上）を立ち上げます。publisherのbme280_3を起動します。
 
 ```
 ssh yoshi.local
 
yoshi@yoshi:~/ros2_ws$ source ~/ros2_ws/install/setup.bash
yoshi@yoshi:~/ros2_ws$ ros2 run works bme280_3
start publish bme280
 ```
 
 　subが動いている最初のターミナルの様子です。実行中にBME280を指でつまんでいます。温度と湿度が変化しています。
  
```
yoshi@yoshi:~/ros2_ws$ ros2 run works sub
start subscribe test
[INFO] [1722197903.804267695] [yoshi_subscriber]: Temp, Press, Humi 26.480000,1007.604309,62.273998
[INFO] [1722197904.804259643] [yoshi_subscriber]: Temp, Press, Humi 26.490000,1007.584839,62.173000
[INFO] [1722197905.804244120] [yoshi_subscriber]: Temp, Press, Humi 26.490000,1007.566833,62.083000
[INFO] [1722197906.804258090] [yoshi_subscriber]: Temp, Press, Humi 26.490000,1007.587341,62.004002
[INFO] [1722197907.804295793] [yoshi_subscriber]: Temp, Press, Humi 26.799999,1007.545654,62.709000
[INFO] [1722197908.804249859] [yoshi_subscriber]: Temp, Press, Humi 28.730000,1007.588135,61.862999
[INFO] [1722197909.804247213] [yoshi_subscriber]: Temp, Press, Humi 29.629999,1007.627319,61.564999
[INFO] [1722197910.804302040] [yoshi_subscriber]: Temp, Press, Humi 30.260000,1007.604370,61.458000
[INFO] [1722197911.804279490] [yoshi_subscriber]: Temp, Press, Humi 30.730000,1007.547974,61.487000
[INFO] [1722197912.804299524] [yoshi_subscriber]: Temp, Press, Humi 31.049999,1007.585999,61.585999
[INFO] [1722197913.804243940] [yoshi_subscriber]: Temp, Press, Humi 31.280001,1007.607971,61.719002
[INFO] [1722197914.804251978] [yoshi_subscriber]: Temp, Press, Humi 31.480000,1007.517029,61.848999
[INFO] [1722197915.804258897] [yoshi_subscriber]: Temp, Press, Humi 31.340000,1007.393738,61.919998
[INFO] [1722197916.804258715] [yoshi_subscriber]: Temp, Press, Humi 30.830000,1007.540833,58.755001
[INFO] [1722197917.804300191] [yoshi_subscriber]: Temp, Press, Humi 30.680000,1007.546143,56.366001
```

```
└── works
    ├── CMakeLists.txt
    ├── include
    │   └── works
    ├── package.xml
    └── src
        ├── bme280
        │   ├── bme280_3.cpp
        │   ├── bme280.cpp
        │   ├── read3data.cpp
        │   └── readTemp.cpp
        ├── exec_sample
        │   └── main.c
        ├── pub
        │   └── pub.cpp
        └── sub
            └── sub.cpp
```


-----------------
<h2>備忘録　ラズパイ5 ROS2</h2>

[①　ハードの用意とUbuntu Desktop 24.04LTS](https://qiita.com/jamjam/items/9ad621bda6ab2e1d325b)

[②　Ubuntu Desktop 24.04LTSでROS2環境　rqt_graphとturtlesim](https://qiita.com/jamjam/items/b7bed8ec9ff68426ac8d)

[③　Ubuntu Desktop 24.04LTSでROS2環境　Python その１ responder（セットアップ）](https://qiita.com/jamjam/items/d124c662813085bc69e3)

[④　Ubuntu Desktop 24.04LTSでROS2環境　Pythonその２responder（コーディングと実行；失敗）](https://qiita.com/jamjam/items/d488e2e4fa88d9882626)

[⑤　Ubuntu Desktop 24.04LTSでROS2環境　C++ その1 セットアップ main.c](https://qiita.com/jamjam/items/4bba331c08805ccda0a8)

[⑥　Ubuntu Desktop 24.04LTSでROS2環境　C++ その2 セットアップ pub.cpp rqt_graph](https://qiita.com/jamjam/items/51eeb26400517883aa59)

[⑦　Ubuntu Desktop 24.04LTSでROS2環境　C++ その3 セットアップ sub.cpp rqt_graph](https://qiita.com/jamjam/items/50f3bc352e4cd0a7959d)

[⑧　Ubuntu Desktop 24.04LTSでROS2環境　C++ その4 bme280.cpp 温度](https://qiita.com/jamjam/items/f64eaae91fefed4eac34)

[⑨ Ubuntu Desktop 24.04LTSでROS2環境　C++ その5 bme280_3.cpp 温度、湿度、気圧](https://qiita.com/jamjam/items/edb799ec88bdfba29c4c)

[⑩ Ubuntu Desktop 24.04LTSでROS2環境　C++ その6 VL53L1X.cpp 距離センサ](https://qiita.com/jamjam/items/21074d7ed830926d7ff4)

--------------

https://qiita.com/jamjam/items/692568361dde688fad16