diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/1000-Hz.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/1000-Hz.png new file mode 100644 index 0000000000..710e9d4b79 Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/1000-Hz.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/500-Hz.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/500-Hz.png new file mode 100644 index 0000000000..f6dce8f95f Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/500-Hz.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/adc-input.svg b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/adc-input.svg new file mode 100644 index 0000000000..9c01902d33 --- /dev/null +++ b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/adc-input.svg @@ -0,0 +1,878 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/alexa.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/alexa.png new file mode 100644 index 0000000000..a7f3af554a Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/alexa.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/digital-io-mosfet.svg b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/digital-io-mosfet.svg new file mode 100644 index 0000000000..ecb8823014 --- /dev/null +++ b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/digital-io-mosfet.svg @@ -0,0 +1,916 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/dsp-install.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/dsp-install.png new file mode 100644 index 0000000000..5783932098 Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/dsp-install.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/edge-impulse.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/edge-impulse.png new file mode 100644 index 0000000000..8d87d61ab8 Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/edge-impulse.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/fw_update.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/fw_update.png new file mode 100644 index 0000000000..b59eb42a36 Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/fw_update.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/imu_gyro.gif b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/imu_gyro.gif new file mode 100644 index 0000000000..42f36415c3 Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/imu_gyro.gif differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/ndp.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/ndp.png new file mode 100644 index 0000000000..1d7df26958 Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/ndp.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nicla-voice-pinout.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nicla-voice-pinout.png index c1bdffcd9a..b2076ef4b6 100644 Binary files a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nicla-voice-pinout.png and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nicla-voice-pinout.png differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nv_acc_gyro_test.rar b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nv_acc_gyro_test.rar deleted file mode 100644 index 97890cde80..0000000000 Binary files a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nv_acc_gyro_test.rar and /dev/null differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nv_acc_gyro_test.zip b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nv_acc_gyro_test.zip new file mode 100644 index 0000000000..198d2a6a1f Binary files /dev/null and b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/nv_acc_gyro_test.zip differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-1.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-1.png deleted file mode 100644 index 0d06b2ab5e..0000000000 Binary files a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-1.png and /dev/null differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-14.gif b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-14.gif deleted file mode 100644 index 5dadceed69..0000000000 Binary files a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-14.gif and /dev/null differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-4.png b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-4.png deleted file mode 100644 index 47acb89f0a..0000000000 Binary files a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/assets/user-manual-4.png and /dev/null differ diff --git a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/content.md b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/content.md index 8f2f89d09d..50999eda55 100644 --- a/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/content.md +++ b/content/hardware/06.nicla/boards/nicla-voice/tutorials/user-manual/content.md @@ -8,7 +8,7 @@ tags: - Cheat sheet - RGB - Communication -author: 'José Bagur and Benjamin Dannegård' +author: 'José Bagur, Benjamin Dannegård and Christopher Méndez' hardware: - hardware/06.nicla/boards/nicla-voice software: @@ -61,7 +61,7 @@ Here is an overview of the board's architecture's main components shown in the i The **Arduino Mbed OS Nicla Boards** core contains the libraries and examples you need to work with the board's components, such as its IMU, magnetometer, and onboard microphone. To install the core for Nicla boards, navigate to **Tools > Board > Boards Manager** or click the Boards Manager icon in the left tab of the IDE. In the Boards Manager tab, search for `nicla` and install the latest `Arduino Mbed OS Nicla Boards` version. -![Installing the Arduino Mbed OS Nicla Boards core in the Arduino IDE bootloader](assets/user-manual-1.png) +![Installing the Arduino Mbed OS Nicla Boards core in the Arduino IDE bootloader](assets/dsp-install.png) ### Pinout @@ -128,52 +128,61 @@ nicla::disableCharging(); ### NDP120 Processor Firmware Update +![NDP Syntiant AI Processor](assets/ndp.png) + It is recommended to update the NDP120 processor firmware and the built-in speech recognition model to the latest release. Follow these three steps to complete the update process: -1. Upload the `Syntiant_upload_fw_ymodem` sketch. This sketch can be found in the board's built-in examples by navigating to **File -> Examples -> NDP -> Syntiant_upload_fw_ymodem**. **Remember to select the board in the Arduino IDE first before navigating to the examples**. -2. After uploading the sketch, **format your board's external Flash memory** before uploading the updated NDP120 processor firmwares files. You can do this by navigating to the Arduino IDE Serial Monitor and typing `F` and then Enter. -3. Extract [this .zip file](assets/nicla_voice_uploader_and_firmwares.zip), which contains the compiled uploaders for various operating systems, and the updated NDP120 processor firmware and speech recognition model, in a known location on your computer. -4. Open a new terminal in the location where the .zip file was extracted and execute the following command: +1. Select the Nicla Voice board in the Arduino IDE so you can have access to the board built-in examples. +2. Upload the `Syntiant_upload_fw_ymodem` sketch. This sketch can be found in the board's built-in examples by navigating to **File > Examples > NDP > Syntiant_upload_fw_ymodem**. +3. After uploading the sketch, **format your board's external Flash memory** before uploading the updated NDP120 processor firmware files. You can do this by navigating to the Arduino IDE Serial Monitor and typing `F` and then `Enter`. +4. Extract [this .zip file](assets/nicla_voice_uploader_and_firmwares.zip), which contains the compiled uploaders for various operating systems, and the updated NDP120 processor firmware and speech recognition model, in a known location on your computer. +5. Open a new terminal in the location where the .zip file was extracted and execute the following command: ```bash - syntiant-uploader send -m "Y" -w "Y" -p $portName $filename + syntiant-uploader- send -m "Y" -w "Y" -p $portName $filename ``` - Replace `portName` and `filename` with the relevant information. Three different files must be uploaded to the board by executing the following three commands, for example in Windows the commands are the following: + Replace `portName` and `filename` with the relevant information. Three different files must be uploaded to the board by executing the following three commands, for example on **Windows** the commands are the following: ```bash - ./syntiant-uploader send -m "Y" -w "Y" -p COM6 mcu_fw_120_v91.synpkg + ./syntiant-uploader-win send -m "Y" -w "Y" -p COM12 mcu_fw_120_v91.synpkg ``` ```bash - ./syntiant-uploader send -m "Y" -w "Y" -p COM6 dsp_firmware_v91.synpkg + ./syntiant-uploader-win send -m "Y" -w "Y" -p COM12 dsp_firmware_v91.synpkg ``` ```bash - ./syntiant-uploader send -m "Y" -w "Y" -p COM6 model_name.synpkg + ./syntiant-uploader-win send -m "Y" -w "Y" -p COM12 alexa_334_NDP120_B0_v11_v91.synpkg ``` + ***As we are using Windows, the command used is `syntiant-uploader-win`, use your OS respective one.*** + Ensure all executed commands return a `filename sent successful` message in the console, as shown in the image below. - ![Uploader feedback messages](assets/user-manual-4.png) + ![Uploader feedback messages](assets/fw_update.png) After uploading the three files, your board's firmware is updated to the latest release and ready to be used. #### External Memory Format -

Your board NDP120 processor files (firmware and models) are stored in your board's external Flash memory. It is recommended to **format your Nicla Voice external Flash memory** every time you are going to update the processor firmware or when you are going to update/add models to the external Flash memory. Follow these steps to perform the external memory format process: -1. Upload the `Syntiant_upload_fw_ymodem` sketch. This sketch can be found in the board's built-in examples by navigating to **File -> Examples -> NDP -> Syntiant_upload_fw_ymodem**. **Remember to select the board in the Arduino IDE first before navigating to the examples**. -2. After uploading the sketch, navigate to the IDE's Serial Monitor, type `F`, and press `Enter`. Your board's external memory should be formatted now, you can confirm this by typing an `L` and pressing `Enter`. +1. Select the Nicla Voice board in the Arduino IDE so you can have access to the board built-in examples. +2. Upload the `Syntiant_upload_fw_ymodem` sketch. This sketch can be found in the board's built-in examples by navigating to **File > Examples > NDP > Syntiant_upload_fw_ymodem**. +3. After uploading the sketch, navigate to the IDE's Serial Monitor, type `F`, and press `Enter`. Your board's external memory should be formatted now, you can confirm this by typing an `L` and pressing `Enter`. After completing this process, you can upload NDP processor's firmware and model files to your board's external memory without issues as explained before. ### Built-in Speech Recognition Example -The speech recognition example can be found in the board's built-in examples by navigating to **File -> Examples -> NDP -> AlexaDemo**. After successfully updating the NDP120 processor firmware and the speech recognition model to the latest release, we can upload the speech recognition example to the Nicla Voice. To test the example, say "Alexa"; this should make the onboard LED of the Nicla Voice blink blue if the keyword "Alexa" is recognized. If there is no response from the board, try speaking from a closer proximity or louder. You should also see in the Serial Monitor if the word "Alexa" was detected, as shown in the image below: +The speech recognition example can be found in the board's built-in examples by navigating to **File > Examples > NDP > AlexaDemo**. + +![Alexa speech recognition example](assets/alexa.png) + +After successfully updating the NDP120 processor firmware and the speech recognition model to the latest release, we can upload the speech recognition example to the Nicla Voice. To test the example, say "Alexa"; this should make the onboard LED of the Nicla Voice blink blue if the keyword "Alexa" is recognized. If there is no response from the board, try speaking from a closer proximity or louder. You should also see in the Serial Monitor if the word "Alexa" was detected, as shown in the image below: ![AlexaDemo example feedback in the Arduino IDE Serial Monitor](assets/user-manual-5.png) @@ -192,31 +201,44 @@ The Nicla Voice has **two analog input pins**, mapped as follows: | `ADC1`/`P0_02` | `A0` | | `ADC2`/`P0_30` | `A1` | -Both pins can be used through the built-in functions of the Arduino programming language. The example code shown below reads the voltage value from a potentiometer connected to `A0` and displays it on the IDE Serial Monitor: +Both pins can be used through the built-in functions of the Arduino programming language. + +Nicla boards ADC can be configured to 8, 10 or 12 bits defining the argument of the following function respectively (default is 10 bits): + +```arduino +analogReadResolution(12); // ADC resolution set to 12 bits (0-4095) +``` + +***The Nicla boards ADC reference voltage is fixed to 1.8V, this means that it will map the ADC range from 0 to 1.8 volts.*** + +The example code shown below reads the voltage value from a potentiometer connected to `A0` and displays it on the IDE Serial Monitor. To understand how to properly connect a potentiometer to the Nicla Voice pins, take the following image as a reference: + +![ADC input example wiring](assets/adc-input.svg) ```arduino -// Define the potentiometer pin and variable to store its value -int potentiometerPin = A0; -int potentiometerValue = 0; +#include "Nicla_System.h" + +int sensorPin = A0; // select the input pin for the potentiometer +int sensorValue = 0; // variable to store the value coming from the sensor void setup() { - // Initialize Serial communication - Serial1.begin(9600); + + analogReadResolution(12); // ADC bits configuration + nicla::begin(); // Nicla peripherals initialization, this enables the VDDIO_EXT 3.3V output. + Serial.begin(115200); // Serial initialization } void loop() { - // Read the voltage value from the potentiometer - potentiometerValue = analogRead(potentiometerPin); - - // Print the potentiometer voltage value to the Serial Monitor - Serial1.print("- Potentiometer voltage value: "); - Serial1.println(potentiometerValue); - - // Wait for 1000 milliseconds + // read the value from the sensor: + sensorValue = analogRead(sensorPin); + // print the value + Serial.println(sensorValue); delay(1000); } ``` +***The ADC inputs support 3.3V even when the ADC reference is 1.8V. In this perspective, the ADC will not sense any change from 1.8V and above.*** + ### Digital Pins The Nicla Voice has **twelve digital pins**, mapped as follows: @@ -238,7 +260,11 @@ The Nicla Voice has **twelve digital pins**, mapped as follows: Notice that analog pins `A0` and `A1` (`P0_02` and `P0_30`) can also be used as digital pins. Please, refer to the [board pinout section](#pins) of the user manual to find them on the board. -The digital pins of the Nicla Voice can be used as inputs or outputs through the built-in functions of the Arduino programming language. The configuration of a digital pin is done in the `setup()` function with the built-in function `pinMode()` as shown below: +The digital pins of the Nicla Voice can be used as inputs or outputs through the built-in functions of the Arduino programming language. + +***The Nicla Voice digital I/O's are low power, so to drive output devices like LEDs, resistive loads, buzzers, etc, it is recommended to use a MOSFET driver or a buffer to guarantee the required current flow. Learn more about the Nicla I/O's considerations [here](https://docs.arduino.cc/learn/hardware/nicla-form-factor).*** + +The configuration of a digital pin is done in the `setup()` function with the built-in function `pinMode()` as shown below: ```arduino // Pin configured as an input @@ -270,7 +296,11 @@ digitalWrite(pin, LOW); The example code shown below uses digital pin `3` to control an LED and reads the state of a button connected to digital pin `2`: +![Digital I/O example wiring](assets/digital-io-mosfet.svg) + ```arduino +#include "Nicla_System.h" + // Define button and LED pin int buttonPin = 2; int ledPin = 3; @@ -279,6 +309,9 @@ int ledPin = 3; int buttonState = 0; void setup() { + + nicla::begin(); // Nicla peripherals initialization, this enables the VDDIO_EXT 3.3V output. + // Configure button and LED pins pinMode(buttonPin, INPUT_PULLUP); pinMode(ledPin, OUTPUT); @@ -307,42 +340,88 @@ void loop() { ``` ### PWM Pins -Most digital and analog pins of the Nicla Voice can be used as PWM (Pulse Width Modulation) pins. This functionality of the Nicla Voice pins can be used with the built-in function `analogWrite()` as shown below: +Most digital and analog pins of the Nicla Voice can be used as PWM (Pulse Width Modulation) pins. This functionality of the Nicla Voice pins can be used with the built-in function `analogWrite()` as shown below: ```arduino analogWrite(pin, value); ``` -The example code shown below uses digital pin `9` PWM functionality to control the brightness of an LED connected to it: +By default, the output resolution is 8 bits, so the output value should be between 0 and 255. To set a greater resolution, do it using the built-in function `analogWriteResolution` as shown below: ```arduino -// Define the LED pin, brightness, and fade amount variables -int ledPin = 9; -int brightness = 0; -int fadeAmount = 5; +analogWriteResolution(bits); +``` + +Here is a complete example code that outputs a 50% duty-cycle PWM signal through pin 3 of the Nicla Voice: + +```arduino +#include "Nicla_System.h" + +#define out_pwm 3 // Nicla Voice pin 3 void setup() { - // Configure the LED pin as an output - pinMode(ledPin, OUTPUT); + // put your setup code here, to run once: + nicla::begin(); // Nicla peripherals initialization, this enables the VDDIO_EXT 3.3V output. + analogWriteResolution(12); + analogWrite(out_pwm, 2048); } void loop() { - // Set the brightness of the LED - analogWrite(ledPin, brightness); + // put your main code here, to run repeatedly: +} +``` - // Update the brightness value - brightness += fadeAmount; +Using this function has some limitations, for example, the PWM signal frequency is fixed at 500 Hz, and this could not be ideal for every application. - // Reverse the fade direction when reaching the limits - if (brightness <= 0 || brightness >= 255) { - fadeAmount = -fadeAmount; - } +![PWM output signal using analogWrite()](assets/500-Hz.png) + +If you need to work with a higher frequency PWM signal, you must do it by working with the PWM peripheral at a lower level as shown in the example code below: + +```arduino +#include "Nicla_System.h" +#include "nrfx_pwm.h" + +static nrfx_pwm_t pwm1 = NRFX_PWM_INSTANCE(0); + +static uint16_t /*const*/ seq1_values[] = {0}; + +static nrf_pwm_sequence_t seq1 = { + .values = { .p_common = seq1_values }, + .length = NRF_PWM_VALUES_LENGTH(seq1_values), + .repeats = 0, + .end_delay = 0 +}; + +void setup() { + + nicla::begin(); // Nicla peripherals initialization, this enables the VDDIO_EXT 3.3V output. + nrfx_pwm_config_t config1 = { + .output_pins = { + 32 + 23, // Nicla Voice pin 3 = pin P0_23 in the ANNAB112 MCU + }, + .irq_priority = APP_IRQ_PRIORITY_LOWEST, + .base_clock = NRF_PWM_CLK_1MHz, // 1 us period + .count_mode = NRF_PWM_MODE_UP, + .top_value = 1000, // PWM counter limit, this will set the final output frequency 1MHz / 1000 = 1KHz + .load_mode = NRF_PWM_LOAD_COMMON, + .step_mode = NRF_PWM_STEP_AUTO, + }; + + nrfx_pwm_init(&pwm1, &config1, NULL); + + (*seq1_values) = 500; // this variable sets the signal duty cycle, for a 50% we are using 500. (1000 / 500 = 1/2) + (void)nrfx_pwm_simple_playback(&pwm1, &seq1, 1, NRFX_PWM_FLAG_LOOP); +} + +void loop() { - // Wait for 30 milliseconds - delay(30); } ``` +The code above results in a 1KHz square waveform with a 50% duty cycle as in the image below. The frequency is defined by the `.base_clock` and `.top_value` variables, and the duty cycle by the `seq1_values` variable. + +![PWM output signal using the PWM at a lower level](assets/1000-Hz.png) + ## Onboard Sensors The Nicla Voice boards come with various onboard sensors that allow you to capture and process environmental and motion data via a high-performance microphone, a 6-axis IMU, and a 3-axis magnetometer. The onboard sensors can be used for developing various applications, such as voice recognition, gesture control, and environmental monitoring. @@ -357,7 +436,7 @@ An external PDM microphone can be connected to the board via an onboard Zero Ins ![Nicla Voice onboard ZIF connector](assets/user-manual-10.png) -The example code shown below captures audio from the onboard microphone of the Nicla Voice, compresses the audio using the G722 codec, and streams the compressed audio data to the serial port. The example can be found in the board's built-in examples by navigating to **File -> Examples -> NDP -> Record_and_stream**. +The example code shown below captures audio from the onboard microphone of the Nicla Voice, compresses the audio using the G722 codec, and streams the compressed audio data to the serial port. The example can be found in the board's built-in examples by navigating to **File > Examples > NDP > Record_and_stream**. Keep in mind that this example code requires the following libraries: @@ -460,99 +539,71 @@ In the `loop()` function: - The length of the extracted audio data is stored in the `len` variable. - The extracted audio data is passed to the G722 encoder, which compresses the audio and sends it to the serial port. -To extract the audio data on a computer, you will need to set up the serial port as raw and dump the data to a file (e.g., test.g722). Then, you can open the file with a software like [Audacity](https://www.audacityteam.org/) to play back the audio. +To extract the audio data on a **Linux computer**, you will need to set up the serial port as raw: + +```bash +stty -F /dev/ttyACM0 115200 raw +``` +Dump the data to a file (e.g., test.g722): + +```bash +cat /dev/ttyACM0 > test.g722 +``` +Then, you can open the file with a software like [Audacity](https://www.audacityteam.org/) to play back the audio. #### Machine Learning and Audio Analysis You can use the Nicla Voice and the [Machine Learning Tools](https://cloud.arduino.cc/machine-learning-tools/) of the Arduino Cloud to create your own audio analysis Machine Learning models. Check out this [tutorial](https://docs.arduino.cc/tutorials/nicla-voice/getting-started-ml) and start with Machine Learning with the Nicla Voice. -### IMU and Magnetometer +![Edge Impulse Studio for ML and AI](assets/edge-impulse.png) -The Nicla Voice features an advanced IMU and a magnetometer, which allows the board to sense motion, orientation, and magnetic fields. The IMU on the Nicla Voice board is the BMI270 from Bosch®. It consists of a 3-axis accelerometer and a 3-axis gyroscope. They can provide information about the board's motion, orientation, and rotation in a 3D space. The BMI270 is designed for wearables and offers low power consumption and high performance, making it suitable for various applications, such as gesture recognition, motion tracking, or stabilization. +Learn more about the Nicla Voice integration with Edge Impulse [here](https://docs.edgeimpulse.com/docs/edge-ai-hardware/mcu-+-ai-accelerators/arduino-nicla-voice). -![Nicla Voice onboard IMU](assets/user-manual-11.png) +### IMU -The onboard magnetometer of the Nicla Voice can be used to determine the board's orientation relative to Earth's magnetic field, which is helpful for compass applications, navigation, or detecting the presence of nearby magnetic objects. The magnetometer on the Nicla Voice board is the BMM150, also from Bosch®. It is a 3-axis sensor that measures the strength and direction of magnetic fields surrounding the board. +The Nicla Voice features an advanced IMU and a magnetometer, which allows the board to sense motion, orientation, and magnetic fields. The IMU on the Nicla Voice board is the BMI270 from Bosch®. It consists of a 3-axis accelerometer and a 3-axis gyroscope. They can provide information about the board's motion, orientation, and rotation in a 3D space. The BMI270 is designed for wearables and offers low power consumption and high performance, making it suitable for various applications, such as gesture recognition, motion tracking, or stabilization. -![Nicla Voice onboard magnetometer](assets/user-manual-12.png) +![Nicla Voice onboard IMU](assets/user-manual-11.png) #### Accelerometer and Gyroscope Data -The example sketch below shows how to get acceleration (m/s2) and angular velocity (in °/s) data from the onboard IMU and streams it to the Arduino IDE Serial Monitor and Serial Plotter. The sketch needs the `BMI270_Init.h` header file to be in the same directory as the sketch. You can download the example sketch and the header files [here](assets/nv_acc_gyro_test.rar). - -```arduino -/** - Nicla Voice accelerometer and gyroscope test sketch - Name: nv_acc_gyro_test.ino - Purpose: Sketch tests onboard accelerometer and gyroscope (BMI270) +The example sketch below shows how to get acceleration (m/s2) and angular velocity (in °/s) data from the onboard IMU and streams it to the Arduino IDE Serial Monitor and Serial Plotter. The sketch needs the `BMI270_Init.h` header file to be in the same directory as the sketch. You can download the example sketch and the header files [here](assets/nv_acc_gyro_test.zip). - @author Arduino PRO Content Team - @version 1.0 22/05/23 -*/ +***For this example to work you must update the NDP processor, see the details on this [section](#ndp120-processor-firmware-update).*** +```arduino #include "NDP.h" #include "BMI270_Init.h" // Named constants -#define READ_START_ADDRESS 0x0C -#define READ_BYTE_COUNT 16 -#define SENSOR_DATA_LENGTH 16 +#define READ_START_ADDRESS 0x0C +#define READ_BYTE_COUNT 16 +#define SENSOR_DATA_LENGTH 16 // Accelerometer range is set to +/-2g -// Raw accelerometer data is represented as a signed 16-bit integer -// Raw accelerometer data can be converted to acceleration in m/s^2 units using the following scale factor: -#define ACCEL_SCALE_FACTOR ((2.0 / 32767.0) * 9.8) +// Raw accelerometer data is represented as a signed 16-bit integer +// Raw accelerometer data can be converted to acceleration in m/s^2 units using the following scale factor: +#define ACCEL_SCALE_FACTOR ((2.0 / 32767.0) * 9.8) // Gyroscope has a sensitivity of 16.4 LSB/dps -#define GYRO_SCALE_FACTOR (1 / 16.4) - -/** - Turns on and off the onboard blue LED. - - @param label to be printed on the Serial Monitor. -*/ -void ledBlueOn(char* label) { - nicla::leds.begin(); - nicla::leds.setColor(blue); - delay(200); - nicla::leds.setColor(off); - Serial.println(label); - nicla::leds.end(); -} - -/** - Turns on and off the onboard green LED. -*/ -void ledGreenOn() { - nicla::leds.begin(); - nicla::leds.setColor(green); - delay(200); - nicla::leds.setColor(off); - nicla::leds.end(); -} - -/** - Blinks onboard red LED periodically every 200 ms. -*/ -void ledRedBlink() { - while (1) { - nicla::leds.begin(); - nicla::leds.setColor(red); - delay(200); - nicla::leds.setColor(off); - delay(200); - nicla::leds.end(); - } -} +#define GYRO_SCALE_FACTOR (1 / 16.4) // Macros for checking the sensor status. -#define CHECK_STATUS(s) do {if (s) {Serial.print("SPI access error in line "); Serial.println(__LINE__); for(;;);}} while (0) +#define CHECK_STATUS(s) \ + do { \ + if (s) { \ + Serial.print("SPI access error in line "); \ + Serial.println(__LINE__); \ + for (;;) \ + ; \ + } \ + } while (0) void setup() { int status; uint8_t __attribute__((aligned(4))) sensor_data[SENSOR_DATA_LENGTH]; - // Initiate Serial communication for debugging and monitoring. + // Initiate Serial communication for debugging and monitoring. Serial.begin(115200); // Initialize Nicla Voice board's system functions. @@ -562,19 +613,10 @@ void setup() { nicla::disableLDO(); nicla::leds.begin(); - // Set up error and event handlers: - // - In case of error, the red LED will blink. - // - In case of match, the blue LED will turn on. - // - In case of any event, the green LED will turn on. - NDP.onError(ledRedBlink); - NDP.onMatch(ledBlueOn); - NDP.onEvent(ledGreenOn); - // NDP processor initialization with firmwares and models Serial.println("- NDP processor initialization..."); NDP.begin("mcu_fw_120_v91.synpkg"); NDP.load("dsp_firmware_v91.synpkg"); - NDP.load("ei_model.synpkg"); Serial.println("- NDP processor initialization done!"); // Set the BMI270 sensor in SPI mode, then read sensor data. @@ -603,7 +645,7 @@ void setup() { status = NDP.sensorBMI270Write(0x59, 0x00); CHECK_STATUS(status); - // Sensor configuration. + // Sensor configuration. Serial.println("- BMI270 initialization starting..."); status = NDP.sensorBMI270Write(0x5E, sizeof(bmi270_maximum_fifo_config_file), (uint8_t*)bmi270_maximum_fifo_config_file); CHECK_STATUS(status); @@ -618,13 +660,13 @@ void setup() { // Configure the device to normal power mode with both accelerometer and gyroscope operational. // Set the accelerometer and gyroscope settings such as measurement range and data rate. - status = NDP.sensorBMI270Write(0x7D, 0x0E); // Normal power mode + status = NDP.sensorBMI270Write(0x7D, 0x0E); // Normal power mode CHECK_STATUS(status); status = NDP.sensorBMI270Write(0x40, 0xA8); // Accelerometer configuration. CHECK_STATUS(status); status = NDP.sensorBMI270Write(0x41, 0x00); // Set the accelerometer range to +/- 2g. CHECK_STATUS(status); - status = NDP.sensorBMI270Write(0x42, 0xA9); // Gyroscope configuration. + status = NDP.sensorBMI270Write(0x42, 0xA9); // Gyroscope configuration. CHECK_STATUS(status); status = NDP.sensorBMI270Write(0x43, 0x00); // Set the gyroscope range to +/- 2000 dps. CHECK_STATUS(status); @@ -658,7 +700,7 @@ void loop() { y_gyr_raw = (0x0000 | sensor_data[8] | sensor_data[9] << 8); z_gyr_raw = (0x0000 | sensor_data[10] | sensor_data[11] << 8); - // Convert raw accelerometer data to acceleration expressed in m/s^2. + // Convert raw accelerometer data to acceleration expressed in m/s^2. x_acc = x_acc_raw * ACCEL_SCALE_FACTOR; y_acc = y_acc_raw * ACCEL_SCALE_FACTOR; z_acc = z_acc_raw * ACCEL_SCALE_FACTOR; @@ -667,8 +709,8 @@ void loop() { x_gyr = x_gyr_raw * GYRO_SCALE_FACTOR; y_gyr = y_gyr_raw * GYRO_SCALE_FACTOR; z_gyr = z_gyr_raw * GYRO_SCALE_FACTOR; - - // Print accelerometer data (expressed in m/s^2). + + // Print accelerometer data (expressed in m/s^2). Serial.print("x_acc:"); Serial.print(x_acc); Serial.print(","); @@ -688,7 +730,7 @@ void loop() { Serial.print("z_gyr:"); Serial.println(z_gyr); - delay(1000); + delay(10); } ``` @@ -699,22 +741,18 @@ First, the necessary libraries are included: - `NDP.h` and `BMI270_Init.h` for the Nicla Voice board's basic functions and the IMU control. - Macros are defined for checking the status of the IMU; these macros allow the sketch to detect and handle sensor errors. -Next, user functions `ledBlueOn()`, `ledGreenOn()`, and `ledRedBlink()` definition: - -- These functions allow the onboard LEDs to flash specific colors to indicate different states: blue for a successful match, green for an event, and red to indicate an error. - Next, in the `setup()` function: -- The serial communication is initialized at a baud rate of 115200. +- The serial communication is initialized at a baud rate of `115200`. - The Nicla Voice board is initialized, and the LDO regulator (used for putting the board into power-saving mode) is disabled to avoid communication problems with the IMU. - Error and event handlers are initialized. -- NDP processor is initialized; this process includes populating the external Flash memory of the board with the NDP processor's internal microcontroller firmware (`mcu_fw_120_v91.synpkg`), the NDP processor's internal DSP firmware (`dsp_firmware_v91.synpkg`), and the Machine Learning model (`ei_model.synpkg`). +- NDP processor is initialized; this process includes populating the external Flash memory of the board with the NDP processor's internal microcontroller firmware (`mcu_fw_120_v91.synpkg`), and the NDP processor's internal DSP firmware (`dsp_firmware_v91.synpkg`). - The BMI270 sensor is initialized; this includes a software reset, loading the sensor configuration, and setting it into normal power mode with the accelerometer and gyroscope operational. Finally, in the `loop()` function: - Memory is allocated for the sensor data; data is then read from the sensor and stored in this allocated space. -- Raw sensor data is then parsed and extracted into raw accelerometer and gyroscope data. This data is represented as 16-bit signed integers ranging from -32 768 to 32 767. +- Raw sensor data is then parsed and extracted into raw accelerometer and gyroscope data. This data is represented as 16-bit signed integers ranging from -32768 to 32767. - Raw sensor data is converted into understandable and standard unit measurements; for the accelerometer, data is converted to meters per second squared, and for the gyroscope, data is converted to degrees per second. - Converted accelerometer and gyroscope data are printed on the Serial Monitor, allowing the user to observe sensor data in real-time. @@ -722,75 +760,36 @@ After uploading the example code, you should see accelerometer and gyroscope dat ![Nicla Voice onboard IMU data on the IDE's Serial Monitor](assets/user-manual-13.png) -Let's use also the Arduino IDE Serial Plotter to test the example IMU sketch; let's start visualizing only accelerometer data. To do so, comment the gyroscope data output as shown below: - -```arduino - // Print accelerometer data (expressed in meters per second squared). - Serial.print("x_acc:"); - Serial.print(x_acc); - Serial.print(","); - Serial.print("y_acc:"); - Serial.print(y_acc); - Serial.print(","); - Serial.print("z_acc:"); - Serial.println(z_acc); +Let's use also the Arduino IDE Serial Plotter to test the example IMU sketch, open the IDE's Serial Plotter by navigating to **Tools > Serial Plotter**. After a while, you should see a real-time graph showing data from the board's onboard accelerometer and gyroscope, as shown below: - /* Print gyroscope data (expressed in degrees per second). - Serial.print("x_gyr:"); - Serial.print(x_gyr); - Serial.print(","); - Serial.print("y_gyr:"); - Serial.print(y_gyr); - Serial.print(","); - Serial.print("z_gyr:"); - Serial.println(z_gyr); */ -``` +![Nicla Voice onboard IMU data on the IDE's Serial Plotter](assets/imu_gyro.gif) -Upload the example sketch again and open the IDE's Serial Plotter by navigating to **Tools > Serial Plotter**. After a while, you should see a real-time graph showing data from the board's onboard accelerometer, as shown below (move the board): +When the board is not moving, you should see acceleration measurements close to zero on the x and y-axis, while the z-axis will be close to 1g (approximately 9.81 m/s2), the gyroscope measurements on the three-axis will stay close to zero. +#### IMU and Machine Learning -![Nicla Voice onboard accelerometer data on the IDE's Serial Plotter](assets/user-manual-14.gif) - -When the board is not moving, you should see acceleration measurements close to zero on the x and y-axis, while the z-axis will be close to 1g (approximately 9.81 m/s2). If you want to visualize gyroscope readings, uncomment the gyroscope data output and comment on the accelerometer data output; when the board is not moving, you should see gyroscope measurements on the three-axis close to zero. - -#### Magnetometer Data +The example code below demonstrates how to use the Nicla Voice board to perform Machine Learning inference on IMU data. The code sets up event indicators using the onboard RGB LED and sends IMU data to the NDP processor for inference. The example can be found in the board's built-in examples by navigating to **File > Examples > NDP > IMUDemo**. -The example code below shows how to get raw magnetic field and Hall resistance data from the onboard magnetometer and stream it to the Arduino IDE Serial Monitor and Serial Plotter. You can download the example sketch [here](assets/nv_mag_test.rar). ```arduino -/** - Nicla Voice magnetometer test sketch - Name: nv_mag_test.ino - Purpose: Sketch tests onboard magnetometer (BMM150) - - @author Arduino PRO Content Team - @version 1.0 30/05/23 -*/ - #include "NDP.h" -// Named constants -#define READ_START_ADDRESS 0x42 -#define READ_BYTE_COUNT 8 -#define SENSOR_DATA_LENGTH 16 +// Set to 'true' for the lowest power consumption mode, 'false' otherwise +const bool lowestPower = false; -/** - Turns on and off the onboard blue LED. - - @param label to be printed on the Serial Monitor. -*/ +// Function to turn on the blue LED and print a label to the serial monitor if not in the lowest power mode void ledBlueOn(char* label) { nicla::leds.begin(); nicla::leds.setColor(blue); delay(200); nicla::leds.setColor(off); - Serial.println(label); + if (!lowestPower) { + Serial.println(label); + } nicla::leds.end(); } -/** - Turns on and off the onboard green LED. -*/ +// Function to turn on the green LED briefly void ledGreenOn() { nicla::leds.begin(); nicla::leds.setColor(green); @@ -799,6 +798,94 @@ void ledGreenOn() { nicla::leds.end(); } +// Function to make the red LED blink continuously +void ledRedBlink() { + while (1) { + nicla::leds.begin(); + nicla::leds.setColor(red); + delay(200); + nicla::leds.setColor(off); + delay(200); + nicla::leds.end(); + } +} + +void setup() { + Serial.begin(115200); + nicla::begin(); + nicla::disableLDO(); + nicla::leds.begin(); + + // Register event handlers for error, match, and event + NDP.onError(ledRedBlink); + NDP.onMatch(ledBlueOn); + NDP.onEvent(ledGreenOn); + + // Load Edge Impulse model and related firmware + Serial.println("Loading synpackages"); + NDP.begin("mcu_fw_120_v91.synpkg"); + NDP.load("dsp_firmware_v91.synpkg"); + NDP.load("ei_model_imu.synpkg"); + Serial.println("packages loaded"); + + NDP.getInfo(); + NDP.configureInferenceThreshold(1088); + NDP.interrupts(); + + // Enter the lowest power mode, if set + nicla::leds.end(); + if (lowestPower) { + NRF_UART0->ENABLE = 0; + } +} + +// Predefined IMU data for testing +extern "C" const unsigned char data_opensset_bin[]; +extern "C" const unsigned char data_circ_bin[]; +extern "C" const unsigned int data_opensset_bin_len; +extern "C" const unsigned int data_circ_bin_len; + +void loop() { + // Send openset data (no match expected) + Serial.println("Sending openset data... (no match expected)"); + NDP.sendData((uint8_t*)data_opensset_bin, data_opensset_bin_len); + delay(1000); + + // Send circular IMU data (match expected) + Serial.println("Sending circular IMU data.... (match expected)"); + NDP.sendData((uint8_t*)data_circ_bin, data_circ_bin_len); + delay(5000); +} +``` + +In the example code above, a Machine Learning model is loaded into the Nicla Voice board, and predefined IMU data is sent to the Machine Learning model for inferencing. Depending on the result, the board will light its built-in RGB LED with different colors: + +- If the model matches the input data with a known motion pattern, the built-in RGB LED is turned blue, and the event label is printed to the IDE's Serial Monitor. +- If an error occurs, the built-in RGB LED will blink red continuously. +- While an event is recognized, the built-in RGB LED is turned on green. + +To learn more about your Nicla Voice board Machine Learning capabilities, check out the following tutorial and learn how to create a simple motion detection application: + +- [Motion Detection with Nicla Voice and Machine Learning Tools](https://docs.arduino.cc/tutorials/nicla-voice/motion-detection-ml) + +### Magnetometer + +The onboard magnetometer of the Nicla Voice can be used to determine the board's orientation relative to Earth's magnetic field, which is helpful for compass applications, navigation, or detecting the presence of nearby magnetic objects. The magnetometer on the Nicla Voice board is the BMM150, also from Bosch®. It is a 3-axis sensor that measures the strength and direction of magnetic fields surrounding the board. + +![Nicla Voice onboard magnetometer](assets/user-manual-12.png) + +#### Magnetometer Data + +The example code below shows how to get raw magnetic field and Hall resistance data from the onboard magnetometer and stream it to the Arduino IDE Serial Monitor and Serial Plotter. You can download the example sketch [here](assets/nv_mag_test.rar). + +```arduino +#include "NDP.h" + +// Named constants +#define READ_START_ADDRESS 0x42 +#define READ_BYTE_COUNT 8 +#define SENSOR_DATA_LENGTH 16 + /** Blinks onboard red LED periodically every 200 ms. */ @@ -814,19 +901,21 @@ void ledRedBlink() { } // Macro definition used for checking the sensor status, print error if SPI access fails. -#define CHECK_STATUS(s) do {\ - if (s) {\ - Serial.print("SPI access error in line ");\ - Serial.println(__LINE__);\ - for(;;);\ - }\ -} while (0) +#define CHECK_STATUS(s) \ + do { \ + if (s) { \ + Serial.print("SPI access error in line "); \ + Serial.println(__LINE__); \ + for (;;) \ + ; \ + } \ + } while (0) void setup() { int status; uint8_t __attribute__((aligned(4))) sensor_data[SENSOR_DATA_LENGTH]; - // Initiate Serial communication for debugging and monitoring. + // Initiate Serial communication for debugging and monitoring. Serial.begin(115200); // Initialize Nicla Voice board's system functions. @@ -838,17 +927,13 @@ void setup() { // Set up error and event handlers: // - In case of error, the red LED will blink. - // - In case of match, the blue LED will turn on. - // - In case of any event, the green LED will turn on. + NDP.onError(ledRedBlink); - NDP.onMatch(ledBlueOn); - NDP.onEvent(ledGreenOn); // NDP processor initialization with firmwares and models. Serial.println("- NDP processor initialization..."); NDP.begin("mcu_fw_120_v91.synpkg"); NDP.load("dsp_firmware_v91.synpkg"); - NDP.load("ei_model.synpkg"); Serial.println("- NDP processor initialization done!"); // Enable power control bit @@ -856,7 +941,7 @@ void setup() { CHECK_STATUS(status); delay(20); - // Read power control byte + // Read power control byte status = NDP.sensorBMM150Read(0x4B, 1, sensor_data); CHECK_STATUS(status); @@ -871,10 +956,10 @@ void setup() { void loop() { // Allocate space for raw sensor data. - uint8_t __attribute__((aligned(4))) sensor_data[SENSOR_DATA_LENGTH]; + uint8_t __attribute__((aligned(4))) sensor_data[SENSOR_DATA_LENGTH]; // Declare variables for magnetometer data. - int16_t x_mag_raw, y_mag_raw, z_mag_raw, hall_raw ; + int16_t x_mag_raw, y_mag_raw, z_mag_raw, hall_raw; float x_mag, y_mag, z_mag; // Read operation status variable. @@ -891,6 +976,7 @@ void loop() { // The sensor data is read into an array of bytes (8-bit values). Each measurement from the magnetometer consists // of two bytes, hence the bit shifting and bitwise OR operations to combine these two bytes into one 16-bit value. // Data for each axis (X, Y, Z) of the magnetometer is extracted from the array. + x_mag_raw = (0x0000 | sensor_data[0] >> 3 | sensor_data[1] << 5); y_mag_raw = (0x0000 | sensor_data[2] >> 3 | sensor_data[3] << 5); z_mag_raw = (0x0000 | sensor_data[4] >> 1 | sensor_data[5] << 7); @@ -909,7 +995,7 @@ void loop() { Serial.print("hall_raw:"); Serial.println(hall_raw); - delay(1000); + delay(100); } ``` @@ -920,16 +1006,16 @@ First, the necessary libraries are included: - `NDP.h` for the Nicla Voice board's basic functions and the magnetometer control. - Macros are defined for checking the status of the magnetometer; these macros allow the sketch to detect and handle sensor errors. -Next, user functions `ledBlueOn()`, `ledGreenOn()`, and `ledRedBlink()` definition: +Next, user function `ledRedBlink()` definition: -- These functions allow the onboard LEDs to flash specific colors to indicate different states: blue for a successful match, green for an event, and red to indicate an error. +- These functions allow the onboard LEDs to flash red to indicate an error. Next, in the `setup()` function: - The serial communication is initialized at a baud rate of 115200. - The Nicla Voice board is initialized, and the LDO regulator (used for putting the board into power-saving mode) is disabled to avoid communication problems with the magnetometer. - Error and event handlers are initialized. -- NDP processor is initialized; this process includes populating the external Flash memory of the board with the NDP processor's internal microcontroller firmware (`mcu_fw_120_v91.synpkg`), the NDP processor's internal DSP firmware (`dsp_firmware_v91.synpkg`), and the Machine Learning model (`ei_model.synpkg`). +- NDP processor is initialized; this process includes populating the external Flash memory of the board with the NDP processor's internal microcontroller firmware (`mcu_fw_120_v91.synpkg`) and the NDP processor's internal DSP firmware (`dsp_firmware_v91.synpkg`). - The BMM150 sensor is initialized; this includes setting it into normal operation with an output data rate (ODR) of 10 Hz. Finally, in the `loop()` function: @@ -946,108 +1032,6 @@ Now open the IDE's Serial Plotter by navigating to **Tools > Serial Plotter**. A ![Nicla Voice onboard raw magnetometer data on the IDE's Serial Plotter](assets/user-manual-16.gif) -#### IMU and Machine Learning - -The example code below demonstrates how to use the Nicla Voice board to perform Machine Learning inference on IMU data. The code sets up event indicators using the onboard RGB LED and sends IMU data to the NDP processor for inference. The example can be found in the board's built-in examples by navigating to **File > Examples > NDP > IMUDemo**. - - -```arduino -#include "NDP.h" - -// Set to 'true' for the lowest power consumption mode, 'false' otherwise -const bool lowestPower = false; - -// Function to turn on the blue LED and print a label to the serial monitor if not in the lowest power mode -void ledBlueOn(char* label) { - nicla::leds.begin(); - nicla::leds.setColor(blue); - delay(200); - nicla::leds.setColor(off); - if (!lowestPower) { - Serial.println(label); - } - nicla::leds.end(); -} - -// Function to turn on the green LED briefly -void ledGreenOn() { - nicla::leds.begin(); - nicla::leds.setColor(green); - delay(200); - nicla::leds.setColor(off); - nicla::leds.end(); -} - -// Function to make the red LED blink continuously -void ledRedBlink() { - while (1) { - nicla::leds.begin(); - nicla::leds.setColor(red); - delay(200); - nicla::leds.setColor(off); - delay(200); - nicla::leds.end(); - } -} - -void setup() { - Serial.begin(115200); - nicla::begin(); - nicla::disableLDO(); - nicla::leds.begin(); - - // Register event handlers for error, match, and event - NDP.onError(ledRedBlink); - NDP.onMatch(ledBlueOn); - NDP.onEvent(ledGreenOn); - - // Load Edge Impulse model and related firmware - Serial.println("Loading synpackages"); - NDP.begin("mcu_fw_120_v91.synpkg"); - NDP.load("dsp_firmware_v91.synpkg"); - NDP.load("ei_model_imu.synpkg"); - Serial.println("packages loaded"); - - NDP.getInfo(); - NDP.configureInferenceThreshold(1088); - NDP.interrupts(); - - // Enter the lowest power mode, if set - nicla::leds.end(); - if (lowestPower) { - NRF_UART0->ENABLE = 0; - } -} - -// Predefined IMU data for testing -extern "C" const unsigned char data_opensset_bin[]; -extern "C" const unsigned char data_circ_bin[]; -extern "C" const unsigned int data_opensset_bin_len; -extern "C" const unsigned int data_circ_bin_len; - -void loop() { - // Send openset data (no match expected) - Serial.println("Sending openset data... (no match expected)"); - NDP.sendData((uint8_t*)data_opensset_bin, data_opensset_bin_len); - delay(1000); - - // Send circular IMU data (match expected) - Serial.println("Sending circular IMU data.... (match expected)"); - NDP.sendData((uint8_t*)data_circ_bin, data_circ_bin_len); - delay(5000); -} -``` - -In the example code above, a Machine Learning model is loaded into the Nicla Voice board, and predefined IMU data is sent to the Machine Learning model for inferencing. Depending on the result, the board will light its built-in RGB LED with different colors: - -- If the model matches the input data with a known motion pattern, the built-in RGB LED is turned blue, and the event label is printed to the IDE's Serial Monitor. -- If an error occurs, the built-in RGB LED will blink red continuously. -- While an event is recognized, the built-in RGB LED is turned on green. - -To learn more about your Nicla Voice board Machine Learning capabilities, check out the following tutorial and learn how to create a simple motion detection application: - -- [Motion Detection with Nicla Voice and Machine Learning Tools](https://docs.arduino.cc/tutorials/nicla-voice/motion-detection-ml) - ## Actuators ### RGB LED @@ -1198,9 +1182,9 @@ digitalWrite(SS, HIGH); The Nicla Voice supports I2C communication, which allows data transmission between the board and other I2C-compatible devices. The pins used in the Nicla Voice for the I2C communication protocol are the following: | **Microcontroller Pin** | **Arduino Pin Mapping** | -|:-----------------------:|:-----------------------:| -| `P0_23` | `SCL` or `3` | -| `P0_22` | `SDA` or `4` | +| :---------------------: | :---------------------: | +| `P0_23` | `I2C_SCL` or `3` | +| `P0_22` | `I2C_SDA` or `4` | Please, refer to the [board pinout section](#pins) of the user manual to find them on the board. The I2C pins are also available through the onboard ESLOV connector of the Nicla Voice. @@ -1265,9 +1249,9 @@ while (Wire.available()) { The pins used in the Nicla Voice for the UART communication protocol are the following: | **Microcontroller Pin** | **Arduino Pin Mapping** | -|:-----------------------:|:-----------------------:| -| `P0_09` | `TX` or `1` | -| `P0_20` | `RX` or `2` | +| :---------------------: | :---------------------: | +| `P0_09` | `SERIAL1_TX` or `1` | +| `P0_20` | `SERIAL1_RX` or `2` | Please, refer to the [board pinout section](#board-pinout) of the user manual to find them on the board.