Библиотека Adafruit_LEDBackpack мешает чтению аналогового ввода

Я пытаюсь сделать что-то простое. Я хотел бы прочитать вход платы электретного микрофона и обновить 24-сегментную светодиодную гистограмму Adafruit. У меня отлично работает каждый отдельный элемент: я могу считывать вход микрофона на аналоговом выводе и обновлять светодиодную гистограмму с помощью I2C.

Проблема возникает, когда я пытаюсь объединить эти две концепции. Когда гистограмма обновляется, на аналоговом входе отображается ВЫСОКИЙ уровень (1023) и он никогда не меняется. Я использовал свой стандартный метод отладки и комментировал код до тех пор, пока проблема не исчезла, поэтому я сузил проблему до одной строки кода (в самом конце). При вызове bar.writeDisplay аналоговый ввод постоянно считывает 1023.

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

Под капотом Adafruit используется библиотека Wire.

Я плохо разбираюсь в электрических схемах, но вот что у меня есть:

RoboDyn Mega 2560 Pro (встроить) 5V, Gnd, SDA (20), SCL (21) к светодиодному рюкзаку 5 В, земля, выход (A15/69)

Тем не менее, я относительно уверен, что это не проблема с проводкой, так как все работает до тех пор, пока программное обеспечение не обработает это.

#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

Adafruit_24bargraph bar = Adafruit_24bargraph();

int pin = 69;
unsigned int sampleWindow = 50; // миллисекунды
unsigned int maxScale = 24;

void setup() {
  Serial.begin(9600);
  bar.begin(0x70);  // передаем адрес
}

void loop() {
  unsigned long startMillis = millis();  // Начало окна примера
  unsigned int peakToPeak = 0;   // размах уровня
  unsigned int sample;
  unsigned int signalMax = 0;
  unsigned int signalMin = 1024;
  while (millis() - startMillis < sampleWindow) {
    sample = analogRead(pin); 
    if (sample < 1024) {  // отбросить ложные показания
      if (sample > signalMax) {
        signalMax = sample;  // сохранить только максимальные уровни
      }
      else if (sample < signalMin) {
        signalMin = sample;  // сохраняем только минимальные уровни
      }
    }
  }
  peakToPeak = signalMax - signalMin;  
  int displayPeak = map(peakToPeak, 0, 1023, 0, maxScale); // сопоставляем уровень 1v pp с максимальным масштабом дисплея
  Serial.print("mic: "); Serial.print(peakToPeak); Serial.print(" "); Serial.println(displayPeak);
  for (uint8_t b = 0; b < 24; b++) {
    if (b <= displayPeak) {
      int c = LED_GREEN;
      if (b >= 20) {
        c = LED_RED;
      }
      else if (b >= 16) {
        c = LED_YELLOW;
      }
      bar.setBar(23 - b, c);
    }
    else {
      bar.setBar(23 - b, LED_OFF);
    }
    //бар.writeDisplay(); // <------- ЭТА СТРОКА
  }
}

Макет

ОБНОВЛЕНИЕ: похоже, что-то связано с тем, как Adafruit использует библиотеку Wire. У меня похожая проблема, когда я использую 7-сегментную библиотеку Adafruit, когда я использую их библиотеку MCP23017.

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

Еще одна вещь, которую я обнаружил: это зависит от того, сколько индикаторов горит на плате I2C. Как только все индикаторы загорятся, аналоговый вывод будет заполнен. Когда горит только пара лампочек, значения ниже. Это похоже на то, что напряжение, подаваемое на микрофон, выше, когда свет ярче.

Ради любопытства я попробовал то же самое на другом Arduino (Adafruit Feather 32u4) с тем же результатом (значит, это не мой Arduino).

, 👍6

Обсуждение

Шаг первый: закомментируйте все, что связано с обратной светодиодной подсветкой, и посмотрите, выдает ли она по-прежнему 1023., @Majenko

Как я уже сказал, это то, что я уже сделал. Если я закомментирую только эту строку, я получу нормальные показания. Если я оставлю эту строку, я получу 1023., @OneCleverMonkey

Возможно, я поторопился сказать, что проблема не в проводке. У меня также не возникает проблемы, если я оставлю эту строку в коде и удалю светодиодный рюкзак с макетной платы. Возможно, проблема в светодиодном рюкзаке. Может я пайку накосячил или плата плохая попалась., @OneCleverMonkey

Ах, я пропустил этот момент. Виноват., @Majenko

Можете выложить фото макетной платы?, @Majenko

Может где резистор нужен?, @OneCleverMonkey

Нет, мне кажется, все в порядке., @Majenko

Падает ли напряжение питания микрофона и/или микроконтроллера, когда горят светодиоды?, @ocrdu

Я нашел что-то похожее https://esp32.com/viewtopic.php?t=2794, @xbox gamer

Имеет ли значение изгиб сигнального провода микрофона вдали от проводов I2C?, @ocrdu

Вы получаете 1023, что? Значение AnalogRead? Значение размаха? Я бы попробовал использовать другой аналоговый контакт для микрофона. Также добавьте небольшую задержку после bar.writeDisplay();. Наконец; Я бы попробовал снабдить плату микрофона собственными проводами питания, а не получать его от модуля гистограммы., @Gerben

Сложите все текущие, необходимые для запуска вашего проекта. Удвойте число. Это сила тока, которую вы должны использовать как минимум для вашего источника питания. Предположим, там 24 светодиода по 3 мА каждый. Это около 100 мА? Добавить еще 50 мА для Arduino Uno и еще 50 мА для микрофона? В сумме это около 200 мА? Таким образом, ваш блок питания должен быть рассчитан как минимум на 1/2 ампера. И вы должны удвоить это, если используете аналоговый регулятор Arduino. Кстати, источники питания USB должны выдавать только 500 мА. Кроме того, им разрешено падение напряжения. Это много догадок. Просто попробуйте большой PS., @st2000


1 ответ


0

Поскольку вы не можете опубликовать схему, я возьму SWAG и скажу, что у вас есть два разных аппаратных устройства, использующих один и тот же контакт по разным причинам. I2C — это только шина, и связанные с ней контакты не могут использоваться ни для чего другого. Убедитесь, что шина I2C подключена только к клеммам I2C. Также убедитесь, что он правильно завершен.

,