Последовательный порт и I2C не работают вместе

У меня есть проблема поважнее. Когда я запускаю этот код, SSD1306 не инициализируется. Выход на последовательной консоли: 20:26:33.194 -> MPU6050 OLED demo

20:26:33.532 -> Ошибка выделения SSD1306>

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>

#define SCREEN_WIDTH 128 // Ширина OLED-дисплея в пикселях
#define SCREEN_HEIGHT 64 // Высота OLED-дисплея, в пикселях
#define OLED_RESET 4 // Reset pin # (или -1 при совместном использовании Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_MPU6050 mpu;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int count =0;

void setup() {
  
  Serial.begin(9600);
  while (!Serial);
  Serial.println("MPU6050 OLED demo");

  if (!mpu.begin()) {
    Serial.println("Sensor init failed");
    while (1)
      yield();
  }
  Serial.println("Found a MPU-6050 sensor");

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; // Don't proceed, loop forever
  }
  
  display.display();
  delay(500); // Pause for 2 seconds
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setRotation(0);
}

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  display.clearDisplay();
  display.setCursor(0, 0);

  display.println("Accelerometer - m/s^2");
  display.print(a.acceleration.x, 1);
  display.print(", ");
  display.print(a.acceleration.y, 1);
  display.print(", ");
  display.print(a.acceleration.z, 1);
  display.println("");
  
  display.println("Gyroscope - rps");
  display.print(g.gyro.x, 1);
  display.print(", ");
  display.print(g.gyro.y, 1);
  display.print(", ");
  display.print(g.gyro.z, 1);
  display.println("");
  display.display();
  delay(100);
}

Но когда я запускаю этот код, без отображения гироскопа все работает нормально. Отображается логотип Adafruit, а затем следуют регулярные данные акселерометра.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_MPU6050.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_Sensor.h>

#define SCREEN_WIDTH 128 // Ширина OLED-дисплея в пикселях
#define SCREEN_HEIGHT 64 // Высота OLED-дисплея, в пикселях
#define OLED_RESET 4 // Reset pin # (или -1 при совместном использовании Arduino reset pin)
#define SCREEN_ADDRESS 0x3D ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_MPU6050 mpu;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int count =0;

void setup() {
  
  //Serial.begin(9600);
  //while (!Serial);
  //Serial.println("MPU6050 OLED demo");

  if (!mpu.begin()) {
    //Serial.println("Sensor init failed");
    while (1)
      yield();
  }
  //Serial.println("Found a MPU-6050 sensor");

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) { // Address 0x3C for 128x32
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ; // Don't proceed, loop forever
  }
  
  display.display();
  delay(500); // Pause for 2 seconds
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setRotation(0);
}

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  display.clearDisplay();
  display.setCursor(0, 0);

  display.println("Accelerometer - m/s^2");
  display.print(a.acceleration.x, 1);
  display.print(", ");
  display.print(a.acceleration.y, 1);
  display.print(", ");
  display.print(a.acceleration.z, 1);
  display.println("");

  display.println("Gyroscope - rps");
  display.print(g.gyro.x, 1);
  display.print(", ");
  display.print(g.gyro.y, 1);
  display.print(", ");
  display.print(g.gyro.z, 1);
  display.println("");
  display.display();
  delay(100);
}

Теперь, во время отладки, когда я отключаю серийные журналы и комментирую все Serial.print, то приведенный выше код работает правильно, отображается логотип, акселерометр и гироскоп оба данных отображаются на OLED правильно.

Журнал компилятора для нерабочего кода таков: Sketch использует 21980 байт (71%) пространства для хранения программ. Максимум-30720 байт. Глобальные переменные используют 761 байт (37%) динамической памяти, оставляя 1287 байт для локальных переменных. Максимум-2048 байт.

Установка, которую я использую как Arduino Nano, MPU6050 подключена через I2C (адрес 0x68), SSD1306 основан на 0.96" 128x64 дисплее через I2C (адрес 0x3D). Я использую контакты A4 и A5 Arduino Nano в качестве I2C. Оба устройства подключены по одной шине. Я использую макетную плату для тестирования.

PS: Оба кода компилируются без ошибок и предупреждений

, 👍0

Обсуждение

В чем разница между этими скетчами?, @Sim Son

Внес исправления, я допустил ошибку при копировании и вставке комментариев, @Pankaj


2 ответа


3

SSD1306 использует много оперативной памяти. Почти вся твоя оперативка. Serial также использует довольно много оперативной памяти. Эти двое изо всех сил стараются работать вместе.

Существует специальная библиотека SSD1306 "только текст", которая использует значительно меньше оперативной памяти: https://github.com/greiman/SSD1306Ascii

,

1

Спасибо тебе, Маенко...

Это была проблема низкой оперативной памяти. SSD1306 занимает 1K, с MPU6050 и последовательной печатью, которую я включил, оставшаяся оперативная память составляет всего 5 байт, отсюда и проблема инициализации. Я следовал простым рекомендациям по уменьшению объема оперативной памяти

Прочтите эту тему https://stackoverflow.com/questions/8649174/checking-memory-footprint-in-arduino

Код для печати доступного SRAM.

Serial.print(availableMemory());

// проверка свободной ОЗУ для отладки. SRAM для ATmega328P = 2048 Кб.
int availableMemory() {
    // Use 1024 with ATmega168
    int size = 2048;
    byte *buf;
    while ((buf = (byte *) malloc(--size)) == NULL);
        free(buf);
    return size;
}
,