From samples domain to time domain

Hi everyone, still having a problem with my timegrapher. The first issue was to implement the fft and I did it with Matlab, and it was ok. On the attached file, you can see the signal (samples[n]) coming from the mic to the Serial plotter. On the Y-axis we have the output in millivolt and the X-axis the samples. Now I want to serial.print a graph with magnitude in dB on the Y-axis and time in second or millisecond on the X-axis. Can someone please tell how to proceed ?
Thanks in advance

#include <SPI.h>    
#define SS 5   

int16_t* samples;
uint32_t n = 0;
int count = 0;
unsigned long start_time;
unsigned long end_time;
const unsigned long event = 10000;
const uint32_t max_samples=50000;

void setup() {
  Serial.begin(115200);                     /* initialization of serial communication */
  SPI.begin();                            /* initialization of SPI port */
  SPI.setDataMode(SPI_MODE0);             /* configuration of SPI communication in mode 0 */
  SPI.setClockDivider(SPI_CLOCK_DIV64);   /* configuration of clock at 1MHz */
  pinMode(SS, OUTPUT);
  Serial.println("Start");
  
  samples = (int16_t*)malloc(sizeof(int16_t)*max_samples);
  if(samples == NULL){
      Serial.print("insufficient memory");
    }
    else{
      Serial.print("malloc ok.");   
    }
}

void loop() {
  start_time = millis();
  for (n=0; n<max_samples; n++)
  {
    samples[n] = Sound();
  }
  end_time = millis();
  Serial.print("Dauer [ms]: ");
  Serial.print((end_time-start_time));
  Serial.print(" ||| ");
  Serial.print("Beats: ");
  Serial.print(n);
  Serial.println(" ||| ");
  for (n = 0; n < max_samples; n++)
  {
    Serial.print(samples[n]);
    //Serial.print(",-32768,32767");
    Serial.println();
  }
}


int16_t Sound(void) {
  digitalWrite(SS, LOW);                                        //activate chip select
  int sound = SPI.transfer(0) | (SPI.transfer(0) << 8);         //reconstruct 12-bit data
  digitalWrite(SS, HIGH);                                       //deactivate chip select
  return sound;
}

Are the 'samples' taken at a known rate? If so, they are already in the time domain. Divide the sample number by the sample rate (samples per second) to get the sample time.

50000 samples in 4431 milliseconde, so 112841,3451 samples / sec

Hi Johnwasser, this is what i did with the for loop

samples is in int16_t* , end_time in unsigned long

int16_t* samples;
unsigned long end_time;

for (n=0; n<max_samples; n++)
  {
    int16_t sampleR = samples[n]/ end_time;      
    int16_t sampleT = samples[n]/sampleR;       
    Serial.println(sampleT);
  }

this is the error I've

Guru Meditation Error: Core  1 panic'ed (IntegerDivideByZero). Exception was unhandled.
Core 1 register dump:
PC      : 0x400d0d27  PS      : 0x00060530  A0      : 0x800d1c48  A1      : 0x3ffb1f90  
A2      : 0x3ffbfe80  A3      : 0x3ffbfe78  A4      : 0x0000c34f  A5      : 0x80000020  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0x00000000  A9      : 0x3ffc1070  
A10     : 0x3ffbfeec  A11     : 0x00000808  A12     : 0x0000000a  A13     : 0x000000ff  
A14     : 0x000000ff  A15     : 0x00000000  SAR     : 0x0000000a  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

ELF file SHA256: 0000000000000000

Backtrace: 0x400d0d27:0x3ffb1f90 0x400d1c45:0x3ffb1fb0 0x40086155:0x3ffb1fd0

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

how can I handle it ?

The result of this operation for sampleR is often zero, as expected for integer division. So sampleT is undefined.

int16_t sampleR = samples[n]/ end_time;

It is not possible to label the x axis on the Arduino serial plotter.

1 Like

I don't want to label the axis, I just want to have the time value on the x-axis and the magnitude in dB on the y-axis.
It can't be zero because samples[n] goes till 50000 and end_time = 4431 millisec

You are mistaken. Print out some values of sampleR.

What does the following sentence mean?

I just want to have the time value on the x-axis

1 Like

If I've time on x axis and magnitude on y axis the output should be like on the picture

Typically means an array has exceeded its bounds. The ESP Exception decoder installed into the Arduino IDE would give more info.

The thing is that Serial.prints are really, really slow.

An ESP32 will do SPI a lot faster than 1MHZ. If you really want speed out of SPI then don't use the Arduino ESP32 core to access the ESP32's SPI module. Instead use the ESP32' SPI API, works under the Arduino IDE really well.

SPI Master Driver - ESP32 - — ESP-IDF Programming Guide latest documentation (espressif.com)

some code I've used, using the ESP32's SPI API.
The .h

#include <driver/spi_master.h>
#include "sdkconfig.h"
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
////////////////////////////////////
//
//#define MAGTYPE  true
//#define XGTYPE   false
//////////////////////////
///////////////////////////
//
////////////////////////////
 uint8_t GetLowBits();
 int8_t GetHighBits();
 int fReadSPIdata16bits( spi_device_handle_t &h, int address );
 int fWriteSPIdata8bits( spi_device_handle_t &h, int address, int sendData );
 int fInitializeSPI_Devices( spi_device_handle_t &h, int csPin);
// spi_device_handle_t fInitializeSPI_Devices( int csPin);
int fInitializeSPI_Channel( int spiCLK, int spiMOSI, int spiMISO, spi_host_device_t SPI_Host, bool EnableDMA);

the .cpp

#include <driver/spi_master.h>
#include "sdkconfig.h"
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
////////////////////////////////////
//
//#define MAGTYPE  true
//#define XGTYPE   false
//////////////////////////
///////////////////////////
//
////////////////////////////
 uint8_t GetLowBits();
 int8_t GetHighBits();
 int fReadSPIdata16bits( spi_device_handle_t &h, int address );
 int fWriteSPIdata8bits( spi_device_handle_t &h, int address, int sendData );
 int fInitializeSPI_Devices( spi_device_handle_t &h, int csPin);
// spi_device_handle_t fInitializeSPI_Devices( int csPin);
int fInitializeSPI_Channel( int spiCLK, int spiMOSI, int spiMISO, spi_host_device_t SPI_Host, bool EnableDMA);

Be aware that

the ESP32 has 3 memory stacks. One memory stack for each core and a shared memory stack and that malloc is not aware of the memory stacks. malloc is, generally, safe to use on an ESP32 using, as you are, only a single core of the ESP32's dual cores. The ESP32's API shows the memory allocation wrappers for macros that they wrote for malloc that is aware.

For better Analog to Digital results use the ESP32's A:D API over the ESP32's Arduino core.

For when I am not using WiFi, splitting the operations of functions amongst the cores results in faster performance.

The Serial Plotter only shows 500 samples. To fit your 50,000 input samples into 500 output samples you will need to group them into sets of 100.

To get an output that looks like that you will need to alternate between the maximum value for a set of 100 samples and the minimum value for a set of 100 samples.

The serial plotter cannot do it. You want a different program, like Matlab, or Python. Transforming the sample number to time is a labelling problem.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.