이 글을 계속 읽기에 앞서, 리눅스 환경에서 Nordic nRF54L15-DK 개발 키트에 Zephyr RTOS를 설치하는 과정을 설명한 이전 글을 참고하시기 바랍니다. 여기에서는 SparkFun 6자유도 센서 LSM6DSO 평가 기판을 이 nRF54L15-DK 개발 키트와 연동하는 과정에 대해 설명하겠습니다. 다음 그림은 두 장치가 어떻게 연결되어 있는지를 보여줍니다.
첫 번째 단계는 다음과 같은 디렉터리 구조를 만들고 Zephyr OS 개발용 파일들을 생성합니다.
|-- CMakeLists.txt
|-- nrf54l15dk_nrf54l15.overlay
|-- prj.conf
`-- src
`-- main.c
CMakeLists.txt 파일은 다음과 같습니다.
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(blinky)
target_sources(app PRIVATE src/main.c)
proj.conf 파일은 아래와 같습니다 (부동소수점 출력을 지원할 수 있도록 CONFIG_CBPRINTF_FP_SUPPORT를 사용하였습니다).
CONFIG_GPIO=y
CONFIG_I2C=y
CONFIG_CBPRINTF_FP_SUPPORT=y
그리고 가장 중요한 부분은 다음의 오버레이 파일로, I²C 인터페이스를 통해 LSM6DSO 센서를 nRF54L15-DK 개발 키트에서 실행 중인 Zephyr “RTOS” 애플리케이션 (main.c)에 연결해 줍니다. 오버레이 파일에서 I²C 마스터 클록 주파수는 100 kHz 그리고 I²C 슬레이브 주소는 0x6B로 설정되었습니다.
&i2c22 {
status = "okay";
pinctrl-0 = <&i2c22_default>;
pinctrl-1 = <&i2c22_sleep>;
clock-frequency = <100000>;
pinctrl-names = "default", "sleep";
mysensor: mysensor@6b{
compatible = "i2c-device";
status = "okay";
reg = < 0x6b >;
};
};
&pinctrl {
/omit-if-no-ref/ i2c22_default: i2c22_default {
group1 {
psels = <NRF_PSEL(TWIM_SCL, 1, 11)>,
<NRF_PSEL(TWIM_SDA, 1, 12)>;
};
};
/omit-if-no-ref/ i2c22_sleep: i2c22_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SCL, 1, 11)>,
<NRF_PSEL(TWIM_SDA, 1, 12)>;
low-power-enable;
};
};
};
main.c 파일은 다음과 같습니다.
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/drivers/i2c.h>
#include <zephyr/sys/printk.h>
#define I2C_NODE DT_NODELABEL(mysensor)
static const struct i2c_dt_spec dev_i2c = I2C_DT_SPEC_GET(I2C_NODE);
#define WHOAMI 0x0F
/* 1000 msec = 1 sec */
#define SLEEP_TIME_MS 1000
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
int main(void)
{
if (!device_is_ready(dev_i2c.bus)) {
printk("I2C bus %s is not ready!\n\r",dev_i2c.bus->name);
return -1;
}
int ret;
bool led_state = true;
if (!gpio_is_ready_dt(&led)) {
return 0;
}
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return 0;
}
while (1) {
uint8_t id = 0;
uint8_t regs[] = {WHOAMI};
int ret = i2c_write_read_dt(&dev_i2c, regs, 1, &id, 1);
if (ret != 0) {
printk("Failed to read register %x \n", regs[0]);
return -1;
}
if (id != 0x6C) {
printk("Invalid chip id! %x \n", id);
return -1;
}
else {
printk("Found WHOAMI = %x\n", id);
}
ret = gpio_pin_toggle_dt(&led);
if (ret < 0) {
return 0;
}
led_state = !led_state;
printf("LED state: %s\n", led_state ? "ON" : "OFF");
k_msleep(SLEEP_TIME_MS);
//Read and print values
uint8_t values[65];
ret = i2c_burst_read_dt(&dev_i2c, 0x00, values, 64);
if (ret != 0) {
printk("Failed to read registers %x \n", 0x00);
return;
}
int i = 0;
while(i < 64)
{
printk("Register %x = %x\n", i, values[i]);
i = i + 1;
}
}
return 0;
}
이 main.c 코드는 LED를 점멸시키는 동시에 WHOAMI 레지스터를 읽고, 센서 내부 ASIC에 있는 65개의 레지스터 주소를 자동 증가 (버스트) 방식으로 읽어옵니다. 이러한 I²C 트랜잭션은 아래와 같으며, Zephyr OS API와 적절한 매크로 기법을 통해 이루어집니다.
int ret = i2c_write_read_dt(&dev_i2c, regs, 1, &id, 1);
ret = i2c_burst_read_dt(&dev_i2c, 0x00, values, 64);
이를 컴파일 (빌드)하기 위해 다음 단계를 실행합니다.
(venv) $ west build -p always -b nrf54l15dk/nrf54l15/cpuapp -- -DEXTRA_DTC_OVERLAY_FILE=nrf54l15dk_nrf54l15.overlay
그 다음, nRF54L15-DK를 다음과 같이 프로그래밍합니다.
(venv) $ west flash
프로그래밍이 완료되면, 아래와 같이 구성하여 LSM6DSO 평가 기판의 I²C 통신 기능을 시연합니다.
이 영상은 I²C 인터페이스가 LSM6DSO 센서와 통신을 하면 LED가 점멸하는 모습과 함께, 이전 게시글에서 설명한 SparkFun 8채널 USB 로직 분석기로 I²C 통신을 캡처하는 모습을 보여줍니다.
IoT용 nRF54L15-DK 개발 키트는 USB를 통해 호스트 PC에 연결되어 있습니다. SparkFun 로직 분석기가 캡처한 I²C 트랜잭션을 보면 아래와 같이 정상적으로 동작하고 있습니다.
이제 다음 명령으로 minicom 터미널을 열어 nRF54L15-DK가 수신하는 데이터를 모니터링합니다.
minicom -D /dev/ttyACM1
LSM6DSO 평가 기판의 WHO_AM_I (0x0F) 레지스터를 읽으면 아래와 같습니다.
Found WHOAMI = 6c
LED state: ON
Register 0 = 0
Register 1 = 0
Register 2 = 3f
Register 3 = 0
Register 4 = 0
Register 5 = 0
Register 6 = 0
Register 7 = 0
Register 8 = 0
Register 9 = 0
Register a = 0
Register b = 0
Register c = 0
Register d = 0
Register e = 0
Register f = 6c
Register 10 = 0
Register 11 = 0
Register 12 = 4
Register 13 = 0
Register 14 = 0
Register 15 = 0
Register 16 = 0
Register 17 = 0
Register 18 = e0
Register 19 = 0
Register 1a = 0
Register 1b = 0
Register 1c = 0
Register 1d = 0
Register 1e = 0
Register 1f = 28
Register 20 = 0
Register 21 = 0
Register 22 = 0
Register 23 = 0
Register 24 = 0
Register 25 = 0
Register 26 = 0
Register 27 = 0
Register 28 = 0
Register 29 = 0
Register 2a = 0
Register 2b = 0
Register 2c = 0
Register 2d = 0
Register 2e = 0
Register 2f = 0
Register 30 = 0
Register 31 = 0
Register 32 = 0
Register 33 = 0
Register 34 = 0
Register 35 = 0
Register 36 = 0
Register 37 = 0
Register 38 = 0
Register 39 = 0
Register 3a = 0
Register 3b = 0
Register 3c = 0
Register 3d = 0
Register 3e = 0
Register 3f = 0
Found WHOAMI = 6c
LED state: OFF
이 글에서는 Nordic nRF54L15-DK 개발 키트에 I²C를 통해 센서를 연결하는 방법을 설명하였습니다. 디지키에서는 여러 IoT 프로젝트에 적용할 수 있는 다양한 I²C 센서를 취급하고 있으며, 이 글에서 설명한 절차를 사용하여 이러한 센서들을 Nordic nRF54L15-DK 개발 키트에 연결할 수 있습니다.
좋은 하루 되세요!
영문 원본: Nordic nRF54L15-DK Zephyr Linux I2C interface to LSM6DSO sensor

