1. Introduction
Au programme figurait la tâche de développer un protocole de communication pour le microcontrôleur nrf52832 avec deux jauges de contrainte chinoises en demi-pont.
La tâche ne s'est pas avérée facile, car je me trouvais face à l'absence de toute information intelligible. Il est plus probable que la «racine du mal» se trouve dans le SDK lui-même de Nordic Semiconductor - il s'agit de mises à jour de version constantes, d'une certaine redondance et d'une confusion des fonctionnalités. J'ai dû tout écrire à partir de zéro.
Je pense que ce sujet est assez pertinent étant donné que cette puce a une pile BLE et tout un ensemble de "bonbons" du mode d'économie d'énergie. Mais je n'entrerai pas dans la partie technique, puisque de nombreux articles ont été écrits sur ce sujet.
2. Description du projet
Le fer:
- Adafruit Feather nRF52 Bluefruit LE (ce qui était à portée de main)
- ADC HX711
- Jauges de contrainte chinoises 2 pcs. (50x2 kg)
- Programmeur ST-LINK V2
Logiciel:
- IDE VSCODE
- SDK NRF 16
- OpenOCD
- Programmeur ST-LINK V2
Tout est dans un seul projet, il vous suffit de shaman Makefile (précisez l'emplacement de votre SDK).
3. Description du code
Nous utiliserons le module GPIOTE pour travailler avec des périphériques basés sur la liaison de tâches et d'événements, ainsi que le module PPI pour transférer des données d'un périphérique à un autre sans la participation du processeur.
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);//
Nous configurons la ligne de synchronisation PD_SCL vers la sortie pour générer des impulsions d'une durée de 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);//
}
Nous configurons la ligne de données DOUT pour lire l'état prêt du HX711, s'il y a un niveau bas, le gestionnaire est déclenché dans lequel nous désactivons l'interruption et démarrons la minuterie pour générer des impulsions d'horloge à la sortie 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);
// activer gpiote
Après cela, nous initialisons le module PPI et commutons notre minuterie sur la sortie PD_SCL, pour générer des impulsions d'une durée de 10 μs lorsque l'événement de comparaison se produit, et allumons également le module 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);//
Nous initialisons le timer zéro et son gestionnaire.
if(m_counter%2 != 0 && m_counter<=48){
buffer <<= 1;//
c_counter++;//
if(nrf_gpio_pin_read(DOUT))buffer++;//
}
La chose la plus intéressante se produit dans le gestionnaire de minuterie. La période d'impulsion est de 20 μs. Nous nous intéressons aux impulsions impaires (sur le front montant) et à condition que leur nombre ne dépasse pas 24, et qu'il y ait 48 événements. Pour chaque événement impair, DOUT est lu
, 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);
}
RTC 10 ( ) HX711, DOUT.
, UART (baud rate 115200, TX — 6 , RX — 8 ) sdk_config.h
Merci à tous pour votre attention, j'espère que cet article sera utile et fera gagner un temps précieux aux développeurs à la recherche d'une solution. Je tiens à dire que l'approche technique utilisée par Nordic dans ses plates-formes est assez intéressante en termes d'efficacité énergétique.
PS
Le projet est toujours en cours de développement, donc si ce sujet est intéressant dans le prochain article, je vais essayer de décrire l'algorithme de calibrage des capteurs de poids, ainsi que de connecter la pile BLE.