Riot: ν”Œλ‘œνŠΈμ™€ 더블이 κ³³κ³³μ—μ„œ μ‚¬μš©λ˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

에 λ§Œλ“  2019λ…„ 08μ›” 20일  Β·  5μ½”λ©˜νŠΈ  Β·  좜처: RIOT-OS/RIOT

μ„€λͺ…

λŒ€λΆ€λΆ„μ˜ ν”Œλž«νΌμ—λŠ” 단정밀도 뢀동 μ†Œμˆ˜μ μ— λŒ€ν•œ HW 지원이 μ—†μœΌλ©° (기본을 μ œμ™Έν•˜κ³ ) 배정밀도λ₯Ό μ§€μ›ν•˜λŠ” ν”Œλž«νΌμ€ μ—†μŠ΅λ‹ˆλ‹€.

grep μ†ŒμŠ€ μ½”λ“œλ₯Ό 톡해 float 및 double의 μΈμŠ€ν„΄μŠ€λ₯Ό 찾을 수 μžˆμŠ΅λ‹ˆλ‹€. λ‹€μŒκ³Ό 같은 이유둜 λ¬Έμ œκ°€ λ©λ‹ˆλ‹€.

  • soft-float 지원이 μ—°κ²°λ˜μ–΄μ•Ό ν•˜λŠ” 경우 μ½”λ“œ 크기λ₯Ό λŠ˜λ¦½λ‹ˆλ‹€.
  • μ†Œν”„νŠΈ ν”Œλ‘œνŠΈλŠ” λŠλ¦½λ‹ˆλ‹€.
  • ν•˜λ“œ ν”Œλ‘œνŠΈλ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” κ²½μš°μ—λ„ 일반적으둜 μΈν„°λŸ½νŠΈ λ˜λŠ” 컀널 μ½”λ“œμ—μ„œ μ‚¬μš©ν•˜μ§€ μ•Šμ•„μ•Ό ν•©λ‹ˆλ‹€. μ΄λŠ” fp λ ˆμ§€μŠ€ν„° μ €μž₯/볡원과 κ΄€λ ¨λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

    • λ“œλΌμ΄λ²„λ₯Ό μ‚¬μš©ν•˜λ©΄ μ–΄λ–€ μ»¨ν…μŠ€νŠΈμ—μ„œ μ‹€ν–‰λ˜λŠ”μ§€ μ•ŒκΈ°κ°€ μ–΄λ ΅μŠ΅λ‹ˆλ‹€.

  • μ‚¬μš©μžλŠ” 예λ₯Ό λ“€μ–΄ sx127x λ“œλΌμ΄λ²„κ°€ double을 μ‚¬μš©ν•˜κ³  μžˆλŠ”μ§€ μ˜μ‹¬μ‘°μ°¨ ν•  수 μ—†μŠ΅λ‹ˆλ‹€.

λ‚΄κ°€ λ³Ό λ•Œ μ΄λŸ¬ν•œ μ‚¬μš©μ˜ λŒ€λΆ€λΆ„μ€ μ •λ‹Ήν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 특히 double의 _all_ μ‚¬μš©μ€ float둜 λŒ€μ²΄λ  수 μžˆμŠ΅λ‹ˆλ‹€.

문제λ₯Ό μž¬ν˜„ν•˜λŠ” 단계

λŒ€λž΅μ μΈ 검색을 ν•˜λŠ” λΉ λ₯Έ 방법은 λ‹€μŒ μ •κ·œμ‹μ„ μ‚¬μš©ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

$ git grep  "^\([^/]\|\(/[^*/]\)\)*\bdouble\b"  -- "*.[ch]"
$ git grep  "^\([^/]\|\(/[^*/]\)\)*\bfloat\b"  -- "*.[ch]"

그듀은 일뢀 거짓 긍정을 ν¬μ°©ν•˜κ³  일뢀 거짓 뢀정을 놓칠 κ²ƒμž…λ‹ˆλ‹€.

μ‹€μ œ κ²°κ³Ό

μˆ˜λ™ 정리 ν›„ κ²°κ³ΌλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.


이쀑 문제

drivers/bmp180/bmp180.c:    return (int16_t)(44330.0 * (1.0 - pow((double)p / pressure_0, 0.1903)));;
drivers/bmp180/bmp180.c:    return (uint32_t)((double)p / pow(1.0 - (altitude / 44330.0), 5.255));;
drivers/sx127x/sx127x_getset.c:    channel = (uint32_t)((double) channel / (double)LORA_FREQUENCY_RESOLUTION_DEFAULT);
drivers/sx127x/sx127x_getset.c:            double bw = 0.0;
drivers/sx127x/sx127x_getset.c:            double rs = bw / (1 << dev->settings.lora.datarate);
drivers/sx127x/sx127x_getset.c:            double ts = 1 / rs;
drivers/sx127x/sx127x_getset.c:            double t_preamble = (dev->settings.lora.preamble_len + 4.25) * ts;
drivers/sx127x/sx127x_getset.c:            double tmp =
drivers/sx127x/sx127x_getset.c:                    / (double) (4 * dev->settings.lora.datarate
drivers/sx127x/sx127x_getset.c:            double n_payload = 8 + ((tmp > 0) ? tmp : 0);
drivers/sx127x/sx127x_getset.c:            double t_payload = n_payload * ts;
drivers/sx127x/sx127x_getset.c:            double t_on_air = t_preamble + t_payload;
drivers/sx127x/sx127x_internal.c:    initial_freq = (double) (((uint32_t) sx127x_reg_read(dev, SX127X_REG_FRFMSB) << 16)
drivers/sx127x/sx127x_internal.c:                             | ((uint32_t) sx127x_reg_read(dev, SX127X_REG_FRFLSB))) * (double)LORA_FREQUENCY_RESOLUTION_DEFAULT;
drivers/tmp006/tmp006.c:    *tamb = (double)rawt / 128.0;
drivers/tmp006/tmp006.c:    double tdie_k = *tamb + 273.15;
drivers/tmp006/tmp006.c:    double sens_v = (double)rawv * TMP006_CCONST_LSB_SIZE;
drivers/tmp006/tmp006.c:    double tdiff = tdie_k - TMP006_CCONST_TREF;
drivers/tmp006/tmp006.c:    double tdiff_pow2 = pow(tdiff, 2);
drivers/tmp006/tmp006.c:    double s = TMP006_CCONST_S0 * (1 + TMP006_CCONST_A1 * tdiff
drivers/tmp006/tmp006.c:    double v_os = TMP006_CCONST_B0 + TMP006_CCONST_B1 * tdiff
drivers/tmp006/tmp006.c:    double f_obj = (sens_v - v_os) + TMP006_CCONST_C2 * pow((sens_v - v_os), 2);
drivers/tmp006/tmp006.c:    double t = pow(pow(tdie_k, 4) + (f_obj / s), 0.25);
sys/crypto/modes/ocb.c:       L_$ = double(L_*)
sys/crypto/modes/ocb.c:       L_0 = double(L_$)
sys/crypto/modes/ocb.c:       L_i = double(L_{i-1}) for every integer i > 0
sys/include/cb_mux.h: * @param[in] head   double pointer to first list entry
sys/include/cb_mux.h: * @param[in] head   double pointer to first list entry
sys/include/net/gnrc/rpl/structs.h:    double link_metric;             /**< metric of the link */
sys/include/random.h:double random_real(void);
sys/include/random.h:double random_real_inclusive(void);
sys/include/random.h:double random_real_exclusive(void);
sys/include/random.h:double random_res53(void);
sys/include/ubjson.h:static inline ssize_t ubjson_get_double(ubjson_cookie_t *__restrict cookie, ssize_t content, double *dest)
sys/include/ubjson.h:        double f;
sys/include/ubjson.h:ssize_t ubjson_write_double(ubjson_cookie_t *__restrict cookie, double value);
sys/net/routing/nhdp/iib_table.c:static const double const_dat = (((double)DAT_CONSTANT) / DAT_MAXIMUM_LOSS);
sys/net/routing/nhdp/iib_table.c:    double sum_total, sum_rcvd, loss;
sys/net/routing/nhdp/iib_table.c:                loss = (((double)ls_elt->hello_interval) * ((double)ls_elt->lost_hellos))
sys/quad_math/fixdfdi.c:quad_t __fixdfdi(double x)
sys/quad_math/fixunsdfdi.c:u_quad_t __fixunsdfdi(double x)
sys/quad_math/fixunssfdi.c:    double x, toppart;
sys/quad_math/fixunssfdi.c:    x -= (double) t.uq;
sys/quad_math/floatdidf.c:double __floatdidf(quad_t x)
sys/quad_math/floatdidf.c:    double d;
sys/quad_math/floatdidf.c:    d = (double) u.ul[H] * (((int) 1 << (INT_BITS - 2)) * 4.0);
sys/quad_math/floatdisf.c:    f = (double) u.ul[H] * (((int) 1 << (INT_BITS - 2)) * 4.0);
sys/quad_math/floatunsdidf.c:double __floatunsdidf(u_quad_t x)
sys/quad_math/floatunsdidf.c:    double d;
sys/quad_math/floatunsdidf.c:    d = (double) u.ul[H] * (((int) 1 << (INT_BITS - 2)) * 4.0);
sys/quad_math/quad.h:quad_t __fixdfdi(double);
sys/quad_math/quad.h:u_quad_t __fixunsdfdi(double);
sys/quad_math/quad.h:double __floatdidf(quad_t);
sys/quad_math/quad.h:double __floatunsdidf(u_quad_t);
sys/random/mersenne.c:double random_real(void)
sys/random/mersenne.c:double random_real_inclusive(void)
sys/random/mersenne.c:double random_real_exclusive(void)
sys/random/mersenne.c:    return ((double) random_uint32() + 0.5) * (1.0 / TWO_POW_32);
sys/random/mersenne.c:double random_res53(void)
sys/random/mersenne.c:    double a = random_uint32() * TWO_POW_26;
sys/random/mersenne.c:    double b = random_uint32() * (1.0 / TWO_POW_6);
sys/random/tinymt32/tinymt32.h:static inline double tinymt32_generate_32double(tinymt32_t *random)
sys/ubjson/ubjson-write.c:ssize_t ubjson_write_double(ubjson_cookie_t *restrict cookie, double value)
sys/ubjson/ubjson-write.c:        double f;
tests/bloom_bytes/main.c:    double false_positive_rate = (double) in / (double) lenA;
tests/float/main.c:    double x = 1234567.0 / 1024.0;
tests/float/main.c:        double z = (x - floor(x));
tests/thread_float/main.c:        printf("T(%" PRIkernel_pid "): %f\n", thread_getpid(), (double)f);
tests/unittests/tests-bloom/tests-bloom.c:    double false_positive_rate = 0;
tests/unittests/tests-bloom/tests-bloom.c:    false_positive_rate = (double) in / (double) lenA;
tests/unittests/tests-printf_float/tests-printf_float.c:static const double in0 = 2016.0349;
tests/unittests/tests-printf_float/tests-printf_float.c:static const double in1 = 123.4567;
tests/unittests/tests-printf_float/tests-printf_float.c:static const double in2 = 0.0;
tests/unittests/tests-sht1x/tests-sht1x.c:    static const double d1_table[] = { -40.1, -39.8, -39.7, -39.6, -39.4 };
tests/unittests/tests-sht1x/tests-sht1x.c:    double d1 = d1_table[dev->vdd];
tests/unittests/tests-sht1x/tests-sht1x.c:    double d2 = (dev->conf & SHT1X_CONF_LOW_RESOLUTION) ? 0.04 : 0.01;
tests/unittests/tests-sht1x/tests-sht1x.c:    double raw = (double)_raw;
tests/unittests/tests-sht1x/tests-sht1x.c:    double temp = d1 + d2 * raw;
tests/unittests/tests-sht1x/tests-sht1x.c:    static const double c1 = -2.0468;
tests/unittests/tests-sht1x/tests-sht1x.c:    static const double t1 = 0.01;
tests/unittests/tests-sht1x/tests-sht1x.c:    double temp = ((double)_temp) / 100.0;
tests/unittests/tests-sht1x/tests-sht1x.c:    double raw = (double)_raw;
tests/unittests/tests-sht1x/tests-sht1x.c:    double c2, c3, t2, hum_linear, hum_real;


μš”μ•½

cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh.h:    float percentage;           /**< vote percentage threshold for approval of being a root */
cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh.h:esp_err_t esp_mesh_set_vote_percentage(float percentage);
cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh.h:float esp_mesh_get_vote_percentage(void);
cpu/esp8266/vendor/esp/phy_info.c:           (float)info->spur_freq_primary / info->spur_freq_divisor,
cpu/esp8266/vendor/esp/phy_info.c:           (float)info->spur_freq_2_primary / info->spur_freq_2_divisor,
cpu/esp8266/vendor/espressif/c_types.h:typedef float               real32_t;
cpu/esp8266/vendor/espressif/c_types.h:typedef float               real32;
drivers/adt7310/adt7310.c:#define ADT7310_TEMPERATURE_LSB_FLOAT (1.f/((float)((int)1 << ADT7310_VALUE_FRAC_BITS)))
drivers/adt7310/adt7310.c:float adt7310_read_float(const adt7310_t *dev)
drivers/adt7310/adt7310.c:    return (((float) raw) * ADT7310_TEMPERATURE_LSB_FLOAT);
drivers/at30tse75x/at30tse75x.c:static inline float temperature_to_float(uint16_t temp)
drivers/at30tse75x/at30tse75x.c:int at30tse75x_get_temperature(const at30tse75x_t *dev, float *temperature)
drivers/hih6130/hih6130.c:    float *relative_humidity_percent, float *temperature_celsius)
drivers/include/adt7310.h:float adt7310_read_float(const adt7310_t *dev);
drivers/include/at30tse75x.h:int at30tse75x_get_temperature(const at30tse75x_t* dev, float* temperature);
drivers/include/hih6130.h:    float *relative_humidity_percent, float *temperature_celsius);
drivers/include/isl29020.h:    float lux_fac;              /**< factor to calculate actual lux value */
drivers/include/isl29125.h:    float red;              /**< red lux value */
drivers/include/isl29125.h:    float green;            /**< green lux value */
drivers/include/isl29125.h:    float blue;             /**< blue lux value */
drivers/include/tmp006.h:void tmp006_convert(int16_t rawv, int16_t rawt,  float *tamb, float *tobj);
drivers/io1_xplained/io1_xplained_saul.c:static float temperature;
drivers/isl29020/isl29020.c:    dev->lux_fac = (float)((1 << (10 + (2 * DEV_RANGE))) - 1) / 0xffff;
drivers/isl29125/isl29125.c:    float luxfactor = (DEV_RANGE == ISL29125_RANGE_10K) ? 10000.0 / 65535.0 : 375.0 / 65535.0;
drivers/lpsxxx/lpsxxx.c:    float res = TEMP_BASE;      /* reference value -> see datasheet */
drivers/lpsxxx/lpsxxx.c:    res += ((float)val) / TEMP_DIVIDER;
drivers/mpu9150/mpu9150.c:    float fsr;
drivers/mpu9150/mpu9150.c:    float fsr;
drivers/mpu9150/mpu9150.c:    output->x_axis = (int16_t) (((float)output->x_axis) *
drivers/mpu9150/mpu9150.c:    output->y_axis = (int16_t) (((float)output->y_axis) *
drivers/mpu9150/mpu9150.c:    output->z_axis = (int16_t) (((float)output->z_axis) *
drivers/mq3/mq3.c:    float res = mq3_read_raw(dev);
drivers/tmp006/tmp006.c:void tmp006_convert(int16_t rawv, int16_t rawt,  float *tamb, float *tobj)
drivers/tmp006/tmp006.c:    float tamb, tobj;
sys/analog_util/adc_util.c:float adc_util_mapf(int sample, adc_res_t res, float min, float max)
sys/analog_util/dac_util.c:uint16_t dac_util_mapf(float value, float min, float max)
sys/color/color.c:    float rd, gd, bd, delta;
sys/color/color.c:    rd = (float)rgb->r / 255.0f;
sys/color/color.c:    gd = (float)rgb->g / 255.0f;
sys/color/color.c:    bd = (float)rgb->b / 255.0f;
sys/color/color.c:        float rc, gc, bc;
sys/color/color.c:    float aa, bb, cc, f, h;
sys/fmt/fmt.c:size_t fmt_float(char *out, float f, unsigned precision)
sys/fmt/fmt.c:void print_float(float f, unsigned precision)
sys/include/analog_util.h:float adc_util_mapf(int sample, adc_res_t res, float min, float max);
sys/include/analog_util.h:uint16_t dac_util_mapf(float value, float min, float max);
sys/include/color.h:    float h;            /**< hue value        [0.0 - 360.0] */
sys/include/color.h:    float s;            /**< saturation value [0.0 - 1.0] */
sys/include/color.h:    float v;            /**< value            [0.0 - 1.0] */
sys/include/ubjson.h:static inline ssize_t ubjson_get_float(ubjson_cookie_t *__restrict cookie, ssize_t content, float *dest)
sys/include/ubjson.h:        float f;
sys/include/ubjson.h:ssize_t ubjson_write_float(ubjson_cookie_t *__restrict cookie, float value);
sys/quad_math/fixsfdi.c:quad_t __fixsfdi(float x)
sys/quad_math/fixunssfdi.c:u_quad_t __fixunssfdi(float f)
sys/quad_math/floatdisf.c:float __floatdisf(quad_t x)
sys/quad_math/floatdisf.c:    float f;
sys/quad_math/quad.h:quad_t __fixsfdi(float);
sys/quad_math/quad.h:u_quad_t __fixunssfdi(float);
sys/quad_math/quad.h:float __floatdisf(quad_t);
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_temper_conv(tinymt32_t *random)
sys/random/tinymt32/tinymt32.h:        float f;
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_temper_conv_open(tinymt32_t *random)
sys/random/tinymt32/tinymt32.h:        float f;
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_generate_float(tinymt32_t *random)
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_generate_float12(tinymt32_t *random)
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_generate_float01(tinymt32_t *random)
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_generate_floatOC(tinymt32_t *random)
sys/random/tinymt32/tinymt32.h:static inline float tinymt32_generate_floatOO(tinymt32_t *random)
sys/shell/commands/sc_at30tse75x.c:            float temperature;
sys/ubjson/ubjson-write.c:ssize_t ubjson_write_float(ubjson_cookie_t *restrict cookie, float value)
sys/ubjson/ubjson-write.c:        float f;
tests/driver_adt7310/main.c:    float celsius_float;
tests/driver_adt7310/main.c:    float integral = 0;
tests/driver_adt7310/main.c:    float fractional;
tests/driver_hih6130/main.c:        float hum = 0.f;
tests/driver_hih6130/main.c:        float temp = 0.f;
tests/driver_hih6130/main.c:        float integral = 0.f;
tests/driver_hih6130/main.c:        float fractional;
tests/driver_io1_xplained/main.c:    float temperature;
tests/driver_tmp006/main.c:    float tamb, tobj;
tests/pkg_cmsis-dsp/main.c:    float int_part;
tests/pkg_cmsis-dsp/main.c:    float frac_part = fabsf(modff(variance, &int_part));
tests/rng/test.c:    float entropy = 0.0;
tests/rng/test.c:            float count = (float) buffer[i] / (float) length;
tests/rng/test.h:#define log2f(x) (logf (x) / (float) 0.693147180559945309417)
tests/thread_float/main.c:    float f, init;
tests/thread_float/main.c:    float f, init;
tests/unittests/tests-scanf_float/tests-scanf_float.c:    float x = 0;\
tests/unittests/tests-scanf_float/tests-scanf_float.c:    float x = 0;
tests/unittests/tests-scanf_float/tests-scanf_float.c:    float x = 0;

μ§€κΈˆ 무엇?

더블은 사라져야 ν•©λ‹ˆλ‹€. λ‚˜λŠ” 그것이 μ•„μ£Ό λΆ„λͺ…ν•˜λ‹€κ³  λ―ΏμŠ΅λ‹ˆλ‹€.

μ„Όμ„œ λ“œλΌμ΄λ²„μ—λŠ” 뢀동 μ†Œμˆ˜μ μ΄ μ‚¬μš©λ©λ‹ˆλ‹€. 이것은 λ‚΄ 생각에 잘λͺ»λœ κ²ƒμž…λ‹ˆλ‹€. λ“œλΌμ΄λ²„μ—λŠ” μž₯μΉ˜μ—μ„œ 데이터 검색을 λ‹΄λ‹Ήν•˜λŠ” 계측이 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€. ν•΄λ‹Ή 계측은 뢀동 μ†Œμˆ˜μ  계산을 μˆ˜ν–‰ν•˜λŠ” 업무가 μ—†μŠ΅λ‹ˆλ‹€. μ–΄λ–€ κ²½μš°μ—λ„ mpu9150κ³Ό 같은 μ„Όμ„œμ˜ 경우 μ •μˆ˜ μ—°μ‚°λ§Œμ„ μ‚¬μš©ν•˜μ—¬ 값을 μ™„λ²½ν•˜κ²Œ ν‘œν˜„ν•˜κ³  μ‘°μž‘ν•  수 μžˆλŠ” κ²½μš°μ—λ„ floatκ°€ ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

drivers sys bug

λͺ¨λ“  5 λŒ“κΈ€

κ΄€μ‹¬μžˆλŠ”! 이 λ¬Έμ œμ— λŒ€ν•΄ μž‘μ—…ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

@garrettluu κ°μ‚¬ν•©λ‹ˆλ‹€! μ—¬λŸ¬λΆ„μ˜ PR을 κΈ°λ‹€λ¦½λ‹ˆλ‹€. 쒋은 μ ‘κ·Ό 방식은 μˆ˜μ •/μ—…λ°μ΄νŠΈλœ 각 λͺ¨λ“ˆμ— λŒ€ν•΄ 단일 PR을 μ—¬λŠ” κ²ƒμž…λ‹ˆλ‹€.
그리고 κΈ°μ—¬μž κ°€μ΄λ“œλ₯Ό μ‚΄νŽ΄λ³΄λŠ” 것을 μžŠμ§€ λ§ˆμ„Έμš”.

여기에 μƒˆλ‘œμš΄ κΈ°λŠ₯이 μžˆμŠ΅λ‹ˆλ‹€. λͺ¨λ“ˆλ‘œ κ°„μ£Όλ˜λŠ” 것은 λ¬΄μ—‡μž…λ‹ˆκΉŒ? 예λ₯Ό λ“€μ–΄, 전체 λ“œλΌμ΄λ²„ 폴더가 λͺ¨λ“ˆμž…λ‹ˆκΉŒ, μ•„λ‹ˆλ©΄ λ“œλΌμ΄λ²„ 폴더 λ‚΄μ˜ 각 폴더가 λͺ¨λ“ˆμž…λ‹ˆκΉŒ? @aabadie

λ“œλΌμ΄λ²„ 폴더 λ‚΄μ˜ 각 ν΄λ”λŠ” λͺ¨λ“ˆμž…λ‹ˆκΉŒ?

λŒ€λΆ€λΆ„ κ·Έλ ‡μŠ΅λ‹ˆλ‹€. 각 λ“œλΌμ΄λ²„μ— λŒ€ν•œ PR을 μ—΄λ©΄ 아무 λ¬Έμ œλ„ μ—†λŠ”μ§€ ν™•μΈν•˜λŠ” 것이 더 μ‰¬μšΈ κ²ƒμž…λ‹ˆλ‹€. PRλ‹Ή ν•˜λ‚˜μ˜ λ“œλΌμ΄λ²„λ§Œ κ²€ν† /ν…ŒμŠ€νŠΈν•  수 μžˆμŠ΅λ‹ˆλ‹€.

sx127x λ“œλΌμ΄λ²„μš©μœΌλ‘œ μž‘μ„±λœ PR μ΄ˆμ•ˆμ΄μ§€λ§Œ μ μ ˆν•œ λ³΄λ“œ 없이 λ³€κ²½ 사항을 ν…ŒμŠ€νŠΈν•˜κ±°λ‚˜ μ΅œμ†Œν•œ μ»΄νŒŒμΌν•˜λŠ” 방법을 잘 λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰