Announcement

Collapse
No announcement yet.

Announcement

Collapse
No announcement yet.

STM to ESP

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Originally posted by ivconic View Post
    Is there a special reason for I2S?
    no

    Comment


    • #17
      Lose I2S first.
      Task:
      4 channels PWM (2 sine + 2 square) on GPIO 14, 15, 16, 17


      Code:
      #include <Arduino.h>
      
      #define PWM_FREQ_CARRIER 20000  // 20 kHz PWM carrier frequency for sine waves
      #define PWM_RESOLUTION 8        // 8-bit resolution
      
      #define SINE_SAMPLES 50
      #define TWO_PI 6.28318530718
      
      // GPIO pins for 4 PWM channels
      const int pwmPins[4] = {14, 15, 16, 17};
      
      // PWM channels for ESP32 LEDC (0-15)
      const int pwmChannels[4] = {0, 1, 2, 3};
      
      // Sine wave sample buffers (8-bit duty cycles)
      uint8_t sineWave1[SINE_SAMPLES];
      uint8_t sineWave2[SINE_SAMPLES];
      
      float phase1 = 0;
      float phase2 = 0;
      float phaseStep1 = TWO_PI / SINE_SAMPLES;   // Adjust to set sine frequency
      float phaseStep2 = TWO_PI / SINE_SAMPLES;
      
      void setup() {
        Serial.begin(115200);
      
        // Generate sine wave lookup tables (duty cycles)
        for (int i = 0; i < SINE_SAMPLES; i++) {
          sineWave1[i] = 128 + 127 * sin(phaseStep1 * i); // 0..255 PWM duty
          sineWave2[i] = 128 + 127 * sin(phaseStep2 * i);
        }
      
        // Setup PWM channels for all pins
        for (int ch = 0; ch < 4; ch++) {
          ledcSetup(pwmChannels[ch], PWM_FREQ_CARRIER, PWM_RESOLUTION);
          ledcAttachPin(pwmPins[ch], pwmChannels[ch]);
        }
      }
      
      void loop() {
        // Advance sine wave phases for channels 1 and 2
        static int index1 = 0;
        static int index2 = 0;
      
        // Update PWM duty for sine wave channels
        ledcWrite(pwmChannels[0], sineWave1[index1]);  // PWM channel 0, GPIO14
        ledcWrite(pwmChannels[1], sineWave2[index2]);  // PWM channel 1, GPIO15
      
        // Square wave channels: 50% duty cycle PWM at desired freq
        // We simulate square wave frequencies by toggling duty cycle on slower time scale
      
        static unsigned long lastToggleTimeCh2 = 0;
        static unsigned long lastToggleTimeCh3 = 0;
        static bool squareStateCh2 = false;
        static bool squareStateCh3 = false;
      
        unsigned long now = millis();
      
        // Square wave channel 3 (GPIO16) toggle every 10 ms (50 Hz)
        if (now - lastToggleTimeCh2 >= 10) {
          squareStateCh2 = !squareStateCh2;
          ledcWrite(pwmChannels[2], squareStateCh2 ? 128 : 0); // 50% or 0% duty cycle
          lastToggleTimeCh2 = now;
        }
      
        // Square wave channel 4 (GPIO17) toggle every 5 ms (100 Hz)
        if (now - lastToggleTimeCh3 >= 5) {
          squareStateCh3 = !squareStateCh3;
          ledcWrite(pwmChannels[3], squareStateCh3 ? 128 : 0);
          lastToggleTimeCh3 = now;
        }
      
        // Advance sine wave sample index (control sine frequency here)
        index1 = (index1 + 1) % SINE_SAMPLES;
        index2 = (index2 + 1) % SINE_SAMPLES;
      
        delay(1); // small delay to control sine wave frequency (adjust as needed)
      }
      ​

      Comment


      • #18
        Channels 0 & 1 (GPIO14 & GPIO15): PWM at 20 kHz carrier frequency with duty cycles modulated by sine wave lookup table.
        Output needs low-pass RC filter to sound like sine wave analog output. RC low-pass filter (e.g., 10k resistor + 0.1uF capacitor)
        Channels 2 & 3 (GPIO16 & GPIO17): Software toggling the duty cycle between 50% and 0% to create square waves of 50 Hz and 100 Hz frequencies approx.
        PWM carrier frequency is still 20 kHz but the duty is toggled slowly for square wave frequency.

        Comment


        • #19
          post #17 3rror
          HTML Code:
          C:\Users\Galinka\Documents\Arduino\4_channels_ivconic\4_channels_ivconic.ino: In function 'void setup()':
          4_channels_ivconic:35:5: error: 'ledcSetup' was not declared in this scope
             35 |     ledcSetup(pwmChannels[ch], PWM_FREQ_CARRIER, PWM_RESOLUTION);
                |     ^~~~~~~~~
          4_channels_ivconic:36:5: error: 'ledcAttachPin' was not declared in this scope; did you mean 'ledcAttach'?
             36 |     ledcAttachPin(pwmPins[ch], pwmChannels[ch]);
                |     ^~~~~~~~~~~~~
                |     ledcAttach
          C:\Users\Galinka\Documents\Arduino\4_channels_ivconic\4_channels_ivconic.ino: At global scope:
          4_channels_ivconic:79:1: error: '​' does not name a type
             79 | ​
                |  
          exit status 1
          'ledcSetup' was not declared in this scope​

          Comment


          • #20
            Missing include of the correct ESP32 LEDC driver library or Arduino core headers,
            Typo or invisible characters in the code (like a zero-width space or non-printable character),
            Or compiling the code with the wrong board selected (like a non-ESP32 board).

            Comment


            • #21
              Make sure you have selected ESP32 board in Arduino IDE
              Go to Tools > Board > ESP32 Arduino > Your ESP32 board
              If you don’t have ESP32 support installed, follow this guide: https://docs.espressif.com/projects/...nstalling.html
              Include the right headers at the top of your sketch
              cpp
              #include <Arduino.h>
              You probably already have it since ledcSetup and ledcAttachPin are part of the ESP32 Arduino core API.
              But they do NOT need a separate include, just make sure your board is ESP32.
              Remove invisible characters or trailing weird characters at the end of your file
              Open your .ino in a text editor that can show hidden characters (e.g., VSCode, Notepad++) and remove any strange symbols.
              ***

              If this minimal example fails to compile, you are either compiling for the wrong board or your ESP32 Arduino core installation is broken.
              Minimal example that compiles on ESP32 (copy-paste as a test).




              Code:
              #include <Arduino.h>
              
              const int pwmPin = 14;
              const int pwmChannel = 0;
              const int freq = 5000;
              const int resolution = 8;
              
              void setup() {
                ledcSetup(pwmChannel, freq, resolution);
                ledcAttachPin(pwmPin, pwmChannel);
                ledcWrite(pwmChannel, 128);
              }
              
              void loop() {
                // do nothing
              }
              ​

              Comment


              • #22
                I almost did it, not sure yet about synchronization

                HTML Code:
                #include "driver/i2s.h"
                //https://esp32.com/viewtopic.php?p=144590&hilit=sin#p144590
                #include "driver/i2s.h"
                ////////////////////////
                #include <driver/ledc.h>
                ////////////////////////
                #define SAMPLE_RATE 400000
                //#define WAVEFORM_SAMPLES 256            //3kHz
                //#define WAVEFORM_SAMPLES 100            // 8kHz
                #define WAVEFORM_SAMPLES 50               //16 kHz
                
                uint8_t stereo_buffer[WAVEFORM_SAMPLES * 2];
                uint8_t wave_data1[WAVEFORM_SAMPLES];
                uint8_t wave_data2[WAVEFORM_SAMPLES];
                ///////////////////
                //const float amp = 127.5; // Half of the max value (255/2)
                const float amp = 60;
                const float stp = 0.1;  // Step size for the sine wave
                float i = 0;
                ///////////////////
                void generateWaveforms() {
                  for (int i = 0; i < WAVEFORM_SAMPLES; i++) {
                   wave_data1[i] = (uint8_t)((255 * i) / WAVEFORM_SAMPLES);
                    wave_data2[i] = (uint8_t)(127.5 * (1 + sin(2 * 3.14159 * i / WAVEFORM_SAMPLES)));
                     //wave_data1[i] = (uint8_t)(amp + amp * sin(stp * i));
                     //   wave_data2[i] = (uint8_t)(amp + amp * sin(stp * i));
                   // int dutyCycle = (int)(amp + amp * sin(stp * i)); // Calculate the duty cycle
                  }
                  for (int i = 0; i < WAVEFORM_SAMPLES; i++) {
                    stereo_buffer[i * 2] = wave_data1[i];      // DAC1
                    stereo_buffer[i * 2 + 1] = wave_data2[i];  // DAC2
                  }
                }
                
                void setup() {
                  Serial.begin(115200);
                  //////////////////////
                ledc_timer_config_t timerConfig = {
                        .speed_mode = LEDC_LOW_SPEED_MODE,
                        .duty_resolution = LEDC_TIMER_10_BIT,
                        .timer_num = LEDC_TIMER_0,
                        .freq_hz = 16000,
                        .clk_cfg = LEDC_AUTO_CLK
                    };
                    ledc_timer_config(&timerConfig);
                
                    
                    ledc_channel_config_t channelConfig1 = {
                        .gpio_num = 12,
                        .speed_mode = LEDC_LOW_SPEED_MODE,
                        .channel = LEDC_CHANNEL_0,
                        .timer_sel = LEDC_TIMER_0,
                        .duty = 512,
                        .hpoint = 0
                    };
                    ledc_channel_config(&channelConfig1);
                
                  
                    ledc_channel_config_t channelConfig2 = {
                        .gpio_num = 14,
                        .speed_mode = LEDC_LOW_SPEED_MODE,
                        .channel = LEDC_CHANNEL_1,
                        .timer_sel = LEDC_TIMER_0,
                        .duty = 512,
                        .hpoint = 0 // 0 deg
                    };
                    ledc_channel_config(&channelConfig2);
                  /////////////////////////
                  generateWaveforms();
                
                  i2s_config_t i2s_config = {
                    .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN),
                    .sample_rate = SAMPLE_RATE,
                    .bits_per_sample = I2S_BITS_PER_SAMPLE_8BIT,
                    .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
                    .communication_format = I2S_COMM_FORMAT_I2S_MSB,
                    .intr_alloc_flags = 0,
                    .dma_buf_count = 8,
                    .dma_buf_len = WAVEFORM_SAMPLES * 2,
                    .use_apll = false,
                  };
                
                  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
                  i2s_set_pin(I2S_NUM_0, NULL);
                  i2s_set_dac_mode(I2S_DAC_CHANNEL_BOTH_EN);
                  i2s_set_sample_rates(I2S_NUM_0, i2s_config.sample_rate);
                }
                
                void loop() {
                  size_t bytes_written;
                  i2s_write(I2S_NUM_0, stereo_buffer, sizeof(stereo_buffer), &bytes_written, portMAX_DELAY);
                }​
                }​

                Comment


                • #23
                  https://youtube.com/shorts/tV-HiK4J3...9tBhpZR-UGUoQM

                  Comment


                  • #24
                    Originally posted by ivconic View Post
                    Make sure you have selected ESP32 board in Arduino IDE
                    Go to Tools > Board > ESP32 Arduino > Your ESP32 board
                    If you don’t have ESP32 support installed, follow this guide: https://docs.espressif.com/projects/...nstalling.html
                    Include the right headers at the top of your sketch
                    cpp
                    #include <Arduino.h>
                    You probably already have it since ledcSetup and ledcAttachPin are part of the ESP32 Arduino core API.
                    But they do NOT need a separate include, just make sure your board is ESP32.
                    Remove invisible characters or trailing weird characters at the end of your file
                    Open your .ino in a text editor that can show hidden characters (e.g., VSCode, Notepad++) and remove any strange symbols.
                    ***

                    If this minimal example fails to compile, you are either compiling for the wrong board or your ESP32 Arduino core installation is broken.
                    Minimal example that compiles on ESP32 (copy-paste as a test).




                    Code:
                    #include <Arduino.h>
                    
                    const int pwmPin = 14;
                    const int pwmChannel = 0;
                    const int freq = 5000;
                    const int resolution = 8;
                    
                    void setup() {
                    ledcSetup(pwmChannel, freq, resolution);
                    ledcAttachPin(pwmPin, pwmChannel);
                    ledcWrite(pwmChannel, 128);
                    }
                    
                    void loop() {
                    // do nothing
                    }
                    ​error the same
                    Click image for larger version

Name:	image.png
Views:	57
Size:	46.8 KB
ID:	438583

                    Comment


                    • #25
                      Pick one generic for staters.
                      Idea is to test your setup for now.

                      Comment


                      • #26
                        Migration from 2.x to 3.0


                        https://docs.espressif.com/projects/..._3.0.html#ledc
                        Click image for larger version  Name:	image.png Views:	0 Size:	69.5 KB ID:	438586

                        Comment


                        • #27
                          Oh right!
                          I have the older settings set for the ESP32S model that I use in my devices.
                          Experience has taught me; once you get the environment working properly: don't touch it again!
                          ...
                          Open Arduino IDE → Tools → Board → Boards Manager.
                          Search for ESP32.
                          Make sure you're using ESP32 core v3.0.0 or newer.
                          ...
                          Minimal working example (new API, ESP32 Arduino 3.x), just to test your environment:



                          Code:
                          #include <Arduino.h>
                          #include <math.h>
                          
                          #define PWM_PIN 25
                          #define SAMPLES 130
                          
                          int val1[SAMPLES];
                          int amp = 40;
                          float stp = 6.2831 / SAMPLES;
                          volatile int sample_index = 0;
                          
                          hw_timer_t *timer = NULL;
                          
                          void IRAM_ATTR onTimer() {
                            ledcWrite(PWM_PIN, val1[sample_index]);
                            sample_index = (sample_index + 1) % SAMPLES;
                          }
                          
                          void init_wave() {
                            for (int i = 0; i < SAMPLES; i++) {
                              val1[i] = 40 + amp * sin(stp * i);  // values from 0 to 80
                            }
                          }
                          
                          void setup() {
                            init_wave();
                          
                            // NEW: uses pin, frequency, resolution (bits)
                            ledcAttach(PWM_PIN, 20000, 8);  // 20kHz, 8-bit resolution
                          
                            timer = timerBegin(0, 80, true);         // 1 MHz clock (80 MHz / 80)
                            timerAttachInterrupt(timer, onTimer);    // no 3rd param in new API
                            timerAlarmWrite(timer, 50, true);        // 50 µs interval
                            timerAlarmEnable(timer);
                          }
                          
                          void loop() {
                            // Everything handled in interrupt
                          }

                          Comment


                          • #28
                            Now it should compile fine:

                            Code:
                            #include <Arduino.h>
                            #include <math.h>
                            
                            #define SAMPLES 130
                            #define PWM_PIN 25  // zamenjuje PB7
                            #define PWM_FREQ 20000  // 20kHz PWM nosilac
                            #define TIMER_US 50     // Tajmer interrupt svakih 50 μs
                            
                            int val1[SAMPLES];
                            int amp = 40;
                            float stp = 6.2831 / SAMPLES;
                            volatile int sample_index = 0;
                            
                            hw_timer_t *timer = NULL;
                            
                            void IRAM_ATTR onTimer() {
                              // imitira DMA slanje jedne vrednosti
                              ledcWrite(PWM_PIN, val1[sample_index]);
                              sample_index = (sample_index + 1) % SAMPLES;
                            }
                            
                            void init_wave() {
                              for (int i = 0; i < SAMPLES; i++) {
                                val1[i] = 40 + amp * sin(stp * i);  // duty od 0 do 80 (8-bit LEDC)
                              }
                            }
                            
                            void setup() {
                              init_wave();
                            
                              // Novi LEDC API: automatski dodeljuje kanal, koristi pin
                              ledcAttach(PWM_PIN, PWM_FREQ, 8);  // 8-bit rezolucija, 20kHz
                            
                              // Timer 0, clock = 80 MHz / 80 = 1 MHz → 1 tick = 1μs
                              timer = timerBegin(0, 80, true);
                              timerAttachInterrupt(timer, &onTimer);
                              timerAlarmWrite(timer, TIMER_US, true);
                              timerAlarmEnable(timer);
                            }
                            
                            void loop() {
                              //  
                            }
                            ​

                            Comment


                            • #29
                              post # 28, error
                              HTML Code:
                              iv_test:35:21: error: too many arguments to function 'hw_timer_t* timerBegin(uint32_t)'
                                 35 |   timer = timerBegin(0, 80, true);
                                    |           ~~~~~~~~~~^~~~~~~~~~~~~
                              In file included from C:\Users\Galinka\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.3\cores\esp32/esp32-hal.h:98,
                                               from C:\Users\Galinka\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.3\cores\esp32/Arduino.h:45,
                                               from C:\Users\Galinka\Documents\Arduino\iv_test\iv_test.ino:1:
                              C:\Users\Galinka\AppData\Local\Arduino15\packages\esp32\hardware\esp32\3.1.3\cores\esp32/esp32-hal-timer.h:35:13: note: declared here
                                 35 | hw_timer_t *timerBegin(uint32_t frequency);
                                    |             ^~~~~~~~~~
                              iv_test:37:3: error: 'timerAlarmWrite' was not declared in this scope; did you mean 'timerWrite'?
                                 37 |   timerAlarmWrite(timer, TIMER_US, true);
                                    |   ^~~~~~~~~~~~~~~
                                    |   timerWrite
                              iv_test:38:3: error: 'timerAlarmEnable' was not declared in this scope; did you mean 'timerAlarm'?
                                 38 |   timerAlarmEnable(timer);
                                    |   ^~~~~~~~~~~~~~~~
                                    |   timerAlarm
                              C:\Users\Galinka\Documents\Arduino\iv_test\iv_test.ino: At global scope:
                              iv_test:44:1: error: '​' does not name a type
                                 44 | ​
                                    |  
                              exit status 1
                              too many arguments to function 'hw_timer_t* timerBegin(uint32_t)'​

                              Comment


                              • #30
                                The errors occur because the ESP32 Arduino core has changed its timer API.
                                Has any simple example worked for you so far?
                                It seems to me that you have set up the environment completely wrong.

                                Comment

                                Working...
                                X