1. Pendahuluan
Agendanya adalah tugas mengembangkan protokol komunikasi untuk mikrokontroler nrf52832 dengan dua pengukur regangan setengah jembatan Tiongkok.
Tugas tersebut ternyata tidak mudah, karena saya dihadapkan pada kurangnya informasi yang dapat dipahami. Kemungkinan besar "akar kejahatan" ada di SDK dari Nordic Semiconductor itu sendiri - pembaruan versi yang konstan, beberapa redundansi, dan fungsionalitas yang membingungkan. Saya harus menulis semuanya dari awal.
Saya rasa topik ini cukup relevan berdasarkan fakta bahwa chip ini memiliki tumpukan BLE dan serangkaian "barang" untuk mode hemat energi. Tapi saya tidak akan membahas bagian teknisnya terlalu jauh, karena banyak artikel telah ditulis tentang topik ini.
2. Deskripsi proyek
Besi:
- Adafruit Feather nRF52 Bluefruit LE (yang kebetulan ada)
- HX711 ADC
- Pengukur regangan cina 2 pcs. (50x2kg)
- Pemrogram ST-LINK V2
Perangkat lunak:
- IDE VSCODE
- NRFSDK 16
- BukaOCD
- Pemrogram ST-LINK V2
Semuanya ada dalam satu proyek, Anda hanya perlu men-tweak Makefile (tentukan lokasi SDK Anda).
3. Deskripsi kode
Kami akan menggunakan modul GPIOTE untuk bekerja dengan periferal berdasarkan pengikatan tugas dan peristiwa, serta modul PPI untuk mentransfer data dari satu periferal ke periferal lainnya tanpa partisipasi prosesor.
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);//Π½Π°ΡΡΡΠ°Π΅Π²Π°Π΅ΠΌ Π½Π° Π²ΡΡ
ΠΎΠ΄
Kami mengkonfigurasi jalur sinkronisasi PD_SCL ke output untuk menghasilkan pulsa dengan durasi 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);//Π²ΠΊΠ»ΡΡΠ°Π΅ΠΌ ΡΠ°ΠΉΠΌΠ΅Ρ
}
Kami mengkonfigurasi jalur data DOUT untuk membaca status kesiapan HX711; jika ada level rendah, pengendali dipicu di mana kami menonaktifkan interupsi dan memulai pengatur waktu untuk menghasilkan pulsa jam pada output 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);
// aktifkan gpiote
Setelah itu kita inisialisasi modul PPI dan menghubungkan timer kita ke output PD_SCL untuk menghasilkan pulsa dengan durasi 10 s ketika terjadi peristiwa perbandingan, dan juga menghidupkan modul 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);// ΡΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ ΠΏΠΎ ΡΡΠ°Π²Π½Π΅Π½ΠΈΡ
Kami menginisialisasi pengatur waktu nol dan pengendalinya.
if(m_counter%2 != 0 && m_counter<=48){
buffer <<= 1;// ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ ΡΡΠΈΡΠ°Π½Π½ΡΡ
Π΄Π°Π½ΡΡ
c_counter++;// ΡΡΠ΅ΡΡΠΈΠΊ ΠΏΠΎΠ»ΠΎΠΆΠΈΡΠ΅Π»ΡΠ½ΡΡ
ΠΈΠΌΠΏΡΠ»ΡΡΠΎΠ²
if(nrf_gpio_pin_read(DOUT))buffer++;//ΡΡΠΈΡΡΠ²Π°Π΅ΠΌ ΡΠΎΡΡΠΎΡΠ½ΠΈΠ΅ Π²Ρ
ΠΎΠ΄Π°
}
Hal yang paling menarik terjadi pada pengatur waktu. Periode pulsa adalah 20 s. Kita tertarik pada pulsa ganjil (sepanjang tepi naik) dengan syarat jumlahnya tidak lebih dari 24, dan kejadiannya 48. Untuk setiap kejadian ganjil, DOUT dibaca
Dari lembar data dapat disimpulkan bahwa jumlah pulsa harus minimal 25, yang sesuai dengan penguatan 128 (dalam kode saya menggunakan 25 pulsa), ini setara dengan 50 kejadian pengatur waktu, yang menunjukkan akhir dari bingkai data.
++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
}
Setelah ini, kami mematikan timer dan memproses data (sesuai dengan datasheet) dan mengalihkan HX711 ke mode konsumsi daya rendah.
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);
}
Kami mengharapkan kejadian dari pengatur waktu RTC dengan interval 10 detik (ini sesuai kebijaksanaan Anda) dan meluncurkan HX711 di handler, menyebabkan interupsi pada jalur DOUT.
Ada satu hal lagi, log dikeluarkan melalui UART (baud rate 115200, TX - 6 pin, RX - 8 pin) semua pengaturan ada di sdk_config.h
Temuan
Terima kasih atas perhatiannya, semoga artikel ini bermanfaat dan mengurangi waktu berharga bagi developer untuk mencari solusinya. Saya ingin mengatakan bahwa pendekatan teknis yang digunakan Nordik dalam platformnya cukup menarik dari sudut pandang efisiensi energi.
PS
Proyek ini masih dalam pengembangan, jadi jika topik ini menarik, pada artikel berikutnya saya akan mencoba menjelaskan algoritma untuk mengkalibrasi sensor berat, serta menghubungkan tumpukan BLE.
Bahan
Sumber: www.habr.com