HX711 ADC๋ฅผ NRF52832์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

1. ์†Œ๊ฐœ

์˜์ œ์—๋Š” 52832๊ฐœ์˜ ํ•˜ํ”„ ๋ธŒ๋ฆฌ์ง€ ์ค‘๊ตญ ์ŠคํŠธ๋ ˆ์ธ ๊ฒŒ์ด์ง€๋ฅผ ๊ฐ–์ถ˜ nrfXNUMX ๋งˆ์ดํฌ๋กœ์ปจํŠธ๋กค๋Ÿฌ์šฉ ํ†ต์‹  ํ”„๋กœํ† ์ฝœ์„ ๊ฐœ๋ฐœํ•˜๋Š” ์ž‘์—…์ด ํฌํ•จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด๊ฐ€ ๋ถ€์กฑํ•˜์—ฌ ์ž‘์—…์ด ์‰ฝ์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค. ์ง€์†์ ์ธ ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ, ์ผ๋ถ€ ์ค‘๋ณต์„ฑ ๋ฐ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด ๊ธฐ๋Šฅ ๋“ฑ "์•…์˜ ๊ทผ์›"์€ Nordic Semiconductor ์ž์ฒด์˜ SDK์— ์žˆ์„ ๊ฐ€๋Šฅ์„ฑ์ด ๋” ๋†’์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ฒ˜์Œ๋ถ€ํ„ฐ ๋ชจ๋“  ๊ฒƒ์„ ์ž‘์„ฑํ•ด์•ผํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด ์นฉ์— BLE ์Šคํƒ๊ณผ ์—๋„ˆ์ง€ ์ ˆ์•ฝ ๋ชจ๋“œ๋ฅผ ์œ„ํ•œ ์ „์ฒด "์ƒํ’ˆ" ์„ธํŠธ๊ฐ€ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ๋ฐ”ํƒ•์œผ๋กœ ์ด ์ฃผ์ œ๊ฐ€ ์ƒ๋‹นํžˆ ๊ด€๋ จ์„ฑ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ฃผ์ œ์— ๋Œ€ํ•ด ๋งŽ์€ ๊ธฐ์‚ฌ๊ฐ€ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฏ€๋กœ ๊ธฐ์ˆ ์ ์ธ ๋ถ€๋ถ„์— ๋„ˆ๋ฌด ๊นŠ์ด ๋“ค์–ด๊ฐ€์ง€๋Š” ์•Š๊ฒ ์Šต๋‹ˆ๋‹ค.

2. ํ”„๋กœ์ ํŠธ ์„ค๋ช…

HX711 ADC๋ฅผ NRF52832์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

์ฒ  :

  • Adafruit Feather nRF52 Bluefruit LE(๋ฌด์Šจ ์ผ์ด ์žˆ์—ˆ๋Š”์ง€)
  • ADC HX711
  • ์ค‘๊ตญ ์ŠคํŠธ๋ ˆ์ธ ๊ฒŒ์ด์ง€ 2๊ฐœ (50x2kg)
  • ํ”„๋กœ๊ทธ๋ž˜๋จธ ST-LINK V2

์†Œํ”„ํŠธ์›จ์–ด:

  • IDE VSCODE
  • NRF SDK 16
  • ์˜คํ”ˆOCD
  • ํ”„๋กœ๊ทธ๋ž˜๋จธ ST-LINK V2

๋ชจ๋“  ๊ฒƒ์ด ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์— ์žˆ์œผ๋ฏ€๋กœ Makefile์„ ์กฐ์ •ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค(SDK์˜ ์œ„์น˜ ์ง€์ •).

3. ์ฝ”๋“œ ์„ค๋ช…

GPIOTE ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—… ๋ฐ ์ด๋ฒคํŠธ ๋ฐ”์ธ๋”ฉ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฃผ๋ณ€ ์žฅ์น˜์™€ ์ž‘์—…ํ•˜๊ณ  PPI ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์„ธ์„œ์˜ ์ฐธ์—ฌ ์—†์ด ํ•œ ์ฃผ๋ณ€ ์žฅ์น˜์—์„œ ๋‹ค๋ฅธ ์ฃผ๋ณ€ ์žฅ์น˜๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ฉ๋‹ˆ๋‹ค.

ret_code_t err_code;
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config);//ะฝะฐัั‚ั€ะฐะตะฒะฐะตะผ ะฝะฐ ะฒั‹ั…ะพะด
   nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);//ะฑัƒะดะตะผ ะฟะตั€ะตะดะตั€ะณะธะฒะฐั‚ัŒ ะฟะธะฝ ะดะปั ะธะผะฟัƒะปัŒัะฐ
   err_code = nrf_drv_gpiote_out_init(PD_SCK, &config);//ะฝะฐัั‚ั€ะฐะตะฒะฐะตะผ ะฝะฐ ะฒั‹ั…ะพะด

PD_SCL ๋™๊ธฐํ™” ๋ผ์ธ์„ ์ถœ๋ ฅ์— ๊ตฌ์„ฑํ•˜์—ฌ 10ฮผs ์ง€์† ์‹œ๊ฐ„์˜ ํŽ„์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

   nrf_drv_gpiote_in_config_t  gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);// ะฟะตั€ะตั…ะพะด ัƒั€ะพะฒะฝั ั ะฒั‹ัะพะบะพะณะพ ะฝะฐ ะฝะธะทะบะธะน
   nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL);// ะฝะฐ ะฒั…ะพะด ะฑะตะท ะฟะพะดั‚ัะถะบะธ
   err_code = nrf_drv_gpiote_in_init(DOUT, &gpiote_config, gpiote_evt_handler); 

static void gpiote_evt_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    nrf_drv_gpiote_in_event_disable(DOUT);//ะพั‚ะบะปัŽั‡ะฐะตะผ ะฟั€ะตั€ั‹ะฒะฐะฝะธะต
    nrf_drv_timer_enable(&m_timer0);//ะฒะบะปัŽั‡ะฐะตะผ ั‚ะฐะนะผะตั€
}
 

HX711์˜ ์ค€๋น„ ์ƒํƒœ๋ฅผ ์ฝ๋„๋ก DOUT ๋ฐ์ดํ„ฐ ๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๊ณ , ๋ ˆ๋ฒจ์ด ๋‚ฎ์œผ๋ฉด ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ  ํƒ€์ด๋จธ๋ฅผ ์‹œ์ž‘ํ•˜์—ฌ PD_SCL ์ถœ๋ ฅ์—์„œ โ€‹โ€‹ํด๋ก ํŽ„์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

 err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,                                         nrf_drv_timer_event_address_get(&m_timer0, NRF_TIMER_EVENT_COMPARE0),                                           nrf_drv_gpiote_out_task_addr_get(PD_SCK));// ะฟะพะดะบะปัŽั‡ะฐะตะผ ั‚ะฐะนะผะตั€ ะบ ะฒั‹ั…ะพะดัƒ
   APP_ERROR_CHECK(err_code);
   err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);// ะฒะบะปัŽั‡ะฐะตะผ ะบะฐะฝะฐะป
   APP_ERROR_CHECK(err_code);
   nrf_drv_gpiote_out_task_enable(PD_SCK); 

// gpiote ํ™œ์„ฑํ™”

๊ทธ๋Ÿฐ ๋‹ค์Œ PPI ๋ชจ๋“ˆ์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ  ํƒ€์ด๋จธ๋ฅผ PD_SCL ์ถœ๋ ฅ์— ์—ฐ๊ฒฐํ•˜์—ฌ ๋น„๊ต ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ 10ฮผs ์ง€์† ์‹œ๊ฐ„์˜ ํŽ„์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  GPIOTE ๋ชจ๋“ˆ๋„ ์ผญ๋‹ˆ๋‹ค.


nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;// ะฟะพ ัƒะผะพะปั‡ะฐะฝะธัŽ
   timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;// ั‚ะฐะบั‚ะธั€ัƒะตะผ ะฝะฐ ั‡ะฐัั‚ะพั‚ะต 1ะœะณั†
   ret_code_t err_code = nrf_drv_timer_init(&m_timer0, &timer_cfg, timer0_event_handler);
   APP_ERROR_CHECK(err_code);
   nrf_drv_timer_extended_compare(&m_timer0,
                                  NRF_TIMER_CC_CHANNEL0,
                                  nrf_drv_timer_us_to_ticks(&m_timer0,
                                                            10),
                                  NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                  true);// ัั€ะฐะฑะฐั‚ั‹ะฒะฐะตั‚ ะฟะพ ัั€ะฐะฒะฝะตะฝะธัŽ

์ œ๋กœ ํƒ€์ด๋จธ์™€ ๊ทธ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

  if(m_counter%2 != 0 && m_counter<=48){
       buffer <<= 1;// ะฟะตั€ะตะผะตะฝะฝะฐั ัั‡ะธั‚ะฐะฝะฝั‹ั… ะดะฐะฝั‹ั…
        c_counter++;// ัั‡ะตั‚ั‡ะธะบ ะฟะพะปะพะถะธั‚ะตะปัŒะฝั‹ั…  ะธะผะฟัƒะปัŒัะพะฒ
           if(nrf_gpio_pin_read(DOUT))buffer++;//ัั‡ะธั‚ั‹ะฒะฐะตะผ ัะพัั‚ะพัะฝะธะต ะฒั…ะพะดะฐ
   }

๊ฐ€์žฅ ํฅ๋ฏธ๋กœ์šด ์ผ์€ ํƒ€์ด๋จธ ํ•ธ๋“ค๋Ÿฌ์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํŽ„์Šค์ฃผ๊ธฐ๋Š” 20ฮผs์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ™€์ˆ˜ ํŽ„์Šค(์ƒ์Šน ์—์ง€๋ฅผ ๋”ฐ๋ผ)์— ๊ด€์‹ฌ์ด ์žˆ๊ณ  ๊ทธ ์ˆ˜๊ฐ€ 24๊ฐœ ์ดํ•˜์ด๊ณ  ์ด๋ฒคํŠธ๊ฐ€ 48๊ฐœ์ธ ๊ฒฝ์šฐ ๊ฐ ํ™€์ˆ˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด DOUT์„ ์ฝ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ์‹œํŠธ์— ๋”ฐ๋ฅด๋ฉด ํŽ„์Šค ์ˆ˜๋Š” 25๊ฐœ ์ด์ƒ์ด์–ด์•ผ ํ•˜๋ฉฐ ์ด๋Š” 128์˜ ์ด๋“์— ํ•ด๋‹นํ•˜๋ฉฐ(์ฝ”๋“œ์—์„œ๋Š” 25๊ฐœ์˜ ํŽ„์Šค๋ฅผ ์‚ฌ์šฉํ•จ) ์ด๋Š” ๋ฐ์ดํ„ฐ ํ”„๋ ˆ์ž„์˜ ๋์„ ๋‚˜ํƒ€๋‚ด๋Š” 50๊ฐœ์˜ ํƒ€์ด๋จธ ์ด๋ฒคํŠธ์™€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

 ++m_counter;// ัั‡ะตั‚ั‡ะธะบ ัะพะฑั‹ั‚ะธะน
if(m_counter==50){
      nrf_drv_timer_disable(&m_timer0);// ะพั‚ะบะปัŽั‡ะฐะตะผ ั‚ะฐะนะผะตั€
       m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED;//
       buffer = buffer ^ 0x800000;
       hx711_stop();//jะพั‚ะบะปัŽั‡ะฐะตะผ hx711
       }
   

๊ทธ๋Ÿฐ ๋‹ค์Œ ํƒ€์ด๋จธ๋ฅผ ๋„๊ณ  ๋ฐ์ดํ„ฐ ์‹œํŠธ์— ๋”ฐ๋ผ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  HX711์„ ์ €์ „๋ ฅ ์†Œ๋น„ ๋ชจ๋“œ๋กœ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค.


static void repeated_timer_handler(void * p_context)
{
   nrf_drv_gpiote_out_toggle(LED_2);
   if(m_simple_timer_state == SIMPLE_TIMER_STATE_STOPPED){
      	hx711_start();// ะฒะบะปัŽั‡ะฐะตะผ hx711
       nrf_drv_gpiote_out_toggle(LED_1);
       m_simple_timer_state = SIMPLE_TIMER_STATE_STARTED;
   }
  
}
/**@brief Create timers.
*/
static void create_timers()
{
   ret_code_t err_code;
 
   // Create timers
   err_code = app_timer_create(&m_repeated_timer_id,
                               APP_TIMER_MODE_REPEATED,
                               repeated_timer_handler);
   APP_ERROR_CHECK(err_code);
}

์šฐ๋ฆฌ๋Š” 10์ดˆ ๊ฐ„๊ฒฉ(๊ท€ํ•˜์˜ ์žฌ๋Ÿ‰์— ๋”ฐ๋ผ ๋‹ค๋ฆ„)์œผ๋กœ RTC ํƒ€์ด๋จธ์˜ ์ด๋ฒคํŠธ๋ฅผ ์˜ˆ์ƒํ•˜๊ณ  ํ•ธ๋“ค๋Ÿฌ์—์„œ HX711์„ ์‹คํ–‰ํ•˜์—ฌ DOUT ๋ผ์ธ์— ์ธํ„ฐ๋ŸฝํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ์ ์ด ๋” ์žˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ๋Š” UART(์ „์†ก ์†๋„ 115200, TX - 6ํ•€, RX - 8ํ•€)๋ฅผ ํ†ตํ•ด ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์„ค์ •์€ sdk_config.h์— ์žˆ์Šต๋‹ˆ๋‹ค.

HX711 ADC๋ฅผ NRF52832์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•

์กฐ์‚ฌ ๊ฒฐ๊ณผ

๊ด€์‹ฌ์„ ๊ฐ€์ ธ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ๊ฐ€ ์œ ์šฉํ•˜๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ์†”๋ฃจ์…˜์„ ์ฐพ๋Š” ๋ฐ ์†Œ์š”๋˜๋Š” ๊ท€์ค‘ํ•œ ์‹œ๊ฐ„์„ ๋‹จ์ถ•ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๋ถ์œ ๋Ÿฝ์ด ํ”Œ๋žซํผ์— ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์ˆ ์  ์ ‘๊ทผ ๋ฐฉ์‹์€ ์—๋„ˆ์ง€ ํšจ์œจ์„ฑ ์ธก๋ฉด์—์„œ ๋งค์šฐ ํฅ๋ฏธ๋กญ๋‹ค๊ณ  ๋งํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

PS

ํ”„๋กœ์ ํŠธ๋Š” ์•„์ง ๊ฐœ๋ฐœ ์ค‘์ด๋ฏ€๋กœ ์ด ์ฃผ์ œ์— ๊ด€์‹ฌ์ด ์žˆ๋‹ค๋ฉด ๋‹ค์Œ ๊ธฐ์‚ฌ์—์„œ๋Š” ๋ฌด๊ฒŒ ์„ผ์„œ ๊ต์ • ๋ฐ BLE ์Šคํƒ ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๋ช…ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

์žฌ๋ฃŒ

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€