diff --git a/README.md b/README.md index 3b6da95..a7ab387 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ The goal of this project is to make a LED matrix/sign for displaying messages in ### Implementation: -The ESP32 will be responsible for sending data to the LED matrix using RMT or SPI depending on which one works best with many LEDs. It will also act as a TCP-server and receive the text you want to display in the window from the RPi. Connect to the RPi via ssh and run *insert file name here* with the text. +The ESP32 will be responsible for sending data to the LED matrix using RMT or SPI depending on which one works best with many LEDs. It will also act as a TCP-server and receive the text you want to display in the window from the RPi. Connect to the RPi via ssh and run `python3 send_text.py "xxx"` to display "xxx" on the LED Matrix. ## Dimensions @@ -13,7 +13,7 @@ The plan is to make it 12 LEDs in height and about 100 LEDs in length, which rou ## Code -Python running on the RPi and C code using the Espress-if build system on the ESP32. +Python running on the RPi and C using the Espress-if build system on the ESP32. ## TODO diff --git a/esp32/main/app_main.c b/esp32/main/app_main.c index ab7337d..fbc7f46 100644 --- a/esp32/main/app_main.c +++ b/esp32/main/app_main.c @@ -10,44 +10,43 @@ static const char *TAG = "LED Matrix"; -led_strip_handle_t configure_led(void) { +led_strip_handle_t setup_led_strip(bool use_spi, uint32_t number_of_leds, int gpio_pin) { - led_strip_config_t strip_config = { - .strip_gpio_num = LED_STRIP_GPIO, - .max_leds = LED_STRIP_LED_NUMBER, + led_strip_config_t led_strip_config = { + .strip_gpio_num = gpio_pin, + .max_leds = number_of_leds, .led_pixel_format = LED_PIXEL_FORMAT_GRB, .led_model = LED_MODEL_WS2812, .flags.invert_out = false, }; - #if LED_STRIP_USE_SPI + led_strip_handle_t led_strip; + + if (use_spi) { led_strip_spi_config_t spi_config = { - .clk_src = SOC_MOD_CLK_APB, // different clock source can lead to different power consumption, - // from clk_tree_defs SPI_CLK_SRC_DEFAULT is set to SOC_MOD_CLK_APB + .clk_src = SPI_CLK_APB, // different clock source can lead to different power consumption .flags.with_dma = true, // Using DMA can improve performance and help drive more LEDs .spi_bus = SPI2_HOST, // SPI bus ID }; - - led_strip_handle_t led_strip; - ESP_ERROR_CHECK(led_strip_new_spi_device(&strip_config, &spi_config, &led_strip)); - ESP_LOGI(TAG, "Created LED strip object with SPI backend"); - #else + ESP_ERROR_CHECK(led_strip_new_spi_device(&led_strip_config, &spi_config, &led_strip)); + ESP_LOGI(TAG, "Created LED strip object using SPI"); + + } else { led_strip_rmt_config_t rmt_config = { #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) .rmt_channel = 0, #else .clk_src = RMT_CLK_SRC_DEFAULT, // different clock source can lead to different power consumption - .resolution_hz = CONFIG_ESP_LED_STRIP_RMT_RES_HZ, // RMT counter clock frequency + .resolution_hz = 10000000, // RMT counter clock frequency: 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) .flags.with_dma = false, // DMA feature is available on ESP target like ESP32-S3 #endif }; - led_strip_handle_t led_strip; - ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip)); - ESP_LOGI(TAG, "Created LED strip object with RMT backend"); - #endif + ESP_ERROR_CHECK(led_strip_new_rmt_device(&led_strip_config, &rmt_config, &led_strip)); + ESP_LOGI(TAG, "Created LED strip object using RMT"); + } return led_strip; } @@ -55,36 +54,30 @@ led_strip_handle_t configure_led(void) { void app_main(void) { start_server(); - // start_client(); - - // led_strip_handle_t led_strip = configure_led(); - // bool led_on_off = false; - - // ESP_LOGI(TAG, "Start blinking LED strip"); - // while (1) { - // if (led_on_off) { - // // uint8_t pattern[CONFIG_ESP_LED_STRIP_LED_NUMBER] = { - // // 0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1, - // // }; - // // Map the pattern to the LED strip - // for (int i = 0; i < CONFIG_ESP_LED_STRIP_LED_NUMBER; i++) { - // ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, 255 : 0, pattern[i] ? 255 : 0, pattern[i] ? 255 : 0)); - // } - - // /* Refresh the strip to send data */ - // ESP_ERROR_CHECK(led_strip_refresh(led_strip)); - // ESP_LOGI(TAG, "LED ON!"); - // } else { - // /* Set all LED off to clear all pixels */ - // ESP_ERROR_CHECK(led_strip_clear(led_strip)); - // ESP_LOGI(TAG, "LED OFF!"); - // } - // led_on_off = !led_on_off; - // vTaskDelay(pdMS_TO_TICKS(500)); - // } + bool use_spi = true; + uint32_t number_of_leds = 40; + int gpio_pin = 13; + + led_strip_handle_t led_strip = setup_led_strip(use_spi, number_of_leds, gpio_pin); + bool is_led_on = false; + + while (1) { + if (is_led_on) { + for (int i = 0; i < number_of_leds; i++) { + ESP_ERROR_CHECK(led_strip_set_pixel(led_strip, i, 255, 255, 255)); + } + + /* Refresh the strip to send data */ + ESP_ERROR_CHECK(led_strip_refresh(led_strip)); + ESP_LOGI(TAG, "LED ON!"); + } else { + /* Set all LED off to clear all pixels */ + ESP_ERROR_CHECK(led_strip_clear(led_strip)); + ESP_LOGI(TAG, "LED OFF!"); + } + is_led_on = !is_led_on; + vTaskDelay(pdMS_TO_TICKS(500)); + } } - - - diff --git a/esp32/main/led_matrix_config.h b/esp32/main/led_matrix_config.h index eda0823..fc8e6e4 100644 --- a/esp32/main/led_matrix_config.h +++ b/esp32/main/led_matrix_config.h @@ -1,20 +1,10 @@ #ifndef LED_MATRIX_CONFIG_H #define LED_MATRIX_CONFIG_H -#define LED_STRIP_USE_SPI 1 -#define LED_STRIP_USE_RMT 0 -#define LED_STRIP_GPIO 13 -#define LED_STRIP_LED_NUMBER 40 -#define LED_STRIP_RMT_RES_HZ 10000000 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) #define WIFI_SSID "myssid" #define WIFI_PASSWORD "mypassword" -#define WIFI_MAXIMUM_RETRY 5 // avoid station reconnecting to the AP unlimited when the AP is really inexistent. -#define WIFI_IPV4_ADDR "000.000.0.000" // esp_client will connect to this address. #define WIFI_IPV4_PORT 3333 -#define TCP_KEEPALIVE_IDLE 5 // Keep-alive idle time. In idle time without receiving any data from peer, will send keep-alive probe packet -#define TCP_KEEPALIVE_INTERVAL 5 // Keep-alive probe packet interval time. -#define TCP_KEEPALIVE_COUNT 3 // Keep-alive probe packet retry count. -#define WIFI_CONNECTED_BIT 0x00000001 -#define WIFI_FAIL_BIT 0x00000002 +#define WIFI_CONNECTED_BIT 0x00000001 +#define WIFI_FAIL_BIT 0x00000002 #endif \ No newline at end of file diff --git a/esp32/main/tcp_client.c b/esp32/main/tcp_client.c index 798e1e4..aae4690 100644 --- a/esp32/main/tcp_client.c +++ b/esp32/main/tcp_client.c @@ -95,7 +95,7 @@ void wifi_init_sta() { void tcp_client(void) { char rx_buffer[128]; - char host_ip[] = WIFI_IPV4_ADDR; + char host_ip[] = "000.000.0.000"; int addr_family = 0; int ip_protocol = 0; diff --git a/esp32/main/tcp_server.c b/esp32/main/tcp_server.c index 39f864e..c376748 100644 --- a/esp32/main/tcp_server.c +++ b/esp32/main/tcp_server.c @@ -59,7 +59,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - if (s_retry_num < WIFI_MAXIMUM_RETRY) { + if (s_retry_num < 5) { // avoid station reconnecting to the AP unlimited times when the AP is inexistent esp_wifi_connect(); s_retry_num++; ESP_LOGI(TAG, "retry to connect to the AP"); @@ -145,9 +145,9 @@ static void tcp_server_task(void *pvParameters) { int addr_family = (int)pvParameters; int ip_protocol = 0; int keepAlive = 1; - int keepIdle = TCP_KEEPALIVE_IDLE; - int keepInterval = TCP_KEEPALIVE_INTERVAL; - int keepCount = TCP_KEEPALIVE_COUNT; + int keepIdle = 5; // Keep-alive idle time. In idle time without receiving any data from peer, will send keep-alive probe packet + int keepInterval = 5; // Keep-alive probe packet interval time + int keepCount = 3; // Keep-alive probe packet retry count. struct sockaddr_storage dest_addr; diff --git a/rpi/send_text.py b/rpi/send_text.py index b6ea1cb..d95144a 100644 --- a/rpi/send_text.py +++ b/rpi/send_text.py @@ -1,17 +1,27 @@ import socket import sys +from pixelFont import Text, Font -def send_to_esp32(text): +def send_to_esp32(): + if len(sys.argv) < 2: + print("No text given to the program! (It's required)\nExample usage: python3 send_text.py \"Gratis kaffe\"") + print("Exiting...") + return + + # set up pixelmaps from image for the text + text = Text(sys.argv[1], Font.readFromImage('./font3.png')) + host = "ESP_IP_ADDRESS" port = 3333 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.connect((host, port)) - s.sendall(str.encode(text)) + s.sendall((text.get_pixelmap())) print(f"Sent {text} to LED matrix") response = s.recv(1024) print(f"Received {response.decode('utf-8')} back from LED matrix") if __name__ == "__main__": - # example usage: python3 send_text.py "GRATIS KAFFE" - send_to_esp32(sys.argv[1]) # sys.argv[1] is now GRATIS KAFFE \ No newline at end of file + send_to_esp32() + + \ No newline at end of file