Lab 1
Net ID: pp386
Objective:
This lab’s main objective is to familiarize us with Arduino IDE and the Artemis board and program simple code examples like blinking an LED on the board, reading/writing messages transferred over USB, measuring temperature using the onboard temperature sensor and also measuring the loudest frequency using the Pulse Density Microphone.
Parts required:
1) 1 x SparkFun RedBoard Artemis Nano
2) 1 x USB C-to-C or A-to-C cable
Software Required
1) Arduino IDE
2) Sparkfun Artemis board examples
Blink It Up (Example 1)
This section implements the example called Blink It Up which is used to turn an LED on the Artemis board ON and OFF after a specific time delay. LED 19 on the Artemis is blinked ON and OFF with a delay of 1000 or 1s. The demonstration can be seen in the video below. The baud rate is set to 115200.
Serial Input (Example 2)
In this section, with the help of the Serial Monitor and Keyboard, the input is sent to the Artemis board connected via USB serially. The board echoes the input and sends it back via the USB to view on the Serial Monitor. The baud rate is set to 115200 and the demonstration can be seen in the video below.
Analog Read (Example 3)
In this section, the onboard temperature sensor on the Artemis is used to measure the temperature count value. Again, a standard example is used from the documentation and the temperature is measured on the Analog Pin A0 of the Artemis. The baud rate is set to 115200 and the number of resolution bits is set to 16. On touching A0, a change in value of the temperature is seen as shown in the video below.
Microphone Input (Example 4)
In this section, the onboard Pulse Density Modulation (PDM) microphone is tested using a simple code example. The code example finds the highest frequency detected by the microphone and then outputs it onto the Serial Monitor.
LED ON/OFF on detecting Microphone input above a certain frequency (Additional task for ECE5960)
In this section, the above code example from the Microphone Input section is taken and then the logic for turning the LED ON/OFF on detecting a frequency higher than 1000 Hz is added to the function. In the demonstration below we can see the LED turning ON when a whistling sound is made and turning OFF otherwise.
Code for above example (Note: My addition to the microphone example is highlighted):
/* Author: Nathan Seidle
Created: July 24, 2019
This example demonstrates how to use the pulse density microphone (PDM) on Artemis boards.
This library and example are heavily based on the Apollo3 pdm_fft example.
*/
/*
// This file is subject to the terms and conditions defined in
// file 'LICENSE.md', which is part of this source code package.
*/
//Global variables needed for PDM library
#define pdmDataBufferSize 4096 //Default is array of 4096 * 32bit
uint16_t pdmDataBuffer[pdmDataBufferSize];
//Global variables needed for the FFT in this sketch
float g_fPDMTimeDomain[pdmDataBufferSize * 2];
float g_fPDMFrequencyDomain[pdmDataBufferSize * 2];
float g_fPDMMagnitudes[pdmDataBufferSize * 2];
uint32_t sampleFreq;
//Enable these defines for additional debug printing
#define PRINT_PDM_DATA 0
#define PRINT_FFT_DATA 0
#include <PDM.h> //Include PDM library included with the Aruino_Apollo3 core
AP3_PDM myPDM; //Create instance of PDM class
//Math library needed for FFT
#include <arm_math.h>
void setup()
{
Serial.begin(115200);
Serial.println("SparkFun PDM Example");
if (myPDM.begin() == false) // Turn on PDM with default settings, start interrupts
{
Serial.println("PDM Init failed. Are you sure these pins are PDM capable?");
while (1)
;
}
Serial.println("PDM Initialized");
//*****************************************************************************
// My addition to the Microphone example
pinMode(LED_BUILTIN, OUTPUT);
//*****************************************************************************
printPDMConfig();
}
void loop()
{
if (myPDM.available())
{
myPDM.getData(pdmDataBuffer, pdmDataBufferSize);
printLoudest();
}
// Go to Deep Sleep until the PDM ISR or other ISR wakes us.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);
}
//*****************************************************************************
//
// Analyze and print frequency data.
//
//*****************************************************************************
void printLoudest(void)
{
float fMaxValue;
uint32_t ui32MaxIndex;
int16_t *pi16PDMData = (int16_t *)pdmDataBuffer;
uint32_t ui32LoudestFrequency;
//
// Convert the PDM samples to floats, and arrange them in the format
// required by the FFT function.
//
for (uint32_t i = 0; i < pdmDataBufferSize; i++)
{
if (PRINT_PDM_DATA)
{
Serial.printf("%d\n", pi16PDMData[i]);
}
g_fPDMTimeDomain[2 * i] = pi16PDMData[i] / 1.0;
g_fPDMTimeDomain[2 * i + 1] = 0.0;
}
if (PRINT_PDM_DATA)
{
Serial.printf("END\n");
}
//
// Perform the FFT.
//
arm_cfft_radix4_instance_f32 S;
arm_cfft_radix4_init_f32(&S, pdmDataBufferSize, 0, 1);
arm_cfft_radix4_f32(&S, g_fPDMTimeDomain);
arm_cmplx_mag_f32(g_fPDMTimeDomain, g_fPDMMagnitudes, pdmDataBufferSize);
if (PRINT_FFT_DATA)
{
for (uint32_t i = 0; i < pdmDataBufferSize / 2; i++)
{
Serial.printf("%f\n", g_fPDMMagnitudes[i]);
}
Serial.printf("END\n");
}
//
// Find the frequency bin with the largest magnitude.
//
arm_max_f32(g_fPDMMagnitudes, pdmDataBufferSize / 2, &fMaxValue, &ui32MaxIndex);
ui32LoudestFrequency = (sampleFreq * ui32MaxIndex) / pdmDataBufferSize;
if (PRINT_FFT_DATA)
{
Serial.printf("Loudest frequency bin: %d\n", ui32MaxIndex);
}
Serial.printf("Loudest frequency: %d \n", ui32LoudestFrequency);
//*****************************************************************************
// My addition to the Microphone example
if(ui32LoudestFrequency>1000)
{
digitalWrite(LED_BUILTIN, HIGH);
}
else
{
digitalWrite(LED_BUILTIN, LOW);
//*****************************************************************************
}
//*****************************************************************************
//
// Print PDM configuration data.
//
//*****************************************************************************
void printPDMConfig(void)
{
uint32_t PDMClk;
uint32_t MClkDiv;
float frequencyUnits;
//
// Read the config structure to figure out what our internal clock is set
// to.
//
switch (myPDM.getClockDivider())
{
case AM_HAL_PDM_MCLKDIV_4:
MClkDiv = 4;
break;
case AM_HAL_PDM_MCLKDIV_3:
MClkDiv = 3;
break;
case AM_HAL_PDM_MCLKDIV_2:
MClkDiv = 2;
break;
case AM_HAL_PDM_MCLKDIV_1:
MClkDiv = 1;
break;
default:
MClkDiv = 0;
}
switch (myPDM.getClockSpeed())
{
case AM_HAL_PDM_CLK_12MHZ:
PDMClk = 12000000;
break;
case AM_HAL_PDM_CLK_6MHZ:
PDMClk = 6000000;
break;
case AM_HAL_PDM_CLK_3MHZ:
PDMClk = 3000000;
break;
case AM_HAL_PDM_CLK_1_5MHZ:
PDMClk = 1500000;
break;
case AM_HAL_PDM_CLK_750KHZ:
PDMClk = 750000;
break;
case AM_HAL_PDM_CLK_375KHZ:
PDMClk = 375000;
break;
case AM_HAL_PDM_CLK_187KHZ:
PDMClk = 187000;
break;
default:
PDMClk = 0;
}
//
// Record the effective sample frequency. We'll need it later to print the
// loudest frequency from the sample.
//
sampleFreq = (PDMClk / (MClkDiv * 2 * myPDM.getDecimationRate()));
frequencyUnits = (float)sampleFreq / (float)pdmDataBufferSize;
Serial.printf("Settings:\n");
Serial.printf("PDM Clock (Hz): %12d\n", PDMClk);
Serial.printf("Decimation Rate: %12d\n", myPDM.getDecimationRate());
Serial.printf("Effective Sample Freq.: %12d\n", sampleFreq);
Serial.printf("FFT Length: %12d\n\n", pdmDataBufferSize);
Serial.printf("FFT Resolution: %15.3f Hz\n", frequencyUnits);
}
Conclusion
In this lab, I was accustomed to the Arduino IDE and how to upload programs onto the Artemis board. I also learned how to access On-board components like the Analog Pin, Microphone and the LED. I also learned how to troubleshoot simple problems and debug some code for the Artemis.