Arduino crashes with 3 I2C devices + GPS

I am trying to put together an OLED 128x64, BMP280, HMC5883L and a GPS Neo 6M.

The device I am using is an Arduino Nano (328p with old bootloader).

The first time I compile the code I get a warning that does not appear again if I compile again. This is the warning:

In file included from C:\Users\gonza\Documents\Arduino\libraries\Adafruit_HMC5883_Unified\Adafruit_HMC5883_U.cpp:38:0:
C:\Users\gonza\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\Wire\src/Wire.h: In member function 'void Adafruit_HMC5883_Unified::read()':
C:\Users\gonza\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\Wire\src/Wire.h:69:13: note: candidate 1: uint8_t TwoWire::requestFrom(int, int, int)
     uint8_t requestFrom(int, int, int);
             ^~~~~~~~~~~
C:\Users\gonza\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\Wire\src/Wire.h:66:13: note: candidate 2: uint8_t TwoWire::requestFrom(uint8_t, uint8_t, uint8_t)
     uint8_t requestFrom(uint8_t, uint8_t, uint8_t);
             ^~~~~~~~~~~

This is my code: (it crashes before reaching loop)

//Agregamos las librerias necesarias
#include <Adafruit_HMC5883_U.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <Adafruit_BMP280.h>
#include <Adafruit_Sensor.h>
#include <SoftwareSerial.h>
#include <TinyGPSPlus.h>
#include <EasyButton.h>
#include <Wire.h>

//OLED
#define ancho 128
#define alto 64
#define OLED_RESET 0
Adafruit_SSD1306 oled(ancho, alto, &Wire, OLED_RESET);
//Tamaño de letra
#define tam 1
//Fuente de letra
#include <Fonts/FreeSans9pt7b.h>

//Objeto del sensor BMP280
Adafruit_BMP280 bmp;

//GPS NEO 6M
static const int RXPin = 3, TXPin = 4; //Al reves
static const uint32_t GPSBaud = 9600;
//TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);

//Brujula
Adafruit_HMC5883_Unified mag;

//Variable botones
EasyButton botonUP(6,35,false,true);
EasyButton botonDWN(5,35,false,true);
EasyButton botonOK(7,35,false,true);
EasyButton backButton(5,35,false,true);

//Temporizadores
unsigned long tiempo1;

//Variables de los menus
byte menu1 = 1;
byte menu2 = 1;
byte submenu = 1;

void setup()
{
  Serial.begin(115200);
  
  //Iniciamos todos los sensores
  //Iniciamos OLED
  if(!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)){Serial.println(F("Error oled"));}
  oled.setTextSize(tam);         //Tamano de letra
  oled.setFont(&FreeSans9pt7b);  //Fuente 
  oled.setTextColor(SSD1306_WHITE);
  
  //Iniciamos BMP280
  bmp.begin();
  
  //Iniciamos GPS
  ss.begin(GPSBaud);
  
  //Easybutton
  botonUP.begin();
  botonUP.onPressed(lecturaUP);
  botonDWN.begin();
  botonDWN.onPressed(lecturaDWN);
  botonOK.begin();
  botonOK.onPressed(lecturaOK);
  
  //Brujula
  mag.begin();
  
  //Mostramos la animacion de inicio
  Inicio();
  
  //Lanzamos la pantalla principal
  actualizarMenu();
}
void Inicio()
{
  oled.clearDisplay();
  oled.setCursor(20,10);
  oled.print(F("Animacion"));
  Serial.println(F("Iniciado"));
  oled.display();
  delay(1000);
}
void loop()
{
  //Leemos los botones constantemente
  botonUP.read();
  botonDWN.read();
  botonOK.read();
}
void lecturaUP()
{
    if(menu1 == 3)
    {
      menu1 = 0; //Uno menos del que hay
    }
    menu1++;
    actualizarMenu();
    Serial.println(menu1);
}
void lecturaDWN()
{
    if(menu1 == 1)
    {
      menu1 = 4; //Uno mas del que hay
    }
    menu1--;
    actualizarMenu();
    Serial.println(menu1);
}
void lecturaOK()
{
    if(submenu == 2)
    {
      //Nada, no hay mas submenus
    }
    else
    {
      submenu++;
      actualizarMenu();
      Serial.println(submenu);
    }
}
void actualizarMenu()
{
  switch(submenu)
  {
    case 1: 
    switch(menu1)
    {
      //menu1 = 1 es el menu principal
      case 1: oled.clearDisplay();
              oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
              oled.setCursor(10,10);
              oled.print(F("GPS"));
              oled.display();
              break;
    }
    case 2: break;
  }
}
void backSubmenu()
{
  if(submenu == 1)
  {
    //Nada, es el primer submenu
  }
  else
  {
    submenu--;
    Serial.println(submenu);
  }
}

This is what I have tested so far:

  • I have tested them individually and everithing works as it should.
  • When connected together I ran I2C scanner and every I2C address showed up.
  • I tried to remove every library, compile and, if it worked, added the next, compile again and so on. (It seems to have something to do with compatibility between libraries but I am not sure, as the arduino crashes with different selection of libraries).
  • I suspected this may be caused by SRAM so I tried with a Wemos D1 mini (esp8266) but the issue persists. I ordered an Arduino Mega so I can try with it.
  • I have checked my code for hours but I can not find any error, also the code is mainly made with other code or examples that already work, I just combined them together.
  • The bmp280 sensor works at 3.3v, I have read this may cause issues with the I2C bus but so far it has worked well (tested oled and bmp together).

I think this is all, if I am missing any important info just let me know.
Any thoughts on why this is would be much appreciated. :slight_smile:

Welcome to the forum.

The SoftwareSerial takes over almost the entire Arduino Nano, there is not much else it can do. The OLED library uses a lot of memory. I think your ran out of SRAM memory.

The ideal board would have more memory and a spare Serial port, such as the ESP32.
The Arduino Mega is okay, but it has a 5V I2C bus and the OLED wants to disturb the I2C bus for others. You need a I2C level shifter.

The ESP8266 could be a different problem.
I rather fix the problem with the ESP8266, because the OLED and BMP280 need a 3.3V I2C bus and the SoftwareSerial is not so demanding on the ESP8266.

Can you give links to the modules ?
Most OLED displays run internally at 3.3V and have a 3.3V I2C bus. Only Adafruit makes their OLED displays compatible with a 5V I2C bus. The BMP280 needs a 3.3V I2C bus.

The Wokwi simulator can not simulate your whole project. It is getting there, but the custom chips are in alpha state and the GPS example does not work anymore. It has an option to give the Arduino Nano more memory. Wait a year, and then Wokwi can simulate it.

Hi, thanks for your answer.
Here are the links to the modules I am using:

  • OLED
  • BMP
    (I can not add more than 2 links per post, I will reply with the 2 left)

I tried to simulate in Wokwi but I could not find all the modules I am using, as you said.

The BMP280 needs a 3.3V I2C bus.

Both, oled and BMP need 3.3v I2C, why do they work with 5v anyways?

So, using ESP32 with a I2C level shifter may solve the issue?
Thanks again.

The ESP32 is a 3.3V board, therefor its I2C bus has 3.3V signals of SDA and SCL. That matches with the 3.3V sensors. No I2C level shifter is needed.

I'm not saying that a ESP32 will solve the problem. Maybe you get the same problem as with the ESP8266. That has to be solved.
The SoftwareSerial for the ESP8266 is not so bad, you could also try that once more.

If you buy a ESP32, then use "Serial" for the Arduino Serial monitor and use "Serial2" as extra serial port. The "Serial1" has somehow fallen in between and has vanished.

It is possible that something is broken or there could be a bug in a library. Keep that in mind, even if everything works on its own.

To save some memory, I use the "SSD1306Ascii" library for my OLED projects. It is text only and takes little memory.

I believe I will need the shifter for the 5V sensors, am I wrong?

I have already ordered an ESP32, I'll give it a try. I'll post an update in case it works.

Hope that's not the case... I won't be able to make it work if so.
Thanks again for your comments.

I use TinyOzOLED and TinyWireM for Attiny85 projects. They are very small, but I am not sure if they will work on the Nano.

You are right, but which sensor runs at 5V ?
If you power the OLED with 5V, it still runs internally at 3.3V and it still has a 3.3V I2C bus.

A level shifter has a "high side" and a "low side" and it connects any 5V I2C bus to any 3.3V I2C bus, regardless on which side the Arduino board is. But, it makes the signals a little weaker. The I2C bus might already fail when there are two level shifters in the signal path.

I've had good luck connecting between 3.3V systems and 5V systems using only a 10k resistor in series with the output of the 5V device.

The 5V devices I've worked with were able (by specification) to sense hi and low signals from a 3.3v device.
The 10k ohm resistor limits any overcurrent from the 5V device to the 3.3V device while staying within the specifications of the 3.3V device.

I've not had good luck with the mosfet level shifters sold on ebay.

I tried using an Arduino Mega and it is working now. It seems to be a SRAM issue, to begin an oled screen you need at least like 1200 bytes free, otherwise it will not work.
Thanks everyone for your suggestions!