ESP32 with I2C OLED dropping commands

grunnels@gmail.com
Posts: 10
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.

Code: Untitled.cpp Select all


#include "SSD1306Wire.h"

#define BUTTON1_PIN 2
#define I2C_SDA 21
#define I2C_SCL 22

SSD1306Wire display(0x3c, I2C_SDA, I2C_SCL);


static const unsigned long BUTTON_INTERVAL = 25;
static const unsigned long DISPLAY_INTERVAL = 2500;
static const unsigned long DISPLAY_ON_INTERVAL = 5000;
static const TickType_t dimDelay = DISPLAY_ON_INTERVAL / portTICK_PERIOD_MS;
static TimerHandle_t displayOffTimer = NULL;


long button1Timer = 0;
long longPressTime = 1250;

boolean button1Active = false;
boolean longPressActive = false;

void setup() {
Serial.begin(38400);
Serial.println("Starting");
pinMode(BUTTON1_PIN, INPUT_PULLUP);
display.init();

// Clear the buffer
Serial.println("Clearing display");
display.clear();

display.setTextAlignment(TEXT_ALIGN_LEFT);
display.setFont(ArialMT_Plain_16);
display.drawString(0, 0, "Starting");
display.drawString(0, 16, "Screen");
display.drawString(0, 32, "Test");
display.display();
delay(2000);

xTaskCreatePinnedToCore(
checkButtonValue, // Function to be called
"checkButtonValue", // Name of task
1024,
NULL, // Parameter to pass to function
5, // Task priority (0 to configMAX_PRIORITIES - 1)
NULL, // Task handle
1); // Run on one core

// // Create a one-shot timer
// displayOffTimer = xTimerCreate(
// "displayOff", // Name of timer
// dimDelay, // Period of timer (in ticks)
// pdFALSE, // Auto-reload
// (void *)0, // Timer ID
// autoDimmerCallback); // Callback function

xTaskCreatePinnedToCore(
checkOnDisplay, // Function to be called
"updateDisplay", // Name of task
4096,
NULL, // Parameter to pass to function
2, // Task priority (0 to configMAX_PRIORITIES - 1)
NULL, // Task handle
1); // Run on one core

vTaskDelete(NULL);
delay(1000);
Serial.println("Set up complete");
}

void checkOnDisplay(void *parameter) {
Serial.print("checkOnDisplay running on core ");
Serial.println(xPortGetCoreID());
// Create a one-shot timer
displayOffTimer = xTimerCreate(
"displayOff", // Name of timer
dimDelay, // Period of timer (in ticks)
pdFALSE, // Auto-reload
(void *)0, // Timer ID
autoDimmerCallback); // Callback function

xTimerStart(displayOffTimer, portMAX_DELAY);
while (1) {
vTaskDelay(DISPLAY_INTERVAL / portTICK_PERIOD_MS);
// updateDisplayLogic();
}
}

// Turn off display when timer expires
void autoDimmerCallback(TimerHandle_t xTimer) {
Serial.println("display timer expired");
turnDisplayOff();
}

void turnDisplayOff() {
Serial.print("Turn display off. Core ");
int codeID = xPortGetCoreID();
Serial.println(codeID);
display.displayOff();
}

void turnDisplayOn() {
Serial.print("Turn display on. Core ");
int codeID = xPortGetCoreID();
Serial.println(codeID);
display.displayOn();
xTimerStart(displayOffTimer, portMAX_DELAY);
}

void checkButtonValue(void *parameter) {
while (1) {
checkTheButton1();
vTaskDelay(BUTTON_INTERVAL / portTICK_PERIOD_MS);
}
}

void checkTheButton1() {
if (digitalRead(BUTTON1_PIN) == LOW) {
if (button1Active == false) {
button1Active = true;
button1Timer = millis();
}
if ((millis() - button1Timer > longPressTime) && (longPressActive == false)) { // long press action
longPressActive = true;
button1LongFunction();
}
} else {
if (button1Active == true) {
if (longPressActive == true) {
longPressActive = false;
} else {
button1ShortFunction(); // short press action
}
}
button1Active = false;
}
}

void button1ShortFunction() {
Serial.println("short press");
turnDisplayOn();
}

void button1LongFunction() {
Serial.println("long press");
turnDisplayOff();
}

void loop() {


}

grunnels@gmail.com
Posts: 10
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: Bing [Bot] and 3 guests