Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

Triangular Example

This example demonstrates how to use a Lookup Table (LUT) to generate a triangular waveform.

Prerequisites

Before running this example, ensure you have:

  • An ESP32 development board.
  • ESP-IDF development environment set up (version 5.4 or later).
  • Familiarity with the ESP-IDF DAC Continuous Signal Generator Example.
  • An oscilloscope to visualize the waveform output.

Usage

  1. Clone the repository:

    git clone https://github.com/tinyalg/waveu.git
  2. Change to this directory:

    cd waveu/examples/triangular

    Alternatively, open this directory in VSCode with the ESP-IDF extension for easier navigation and editing.

  3. Run menuconfig:

    In VSCode, open the ESP-IDF Terminal.

    idf.py menuconfig

    In menuconfig, configure the following settings under [Component config > Waveu Configuration]:

    • Select active DAC channels:
      • CH0 and CH1: Output to both channels.
      • CH0 only: Output to DAC Channel 0.
      • CH1 only: Output to DAC Channel 1.
  4. Flash the example:

    idf.py build flash
  5. Monitor the output:

    idf.py monitor

    You should observe messages in the console confirming the start of waveform generation.

    I (292) Waveu-ESP32Config: waveformDataOutputTask to on core 0 at priority 10.
    I (292) Waveu: LEN_DATA_BUFFER=16000, SAMPLE_RATE=1000000, TIMER_PERIOD=16000
    I (292) Waveu: Started waveformDataGenerationTask on core 1 at priority 5.
    I (302) UserWaveConfig: Frequency set to 293.66Hz
    
  6. Connect your oscilloscope: Attach the oscilloscope to the DAC output channel as configured in menuconfig.

Example Breakdown

1. Define the Triangular Function

The triangular function generates LUT values. It calculates values based on the current phase, amplitude, and offset:

virtual lut_type_t fill_function_triangular(LUTSize size, size_t index, float amplitude, float offset) {
   ...

   // Generate the triangular value
   float triangular_value = (phase < 0.5)
      ? (2 * phase)                    // Rising edge
      : (2 * (1 - phase));             // Falling edge

   // Scale and shift to amplitude and offset
   return static_cast<lut_type_t>((2 * triangular_value - 1) * amplitude + offset + 0.5);
}

2. Override initialize() Method

The initialize() method sets up the PhaseGenerator and LUT index calculation.

2.1 Initialize the Phase Generator

Set the sample rate and create the phase generator.

initializePhaseGenerator(sampleRate);

2.2 Retrieve the LUT Index Function

Retrieve a function to map the current phase to an LUT index.

_getIndex = LUTHelper::getIndexFunction(_lutSize);

3. Override configure() Method

The configure() method prepares waveform generation.

3.1 Set the Frequency

Set the desired frequency and calculate the phase increment.

setPhaseGeneratorFrequency(waveArgs.frequency);

3.2 Adjust Amplitude and Offset

Ensure the amplitude and offset values are valid for the DAC.

auto [adjustedAmplitude, adjustedOffset] 
    = LUTHelper::adjustAmplitudeAndOffset(waveArgs.amplitude, waveArgs.offset);

3.3 Populate the LUT

Fill the LUT using the triangular function.

populateLUTs(adjustedAmplitude, adjustedOffset);

4. Override nextSample() Method

The nextSample() method generates waveform samples dynamically.

4.1 Update the Phase

Advance the phase to the next position.

_phaseGenerator->updatePhase();

4.2 Retrieve the Current Phase

Get the current phase value from the phase generator.

uint32_t currentPhase = _phaseGenerator->getPhase();

4.3 Map to LUT Index

Calculate the corresponding LUT index.

int lutIndex = _getIndex(currentPhase, PhaseGenerator::N_BITS);

4.4 Generate Voltage Value

Convert the phase or LUT index to a voltage value.

lut_type_t digi_val = GET_LUT_VALUE(_lut, lutIndex);

4.5 Return the Voltage

Return the voltage value for output.

return (uint8_t)digi_val;

Notes

  • Configure the DAC output channel via menuconfig.
  • Adjust frequency, amplitude, and offset in the app_main() function to match your testing requirements.
  • This example demonstrates using an LUT for waveform generation and is ideal for learning signal generation techniques.