Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Raspberry Pi picoでI2C接続の温度センサーADT7410を使う
- 以下にRaspberry Pi 4上でビルドする方法を説明します。
- (~/pico/pico-sdkにpico-sdkが入ってると仮定してます。
- 違う場所にpico-sdkを入れた人は適宜読み替えてください)
- 1.プロジェクトを置きたい場所にプロジェクトのディレクトリを作る
- mkdir test_adt7410_usb01
- cd test_adt7410_usb01
- 2.ソースの作成
- 一番下にtest_adt7410_usb01.cのプログラムソースを記載してます
- 3.CMakeLists.txtの作成
- vi CMakeLists.txt
- 下記の内容で作成
- cmake_minimum_required(VERSION 3.12)
- # Pull in PICO SDK (must be before project)
- include(~/pico/pico-sdk/external/pico_sdk_import.cmake)
- project(test_adt7410_usb01_project)
- set(CMAKE_C_STANDARD 11)
- set(CMAKE_CXX_STANDARD 17)
- # Initialize the SDK
- pico_sdk_init()
- add_executable(
- test_adt7410_usb01 test_adt7410_usb01.c
- )
- target_link_libraries(test_adt7410_usb01 pico_stdlib hardware_i2c)
- pico_enable_stdio_usb(test_adt7410_usb01 1)
- pico_enable_stdio_uart(test_adt7410_usb01 0)
- pico_add_extra_outputs(test_adt7410_usb01)
- 上記のようにI2Cを使う場合はtarget_link_librariesでhardware_i2cを指定する必要があります
- 4.buildディレクトリの作成し、カレントディレクトリをbuildに移動
- mkdir build
- cd build
- 5.ビルドの実行
- export PICO_SDK_PATH=~/pico/pico-sdk
- cmake ..
- make
- cmake ..の..の部分は親のディレクトリを指してます
- つまり、今いるbuildディレクトリの上にCMakeLists.txtがあることを指定してます
- ビルドが終わるとbuildディレクトリ内に
- test_adt7410_usb01.bin test_adt7410_usb01.dis test_adt7410_usb01.elf test_adt7410_usb01.elf.map test_adt7410_usb01.hex test_adt7410_usb01.uf2
- ができます
- 6.picoへの書き込み
- picoのbootselボタンを押しながらpicoをRaspberry Pi 4のUSB2ポートに差します
- するとUSBストレージを何も差してなければ新たに/dev/sda1ができます
- 他にUSBストレージが差してある場合は/dev/sdb1、/dev/sdc1、/dev/sdd1など
- すでにあるストレージデバイスの次の番号のストレージデバイスが/devに追加されます
- Raspberry Pi 4が自動マウントすればそこにビルドで出来上がったtest_adt7410_usb01.uf2をコピーして
- syncを1回実行してからsudo umountでマウントを解除します
- 自動マウントしない場合は
- 新しくできたデバイスが/dev/sda1の場合は下記のようになります
- sudo mount -t vfat /dev/sda1 /mnt
- sudo cp test_adt7410_usb01.uf2 /mnt
- sync
- sudo umount /mnt
- 7.USBシリアルに接続する
- test_adt7410_usb01はUSBシリアルを使うようにプログラムされているので
- test_adt7410_usb01.uf2をpicoへコピーしてマウントを解除したあとにpicoが再起動して
- /dev/ttyACM0ができます
- minicomで/dev/ttyACM0に接続します
- minicomがない場合は
- sudo apt install minicom
- でインストールしてください
- minicom -D /dev/ttyACM0 -b 115200
- minicomの終了方法はCTRL+aを押した後にzを押すとメニューが出ます
- メニューが出たらxを押して「はい」を選択すると終了します
- 以下、test_adt7410_usb01.cのソースになります
- このソースではADT7410のI2Cアドレスは0x48にしてあります。
- ADT7410のI2Cアドレスが違う場合は変更してください
- I2CはpicoのI2C0を使ってます(SDAがGPIO4(6番ピン)、SCLがGPIO5(7番ピン))
- #include <stdio.h>
- #include "pico/stdlib.h"
- #include "hardware/i2c.h"
- #include "pico/time.h"
- #include "pico/binary_info.h"
- #define ADT7410_DEVICE_ADDRESS 0x48
- #define I2C_PORT i2c0
- void loop(void);
- void i2c_write_byte_non_addr(int addr, uint8_t val);
- void i2c_write_byte(int addr, uint8_t reg, uint8_t val);
- void i2c_write_half_word_little(int addr, uint8_t reg, uint16_t val);
- void i2c_write_half_word_big(int addr, uint8_t reg, uint16_t val);
- uint8_t i2c_read_byte(int addr, uint8_t reg);
- uint16_t i2c_read_half_word_little(int addr, uint8_t reg);
- uint16_t i2c_read_half_word_big(int addr, uint8_t reg);
- int main() {
- stdio_init_all();
- // This example will use I2C0 on GPIO4 (SDA) and GPIO5 (SCL)
- i2c_init(I2C_PORT, 400 * 1000); // I2C clock 400kHz
- gpio_set_function(4, GPIO_FUNC_I2C);
- gpio_set_function(5, GPIO_FUNC_I2C);
- gpio_pull_up(4);
- gpio_pull_up(5);
- // Make the I2C pins available to picotool
- bi_decl( bi_2pins_with_func(4, 5, GPIO_FUNC_I2C));
- // ADT7410のリセット
- i2c_write_byte_non_addr(ADT7410_DEVICE_ADDRESS, (uint8_t)0x2f);
- // リセット後、動作するまでに200ms必要
- sleep_ms(1000);
- while (1) {
- loop();
- }
- return 0;
- }
- void loop(void) {
- int32_t temp_raw = 0;
- float temp = 0.0;
- // 16bit 1-shot
- uint8_t data01 = 0xa0;
- //// 13bit 1-shot
- //uint8_t data01 = 0x20;
- i2c_write_byte(ADT7410_DEVICE_ADDRESS, (uint8_t)0x03, data01);
- // 読み出し可能になるまで待機(ステータスレジスタの最上位bit(bit7)が0になったら読み出し可能)
- long long read_wait_time01 = time_us_64();
- sleep_ms(230);
- uint8_t status_reg = 0;
- int count001 = 0;
- while (1) {
- // 10ms待機
- sleep_ms(10);
- // ステータスレジスタの読み込み
- status_reg = i2c_read_byte(ADT7410_DEVICE_ADDRESS, (uint8_t)0x02);
- if (count001 >= 500) {
- break;
- }
- if ((((int)status_reg >> 7) & 1) == 0) {
- break;
- }
- count001++;
- }
- // ADT7410のステータスレジスタの値の表示
- // printf("status=0x%02x, count001=%d, %lld ms\r\n", (int)status_reg, count001, (time_us_64() - read_wait_time01) / 1000LL);
- temp_raw = (int32_t)i2c_read_half_word_big(ADT7410_DEVICE_ADDRESS, (uint8_t)0x00);
- // 16bitの計算
- if (temp_raw >= 32768) {
- temp_raw -= 65536;
- }
- temp = temp_raw / 128.0;
- //// 13bitの計算
- //temp_raw = temp_raw >> 3;
- //if (temp_raw >= 4096) {
- // temp_raw -= 8192;
- //}
- //temp = temp_raw / 16.0;
- printf("Temp : %.4f degC\r\n", temp);
- sleep_ms(5000);
- }
- void i2c_write_byte_non_addr(int addr, uint8_t val) {
- i2c_write_blocking(I2C_PORT, addr, &val, 1, false);
- }
- void i2c_write_byte(int addr, uint8_t reg, uint8_t val) {
- uint8_t buf[2];
- buf[0] = reg;
- buf[1] = val;
- i2c_write_blocking(I2C_PORT, addr, buf, 2, false);
- }
- void i2c_write_half_word_little(int addr, uint8_t reg, uint16_t val) {
- uint8_t buf[3];
- buf[0] = reg;
- buf[1] = (uint16_t)(val & 0x00ff);
- buf[2] = (uint16_t)((val >> 8) & 0x00ff);
- i2c_write_blocking(I2C_PORT, addr, buf, 3, false);
- }
- void i2c_write_half_word_big(int addr, uint8_t reg, uint16_t val) {
- uint8_t buf[3];
- buf[0] = reg;
- buf[1] = (uint16_t)((val >> 8) & 0x00ff);
- buf[2] = (uint16_t)(val & 0x00ff);
- i2c_write_blocking(I2C_PORT, addr, buf, 3, false);
- }
- uint8_t i2c_read_byte(int addr, uint8_t reg) {
- uint8_t buf;
- i2c_write_blocking(I2C_PORT, addr, ®, 1, true);
- i2c_read_blocking(I2C_PORT, addr, &buf, 1, false); // False - finished with bus
- return buf;
- }
- uint16_t i2c_read_half_word_little(int addr, uint8_t reg) {
- uint8_t buf[2];
- uint16_t ret;
- i2c_write_blocking(I2C_PORT, addr, ®, 1, true);
- i2c_read_blocking(I2C_PORT, addr, buf, 2, false); // False - finished with bus
- ret = (uint16_t)(((uint16_t)buf[1] << 8) | (uint16_t)buf[0]);
- return ret;
- }
- uint16_t i2c_read_half_word_big(int addr, uint8_t reg) {
- uint8_t buf[2];
- uint16_t ret;
- i2c_write_blocking(I2C_PORT, addr, ®, 1, true);
- i2c_read_blocking(I2C_PORT, addr, buf, 2, false); // False - finished with bus
- ret = (uint16_t)(((uint16_t)buf[0] << 8) | (uint16_t)buf[1]);
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement