Originally posted by ivconic
View Post
Announcement
Collapse
No announcement yet.
Announcement
Collapse
No announcement yet.
STM to ESP
Collapse
X
-
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
-
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
-
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
-
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
-
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
-
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
-
-
Originally posted by ivconic View PostMake 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
Comment
-
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
-
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
-
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

Comment