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:
- #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();
- }
I can't get a stable frequency while wifi module is working. 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