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();
}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