I am developing a quite complex application involving TCP networking and parallel ADC sampling. This code is going through quite some commands and has many functions, but please focus only on app main. The idea is that at first ESP32 goes through some UDP broadcasting - IP recognition (with server) handshake algorithm, then establishes the TCP connection and starts to constantly sample GPIO states (the ESP32 reads whole GPIO state registers and sends that information via TCP to the server. Testing showed, that this is the fastest way to sample - read raw 32 bit register with ESP32, send it to server, and perform the processing on the server side. The server then extract the 12 bits that correspond to the pins connected to the ADC, and with a help of bitwise operations builds the corresponding decimal number, this mathematical algorithm is tested and I had it working in some earlier versions of my code) The networking part is well tested, it works fine. Interrupt works as well, no problem with that. I hope the idea is clear until here...
My problem is that ESP is constantly reading 0 on all pins (all 12 which I am interested in). But I have verified with both multimeter and oscilloscope, that my ADC is working, and 1s and 0s are indeed reaching the ESP pins in 3.3V logic states. The pin configuration is defined in app main function, so I guess it is the only relevant part in this code. I have been debugging for days now, but I can not solve the issue. Any ideas? Thank you in advance.
Code: Select all
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "freertos/timers.h"
#include "soc/soc.h"
#include "soc/gpio_struct.h"
#include "soc/gpio_reg.h"
#include "esp32/rom/ets_sys.h"
#include "soc/rtc.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "protocol_examples_common.h"
#include "esp_transport.h"
#include "esp_transport_tcp.h"
#include "esp_transport_socks_proxy.h"
#include <sys/time.h>
#include <errno.h>
#include <arpa/inet.h>
#include <math.h>
#include "ethernet_init.h"
#include "sdkconfig.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include <netinet/in.h>
#define BROADCAST_PORT 5000
#define MESSAGE "Scintilator"
#define MAX_MESSAGE_LEN 128
#ifdef CONFIG_EXAMPLE_ENABLE_PROXY
#define PROXY_ADDR CONFIG_EXAMPLE_PROXY_ADDR
#define PROXY_PORT CONFIG_EXAMPLE_PROXY_PORT
#endif
#define MAX_RETRY_COUNT 5
#define MAX_POLL_TIMEOUT_ERRORS 5
#define INTERRUPT_INPUT 15
#define GPIO_CLOCK 14
#define NUM_GPIO_PINS 12
#define NUM_CYCLES 64
#define GPIO_PIN_12 12
#define GPIO_PIN_13 13
#define GPIO_PIN_2 2
#define GPIO_PIN_4 4
#define GPIO_PIN_16 16
#define GPIO_PIN_17 17
#define GPIO_PIN_32 32
#define GPIO_PIN_33 33
#define GPIO_PIN_34 34
#define GPIO_PIN_35 35
#define GPIO_PIN_36 36
#define GPIO_PIN_39 39
#define MAX_BROADCAST_ADDR_LEN 16
uint64_t get_time_us() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
}
static const char *TAG = "tcp_transport_client";
esp_transport_handle_t transport = NULL;
static bool is_connected = false;
static int unsuccessful_retries = 0;
static int consecutive_poll_timeout_errors = 0;
static bool received_from_server = false;
char global_broadcast_address_str[MAX_BROADCAST_ADDR_LEN];
bool trigger = false;
bool protocol_transition = false;
uint32_t data_array[NUM_CYCLES] = {0};
static const gpio_num_t GPIO_PINS[NUM_GPIO_PINS] = {
GPIO_PIN_12, GPIO_PIN_13, GPIO_PIN_2, GPIO_PIN_4,
GPIO_PIN_16, GPIO_PIN_17, GPIO_PIN_32, GPIO_PIN_33,
GPIO_PIN_34, GPIO_PIN_35, GPIO_PIN_36, GPIO_PIN_39
};
TaskHandle_t tcpTaskHandle;
SemaphoreHandle_t tcpMutex;
SemaphoreHandle_t dataReceivedSemaphore;
QueueHandle_t tcpDataQueue;
TimerHandle_t timerHandle;
int counter = 0;
bool global_digit = false;
int received_integer = 0;
bool timer_started = false;
void establish_connection();
void disconnect_if_connected();
void Impulse_Count();
void close_connection();
void send_data_over_tcp(uint32_t *data_array, size_t num_elements);
void send_data_task(void *pvParameters);
void receive_data_task(void *pvParameters);
static void IRAM_ATTR gpio_interrupt_handler(void *args);
static void eth_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data){
uint8_t mac_addr[6] = {0};
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
esp_eth_ioctl(eth_handle, ETH_CMD_G_MAC_ADDR, mac_addr);
ESP_LOGI(TAG, "Ethernet Link Up");
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
vTaskDelay(100 / portTICK_PERIOD_MS);
break;
case ETHERNET_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "Ethernet Link Down");
break;
case ETHERNET_EVENT_START:
ESP_LOGI(TAG, "Ethernet Started");
break;
case ETHERNET_EVENT_STOP:
ESP_LOGI(TAG, "Ethernet Stopped");
break;
default:
break;
}
}
esp_err_t renew_eth_dhcp_lease() {
esp_netif_dhcpc_stop(esp_netif_get_handle_from_ifkey("ETH_0")); // Stop DHCP client for Ethernet interface
esp_netif_dhcpc_start(esp_netif_get_handle_from_ifkey("ETH_0")); // Start DHCP client again for Ethernet interface
return ESP_OK;
}
void udp_client_send_message(char *ip, int dest_port, char *message) {
int addr_family = AF_INET;
int ip_protocol = IPPROTO_IP;
struct sockaddr_in dest_addr;
dest_addr.sin_addr.s_addr = inet_addr(ip);
dest_addr.sin_family = AF_INET;
dest_addr.sin_port = htons(dest_port);
int sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return;
}
ESP_LOGI(TAG, "Socket created, sending to %s:%d", ip, dest_port);
int err = sendto(sock, message, strlen(message), 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
if (err < 0) {
ESP_LOGE(TAG, "Error occurred during sending: errno %d", errno);
} else {
ESP_LOGI(TAG, "Message sent: %s", message);
}
if (sock != -1) {
shutdown(sock, 0);
close(sock);
}
}
static void got_ip_event_handler(void *arg, esp_event_base_t event_base,int32_t event_id, void *event_data){
vTaskDelay(100 / portTICK_PERIOD_MS);
ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
if (!event) {
ESP_LOGE(TAG, "Event data is NULL");
printf("Could not retrieve network parameters");
return;
}
bool first_retry = false;
bool second_retry = false;
bool third_retry = false;
bool server_reception = false;
char ip[16];
char subnet_mask[16];
inet_ntoa_r(event->ip_info.ip, ip, sizeof(ip));
inet_ntoa_r(event->ip_info.netmask, subnet_mask, sizeof(subnet_mask));
struct in_addr addr;
inet_aton(ip, &addr);
struct in_addr subnet;
inet_aton(subnet_mask, &subnet);
struct in_addr network_address;
network_address.s_addr = addr.s_addr & subnet.s_addr;
struct in_addr broadcast_address;
broadcast_address.s_addr = network_address.s_addr | ~subnet.s_addr;
snprintf(global_broadcast_address_str, MAX_BROADCAST_ADDR_LEN, "%lu.%lu.%lu.%lu",
(broadcast_address.s_addr >> 24) & 0xFF,
(broadcast_address.s_addr >> 16) & 0xFF,
(broadcast_address.s_addr >> 8) & 0xFF,
broadcast_address.s_addr & 0xFF);
while((strncmp(ip, "169", 3) == 0) && !third_retry){
if (!first_retry && !second_retry && !third_retry) {
ESP_LOGW(TAG, "Obtained IP address is auto-configured (169.xxx.xxx.xxx). 5 seconds before retrying...");
vTaskDelay(5000 / portTICK_PERIOD_MS);
esp_netif_dhcpc_start(esp_netif_get_handle_from_ifkey("ETH_0"));
first_retry= true;
return;
}
if (first_retry && !second_retry && !third_retry) {
ESP_LOGW(TAG, "Obtained IP address is auto-configured (169.xxx.xxx.xxx). 10 seconds before retrying...");
vTaskDelay(10000 / portTICK_PERIOD_MS);
esp_netif_dhcpc_start(esp_netif_get_handle_from_ifkey("ETH_0"));
second_retry= true;
return;
}
if (second_retry && first_retry && !third_retry) {
ESP_LOGW(TAG, "Obtained IP address is auto-configured (169.xxx.xxx.xxx). 15 seconds before retrying...");
vTaskDelay(15000 / portTICK_PERIOD_MS);
esp_netif_dhcpc_start(esp_netif_get_handle_from_ifkey("ETH_0"));
third_retry= true;
return;
}
}
if(third_retry){
ESP_LOGE(TAG, "Failed to obtain dynamic IP address from DHCP in 3 tries, restarting...");
}
printf("Network Address: %s\n", inet_ntoa(network_address));
printf("Broadcast Address: %s\n", inet_ntoa(broadcast_address));
vTaskDelay(100 / portTICK_PERIOD_MS);
udp_client_send_message(inet_ntoa(broadcast_address),BROADCAST_PORT,MESSAGE);
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock < 0) {
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
return;
}
struct sockaddr_in client_addr;
client_addr.sin_addr.s_addr = htonl(INADDR_ANY);
client_addr.sin_family = AF_INET;
client_addr.sin_port = htons(BROADCAST_PORT);
if (bind(sock, (struct sockaddr *)&client_addr, sizeof(client_addr)) < 0) {
ESP_LOGE(TAG, "Socket bind failed: errno %d", errno);
return;
}
char rx_buffer[MAX_MESSAGE_LEN];
struct sockaddr_in source_addr;
socklen_t socklen = sizeof(source_addr);
while (!server_reception) {
int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0, (struct sockaddr *)&source_addr, &socklen);
if (len < 0) {
ESP_LOGE(TAG, "recvfrom failed: errno %d", errno);
break;
} else {
rx_buffer[len] = 0;
ESP_LOGI(TAG, "Message received: Scintilator. From %s:%d",inet_ntoa(source_addr.sin_addr), ntohs(source_addr.sin_port));
server_reception = true;
}
}
if (sock != -1) {
shutdown(sock, 0);
close(sock);
}
protocol_transition = true;
}
void timerCallback(TimerHandle_t xTimer) {
gpio_intr_disable(GPIO_NUM_15);
vTaskDelay(100 / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "Timer expired. Disconnecting from server...");
vTaskDelay(5000 / portTICK_PERIOD_MS);
close_connection();
ESP_LOGI(TAG, "Interrupt count: %d", counter);
}
void Impulse_Count(){
vTaskDelay(50 / portTICK_PERIOD_MS);
ESP_LOGI(TAG, "Impulse target was reached. Disconnecting from server...");
vTaskDelay(5000 / portTICK_PERIOD_MS);
close_connection();
ESP_LOGI(TAG, "Interrupt count: %d", counter);
}
float ntohf(float netfloat) {
union {
uint32_t n;
float f;
} tmp;
tmp.n = htonl(*(uint32_t *)&netfloat);
global_digit = (int)tmp.f & 1;
int intPart = (int)tmp.f;
float fracPart = tmp.f - intPart;
if (intPart != 0) {
intPart >>= 1;
} else {
fracPart /= 2.0;
}
tmp.f = intPart + fracPart;
return tmp.f;
}
void establish_connection() {
if (transport == NULL) {
ESP_LOGE(TAG, "Error: TCP transport not initialized");
return;
}
const int connection_timings[MAX_RETRY_COUNT] = {1, 1, 1, 2, 3, 3, 5, 5, 5, 0};
for (int i = 0; i < MAX_RETRY_COUNT; i++) {
if (!is_connected) {
vTaskDelay(connection_timings[i] * 1000 / portTICK_PERIOD_MS);
int err = esp_transport_connect(transport, global_broadcast_address_str, BROADCAST_PORT, 30000);
ESP_LOGI(TAG, "Connected successfully");
is_connected = true;
break;
} else {
ESP_LOGE(TAG, "Connection failed: errno %d", errno);
}
}
}
void disconnect_if_connected() {
if (is_connected) {
int err = esp_transport_close(transport);
if (err == 0) {
ESP_LOGI(TAG, "Closed the connection successfully");
} else {
ESP_LOGE(TAG, "Error closing the connection: errno %d", errno);
}
is_connected = false;
}
}
void close_connection() {
disconnect_if_connected();
}
void send_data_over_tcp(uint32_t *data_array, size_t num_elements) {
if (transport == NULL) {
ESP_LOGE(TAG, "Error: TCP transport not initialized");
return;
}
if (!is_connected || !received_from_server) {
ESP_LOGE(TAG, "Error: Not connected to server or message not received from server");
return;
}
size_t total_bytes_sent = 0;
size_t remaining_elements = num_elements;
uint8_t *data_ptr = (uint8_t *)data_array;
int retry_count = 0;
bool retry_exceeded = false;
while (remaining_elements > 0 && !retry_exceeded) {
int bytes_written = esp_transport_write(transport, (char *)data_ptr, sizeof(uint32_t) * remaining_elements, 0);
if (bytes_written < 0) {
int error_code = errno;
ESP_LOGE(TAG, "Error occurred during sending: esp_transport_write() returned %d, errno %d", bytes_written, error_code);
if (error_code == ECONNRESET) {
ESP_LOGE(TAG, "Connection reset by peer. Attempting to reconnect...");
is_connected = false;
esp_transport_close(transport);
} else {
ESP_LOGE(TAG, "Unhandled error. Closing the transport.");
esp_transport_close(transport);
}
consecutive_poll_timeout_errors++;
vTaskDelay(1000 / portTICK_PERIOD_MS);
continue;
}
if (bytes_written == 0) {
ESP_LOGW(TAG, "Zero bytes written to TCP. Retrying...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
retry_count++;
if (retry_count >= MAX_RETRY_COUNT) {
ESP_LOGE(TAG, "Maximum retry count exceeded. Disconnecting...");
disconnect_if_connected();
retry_exceeded = true;
}
continue;
}
remaining_elements -= bytes_written / sizeof(uint32_t);
data_ptr += bytes_written;
total_bytes_sent += bytes_written;
consecutive_poll_timeout_errors = 0;
ESP_LOGI(TAG, "Sent %d bytes over TCP", bytes_written);
if(global_digit && (received_integer == counter)){
Impulse_Count();
}
counter++;
}
}
void receive_data_task(void *pvParameters) {
char recv_buffer[256];
int recv_len;
while (1) {
if (is_connected) {
recv_len = esp_transport_read(transport, recv_buffer, sizeof(recv_buffer), 0);
if (recv_len > 0) {
float received_float;
memcpy(&received_float, recv_buffer, sizeof(float));
received_float = ntohf(received_float);
received_from_server = true;
if(!global_digit){
ESP_LOGI(TAG, "Received measurement time from server: %.3f s", received_float);
uint32_t seconds = (uint32_t)received_float;
float fraction = received_float - seconds;
uint32_t microseconds = fraction * 1000000;
if (!timer_started) {
if (timerHandle != NULL) {
xTimerDelete(timerHandle, 0);
}
timerHandle = xTimerCreate("Timer", pdMS_TO_TICKS(seconds * 1000 + microseconds / 1000), pdFALSE, NULL, timerCallback);
if (timerHandle != NULL) {
xTimerStart(timerHandle, 0);
timer_started = true;
}
}
}
else {
received_integer = (int)received_float;
ESP_LOGI(TAG, "Received impulse target from server: %d ", received_integer);
}
xSemaphoreGive(dataReceivedSemaphore);
}
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
void send_data_task(void *pvParameters) {
uint32_t received_data[NUM_CYCLES];
int retry_delay = 1000;
while (1) {
if (xSemaphoreTake(tcpMutex, portMAX_DELAY)) {
if (xQueueReceive(tcpDataQueue, received_data, portMAX_DELAY)) {
int retries = 0;
int retry_delay = 0;
while (retries < 5) {
send_data_over_tcp(received_data, NUM_CYCLES);
if (is_connected) {
retry_delay = 0;
break;
} else {
vTaskDelay(retry_delay / portTICK_PERIOD_MS);
retries++;
if (retries == 1) {
retry_delay = 2000;
} else if (retries == 2) {
retry_delay = 3000;
} else if (retries == 3) {
retry_delay = 5000;
} else if (retries == 4) {
retry_delay = 8000;
}
}
}
if (retries == 5) {
ESP_LOGE(TAG, "Failed to send data after 5 retries. Performing a software reset...");
ESP_LOGW(TAG, "Intentional reset triggered by software (esp_restart())");
esp_restart();
}
} else {
if (is_connected) {
ESP_LOGI(TAG, "Connection lost. Attempting to reconnect...");
esp_transport_close(transport);
is_connected = false;
}
}
xSemaphoreGive(tcpMutex);
}
}
}
static void IRAM_ATTR gpio_interrupt_handler(void *args) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
uint32_t local_data_array[NUM_CYCLES];
for (int i = 0; i < NUM_CYCLES; ++i) {
local_data_array[i] = data_array[i];
}
xQueueSendFromISR(tcpDataQueue, local_data_array, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken == pdTRUE) {
portYIELD_FROM_ISR();
}
}
void app_main() {
vTaskDelay(500 / portTICK_PERIOD_MS);
esp_log_level_set("transport", ESP_LOG_INFO);
esp_log_level_set("transport_base", ESP_LOG_INFO);
esp_log_level_set("transport_proxy", ESP_LOG_INFO);
uint8_t eth_port_cnt = 0;
esp_eth_handle_t *eth_handles;
ESP_ERROR_CHECK(example_eth_init(ð_handles, ð_port_cnt));
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
if (eth_port_cnt == 1) {
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
esp_netif_t *eth_netif = esp_netif_new(&cfg);
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0])));
} else {
esp_netif_inherent_config_t esp_netif_config = ESP_NETIF_INHERENT_DEFAULT_ETH();
esp_netif_config_t cfg_spi = {
.base = &esp_netif_config,
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH
};
char if_key_str[10];
char if_desc_str[10];
char num_str[3];
for (int i = 0; i < eth_port_cnt; i++) {
itoa(i, num_str, 10);
strcat(strcpy(if_key_str, "ETH_"), num_str);
strcat(strcpy(if_desc_str, "eth"), num_str);
esp_netif_config.if_key = if_key_str;
esp_netif_config.if_desc = if_desc_str;
esp_netif_config.route_prio -= i*5;
esp_netif_t *eth_netif = esp_netif_new(&cfg_spi);
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[i])));
}
}
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, ð_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &got_ip_event_handler, NULL));
for (int i = 0; i < eth_port_cnt; i++) {
ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
}
while(!protocol_transition){
vTaskDelay(100 / portTICK_PERIOD_MS);
}
//printf("End");
ESP_ERROR_CHECK(nvs_flash_init());
//ESP_ERROR_CHECK(esp_netif_init());
//ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(example_connect());
transport = esp_transport_tcp_init();
establish_connection();
#ifdef CONFIG_EXAMPLE_ENABLE_PROXY
esp_transport_handle_t parent = transport;
esp_transport_socks_proxy_config_t proxy_config = {.port = PROXY_PORT, .address = PROXY_ADDR, .version = SOCKS4};
transport = esp_transport_socks_proxy_init(parent, &proxy_config);
#endif
dataReceivedSemaphore = xSemaphoreCreateBinary();
xTaskCreatePinnedToCore(receive_data_task, "TCP_Task", 8192, NULL, 3, &tcpTaskHandle, APP_CPU_NUM); // Increased priority
if (xSemaphoreTake(dataReceivedSemaphore, portMAX_DELAY) == pdTRUE) {
tcpDataQueue = xQueueCreate(1, sizeof(data_array));
xTaskCreatePinnedToCore(send_data_task, "TCP_Task", 8192, NULL, 4, &tcpTaskHandle, APP_CPU_NUM); // Increased priority
tcpMutex = xSemaphoreCreateMutex();
gpio_config_t io_conf_output = {
.pin_bit_mask = (1ULL << GPIO_CLOCK),
.mode = GPIO_MODE_OUTPUT,
};
gpio_config(&io_conf_output);
gpio_config_t io_conf;
for (int i = 0; i < NUM_GPIO_PINS; ++i) {
io_conf = (gpio_config_t){
.pin_bit_mask = (1ULL << GPIO_PINS[i]),
.mode = GPIO_MODE_INPUT,
.intr_type = GPIO_INTR_DISABLE,
.pull_up_en = GPIO_PULLUP_DISABLE,
.pull_down_en = GPIO_PULLDOWN_ENABLE,
};
gpio_config(&io_conf);
}
esp_rom_gpio_pad_select_gpio(INTERRUPT_INPUT);
gpio_set_direction(INTERRUPT_INPUT, GPIO_MODE_INPUT);
gpio_pulldown_en(INTERRUPT_INPUT);
gpio_pullup_dis(INTERRUPT_INPUT);
gpio_set_intr_type(INTERRUPT_INPUT, GPIO_INTR_NEGEDGE);
gpio_install_isr_service(0);
gpio_isr_handler_add(INTERRUPT_INPUT, gpio_interrupt_handler, (void *)INTERRUPT_INPUT);
if(global_digit){
counter = 0;
}
}
uint8_t k = 0;
while (1) {
REG_WRITE(GPIO_OUT_W1TS_REG, (1 << GPIO_CLOCK));
data_array[k] = REG_READ(GPIO_IN_REG);
data_array[k + 1] = REG_READ(GPIO_IN1_REG);
k = (k + 2) % NUM_CYCLES;
REG_WRITE(GPIO_OUT_W1TC_REG, (1 << GPIO_CLOCK));
}
close_connection();
#ifdef CONFIG_EXAMPLE_ENABLE_PROXY
esp_transport_destroy(parent);
#endif
}