segunda-feira, 28 de dezembro de 2020

U-BLOX NINA B302 COMO TECLADO BLE (HID)

U-BLOX NINA B302 COMO TECLADO BLE (HID)


O objetivo deste BLOG é demonstrar como é possível utilizar a IDE do Arduino para programar o módulo U-BLOX NINA B302 e transformá-lo em um teclado ble (HID) para o IPHONE. Foi utilizado o módulo NINA B302 para o teste.

O exemplo criado no NINA B302 lê a um SWITCH e detecta Single Click, Double Click e Long Click.

Este exemplo é baseado no exemplo do aplicativo de teclado HID periférico BLE. Ele implementa o perfil HID sobre GATT para teclado e permite o emparelhamento a partir de um dispositivo BLE Central, no caso IPHONE.

O aplicativo mostra o uso do módulo de geração de mensagens de emparelhamento BLE. 


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 


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"

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




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 B302, 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.

Acrescente no final de 

C:\Users\tcpipchip\AppData\Local\Arduino15\packages\adafruit\hardware\nrf52\0.19.0\

# ----------------------------------
# NINA B302
# ----------------------------------
ninab302.name=NINA B302 u-blox 

# VID/PID for bootloader with/without UF2, Arduino + Circuitpython App
ninab302.vid.0=0x239A
ninab302.pid.0=0x8029
ninab302.vid.1=0x239A
ninab302.pid.1=0x0029
ninab302.vid.2=0x7239A
ninab302.pid.2=0x002A
ninab302.vid.3=0x239A
ninab302.pid.3=0x802A

# Upload
ninab302.bootloader.tool=bootburn
ninab302.upload.tool=nrfutil
ninab302.upload.protocol=nrfutil
ninab302.upload.use_1200bps_touch=true
ninab302.upload.wait_for_upload_port=true
ninab302.upload.maximum_size=815104
ninab302.upload.maximum_data_size=237568

# Build
ninab302.build.mcu=cortex-m4
ninab302.build.f_cpu=64000000
ninab302.build.board=NRF52840_FEATHER
ninab302.build.core=nRF5
ninab302.build.variant=feather_nrf52840_express
ninab302.build.usb_manufacturer="Adafruit LLC"
ninab302.build.usb_product="Feather nRF52840 Express"
ninab302.build.extra_flags=-DNRF52840_XXAA {build.flags.usb}
ninab302.build.ldscript=nrf52840_s140_v6.ld
ninab302.build.vid=0x239A
ninab302.build.pid=0x8029

# SofDevice Menu
ninab302.menu.softdevice.s140v6=0.3.2 SoftDevice s140 6.1.1
ninab302.menu.softdevice.s140v6.build.sd_name=s140
ninab302.menu.softdevice.s140v6.build.sd_version=6.1.1
ninab302.menu.softdevice.s140v6.build.sd_fwid=0x00B6

# Debug Menu
ninab302.menu.debug.l0=Level 0 (Release)
ninab302.menu.debug.l0.build.debug_flags=-DCFG_DEBUG=0
ninab302.menu.debug.l1=Level 1 (Error Message)
ninab302.menu.debug.l1.build.debug_flags=-DCFG_DEBUG=1
ninab302.menu.debug.l2=Level 2 (Full Debug)
ninab302.menu.debug.l2.build.debug_flags=-DCFG_DEBUG=2
ninab302.menu.debug.l3=Level 3 (Segger SystemView)

ninab302.menu.debug.l3.build.debug_flags=-DCFG_DEBUG=3

Pegue aqui (inclusive "boards")

https://ricardoadulis.sharepoint.com/:f:/s/smartcore/Ek8KZOWlww9Dg77E27bqkxsBxru3jOnkUex2BiMlO0kVFw?e=pTDLsV

Criado pelo Autor

variant.h
viariant.cpp

ÓTIMA REFERÊNCIA 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

Crie um novo Sketch

Instale LIB http://www.mathertel.de/Arduino/OneButtonLibrary.aspx

/********************************************************************* This is an example for our nRF52 based Bluefruit LE modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution Rewrote By Miguel Wisintainer //https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/master/libraries/Bluefruit52Lib/examples/Peripheral/hid_keyboard/hid_keyboard.ino //http://www.mathertel.de/Arduino/OneButtonLibrary.aspx *********************************************************************/ #include <bluefruit.h> BLEDis bledis; BLEHidAdafruit blehid; bool hasKeyPressed = false; #include "OneButton.h" // Example for Arduino UNO with input button on A1 #define PIN_INPUT PIN_BUTTON1 //NINA B302 GPIO 29 (PANIC KEY) // Setup a new OneButton on pin PIN_INPUT // The 2. parameter activeLOW is true, because external wiring sets the button to LOW when pressed. OneButton button(PIN_INPUT, true); //click to send to APP (single, long, double) char WichKey; void doubleclick() { // what happens when button is double-clicked WichKey = 'D'; } void singleclick(){ // what happens when the button is clicked WichKey = 'S'; } void longclick(){ // what happens when buton is long-pressed WichKey = 'L'; } void setup() { button.attachDoubleClick(doubleclick); // link the function to be called on a doubleclick event. button.attachClick(singleclick); // link the function to be called on a singleclick event. button.attachLongPressStop(longclick); // link the function to be called on a longpress event. Bluefruit.begin(); Bluefruit.setTxPower(4); // Check bluefruit.h for supported values Bluefruit.setName("Bluefruit52"); // Configure and Start Device Information Service bledis.setManufacturer("Adafruit Industries"); bledis.setModel("Bluefruit Feather 52"); bledis.begin(); /* Start BLE HID * Note: Apple requires BLE device must have min connection interval >= 20m * ( The smaller the connection interval the faster we could send data). * However for HID and MIDI device, Apple could accept min connection interval * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max * connection interval to 11.25 ms and 15 ms respectively for best performance. */ blehid.begin(); // Set callback for set LED from central blehid.setKeyboardLedCallback(set_keyboard_led); /* Set connection interval (min, max) to your perferred value. * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms */ /* Bluefruit.Periph.setConnInterval(9, 12); */ // Set up and start advertising startAdv(); WichKey=' '; //No pressed Key } void startAdv(void) { // Advertising packet Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); Bluefruit.Advertising.addTxPower(); Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD); // Include BLE HID service Bluefruit.Advertising.addService(blehid); // There is enough room for the dev name in the advertising packet Bluefruit.Advertising.addName(); /* Start Advertising * - Enable auto advertising if disconnected * - Interval: fast mode = 20 ms, slow mode = 152.5 ms * - Timeout for fast mode is 30 seconds * - Start(timeout) with timeout = 0 will advertise forever (until connected) * * For recommended advertising interval * https://developer.apple.com/library/content/qa/qa1931/_index.html */ Bluefruit.Advertising.restartOnDisconnect(true); Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds } void loop() { button.tick(); // Only send KeyRelease if previously pressed to avoid sending // multiple keyRelease reports (that consume memory and bandwidth) if ( hasKeyPressed ) { hasKeyPressed = false; blehid.keyRelease(); //Key no pressed WichKey=' '; // Delay a bit after a report delay(5); } //See if key was pressed if(!(WichKey==' ')) { blehid.keyPress(WichKey); hasKeyPressed = true; // Delay a bit after a report delay(5); } } /** * Callback invoked when received Set LED from central. * Must be set previously with setKeyboardLedCallback() * * The LED bit map is as follows: (also defined by KEYBOARD_LED_* ) * Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0) */ void set_keyboard_led(uint16_t conn_handle, uint8_t led_bitmap) { (void) conn_handle; }













Habilite NINA B302


Selecione sua placa nRF5 no menu Ferramentas -> Placa->NINA B302 u-blox

Compilando e Transferindo o programa HID




Execução

No Pino GPIO 29 do módulo foi colocado um SWITCH, o qual aterrará o pino quando pressionado.
Ao pressionar o SWITCH, é monitorado se é CURTO, DUPLO ou LONGO, enviando a letras S, D ou L via HID ao IPHONE.
No GPIO 20 ligue um LED para acompanhar o STATUS da conexão.


Ao executar o programa no NINA B302, procure no seu celular o dispositivo HID e faça o emparelhamento!






Abra o bloco de nota dos IPHONE e tecle no SWITCH na seguinte sequência,  Single Click, Double Click e Long Click


Veja o que aparecerá no bloco de notas!

 

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

 

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