DHT20 и дисплей Oled не работают вместе

Я пытаюсь заставить DHT20 и Oled (оба из комплекта датчиков Arduino) работать одновременно. Я могу заставить их работать отдельно с соответствующими тестовыми кодами, но когда я пытаюсь объединить коды, дисплей Oled больше не работает. Оба соединения являются соединениями I2C, но я проверил, каждое устройство имеет свой адрес, так что проблем быть не должно.

Вот мой тестовый код DHT20:

#include "Arduino_SensorKit.h"

//раскомментируйте строку ниже, если используете DHT20
#define Environment Environment_I2C

void setup() {
  //раскомментируйте строку ниже, если используете DHT20
  Wire.begin();
  Serial.begin(9600);
  Environment.begin();
}

void loop() {
  Serial.print("Temperature = ");
  Serial.print(Environment.readTemperature()); //температура печати
  Serial.println(" C");
  Serial.print("Humidity = ");
  Serial.print(Environment.readHumidity()); //печатаем влажность
  Serial.println(" %");
  delay(2000);
}

Вот мой тестовый код Oled-дисплея:

#include "Arduino_SensorKit.h"
void setup() {
  Oled.begin();
  Oled.setFlipMode(true);
}

void loop() {
  int random_value = random(0, 1023);   // создаем случайное значение

  Oled.setFont(u8x8_font_chroma48medium8_r); 
  Oled.setCursor(0, 3);
  Oled.print("Value: ");
  Oled.print(random_value);
  delay(1000);
}

Это мой код, в котором я пытался заставить оба устройства работать одновременно:

#include "Arduino_SensorKit.h"
#define Environment Environment_I2C

void setup() {

  Oled.begin();
  Oled.setFlipMode(true);

  Wire.begin();
  Serial.begin(9600);
  Environment.begin();
}

void loop() {
  
  Oled.setFont(u8x8_font_chroma48medium8_r); 
  Oled.setCursor(0, 3);
  Oled.print("Testing");

  Serial.print("Temperature = ");
  Serial.print(Environment.readTemperature()); //температура печати
  Serial.println(" C");
  Serial.print("Humidity = ");
  Serial.print(Environment.readHumidity()); //печатаем влажность
  Serial.println(" %");


  delay(2000);

}

Когда я использую приведенный выше код, значения температуры и влажности печатаются на последовательном мониторе, но Oled ничего не отображает.

Любая помощь приветствуется!

, 👍1

Обсуждение

что произойдет, если вы измените порядок инициализации двух модулей в setup()?, @jsotola

К сожалению, изменение порядка инициализации в setup() ничего не меняет., @Darren D'Arcy


2 ответа


3

Основная проблема

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

Основная проблема заключается в том, что библиотека Arduino_SensorKit написана для использования программного обеспечения/битового I2C для отображения. Вернее, он приказывает U8G2LIB это сделать, по какой причине я не знаю. Когда периферийное устройство ATmega328P I2C включено, оборудование GPIO больше не управляет выводами. Таким образом, в тот момент, когда вы включаете аппаратный I2C (через код DHT20), код битов GPIO в U8G2LIB не может работать правильно.

Итак, есть как минимум два способа заставить это работать.

  • Изменение вашего кода, чтобы он соответствовал тому, как написана библиотека Arduino_SensorKit.

  • Другой — модификация библиотеки Arduino_SensorKit для использования аппаратного I2C, и в этом случае исходный код работает дословно.

Изменение скетча

Вы можете изменить свой скетч следующим образом:

#include "Arduino_SensorKit.h"
#define Environment Environment_I2C

void setup() {
  Oled.begin();
  Oled.setFlipMode(true);

  Serial.begin(9600);

  Wire.begin(); // только здесь, чтобы соответствовать последующему .end()
}

void loop() {
  Wire.end();  // возвращаем управление выпуском I2C обратно в GPIO
  {
    Oled.setFont(u8x8_font_chroma48medium8_r);
    Oled.setCursor(0, 3);
    Oled.print(millis()); //Oled.print("Тестирование");
  }
  Wire.begin(); // повторно включаем I2C для использования DHT20 («Среда»);

  Serial.print("Temperature = ");
  Serial.print(Environment.readTemperature()); //температура печати
  Serial.println(" C");
  Serial.print("Humidity = ");
  Serial.print(Environment.readHumidity()); //печатаем влажность
  Serial.println(" %");

  delay(2000);
}

По большей части библиотеке AVR Wire не важно, используете ли вы повторяющиеся вызовы begin() или повторяющиеся вызовы end(). Однако это может повлиять на настройку скорости. Фигурные скобки вокруг использования Oled предназначены только для визуального эффекта.

В любом случае, это работает, если вы уверены, что Oled может использовать GPIO.

Изменение Arduino_SensorKit

Благодаря следующим изменениям в библиотеке Arduino_SensorKit версии 1.2.1 (действующей на момент написания) я могу использовать ваш код скетча дословно. Я также изменил его, чтобы печатать millis(), а не "Тестирование", чтобы быть уверенным, что продолжается обновление дисплея.

Arduino_SensorKit.h

В строке 24 файла библиотеки Arduino_SensorKit.h, изменить:

extern U8X8_SSD1306_128X64_NONAME_SW_I2C Oled;

в

extern U8X8_SSD1306_128X64_NONAME_HW_I2C Oled;

Обратите внимание на HW (аппаратное обеспечение), а не на SW (программное обеспечение).

Arduino_SensorKit.cpp

Аналогичным образом измените аналог на определение Oled соответствует приведенному выше изменению в объявлении extern Oled , из:

U8X8_SSD1306_128X64_NONAME_SW_I2C Oled(/* clock=*/ _PIN_SCL, /* data=*/ _PIN_SDA, /* reset=*/ U8X8_PIN_NONE);

кому:

U8X8_SSD1306_128X64_NONAME_HW_I2C Oled(/* clock=*/ _PIN_SCL, /* data=*/ _PIN_SDA, /* reset=*/ U8X8_PIN_NONE);

Вероятно, здесь можно удалить аргументы из вызова конструктора; ATMega328P не имеет возможностей настройки TWI/I2C для более чем одного набора контактов.


Также ничто не мешает вам оставить его как U8X8_SSD1306_128X64_NONAME_SW_I2C, но изменить контакты так, чтобы программный I2C использовал контакты, отличные от A4/A5, чтобы не конфликтовать с использованием аппаратного I2C библиотеками DHT20. .


Для справки: версия U8G2LIB, которую я тестировал, была 2.33.15. ардуино-кли версии 0.32.2. ардуино: avr ядро 1.8.7. Я не думаю, что они вам нужны. Я просто уточняю на случай, если кто-нибудь найдет это через 5 лет или где-то еще.

,

Большое спасибо! Я изменил скетч, и теперь он работает отлично!, @Darren D'Arcy


1

Я использую переменную для хранения показаний.

#include "Arduino_SensorKit.h"

#define Environment Environment_I2C

void setup() {
  Oled.begin();
  Oled.setFlipMode(true); // Устанавливает поворот экрана
  // раскомментируйте строку ниже, если используете DHT20 (черный датчик)
  Wire.begin();
  // раскомментируйте строку ниже, если вы подключаете DHT20 к контакту, отличному от 3
  Serial.begin(9600);
  Environment.begin();
}

void loop() {
  Wire.begin();

  // Вам нужна переменная для сохранения показаний, потому что среда не будет работать, когда светодиод работает
  float temp= Environment.readTemperature();
  float hum= Environment.readHumidity();
  Serial.print("Temperature = ");
  Serial.print(temp); //температура печати
  Serial.println(" C");
  Serial.print("Humidity = ");
  Serial.print(hum); //печатаем влажность
  Serial.println(" %");
  
  delay(2000);
    
  // int random_value = AnalogRead(A0);
  Wire.end();

  {
    Oled.setFont(u8x8_font_chroma48medium8_r); 
    Oled.setCursor(0, 0);    // Устанавливаем координаты
    Oled.print("temp: ");   
    Oled.print(temp); // Распечатываем значения

    Oled.setCursor(0, 3); // Устанавливаем координаты
    Oled.print("Humidity: ");   
    Oled.print(hum); // Распечатываем значения
    Oled.refreshDisplay(); // Обновляем отображение
  }
}
,