ESP32 with I2C OLED dropping commands

grunnels@gmail.com
Posts: 9
Joined: Wed Mar 16, 2022 7:20 pm

ESP32 with I2C OLED dropping commands

Postby grunnels@gmail.com » Thu Mar 17, 2022 9:15 pm

Hello. I have an ESP-WROOM-32 dev kit with an I2C OLED and one button connected to it. I'm trying to control the display from Core 1. I have a software timer setup to turn the display off after a few seconds. It works once, then it will not turn the display off again after the first time. If I put some code in the button routine to turn the display on and off, it works fine. I've noticed that with the button, the routines are executed on Core 1. With the software timer the routines are executed on core 0. How can I have the software timer execute on Core 1? I've attached some code that recreates my issue. Thanks.
  1. #include "SSD1306Wire.h"
  2.  
  3. #define BUTTON1_PIN      2
  4. #define I2C_SDA         21
  5. #define I2C_SCL         22
  6.  
  7. SSD1306Wire display(0x3c, I2C_SDA, I2C_SCL);
  8.  
  9.  
  10. static const unsigned long BUTTON_INTERVAL = 25;
  11. static const unsigned long DISPLAY_INTERVAL = 2500;
  12. static const unsigned long DISPLAY_ON_INTERVAL = 5000;
  13. static const TickType_t dimDelay = DISPLAY_ON_INTERVAL / portTICK_PERIOD_MS;
  14. static TimerHandle_t displayOffTimer = NULL;
  15.  
  16.  
  17. long button1Timer = 0;
  18. long longPressTime = 1250;
  19.  
  20. boolean button1Active = false;
  21. boolean longPressActive = false;
  22.  
  23. void setup() {
  24.   Serial.begin(38400);
  25.   Serial.println("Starting");
  26.   pinMode(BUTTON1_PIN, INPUT_PULLUP);
  27.   display.init();
  28.  
  29.   // Clear the buffer
  30.   Serial.println("Clearing display");
  31.   display.clear();
  32.  
  33.   display.setTextAlignment(TEXT_ALIGN_LEFT);
  34.   display.setFont(ArialMT_Plain_16);
  35.   display.drawString(0, 0, "Starting");
  36.   display.drawString(0, 16, "Screen");
  37.   display.drawString(0, 32, "Test");
  38.   display.display();
  39.   delay(2000);
  40.  
  41.   xTaskCreatePinnedToCore(
  42.     checkButtonValue,  // Function to be called
  43.     "checkButtonValue",   // Name of task
  44.     1024,
  45.     NULL,         // Parameter to pass to function
  46.     5,            // Task priority (0 to configMAX_PRIORITIES - 1)
  47.     NULL,         // Task handle
  48.     1);     // Run on one core
  49.  
  50.   //  // Create a one-shot timer
  51.   //  displayOffTimer = xTimerCreate(
  52.   //                      "displayOff",     // Name of timer
  53.   //                      dimDelay,            // Period of timer (in ticks)
  54.   //                      pdFALSE,              // Auto-reload
  55.   //                      (void *)0,            // Timer ID
  56.   //                      autoDimmerCallback);  // Callback function
  57.  
  58.   xTaskCreatePinnedToCore(
  59.     checkOnDisplay,  // Function to be called
  60.     "updateDisplay",   // Name of task
  61.     4096,
  62.     NULL,         // Parameter to pass to function
  63.     2,            // Task priority (0 to configMAX_PRIORITIES - 1)
  64.     NULL,         // Task handle
  65.     1);     // Run on one core
  66.  
  67.   vTaskDelete(NULL);
  68.   delay(1000);
  69.   Serial.println("Set up complete");
  70. }
  71.  
  72. void checkOnDisplay(void *parameter) {
  73.   Serial.print("checkOnDisplay running on core ");
  74.   Serial.println(xPortGetCoreID());
  75.   // Create a one-shot timer
  76.   displayOffTimer = xTimerCreate(
  77.                       "displayOff",     // Name of timer
  78.                       dimDelay,            // Period of timer (in ticks)
  79.                       pdFALSE,              // Auto-reload
  80.                       (void *)0,            // Timer ID
  81.                       autoDimmerCallback);  // Callback function
  82.  
  83.   xTimerStart(displayOffTimer, portMAX_DELAY);
  84.   while (1) {
  85.     vTaskDelay(DISPLAY_INTERVAL / portTICK_PERIOD_MS);
  86.     //    updateDisplayLogic();
  87.   }
  88. }
  89.  
  90. // Turn off display when timer expires
  91. void autoDimmerCallback(TimerHandle_t xTimer) {
  92.   Serial.println("display timer expired");
  93.   turnDisplayOff();
  94. }
  95.  
  96. void turnDisplayOff() {
  97.   Serial.print("Turn display off. Core ");
  98.   int codeID = xPortGetCoreID();
  99.   Serial.println(codeID);
  100.   display.displayOff();
  101. }
  102.  
  103. void turnDisplayOn() {
  104.   Serial.print("Turn display on. Core ");
  105.   int codeID = xPortGetCoreID();
  106.   Serial.println(codeID);
  107.   display.displayOn();
  108.   xTimerStart(displayOffTimer, portMAX_DELAY);
  109. }
  110.  
  111. void checkButtonValue(void *parameter) {
  112.   while (1) {
  113.     checkTheButton1();
  114.     vTaskDelay(BUTTON_INTERVAL / portTICK_PERIOD_MS);
  115.   }
  116. }
  117.  
  118. void checkTheButton1() {
  119.   if (digitalRead(BUTTON1_PIN) == LOW) {
  120.     if (button1Active == false) {
  121.       button1Active = true;
  122.       button1Timer = millis();
  123.     }
  124.     if ((millis() - button1Timer > longPressTime) && (longPressActive == false)) {   // long press action
  125.       longPressActive = true;
  126.       button1LongFunction();
  127.     }
  128.   } else {
  129.     if (button1Active == true) {
  130.       if (longPressActive == true) {
  131.         longPressActive = false;
  132.       } else {
  133.         button1ShortFunction();  // short press action
  134.       }
  135.     }
  136.     button1Active = false;
  137.   }
  138. }
  139.  
  140. void button1ShortFunction() {
  141.   Serial.println("short press");
  142.   turnDisplayOn();
  143. }
  144.  
  145. void button1LongFunction() {
  146.   Serial.println("long press");
  147.   turnDisplayOff();
  148. }
  149.  
  150. void loop() {
  151.  
  152.  
  153. }

grunnels@gmail.com
Posts: 9
Joined: Wed Mar 16, 2022 7:20 pm

Re: ESP32 with I2C OLED dropping commands

Postby grunnels@gmail.com » Wed Mar 23, 2022 12:52 am

I noticed that if I slow the I2C bus to 100kHz, everything works fine. Is there something about I2C that is tied to a core and has to have time to shift over to a different core? Not sure why this would be an issue when using both cores, but not an issue when using only one core.

Who is online

Users browsing this forum: No registered users and 70 guests