ESP32 Dev Kit C LEDC jitter while WIFI

steven84009
Posts: 1
Joined: Mon Jul 11, 2022 9:55 am

ESP32 Dev Kit C LEDC jitter while WIFI

Postby steven84009 » Mon Jul 11, 2022 10:37 am

Hello everyone,
in my project i create a wifi and a socket. Clients then can connect to the wifi and transmit frequency numbers. The server has to assign the clients to a ledc channel and create a signal based on the frequency of the send data. This frequency is adjusted every 2ms. So i more use the ledc module as a FM instead of an PWM generator.

I'm using Eclipse IDE for programming, here is my code:

Code: Untitled.cpp Select all

#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_wpa2.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_netif.h"


#include <sys/param.h>
#include "protocol_examples_common.h"
#include "addr_from_stdin.h"
#include "lwip/err.h"
#include "lwip/sockets.h"


#include <stdio.h>
#include "string.h"
#include "esp_attr.h"
#include "soc/rtc.h"
#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"
#include "esp_intr_alloc.h"

#include "driver/timer.h"
#include "hal/mcpwm_types.h"
#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"

#include "driver/ledc.h"
#include "driver/mcpwm.h"
#include "driver/rmt.h"

#define PORT 4827
#define HOST_IP_ADDR "192.168.43.124"
#define KEEPALIVE_IDLE 5
#define KEEPALIVE_INTERVAL 5
#define KEEPALIVE_COUNT 3

#define GPIO_MCPWM0A 16

static const char *TAG = "example";

/* FreeRTOS event group to signal when we are connected & ready to make a request */
static EventGroupHandle_t wifi_event_group;

/* esp netif object representing the WIFI station */

/* The event group allows multiple bits for each event,
but we only care about one event - are we connected
to the AP with an IP? */
//static esp_netif_t *ap_netif = NULL;

const int CONNECTED_BIT = BIT0;

typedef struct {
int timer_group;
int timer_idx;
int alarm_interval;
bool auto_reload;
} example_timer_info_t;

typedef struct {
uint32_t frequency;
int channel;
}rx_data;



#define led_duty 1
#define led_speep_mode LEDC_HIGH_SPEED_MODE
#define led_intr_type LEDC_INTR_DISABLE
#define led_timer_clk_cfg LEDC_USE_REF_TICK
#define led_timer_duty_resolution LEDC_TIMER_1_BIT
#define led_timer_freq_hz 60000
#define led_timer_speed_mode LEDC_HIGH_SPEED_MODE

#define led_out0 16
#define led_out1 17
#define led_out2 18
#define led_out3 19

typedef struct {
ledc_channel_config_t led_config;
ledc_timer_config_t led_timer_config;
uint8_t mac[6];
xQueueHandle f_buffer;
uint8_t socket;
int freq_default;
} channel;

channel channel_default = {.led_config = {.speed_mode = led_speep_mode, .intr_type = led_intr_type, .duty = led_duty},
.led_timer_config = {.speed_mode = led_timer_speed_mode, .duty_resolution = led_timer_duty_resolution,
.freq_hz = led_timer_freq_hz, .clk_cfg = led_timer_clk_cfg},
.socket = 0,
.freq_default = 60000};
typedef struct{
channel channel[4];
uint8_t num;
}channel_list;

channel_list list;

xQueueHandle incoming_mac;

static void tcp_server_task();

static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{

if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_START) {
xTaskCreate(tcp_server_task, "tcp_server_task", 4096, NULL, 5, NULL);
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STADISCONNECTED) {
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
xQueueSendToFront(incoming_mac, &event->mac, 0);
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d, is this working?!?!?!", MAC2STR(event->mac), event->aid);
}
}


static void init_channels(){
int i =0;
while(i<4){
list.channel[i]=channel_default;
list.channel[i].led_config.gpio_num = led_out0 + i;
list.channel[i].led_config.channel = i;
list.channel[i].led_config.timer_sel = 3;
list.channel[i].led_timer_config.timer_num = 3;
list.channel[i].led_timer_config.freq_hz = 60000+10000*i;
list.channel[i].f_buffer = xQueueCreate(2500, sizeof(rx_data));
int j =0;
while(j<6){
list.channel[i].mac[j] = 0;
j++;
}
i++;
}

list.num=0;
}

static int check_mac(uint8_t *mac_to_check, uint8_t *mac){
int j=0;
int result =0;
while(*mac+j == *mac_to_check+j && j<6){
j++;
}
if(j==6)
return 1;
else if(j==0){
while (mac[j]==0 && j<6){
j++;
}
if(j==6)
result = 2;
else
result = 0;
}
else
result = 0;
return result;
}

static void cpyMac(uint8_t *mac, uint8_t *mac_change){
int i=0;
while(i<6){
mac[i] = mac_change[i];
i++;
}
}

static void start_dhcp_server(){

// initialize the tcp stack
tcpip_adapter_init();
// stop DHCP server
ESP_ERROR_CHECK(tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP));
// assign a static IP to the network interface
tcpip_adapter_ip_info_t info;
memset(&info, 0, sizeof(info));
IP4_ADDR(&info.ip, 192, 168, 43, 124);
IP4_ADDR(&info.gw, 192, 168, 43, 124);//ESP acts as router, so gw addr will be its own addr
IP4_ADDR(&info.netmask, 255, 255, 255, 0);
ESP_ERROR_CHECK(tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_AP, &info));
// start the DHCP server
ESP_ERROR_CHECK(tcpip_adapter_dhcps_start(TCPIP_ADAPTER_IF_AP));
printf("DHCP server started \n");
}


static void initialise_wifi(void *arg)
{

#ifdef CONFIG_EXAMPLE_EAP_METHOD_TLS
unsigned int client_crt_bytes = client_crt_end - client_crt_start;
unsigned int client_key_bytes = client_key_end - client_key_start;
#endif /* CONFIG_EXAMPLE_EAP_METHOD_TLS */

ESP_ERROR_CHECK(esp_netif_init());
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_create_default());
/*ap_netif = esp_netif_create_default_wifi_ap();
assert(ap_netif);*/

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();

ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
ESP_ERROR_CHECK( esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL) );
//ESP_ERROR_CHECK( esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL) );
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );

wifi_config_t wifi_config = {
.ap = {
.ssid = "wpa2_test",
.password = "123456789",
.authmode = WIFI_AUTH_WPA_WPA2_PSK,
.max_connection = 16,
},
};

ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.ap.ssid);
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_AP) );
ESP_ERROR_CHECK( esp_wifi_set_config(WIFI_IF_AP, &wifi_config) );

ESP_ERROR_CHECK( esp_wifi_start() );
vTaskDelete(NULL);
}


static void ledc_config(channel *channel){

/*led0_config.channel = LEDC_CHANNEL_0;
led0_config.duty = 1;
led0_config.speed_mode = LEDC_HIGH_SPEED_MODE;
led0_config.gpio_num = 16;
led0_config.timer_sel = LEDC_TIMER_0;
led0_config.intr_type = LEDC_INTR_DISABLE;

led_timer0_config.timer_num = LEDC_TIMER_0;
led_timer0_config.clk_cfg = LEDC_USE_APB_CLK;
led_timer0_config.duty_resolution = LEDC_TIMER_1_BIT;
led_timer0_config.freq_hz = 100000;
led_timer0_config.speed_mode = LEDC_HIGH_SPEED_MODE;
*/
ledc_channel_config(&channel->led_config);
ledc_timer_config(&channel->led_timer_config);
ledc_set_pin(channel->led_config.gpio_num, channel->led_config.speed_mode, channel->led_config.channel);
//ledc_isr_register(isr_pwm_handler, NULL, ESP_INTR_FLAG_IRAM, NULL);
ledc_timer_set(channel->led_timer_config.speed_mode, channel->led_timer_config.timer_num, 0, channel->led_timer_config.duty_resolution, LEDC_REF_TICK);

ledc_set_freq(channel->led_config.speed_mode, channel->led_timer_config.timer_num, channel->led_timer_config.freq_hz);
}

static void mcpwm_example_config()
{
mcpwm_config_t pwm_config = {.frequency=80000, .cmpr_a=50.0, .cmpr_b=50.0, .duty_mode=MCPWM_DUTY_MODE_0 , .counter_mode=MCPWM_UP_COUNTER};

mcpwm_gpio_init(0, MCPWM0A, 16);
mcpwm_init(0, 0, &pwm_config);
mcpwm_set_frequency(0, 0, 40000);
mcpwm_set_duty(0, 0, 0, 50.0);
mcpwm_set_duty_type(0, 0, 0, 0);
mcpwm_start(0, 0);

}


static rx_data get_channel(const int sock)
{
int len;
char rx_buffer[10];
rx_data event;
event.frequency=0;
event.channel = 1;

len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
switch (rx_buffer[0]){
case 11:
event.channel = 0;
break;
case 12:
event.channel = 1;
break;
case 21:
event.channel = 2;
break;
case 22:
event.channel = 3;
break;
}

/*do {
len = recv(sock, rx_buffer, sizeof(rx_buffer) - 1, 0);
printf("number of received bytes: %i\n", len);
if (len < 0) {
ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
} else if (len == 0) {
ESP_LOGW(TAG, "Connection closed");
} else {
rx_buffer[len] = 0; // Null-terminate whatever is received and treat it like a string
int to_write = 0;
while (to_write < len) {
if(to_write == 0){
switch (rx_buffer[to_write]){
case 11:
event.channel = 0;
break;
case 12:
event.channel = 1;
break;
case 21:
event.channel = 2;
break;
case 22:
event.channel = 3;
break;
}
}
else if (i < 6){
event.frequency = (10 * event.frequency) + (int)(rx_buffer[to_write])-48;
i++;
}
else if(i >= 6){
}
to_write ++;
}
}
} while (i < 6);*/
return event;
}


static void do_receive(void *arg)
{
int channel = (int)arg;
int len;
int i = 0;
char rx_buffer[128];
rx_data event;
event.frequency=0;
event.channel = channel;
do {
len = recv(list.channel[channel].socket, rx_buffer, sizeof(rx_buffer) - 1, 0);
if (len < 0) {
ESP_LOGE(TAG, "Error occurred during receiving: errno %d", errno);
} else if (len == 0) {
ESP_LOGW(TAG, "Connection closed");
} else {
rx_buffer[len] = 0; // Null-terminate whatever is received and treat it like a string
int to_write = 0;
while (to_write < len) {
if (i < 6){
event.frequency = (10 * event.frequency) + (rx_buffer[to_write])-48;
i++;
}
else if(i >= 6){
//ESP_LOGI(TAG, "Data: %i", event.frequency);
//ESP_LOGI(TAG, "%i", mcpwm_get_frequency(0,0));
//mcpwm_set_frequency(MCPWM_UNIT_0, MCPWM0A, event.frequency);
//ledc_set_freq(list.channel[0].led_timer_config.speed_mode, list.channel[0].led_timer_config.timer_num, list.channel[0].led_timer_config.freq_hz);
xQueueSendToFront(list.channel[channel].f_buffer, &event, 0);
event.frequency = 0;
i = 0;
}
to_write ++;
}
}
} while (len > 0);
shutdown(list.channel[channel].socket, 0);
close(list.channel[channel].socket);
vTaskDelete(NULL);
}

static void tcp_server_task(void *arg)
{
char addr_str[128];
uint8_t mac_address[6];
char host_ip[] = HOST_IP_ADDR;
int addr_family = 2;
int ip_protocol = 0;
int keepAlive = 1;
int keepIdle = KEEPALIVE_IDLE;
int keepInterval = KEEPALIVE_INTERVAL;
int keepCount = KEEPALIVE_COUNT;
struct sockaddr_storage dest_addr;
rx_data connecting_channel;

vTaskDelay(1000 / portTICK_PERIOD_MS);

if (addr_family == AF_INET) {
struct sockaddr_in *dest_addr_ip4 = (struct sockaddr_in *)&dest_addr;
dest_addr_ip4->sin_addr.s_addr = inet_addr(host_ip);
dest_addr_ip4->sin_family = AF_INET;
dest_addr_ip4->sin_port = htons(PORT);
ip_protocol = IPPROTO_IP;
}

int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
if (listen_sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
vTaskDelete(NULL);
return;
}
int opt = 1;
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));


ESP_LOGI(TAG, "Socket created");

int err = bind(listen_sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err != 0) {
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
ESP_LOGE(TAG, "IPPROTO: %d", addr_family);
goto CLEAN_UP;
}
ESP_LOGI(TAG, "Socket bound, port %d", PORT);

err = listen(listen_sock, 1);
if (err != 0) {
ESP_LOGE(TAG, "Error occurred during listen: errno %d", errno);
goto CLEAN_UP;
}

while (1) {

ESP_LOGI(TAG, "Socket listening");

struct sockaddr_storage source_addr; // Large enough for both IPv4 or IPv6
socklen_t addr_len = sizeof(source_addr);
int sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
break;
}

// Set tcp keepalive option
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &keepAlive, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepIdle, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepInterval, sizeof(int));
setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT, &keepCount, sizeof(int));
// Convert ip address to string
if (source_addr.ss_family == PF_INET) {
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str, sizeof(addr_str) - 1);
}
ESP_LOGI(TAG, "Socket accepted ip address: %s", addr_str);


connecting_channel = get_channel(sock);
xQueueReceive(incoming_mac, &( mac_address ), ( TickType_t ) 10);
ESP_LOGI(TAG, "stations mac: "MACSTR"", MAC2STR(mac_address));
ESP_LOGI(TAG, "saved mac: "MACSTR"", MAC2STR(list.channel[connecting_channel.channel].mac));

int check = check_mac(&mac_address[0], &list.channel[connecting_channel.channel].mac[0]);

if(check==1){ //mac stimmt überein
ESP_LOGI(TAG, "Mac stimmt überein");
list.channel[connecting_channel.channel].socket=sock;
//xQueueSendToFront(list.channel[connecting_channel.channel].f_buffer, &connecting_channel.frequency, 0);
xTaskCreate(do_receive, "do_receive", 4096, connecting_channel.channel, 5, NULL);
}
else if (check ==2){ //noch keine mac vorhanden
ESP_LOGI(TAG, "Der Channel ist noch nicht vorhanden");
cpyMac(&list.channel[connecting_channel.channel].mac[0], &mac_address[0]);
list.channel[connecting_channel.channel].socket=sock;
//list.channel[connecting_channel.channel].led_timer_config.freq_hz = connecting_channel.frequency;
ledc_config(&list.channel[connecting_channel.channel]);
//xQueueSendToFront(list.channel[connecting_channel.channel].f_buffer, &connecting_channel.frequency, 0);
xTaskCreate(do_receive, "do_receive", 4096, connecting_channel.channel, 5, NULL);
//do_receive(&channel_list.channel[connecting_channel.channel]);
}
else{ //mac ist falsch: zugriff verweigern
shutdown(sock, 0);
close(sock);
}
}

CLEAN_UP:
close(listen_sock);
vTaskDelete(NULL);
}

static bool IRAM_ATTR timer_group_isr_callback(void *arg){
rx_data evt;
BaseType_t xTaskWokenByReceive = pdFALSE;
int i=0;
//while(i<4){
if(xQueueReceiveFromISR(list.channel[0].f_buffer, &evt, &xTaskWokenByReceive)){
if(evt.frequency>=30000 && evt.frequency<=220000){
list.channel[0].led_timer_config.freq_hz = evt.frequency;
//mcpwm_set_frequency(MCPWM_UNIT_0, MCPWM0A, evt.frequency);
//ledc_set_freq(list.channel[0].led_timer_config.speed_mode, list.channel[0].led_timer_config.timer_num, list.channel[0].led_timer_config.freq_hz);
}
}
i++;
//}
return 0;
}

static void timer_config(){
timer_config_t t0_config = {
.alarm_en = TIMER_ALARM_DIS, //enable alarm
.counter_en = TIMER_PAUSE, //counter disabled
.counter_dir = TIMER_COUNT_UP, //direction count up
.auto_reload = true, //enable auto reload on interrupt
.divider = 2}; //no divider

timer_group_t group = 0;
timer_idx_t timer = 0;

timer_init(group, timer, &t0_config);

//Timer's counter will initially start from value below.
// Also, if auto_reload is set, this value will be automatically reload on alarm
timer_set_counter_value(group, timer, 0);

// Configure the alarm value and the interrupt on alarm.
timer_set_alarm_value(group, timer, 40000);
timer_enable_intr(group, timer);
timer_set_alarm(group, timer, TIMER_ALARM_EN);

timer_isr_callback_add(group, timer, timer_group_isr_callback, NULL, 0);

timer_start(group, timer);
}

void app_main(void)
{
ESP_ERROR_CHECK( nvs_flash_init() );
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/

init_channels();
incoming_mac = xQueueCreate(1, sizeof(rx_data));
start_dhcp_server();
xTaskCreate(initialise_wifi, "initialise_wifi", 4096, NULL, 5, NULL);
timer_config();
//mcpwm_example_config();
}
Now the issues i face:
I can't get a stable frequency while wifi module is working.
U9B03.PNG
U9B03.PNG (8.36 KiB) Viewed 1167 times
U9B03.PNG
U9B03.PNG (8.36 KiB) Viewed 1167 times
U9B03.PNG
U9B03.PNG (8.36 KiB) Viewed 1167 times
When turning WIFI off and changing frequency by a counter every 2ms, there is no jitter. When there are clients connected there is more jitter than without clients connected. Since there is more jitter while communication is active, i guess there are some internal interrupts generated which delay ledc functionallity.

Has anyone else had this kind of issues with the ledc module?
I also tried mcpwm module with same outcome.
RMT module isnt working for me since my eclipse shows errors in rmt.c file

Thanks in advance
Attachments
U9B04.PNG
U9B04.PNG (8.25 KiB) Viewed 1167 times
U9B06.PNG
U9B06.PNG (8.19 KiB) Viewed 1167 times

Who is online

Users browsing this forum: Baidu [Spider] and 3 guests