Advertisement
Guest User

Raspberry Pi picoでI2C接続の温度センサーADT7410を使う

a guest
Feb 4th, 2021
618
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.01 KB | None | 0 0
  1. Raspberry Pi picoでI2C接続の温度センサーADT7410を使う
  2.  
  3. 以下にRaspberry Pi 4上でビルドする方法を説明します。
  4.  
  5. (~/pico/pico-sdkにpico-sdkが入ってると仮定してます。
  6. 違う場所にpico-sdkを入れた人は適宜読み替えてください)
  7.  
  8.  
  9. 1.プロジェクトを置きたい場所にプロジェクトのディレクトリを作る
  10.  
  11. mkdir test_adt7410_usb01
  12.  
  13. cd test_adt7410_usb01
  14.  
  15.  
  16. 2.ソースの作成
  17.  
  18. 一番下にtest_adt7410_usb01.cのプログラムソースを記載してます
  19.  
  20.  
  21. 3.CMakeLists.txtの作成
  22.  
  23.  
  24. vi CMakeLists.txt
  25.  
  26. 下記の内容で作成
  27.  
  28. cmake_minimum_required(VERSION 3.12)
  29.  
  30. # Pull in PICO SDK (must be before project)
  31. include(~/pico/pico-sdk/external/pico_sdk_import.cmake)
  32.  
  33. project(test_adt7410_usb01_project)
  34. set(CMAKE_C_STANDARD 11)
  35. set(CMAKE_CXX_STANDARD 17)
  36.  
  37. # Initialize the SDK
  38. pico_sdk_init()
  39. add_executable(
  40. test_adt7410_usb01 test_adt7410_usb01.c
  41. )
  42. target_link_libraries(test_adt7410_usb01 pico_stdlib hardware_i2c)
  43.  
  44. pico_enable_stdio_usb(test_adt7410_usb01 1)
  45. pico_enable_stdio_uart(test_adt7410_usb01 0)
  46.  
  47. pico_add_extra_outputs(test_adt7410_usb01)
  48.  
  49.  
  50.  
  51. 上記のようにI2Cを使う場合はtarget_link_librariesでhardware_i2cを指定する必要があります
  52.  
  53.  
  54. 4.buildディレクトリの作成し、カレントディレクトリをbuildに移動
  55.  
  56. mkdir build
  57.  
  58. cd build
  59.  
  60.  
  61.  
  62. 5.ビルドの実行
  63.  
  64. export PICO_SDK_PATH=~/pico/pico-sdk
  65.  
  66. cmake ..
  67.  
  68. make
  69.  
  70.  
  71. cmake ..の..の部分は親のディレクトリを指してます
  72. つまり、今いるbuildディレクトリの上にCMakeLists.txtがあることを指定してます
  73. ビルドが終わるとbuildディレクトリ内に
  74. 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
  75. ができます
  76.  
  77.  
  78. 6.picoへの書き込み
  79.  
  80. picoのbootselボタンを押しながらpicoをRaspberry Pi 4のUSB2ポートに差します
  81. するとUSBストレージを何も差してなければ新たに/dev/sda1ができます
  82. 他にUSBストレージが差してある場合は/dev/sdb1、/dev/sdc1、/dev/sdd1など
  83. すでにあるストレージデバイスの次の番号のストレージデバイスが/devに追加されます
  84. Raspberry Pi 4が自動マウントすればそこにビルドで出来上がったtest_adt7410_usb01.uf2をコピーして
  85. syncを1回実行してからsudo umountでマウントを解除します
  86. 自動マウントしない場合は
  87. 新しくできたデバイスが/dev/sda1の場合は下記のようになります
  88.  
  89. sudo mount -t vfat /dev/sda1 /mnt
  90. sudo cp test_adt7410_usb01.uf2 /mnt
  91. sync
  92. sudo umount /mnt
  93.  
  94.  
  95. 7.USBシリアルに接続する
  96.  
  97. test_adt7410_usb01はUSBシリアルを使うようにプログラムされているので
  98. test_adt7410_usb01.uf2をpicoへコピーしてマウントを解除したあとにpicoが再起動して
  99. /dev/ttyACM0ができます
  100.  
  101. minicomで/dev/ttyACM0に接続します
  102.  
  103. minicomがない場合は
  104. sudo apt install minicom
  105. でインストールしてください
  106.  
  107. minicom -D /dev/ttyACM0 -b 115200
  108.  
  109.  
  110. minicomの終了方法はCTRL+aを押した後にzを押すとメニューが出ます
  111. メニューが出たらxを押して「はい」を選択すると終了します
  112.  
  113.  
  114.  
  115.  
  116.  
  117. 以下、test_adt7410_usb01.cのソースになります
  118. このソースではADT7410のI2Cアドレスは0x48にしてあります。
  119. ADT7410のI2Cアドレスが違う場合は変更してください
  120. I2CはpicoのI2C0を使ってます(SDAがGPIO4(6番ピン)、SCLがGPIO5(7番ピン))
  121.  
  122.  
  123. #include <stdio.h>
  124. #include "pico/stdlib.h"
  125. #include "hardware/i2c.h"
  126. #include "pico/time.h"
  127. #include "pico/binary_info.h"
  128.  
  129. #define ADT7410_DEVICE_ADDRESS 0x48
  130. #define I2C_PORT i2c0
  131.  
  132. void loop(void);
  133. void i2c_write_byte_non_addr(int addr, uint8_t val);
  134. void i2c_write_byte(int addr, uint8_t reg, uint8_t val);
  135. void i2c_write_half_word_little(int addr, uint8_t reg, uint16_t val);
  136. void i2c_write_half_word_big(int addr, uint8_t reg, uint16_t val);
  137. uint8_t i2c_read_byte(int addr, uint8_t reg);
  138. uint16_t i2c_read_half_word_little(int addr, uint8_t reg);
  139. uint16_t i2c_read_half_word_big(int addr, uint8_t reg);
  140.  
  141. int main() {
  142. stdio_init_all();
  143.  
  144. // This example will use I2C0 on GPIO4 (SDA) and GPIO5 (SCL)
  145. i2c_init(I2C_PORT, 400 * 1000); // I2C clock 400kHz
  146. gpio_set_function(4, GPIO_FUNC_I2C);
  147. gpio_set_function(5, GPIO_FUNC_I2C);
  148. gpio_pull_up(4);
  149. gpio_pull_up(5);
  150. // Make the I2C pins available to picotool
  151. bi_decl( bi_2pins_with_func(4, 5, GPIO_FUNC_I2C));
  152.  
  153.  
  154. // ADT7410のリセット
  155. i2c_write_byte_non_addr(ADT7410_DEVICE_ADDRESS, (uint8_t)0x2f);
  156. // リセット後、動作するまでに200ms必要
  157. sleep_ms(1000);
  158.  
  159. while (1) {
  160. loop();
  161. }
  162.  
  163. return 0;
  164. }
  165.  
  166. void loop(void) {
  167.  
  168. int32_t temp_raw = 0;
  169. float temp = 0.0;
  170.  
  171. // 16bit 1-shot
  172. uint8_t data01 = 0xa0;
  173.  
  174. //// 13bit 1-shot
  175. //uint8_t data01 = 0x20;
  176.  
  177. i2c_write_byte(ADT7410_DEVICE_ADDRESS, (uint8_t)0x03, data01);
  178.  
  179. // 読み出し可能になるまで待機(ステータスレジスタの最上位bit(bit7)が0になったら読み出し可能)
  180. long long read_wait_time01 = time_us_64();
  181. sleep_ms(230);
  182.  
  183. uint8_t status_reg = 0;
  184. int count001 = 0;
  185. while (1) {
  186. // 10ms待機
  187. sleep_ms(10);
  188.  
  189. // ステータスレジスタの読み込み
  190. status_reg = i2c_read_byte(ADT7410_DEVICE_ADDRESS, (uint8_t)0x02);
  191.  
  192. if (count001 >= 500) {
  193. break;
  194. }
  195. if ((((int)status_reg >> 7) & 1) == 0) {
  196. break;
  197. }
  198. count001++;
  199. }
  200. // ADT7410のステータスレジスタの値の表示
  201. // printf("status=0x%02x, count001=%d, %lld ms\r\n", (int)status_reg, count001, (time_us_64() - read_wait_time01) / 1000LL);
  202.  
  203. temp_raw = (int32_t)i2c_read_half_word_big(ADT7410_DEVICE_ADDRESS, (uint8_t)0x00);
  204. // 16bitの計算
  205. if (temp_raw >= 32768) {
  206. temp_raw -= 65536;
  207. }
  208. temp = temp_raw / 128.0;
  209.  
  210. //// 13bitの計算
  211. //temp_raw = temp_raw >> 3;
  212. //if (temp_raw >= 4096) {
  213. // temp_raw -= 8192;
  214. //}
  215. //temp = temp_raw / 16.0;
  216.  
  217. printf("Temp : %.4f degC\r\n", temp);
  218.  
  219. sleep_ms(5000);
  220. }
  221.  
  222. void i2c_write_byte_non_addr(int addr, uint8_t val) {
  223. i2c_write_blocking(I2C_PORT, addr, &val, 1, false);
  224. }
  225.  
  226. void i2c_write_byte(int addr, uint8_t reg, uint8_t val) {
  227. uint8_t buf[2];
  228. buf[0] = reg;
  229. buf[1] = val;
  230. i2c_write_blocking(I2C_PORT, addr, buf, 2, false);
  231. }
  232.  
  233. void i2c_write_half_word_little(int addr, uint8_t reg, uint16_t val) {
  234. uint8_t buf[3];
  235. buf[0] = reg;
  236. buf[1] = (uint16_t)(val & 0x00ff);
  237. buf[2] = (uint16_t)((val >> 8) & 0x00ff);
  238. i2c_write_blocking(I2C_PORT, addr, buf, 3, false);
  239. }
  240.  
  241. void i2c_write_half_word_big(int addr, uint8_t reg, uint16_t val) {
  242. uint8_t buf[3];
  243. buf[0] = reg;
  244. buf[1] = (uint16_t)((val >> 8) & 0x00ff);
  245. buf[2] = (uint16_t)(val & 0x00ff);
  246. i2c_write_blocking(I2C_PORT, addr, buf, 3, false);
  247. }
  248.  
  249. uint8_t i2c_read_byte(int addr, uint8_t reg) {
  250. uint8_t buf;
  251. i2c_write_blocking(I2C_PORT, addr, &reg, 1, true);
  252. i2c_read_blocking(I2C_PORT, addr, &buf, 1, false); // False - finished with bus
  253. return buf;
  254. }
  255.  
  256. uint16_t i2c_read_half_word_little(int addr, uint8_t reg) {
  257. uint8_t buf[2];
  258. uint16_t ret;
  259. i2c_write_blocking(I2C_PORT, addr, &reg, 1, true);
  260. i2c_read_blocking(I2C_PORT, addr, buf, 2, false); // False - finished with bus
  261.  
  262. ret = (uint16_t)(((uint16_t)buf[1] << 8) | (uint16_t)buf[0]);
  263. return ret;
  264. }
  265.  
  266. uint16_t i2c_read_half_word_big(int addr, uint8_t reg) {
  267. uint8_t buf[2];
  268. uint16_t ret;
  269. i2c_write_blocking(I2C_PORT, addr, &reg, 1, true);
  270. i2c_read_blocking(I2C_PORT, addr, buf, 2, false); // False - finished with bus
  271.  
  272. ret = (uint16_t)(((uint16_t)buf[0] << 8) | (uint16_t)buf[1]);
  273. return ret;
  274. }
  275.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement