1. Hyrje
Në rendin e ditës ishte detyra për të zhvilluar një protokol komunikimi midis mikroçipit nrf52832 dhe dy sensorëve të tensionit kinez të tipit polumbras.
Detyra u tregua e vĂ«shtirĂ«, pasi u pĂ«rballa me mungesĂ«n e informacionit tĂ« dukshĂ«m. MĂ« duket se "rrĂ«nja e sĂ« keqes" ndodhet nĂ« vetĂ« SDK-nĂ« e Nordic Semiconductor â kĂ«to janĂ« pĂ«rditĂ«sime tĂ« vazhdueshme tĂ« versioneve, disa teprim dhe ngatĂ«rrim tĂ« funksionalitetit. Duhej tĂ« shkruaja gjithçka nga e para.
Mendoj se ky temë është mjaft aktuale, duke marrë parasysh se ky çip ka një stak BLE dhe një gamë të tërë "mashkullore" të modit të ruajtjes së energjisë. Por nuk do të thellohem shumë në pjesën teknike, pasi për këtë temë janë shkruar shumë artikuj.
2. Përshkrimi i projektit

Hardueri:
- Adafruit Feather nRF52 Bluefruit LE (ato që ishin në dorë)
- ADC HX711
- Sensors kinezë 2 copë (50x2 kg)
- Programatori ST-LINK V2
Software:
- IDE VSCODE
- NRF SDK 16
- OpenOCD
- Programatori ST-LINK V2
Të gjitha ndodhen në një projekt, do të duhet vetëm të bëni disa modifikime në Makefile (të përcaktoni vendndodhjen e SDK-së tuaj).
3. Përshkrimi i kodit
Do të përdorim modul GPIOTE për të punuar me periferitë, duke u bazuar në lidhjen e detyrave dhe ngjarjeve, si dhe modul PPI për të transferuar të dhëna nga një periferik në tjetrin pa ndihmën e procesorit.
ret_code_t err_code;
err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); // konfigurojmë për daljen
nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); // do të ndërronim pin-in për impuls
err_code = nrf_drv_gpiote_out_init(PD_SCK, &config); // konfigurojmë për daljen
Konfigurojmë linjën e sinkronizimit PD_SCL për të dalë për të gjeneruar impulse me një kohëzgjatje prej 10 ”s.
nrf_drv_gpiote_in_config_t gpiote_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // kalimi i niveleve nga i lartë në të ulët
nrf_gpio_cfg_input(DOUT, NRF_GPIO_PIN_NOPULL); // në hyrje pa tërheqje
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); // çaktivizojmë ndërprerjen
nrf_drv_timer_enable(&m_timer0); // aktivizojmë modularin e kohës
}
Konfigurojmë linjën e të dhënave DOUT për të lexuar gjendjen e gatishmërisë HX711, kur niveli është i ulët aktivizohet menaxheri në të cilin çaktivizojmë ndërprerjen dhe aktivizojmë modularin e kohës për gjenerimin e impulseve të sinkronizimit në daljen 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)); // we connect the timer to the output
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1); // enable the channel
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(PD_SCK); // ĐČĐșĐ»ŃŃĐ°Đ”ĐŒ gpiote
Then we initialize the PPI module and connect our timer to the PD_SCL output to generate pulses lasting 10”s upon the comparison event, and we also enable the GPIOTE module.
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; // by default
timer_cfg.frequency = NRF_TIMER_FREQ_1MHz; // clocked at 1MHz
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); // triggers on comparisonWe initialize the zero timer and its handler.
if(m_counter%2 != 0 && m_counter<=48){
buffer <<= 1; // the variable for read data
c_counter++; // positive pulse counter
if(nrf_gpio_pin_read(DOUT)) buffer++; // read the state of the input
}
The most interesting part occurs in the timer handler. The pulse period is 20”s. We are interested in odd pulses (on the rising edge) on the condition that their number does not exceed 24, while the total events are 48. Each odd event reads the DOUT.
According to the datasheet, the number of pulses must be at least 25, which corresponds to a gain of 128 (in the code, I used 25 pulses), which is equivalent to 50 timer events, indicating the end of the data frame.
++m_counter; // event counter
if(m_counter==50){
nrf_drv_timer_disable(&m_timer0); // disable the timer
m_simple_timer_state = SIMPLE_TIMER_STATE_STOPPED; //
buffer = buffer ^ 0x800000;
hx711_stop(); // disable hx711
}
After that, we disable the timer and process the data (according to the datasheet) and switch the HX711 to low power mode.
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 Krijoni timerat.
*/
static void create_timers()
{
ret_code_t err_code;
// Krijoni timerat
err_code = app_timer_create(&m_repeated_timer_id,
APP_TIMER_MODE_REPEATED,
repeated_timer_handler);
APP_ERROR_CHECK(err_code);
}
Pritetni ngjarjen nga RTC timer me një interval prej 10 s (kjo është sipas dëshirës suaj) në trajtuesin aktivizojmë HX711, duke thirrur një ndërprerje në linjën DOUT.
Ka njĂ« pikĂ« tjetĂ«r, logot dalin pĂ«rmes UART (baud rate 115200, TX â pin 6, RX â pin 8) tĂ« gjitha konfigurimet ndodhen nĂ« sdk_config.h

Përfundimet
Faleminderit të gjithëve për vëmendjen, shpresoj që ky artikull do të jetë i dobishëm dhe do të reduktojë kohën e çmuar në kërkimin e zgjidhjes për zhvilluesit. Dua të them se qasja teknike që përdor Nordic në platformat e saj është mjaft interesante nga pikëpamja e efikasitetit energjitik.
P.S.
Projekti është ende në proces zhvillimi, prandaj nëse ky temë ju intereson, në artikullin e ardhshëm do të përpiqem të përshkruaj algoritemin e kalibrimit të sensorëve të peshës, si dhe lidhjen e stacks BLE.
Materialet
Burimi: habr.com
