Test Code for (2) SparkFun Qwiic Micro OLED Breakout

Hello,

I am attempting to write a test to prove that (2) SparkFun Qwiic Micro OLED Breakout products can be run off the same board. However, I am running into an issue where it is not compiling correctly.

First, before I go into the code, resulting error message, and troubleshooting steps taken, I first want to establish the components I’m using and basic tests I’ve already performed:

Components:

  • (2) SparkFun Qwiic Micro OLED Breakout products - One (1) with an open jumper and one (1) with a closed jumper to set varying addresses

  • (1) SparkFun Thing Plus - ESP32 WROOM - Set up according to SparkFun’s Hook Up guide for this product
  • Address Change Test/Proof:

    Here is what I have done and have been able to prove so far, before my two (2) screen test:

  • Closed the jumper to ground the address pin, giving an I2C address of 0X3C, and changed the #define JUMPER from a 1 to a 0, in the MicroOLED_Demo_I2C, where one (1) screen was able to run the demo
  • After proving that the Jumper definition worked, I went to work pairing down the MicroOLED_Demo_I2C code (removed some parts of the demo) and adjusted it to what I thought would run different parts of the demo on the two (2) screens. And came up with the following code:

    Paired Down MicroOLED_Demo_I2C for two (2) Screens:

    #include <Wire.h>  // Include Wire if you're using I2C
    #include <SFE_MicroOLED.h>  // Include the SFE_MicroOLED library
    
    //////////////////////////
    // MicroOLED Definition //
    //////////////////////////
    //The library assumes a reset pin is necessary. The Qwiic OLED has RST hard-wired, so pick an arbitrary IO pin that is not being used
    #define PIN_RESET_OPEN_DEFAULT_SCREEN 9
    #define PIN_RESET_CLOSED_ADJUSTED_ADDRESS_SCREEN 10    
    
    //The DC_JUMPER is the I2C Address Select jumper. Set to 1 if the jumper is open (Default), or set to 0 if it's closed.
    #define JUMPER_OPEN_DEFAULT_SCREEN 1 
    #define JUMPER_CLOSED_ADJUSTED_ADDRESS_SCREEN 0
    
    //////////////////////////////////
    // MicroOLED Object Declaration //
    //////////////////////////////////
    MicroOLED oledDEFAULTOPEN(PIN_RESET_OPEN_DEFAULT_SCREEN, JUMPER_OPEN_DEFAULT_SCREEN);    // I2C declaration
    MicroOLED oledCLOSEDADDRESSCHANGE(PIN_RESET_CLOSED_ADJUSTED_ADDRESS_SCREEN, JUMPER_CLOSED_ADJUSTED_ADDRESS_SCREEN);    // I2C declaration
    
    
    void setup()
    {
      delay(100);
      Wire.begin();
      oledDEFAULTOPEN.begin();    // Initialize the OLED
      oledDEFAULTOPEN.clear(ALL); // Clear the display's internal memory
      oledDEFAULTOPEN.display();  // Display what's in the buffer (splashscreen)
      delay(1000);     // Delay 1000 ms
      oledDEFAULTOPEN.clear(PAGE); // Clear the buffer.
      
      randomSeed(analogRead(A0) + analogRead(A1));
    
    
      delay(100);
      Wire.begin();
      oledCLOSEDADDRESSCHANGE.begin();    // Initialize the OLED
      oledCLOSEDADDRESSCHANGE.clear(ALL); // Clear the display's internal memory
      oledCLOSEDADDRESSCHANGE.display();  // Display what's in the buffer (splashscreen)
      delay(1000);     // Delay 1000 ms
      oledCLOSEDADDRESSCHANGE.clear(PAGE); // Clear the buffer.
      
      randomSeed(analogRead(A0) + analogRead(A1));
    }
    
    
    void pixelExample()
    {
    
      
      for (int i=0; i<512; i++)
      {
        oledDEFAULTOPEN.pixel(random(oledDEFAULTOPEN.getLCDWidth()), random(oledDEFAULTOPEN.getLCDHeight()));
        oledDEFAULTOPEN.display();
      }
    }
    
    void lineExample()
    {
      int middleX = oledCLOSEDADDRESSCHANGE.getLCDWidth() / 2;
      int middleY = oledCLOSEDADDRESSCHANGE.getLCDHeight() / 2;
      int xEnd, yEnd;
      int lineWidth = min(middleX, middleY);
      
    
      
      for (int i=0; i<3; i++)
      {
        for (int deg=0; deg<360; deg+=15)
        {
          xEnd = lineWidth * cos(deg * PI / 180.0);
          yEnd = lineWidth * sin(deg * PI / 180.0);
          
          oledCLOSEDADDRESSCHANGE.line(middleX, middleY, middleX + xEnd, middleY + yEnd);
          oledCLOSEDADDRESSCHANGE.display();
          delay(10);
        }
        for (int deg=0; deg<360; deg+=15)
        {
          xEnd = lineWidth * cos(deg * PI / 180.0);
          yEnd = lineWidth * sin(deg * PI / 180.0);
          
          oledCLOSEDADDRESSCHANGE.line(middleX, middleY, middleX + xEnd, middleY + yEnd, BLACK, NORM);
          oledCLOSEDADDRESSCHANGE.display();
          delay(10);
        }
      }
    }
    

    After attempting to verify the code, I got the following error message:

    Error Message:

    C:\Users\nreis\AppData\Local\Temp\arduino_build_593296/arduino.ar(main.cpp.o):(.literal._Z8loopTaskPv+0x0): undefined reference to `loop()'
    C:\Users\nreis\AppData\Local\Temp\arduino_build_593296/arduino.ar(main.cpp.o): In function `loopTask(void*)':
    C:\Users\nreis\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.0\cores\esp32/main.cpp:15: undefined reference to `loop()'
    collect2.exe: error: ld returned 1 exit status
    exit status 1
    Error compiling for board Adafruit ESP32 Feather.
    

    Basic Troubleshooting Steps Taken:

  • Restart my computer

  • Uninstall and reinstall Arduino (running version 1.8.13)

  • Try different versions of the esp32

  • Ensured that only one pull-up resistor was connected (modified the one with the closed jumper) per SparkFun’s HookUp Guide recommendation for the SparkFun Qwiic Micro OLED
  • Conclusion:

    Honestly, at this point, I’m curious if it’s even possible to run two (2) of the SparkFun Qwiic Micro OLED Breakout products off of the same board. If anyone has any idea of how to help me solve this error or write a better test to prove that (2) of the SparkFun Qwiic Micro OLED Breakout products can be run off the same board, it would be much appreciated! Otherwise, I’m at a loss at how to proceed, so any feedback is welcome!

    this error message is because you have not defined a function loop(). Each sketch must has setup() and loop(). just add in your code.

    loop() {} 
    

    You may have other issues but this will solve the current error message.

    Of course, it ended up being something simple like that! I still need to tweak the code so that the displays are projecting the intended effect (i.e., only half of the screen is working as intended, with the other half a spattering of pixels), but it now compiles. Thank you, paulvha!

    For those that are curious, here is the updated code, which still a work in progress:

    #include <Wire.h>  // Include Wire if you're using I2C
    #include <SFE_MicroOLED.h>  // Include the SFE_MicroOLED library
    
    //////////////////////////
    // MicroOLED Definition //
    //////////////////////////
    //The library assumes a reset pin is necessary. The Qwiic OLED has RST hard-wired, so pick an arbitrary IO pin that is not being used
    #define PIN_RESET_OPEN_DEFAULT_SCREEN 9
    #define PIN_RESET_CLOSED_ADJUSTED_ADDRESS_SCREEN 10    
    
    //The DC_JUMPER is the I2C Address Select jumper. Set to 1 if the jumper is open (Default), or set to 0 if it's closed.
    #define JUMPER_OPEN_DEFAULT_SCREEN 1 
    #define JUMPER_CLOSED_ADJUSTED_ADDRESS_SCREEN 0
    
    //////////////////////////////////
    // MicroOLED Object Declaration //
    //////////////////////////////////
    MicroOLED oledDEFAULTOPEN(PIN_RESET_OPEN_DEFAULT_SCREEN, JUMPER_OPEN_DEFAULT_SCREEN);    // I2C declaration
    MicroOLED oledCLOSEDADDRESSCHANGE(PIN_RESET_CLOSED_ADJUSTED_ADDRESS_SCREEN, JUMPER_CLOSED_ADJUSTED_ADDRESS_SCREEN);    // I2C declaration
    
    
    
    void setup()
    {
      delay(100);
      Wire.begin();
      oledDEFAULTOPEN.begin();    // Initialize the OLED
      oledDEFAULTOPEN.clear(ALL); // Clear the display's internal memory
      oledDEFAULTOPEN.display();  // Display what's in the buffer (splashscreen)
      delay(1000);     // Delay 1000 ms
      oledDEFAULTOPEN.clear(PAGE); // Clear the buffer.
      
      randomSeed(analogRead(A0) + analogRead(A1));
    
    
      delay(100);
      Wire.begin();
      oledCLOSEDADDRESSCHANGE.begin();    // Initialize the OLED
      oledCLOSEDADDRESSCHANGE.clear(ALL); // Clear the display's internal memory
      oledCLOSEDADDRESSCHANGE.display();  // Display what's in the buffer (splashscreen)
      delay(1000);     // Delay 1000 ms
      oledCLOSEDADDRESSCHANGE.clear(PAGE); // Clear the buffer.
      
      randomSeed(analogRead(A0) + analogRead(A1));
    }
    
    
    void pixelExample()
    {
    
      
      for (int i=0; i<512; i++)
      {
        oledDEFAULTOPEN.pixel(random(oledDEFAULTOPEN.getLCDWidth()), random(oledDEFAULTOPEN.getLCDHeight()));
        oledDEFAULTOPEN.display();
      }
    }
    
    void lineExample()
    {
      int middleX = oledCLOSEDADDRESSCHANGE.getLCDWidth() / 2;
      int middleY = oledCLOSEDADDRESSCHANGE.getLCDHeight() / 2;
      int xEnd, yEnd;
      int lineWidth = min(middleX, middleY);
      
    
      
      for (int i=0; i<3; i++)
      {
        for (int deg=0; deg<360; deg+=15)
        {
          xEnd = lineWidth * cos(deg * PI / 180.0);
          yEnd = lineWidth * sin(deg * PI / 180.0);
          
          oledCLOSEDADDRESSCHANGE.line(middleX, middleY, middleX + xEnd, middleY + yEnd);
          oledCLOSEDADDRESSCHANGE.display();
          delay(10);
        }
        for (int deg=0; deg<360; deg+=15)
        {
          xEnd = lineWidth * cos(deg * PI / 180.0);
          yEnd = lineWidth * sin(deg * PI / 180.0);
          
          oledCLOSEDADDRESSCHANGE.line(middleX, middleY, middleX + xEnd, middleY + yEnd, BLACK, NORM);
          oledCLOSEDADDRESSCHANGE.display();
          delay(10);
        }
      }
    }
    
    void loop()
    {
      pixelExample();  // Run the pixel example function
      lineExample();  // Then the line example function
    
    }
    

    Hello,

    I just wanted to follow up in case someone in the future was trying to accomplish something similar. Here is code that proves two Qwiic Micro OLEDs can be controlled (mostly) independently on a SparkFun Thing Plus - ESP32 WROOM without using a multiplexer.

    /* 
      Adam & Nicole (gidet08) E.  
      Creation Date: 1/24/2021
    
      Example to prove two Qwiic Micro OLEDs can be controlled (mostly) independently,
      without the use of a multiplexer
    
      Link to SparkFun Qwiic Micro OLED
      https://www.sparkfun.com/products/14532
    
      Distributed as-is; no warranty is given.
    */
    
    
    
    // Include Wire Library for I2C
    #include <Wire.h>
    
    ////SparkFun Micro OLED Breakout Items////
    
    // Include SparkFun Micro OLED Breakout (Qwiic) library
    #include <SFE_MicroOLED.h>
    
    // Define reset pin for Micro OLED. This is a pin that is not used and is a requirement of the library
    // for SparkFun Micro OLED Breakout library use
    #define PIN_RESET 9
    
    // SFE_MicroOLED.h I2C instantiate (v1.3 of SFE_MicroOLED.h)
    // See note in "void showSplashScreens" below
    MicroOLED oledThatHasTheDefaultAddressAndPullUpResistor(PIN_RESET);
    MicroOLED oledThatHasADifferentAddressAndPullUpResistorNotConnected(PIN_RESET);
    
    ////End SparkFun Micro OLED Breakout Items////
    
    // This method will initialize the TwoWire I2C library and both OLEDs
    void initializehardware()
    {
      Wire.begin();
    
      oledThatHasTheDefaultAddressAndPullUpResistor.begin(0x3D, Wire);  
      oledThatHasADifferentAddressAndPullUpResistorNotConnected.begin(0x3C, Wire);
    }
    
    void showSplashScreens()
    {
      // NOTE THE BUFFER IS SHARED BETWEEN ALL "MicroOLED" CLASSES!!
      // BE AWARE OF YOUR BOARD MEMORY CAPABILITIES
      oledThatHasTheDefaultAddressAndPullUpResistor.clear(ALL);
      oledThatHasADifferentAddressAndPullUpResistorNotConnected.clear(ALL);
      oledThatHasTheDefaultAddressAndPullUpResistor.display();
      oledThatHasADifferentAddressAndPullUpResistorNotConnected.display();
      oledThatHasTheDefaultAddressAndPullUpResistor.clear(PAGE);
      oledThatHasADifferentAddressAndPullUpResistorNotConnected.clear(PAGE); 
    }
    
    void setup()
    {
      initializehardware();
      showSplashScreens();
    }
    
    void printDisplay(MicroOLED oled, const String & stringText)
    {
      // Sets cursor to the upper left hand corner
      oled.setCursor(0,0);
      
          // There are different styles of the font the SparkFun Micro OLED Uses:
        // Font 0: 5x8   - Smallest font
        // Font 1: 8x16
        // Font 2: 10x16 - This one looks most like a 7-segment display
        // Font 3: 12x48 - Largest font
        
      oled.setFontType(3);
      oled.print(stringText);
      oled.display(); 
    }
    
    void loop()
    {
      printDisplay(oledThatHasTheDefaultAddressAndPullUpResistor, "123");
      printDisplay(oledThatHasADifferentAddressAndPullUpResistorNotConnected, "456");
    }