온도 adc 측정 추가
This commit is contained in:
@@ -10,6 +10,7 @@ target_include_directories(app PRIVATE
|
|||||||
src/drivers/battery
|
src/drivers/battery
|
||||||
src/drivers/led
|
src/drivers/led
|
||||||
src/drivers/imu
|
src/drivers/imu
|
||||||
|
src/drivers/temperature
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(app PRIVATE
|
target_sources(app PRIVATE
|
||||||
@@ -20,4 +21,5 @@ target_sources(app PRIVATE
|
|||||||
src/drivers/battery/battery_adc.c
|
src/drivers/battery/battery_adc.c
|
||||||
src/drivers/led/led_control.c
|
src/drivers/led/led_control.c
|
||||||
src/drivers/imu/imu_i2c.c
|
src/drivers/imu/imu_i2c.c
|
||||||
|
src/drivers/temperature/tmp235.c
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
* IMU_SDA: P1.15 (I2C0 data)
|
* IMU_SDA: P1.15 (I2C0 data)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* ADC 채널 공통 매크로 (ADC_GAIN_*, ADC_REF_*, ADC_ACQ_TIME 등) */
|
||||||
#include <zephyr/dt-bindings/adc/adc.h>
|
#include <zephyr/dt-bindings/adc/adc.h>
|
||||||
|
/* nRF SAADC 전용 매크로 (NRF_SAADC_AIN* 채널 번호 정의) */
|
||||||
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
|
#include <zephyr/dt-bindings/adc/nrf-saadc.h>
|
||||||
/* nRF 핀 컨트롤 매크로 (NRF_PSEL - I2C/SPI 등 핀 재배치에 필요) */
|
/* nRF 핀 컨트롤 매크로 (NRF_PSEL - I2C/SPI 등 핀 재배치에 필요) */
|
||||||
#include <zephyr/dt-bindings/pinctrl/nrf-pinctrl.h>
|
#include <zephyr/dt-bindings/pinctrl/nrf-pinctrl.h>
|
||||||
@@ -64,6 +66,20 @@
|
|||||||
zephyr,resolution = <12>;
|
zephyr,resolution = <12>;
|
||||||
zephyr,oversampling = <2>; /* 2^2 = 4X */
|
zephyr,oversampling = <2>; /* 2^2 = 4X */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 온도 센서 채널 (AIN3 = P0.05, TMP235-Q1)
|
||||||
|
* 1/6 gain + 0.6V ref → 풀스케일 3.6V
|
||||||
|
* TMP235 출력 범위: 100mV(-40°C) ~ 2000mV(150°C) */
|
||||||
|
channel@3
|
||||||
|
{
|
||||||
|
reg = <3>;
|
||||||
|
zephyr,gain = "ADC_GAIN_1_6";
|
||||||
|
zephyr,reference = "ADC_REF_INTERNAL";
|
||||||
|
zephyr,acquisition-time = <ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40)>;
|
||||||
|
zephyr,input-positive = <NRF_SAADC_AIN3>;
|
||||||
|
zephyr,resolution = <12>;
|
||||||
|
zephyr,oversampling = <2>; /* 2^2 = 4X */
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* P0.04(AIN2)가 DK Arduino 헤더에 GPIO로 잡혀있어서 SAADC 충돌 → 비활성화 */
|
/* P0.04(AIN2)가 DK Arduino 헤더에 GPIO로 잡혀있어서 SAADC 충돌 → 비활성화 */
|
||||||
@@ -76,7 +92,8 @@
|
|||||||
/* ADC 채널을 코드에서 참조하기 위한 zephyr,user 노드 */
|
/* ADC 채널을 코드에서 참조하기 위한 zephyr,user 노드 */
|
||||||
zephyr,user
|
zephyr,user
|
||||||
{
|
{
|
||||||
io-channels = <&adc 2>;
|
io-channels = <&adc 2>, <&adc 3>;
|
||||||
|
io-channel-names = "battery", "temperature";
|
||||||
};
|
};
|
||||||
|
|
||||||
led
|
led
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
|
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
|
||||||
|
|
||||||
/* 디바이스트리에서 ADC 채널 스펙 가져오기 (gain, ref, acq time, input, resolution, oversampling) */
|
/* 디바이스트리에서 ADC 채널 스펙 가져오기 (gain, ref, acq time, input, resolution, oversampling) */
|
||||||
static const struct adc_dt_spec battery_adc = ADC_DT_SPEC_GET(ZEPHYR_USER_NODE);
|
static const struct adc_dt_spec battery_adc = ADC_DT_SPEC_GET_BY_NAME(ZEPHYR_USER_NODE, battery);
|
||||||
|
|
||||||
static int16_t adc_buffer;
|
static int16_t adc_buffer;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file tmp235.c
|
||||||
|
* @brief TMP235-Q1 온도 센서 드라이버 (Zephyr SAADC, AIN3 = P0.05)
|
||||||
|
*
|
||||||
|
* 배터리 ADC와 동일한 방식 (ADC_DT_SPEC_GET_BY_NAME + adc_read_dt).
|
||||||
|
* 채널 설정은 overlay channel@3에서 관리.
|
||||||
|
*
|
||||||
|
* 변환 공식:
|
||||||
|
* V_mV = raw × 3600 / 4095 (1/6 gain, 0.6V ref, 12-bit)
|
||||||
|
* T(°C × 100) = (V_mV - 500) × 10
|
||||||
|
******************************************************************************/
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/drivers/adc.h>
|
||||||
|
#include <zephyr/devicetree.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include "tmp235.h"
|
||||||
|
#include "debug_print.h"
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
* ADC 디바이스트리 설정
|
||||||
|
*============================================================================*/
|
||||||
|
#define ZEPHYR_USER_NODE DT_PATH(zephyr_user)
|
||||||
|
|
||||||
|
static const struct adc_dt_spec temp_adc =
|
||||||
|
ADC_DT_SPEC_GET_BY_NAME(ZEPHYR_USER_NODE, temperature);
|
||||||
|
|
||||||
|
static int16_t adc_buffer;
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
* 내부 변환
|
||||||
|
*============================================================================*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ADC raw → 온도 (°C × 100)
|
||||||
|
*
|
||||||
|
* V_mV = raw × 3600 / 4095
|
||||||
|
* T_cdeg = (V_mV - 500) × 10
|
||||||
|
*
|
||||||
|
* 정수 연산 (오버플로 없음):
|
||||||
|
* raw 최대 4095 → V_mV 최대 3600 → T_cdeg 최대 31000 → int32 OK
|
||||||
|
*/
|
||||||
|
static int16_t raw_to_cdeg(int16_t raw)
|
||||||
|
{
|
||||||
|
if (raw < 0) {
|
||||||
|
raw = 0;
|
||||||
|
}
|
||||||
|
int32_t v_mv = (int32_t)raw * 3600 / 4095;
|
||||||
|
int32_t t_cdeg = (v_mv - 500) * 10;
|
||||||
|
return (int16_t)t_cdeg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*==============================================================================
|
||||||
|
* 공개 API
|
||||||
|
*============================================================================*/
|
||||||
|
|
||||||
|
int temp_init(void)
|
||||||
|
{
|
||||||
|
if (!adc_is_ready_dt(&temp_adc)) {
|
||||||
|
DBG_PRINTF("[TEMP] FAIL — ADC device not ready\r\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = adc_channel_setup_dt(&temp_adc);
|
||||||
|
if (err) {
|
||||||
|
DBG_PRINTF("[TEMP] FAIL — channel setup (err=%d)\r\n", err);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG_PRINTF("[TEMP] OK — TMP235 ch=%d, res=%d, os=%d\r\n",
|
||||||
|
temp_adc.channel_id,
|
||||||
|
temp_adc.resolution,
|
||||||
|
temp_adc.oversampling);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t temp_read_cdeg(void)
|
||||||
|
{
|
||||||
|
/* 매번 채널 재설정 (배터리 ADC와 SAADC 공유) */
|
||||||
|
int err = adc_channel_setup_dt(&temp_adc);
|
||||||
|
if (err) {
|
||||||
|
DBG_PRINTF("[TEMP] FAIL — channel setup (err=%d)\r\n", err);
|
||||||
|
return INT16_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct adc_sequence seq = {0};
|
||||||
|
|
||||||
|
err = adc_sequence_init_dt(&temp_adc, &seq);
|
||||||
|
if (err) {
|
||||||
|
DBG_PRINTF("[TEMP] FAIL — sequence init (err=%d)\r\n", err);
|
||||||
|
return INT16_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
seq.buffer = &adc_buffer;
|
||||||
|
seq.buffer_size = sizeof(adc_buffer);
|
||||||
|
|
||||||
|
err = adc_read_dt(&temp_adc, &seq);
|
||||||
|
if (err) {
|
||||||
|
DBG_PRINTF("[TEMP] FAIL — read (err=%d)\r\n", err);
|
||||||
|
return INT16_MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t t = raw_to_cdeg(adc_buffer);
|
||||||
|
|
||||||
|
DBG_PRINTF("[TEMP] raw=%d -> %d.%02d C\r\n",
|
||||||
|
adc_buffer, t / 100, (t < 0 ? -t : t) % 100);
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* @file tmp235.h
|
||||||
|
* @brief TMP235-Q1 온도 센서 드라이버 (Zephyr SAADC, AIN3 = P0.05)
|
||||||
|
*
|
||||||
|
* 출력 공식: V = 500mV + 10mV/°C × T
|
||||||
|
* → T(°C) = (V_mV - 500) / 10
|
||||||
|
* → T(°Cx100) = (V_mV - 500) × 10
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef TMP235_H__
|
||||||
|
#define TMP235_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 온도 센서 초기화 — ADC 채널 설정
|
||||||
|
* @return 0 성공, 음수 에러
|
||||||
|
*/
|
||||||
|
int temp_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 온도 1회 측정
|
||||||
|
* @return 온도 (°C × 100), 에러 시 INT16_MIN
|
||||||
|
*/
|
||||||
|
int16_t temp_read_cdeg(void);
|
||||||
|
|
||||||
|
#endif /* TMP235_H__ */
|
||||||
+3
-1
@@ -24,6 +24,7 @@
|
|||||||
#include "battery_adc.h"
|
#include "battery_adc.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "imu_i2c.h"
|
#include "imu_i2c.h"
|
||||||
|
#include "tmp235.h"
|
||||||
|
|
||||||
LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
LOG_MODULE_REGISTER(vesiscan, LOG_LEVEL_INF);
|
||||||
|
|
||||||
@@ -309,8 +310,9 @@ int main(void)
|
|||||||
led_init();
|
led_init();
|
||||||
battery_adc_init();
|
battery_adc_init();
|
||||||
battery_timer_init();
|
battery_timer_init();
|
||||||
DBG_PRINTF(" gpio/timer/config/led/batt OK\r\n");
|
|
||||||
imu_init();
|
imu_init();
|
||||||
|
temp_init();
|
||||||
|
DBG_PRINTF(" gpio/timer/config/led/batt/imu/temp OK\r\n");
|
||||||
|
|
||||||
/*── Phase 2: BLE 스택 + NUS ──*/
|
/*── Phase 2: BLE 스택 + NUS ──*/
|
||||||
DBG_PRINTF("[2] BLE Init\r\n");
|
DBG_PRINTF("[2] BLE Init\r\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user