terça-feira, 3 de novembro de 2020

NINA B302 E ARDUINO - TIMERS

 U-BLOX NINA B302 e ARDUINO ADAFRUIT

  TIMER INTERRUPTS


O objetivo deste BLOG é demonstrar como é possível utilizar a IDE do Arduino para programar o módulo U-BLOX NINA B302 com Interrupts. Foi utilizado o módulo NINA B302 para teste e montado no BREAKOUT da Smartcore. 

O exemplo utilizado gerará 3 interrupts que vão ocorrer nos intervalos de 1S, 2S e 5S, mostrando as letras G,B,R no terminal e escrevendo em no GPIO correspondente à Interrupt. Um LED foi colocado no GPIO que ocorre a cada 2 segundos.


Características

Esta biblioteca permite que você use a interrupção de temporizadores de hardware em uma placa baseada em NRF52.

Por que precisamos dessa interrupção do temporizador de hardware?
Imagine que você tem um sistema com uma função de missão crítica, medindo o nível de água e controlando a bomba do reservatório ou fazendo algo muito mais importante. Você normalmente usa um temporizador de software para pesquisar ou até mesmo colocar a função em loop (). Mas e se outra função estiver bloqueando o loop() ou setup().

Portanto, sua função pode não ser executada e o resultado seria desastroso.

Você prefere que sua função seja chamada, independentemente do que aconteça com outras funções (loop ocupado, bug, etc.).

A escolha correta é usar um temporizador de hardware com interrupção para chamar sua função.

Esses temporizadores de hardware, usando interrupção, ainda funcionam mesmo se outras funções estiverem bloqueando. Além disso, eles são muito mais precisos (certamente dependendo da precisão da freqüência do clock) do que outros temporizadores de software que usam millis() ou micros(). Isso é necessário se você precisar medir alguns dados que exigem maior precisão.

Funções usando temporizadores de software normais, contando com loop() e chamando millis(), não funcionarão se o loop() ou setup() for bloqueado por determinada operação. Por exemplo, certa função está bloqueando enquanto está se conectando a WiFi ou alguns serviços.

O problema é que sua função agora faz parte de uma ISR (Rotina de Serviço de Interrupção) e deve ser enxuta / média e seguir certas regras. Mais para ler:


Anotações importantes:
Dentro da função anexada, delay() não funcionará e o valor retornado por millis() não aumentará. Os dados seriais recebidos durante a função podem ser perdidos. Você deve declarar como voláteis todas as variáveis ​​que modificar na função anexada.

Normalmente, as variáveis ​​globais são usadas para passar dados entre um ISR e o programa principal. Para garantir que as variáveis ​​compartilhadas entre um ISR e o programa principal sejam atualizadas corretamente, declare-as como voláteis.

MONTAGEM



Adquirimos então os seguintes componentes



Montado ficou assim



O esquema elétrico é este



Algumas características do Kit

-Botão de RESET;
-Botão de Modo BOOTLOADER (W102);
-Plugável no PROTOBOARD;
-Acesso às várias GPIOS;

Pequena 


Instalando Arduino Adafruit no NINA B302

Abaixo o roteiro para você seguir:

Baixe e instale o Arduino IDE 
Inicie o Arduino IDE, vá em Preferências e adicione 

https://www.adafruit.com/package_adafruit_index.json




como "URL adicional do gerenciador de pastas"

Abra o Boards Manager no menu Tools -> Board e instale o "Adafruit nRF52 by Adafruit"

Selecione sua placa nRF5 no menu Ferramentas -> Placa

Adafruit Bluefruit nRF52 Feather





OBSERVAÇÃO: Durante a instalação, o Arduino IDE leva alguns minutos para extrair as ferramentas após o download, por favor, seja paciente.

Gravando bootloader da Adafruit


Use o gravador SEGGER JLINK para gravar o BREAKOUT com módulo NINA B302, conecte nos pinos do SWCLK (pino 7) e SWDIO (pino 9) do SEGGER JLINK nos pinos  SWDCLK e SWDIO do BREAKOUT (pinos nas laterais, próximo à antena). Não esquecer de ligar os GND do BREAKOUT no GND do SEGGER JTAG, bem como alimentar o BREAKOUT com 3.3V.





Ligue os pinos SWD DIO e CLK ...



...nestes pinos da placa BREAKOUT


Você pode também usar o ST-LINK V2



Abra J-FLASH lite e grave o bootloader da Adafruit


Mudar NRF52840
 
O mesmo se encontra em 

....\packages\adafruit\hardware\nrf52\0.19.0\bootloader\feather_nrf52840_express

Compile depois para o NINA B302
https://github.com/adafruit/Adafruit_nRF52_Bootloader

Com ele, você poderá transferir programas via DFU USB. Maiores detalhes sobre este bootloader

https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/update-bootloader

Segundo a documentação, se você pressionar o reset, o módulo aguardará por um certo tempo se há algo sendo enviado pelo Arduino, ou seja, o programa a ser gravado via DFU.

ATENÇÃO, o bootloader usa USB para gravação do NINA 302, OU SEJA, CRIA UMA COMM VIRTUAL, TAMBÉM PARA SER A SERIAL PADRÃO DO ARDUINO

INSTALE OS DRIVERS
https://github.com/adafruit/Adafruit_Windows_Drivers

Conecte na USB + e USB - um cabo USB, AGUARDE INSTALAR OS DRIVERS


Futuramente altere arquivo variant.cpp para que as GPIOS sejam os mesmos do NINA B302, atualmente estão para o ADAFRUIT FEATHER EXPRESS.




Atualize Arduino com a LIB

siga o Roteiro!

ÓTIMA REFERENCIA PARA PINOS DO ARDUINO E PINOS (GPIOS) DO NINA B302


Consulte

https://www.u-blox.com/sites/default/files/NINA-B3_DataSheet_%28UBX-17052099%29.pdf

Compile o programa TimerInterruptLEDDemo e pressione o botão para gravar.

/**************************************************************************************************************************** TimerInterruptLEDDemo.ino For NRF52 boards Written by Khoi Hoang Built by Khoi Hoang https://github.com/khoih-prog/NRF52_TimerInterrupt Licensed under MIT license Now even you use all these new 16 ISR-based timers,with their maximum interval practically unlimited (limited only by unsigned long miliseconds), you just consume only one NRF52 timer and avoid conflicting with other cores' tasks. The accuracy is nearly perfect compared to software timers. The most important feature is they're ISR-based timers Therefore, their executions are not blocked by bad-behaving functions / tasks. This important feature is absolutely necessary for mission-critical tasks. Based on SimpleTimer - A timer library for Arduino. Author: mromani@ottotecnica.com Copyright (c) 2010 OTTOTECNICA Italy Based on BlynkTimer.h Author: Volodymyr Shymanskyy Version: 1.0.0 Version Modified By Date Comments ------- ----------- ---------- ----------- 1.0.0 K Hoang 02/11/2020 Initial coding *****************************************************************************************************************************/ /* Notes: Special design is necessary to share data between interrupt code and the rest of your program. Variables usually need to be "volatile" types. Volatile tells the compiler to avoid optimizations that assume variable can not spontaneously change. Because your function may change variables while your program is using them, the compiler needs this hint. But volatile alone is often not enough. When accessing shared variables, usually interrupts must be disabled. Even with volatile, if the interrupt changes a multi-byte variable between a sequence of instructions, it can be read incorrectly. If your data is multiple variables, such as an array and a count, usually interrupts need to be disabled or the entire sequence of your code which accesses the data. */ #if !(defined(NRF52840_FEATHER) || defined(NRF52832_FEATHER) || defined(NRF52_SERIES) || defined(ARDUINO_NRF52_ADAFRUIT) || \ defined(NRF52840_FEATHER_SENSE) || defined(NRF52840_ITSYBITSY) || defined(NRF52840_CIRCUITPLAY) || \ defined(NRF52840_CLUE) || defined(NRF52840_METRO) || defined(NRF52840_PCA10056) || defined(PARTICLE_XENON) \ || defined(NINA_B302_ublox) || defined(NINA_B112_ublox) ) #error This code is designed to run on nRF52 platform! Please check your Tools->Board setting. #endif // These define's must be placed at the beginning before #include "NRF52TimerInterrupt.h" // Don't define NRF52_TIMER_INTERRUPT_DEBUG > 2. Only for special ISR debugging only. Can hang the system. #define NRF52_TIMER_INTERRUPT_DEBUG 1 //#ifndef LED_BUILTIN // #define LED_BUILTIN 3 //#endif #ifndef LED_BLUE_PIN #define LED_BLUE_PIN 7 #endif #ifndef LED_RED #define LED_RED 8 #endif #include "NRF52TimerInterrupt.h" #include "NRF52_ISR_Timer.h" #define HW_TIMER_INTERVAL_MS 1 // Depending on the board, you can select NRF52 Hardware Timer from NRF_TIMER_1-NRF_TIMER_4 (1 to 4) // If you select the already-used NRF_TIMER_0, it'll be auto modified to use NRF_TIMER_1 // Init NRF52 timer NRF_TIMER1 NRF52Timer ITimer(NRF_TIMER_1); // Init NRF52_ISR_Timer // Each NRF52_ISR_Timer can service 16 different ISR-based timers NRF52_ISR_Timer ISR_Timer; #define TIMER_INTERVAL_1S 1000L #define TIMER_INTERVAL_2S 2000L #define TIMER_INTERVAL_5S 5000L void TimerHandler(void) { ISR_Timer.run(); } // In NRF52, avoid doing something fancy in ISR, for example complex Serial.print with String() argument // The pure simple Serial.prints here are just for demonstration and testing. Must be eliminate in working environment // Or you can get this run-time error / crash void doingSomething1() { digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN)); Serial.println("G"); } void doingSomething2() { digitalWrite(LED_BLUE, !digitalRead(LED_BLUE)); Serial.println("B"); } void doingSomething3() { digitalWrite(LED_RED, !digitalRead(LED_RED)); Serial.println("R"); } void setup() { Serial.begin(115200); while (!Serial); Serial.println("\nTimerInterruptLEDDemo on " + String(BOARD_NAME)); Serial.println("CPU Frequency = " + String(F_CPU / 1000000) + " MHz"); // Instantiate HardwareTimer object. Thanks to 'new' instanciation, HardwareTimer is not destructed when setup() function is finished. //HardwareTimer *MyTim = new HardwareTimer(Instance); // configure pin in output mode pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BLUE, OUTPUT); pinMode(LED_RED, OUTPUT); // Interval in microsecs if (ITimer.attachInterruptInterval(HW_TIMER_INTERVAL_MS * 1000, TimerHandler)) { Serial.println("Starting ITimer OK, millis() = " + String(millis())); } else Serial.println("Can't set ITimer correctly. Select another freq. or interval"); // Just to demonstrate, don't use too many ISR Timers if not absolutely necessary // You can use up to 16 timer for each ISR_Timer ISR_Timer.setInterval(TIMER_INTERVAL_1S, doingSomething1); ISR_Timer.setInterval(TIMER_INTERVAL_2S, doingSomething2); ISR_Timer.setInterval(TIMER_INTERVAL_5S, doingSomething3); } void loop() { /* Nothing to do all is done by hardware. Even no interrupt required. */ }




Como podem observar, o programa será transferido!



THANKS TO Khoi Hoang


Sobre a SMARTCORE

A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portfólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.
Mais detalhes em www.smartcore.com.br