I'm trying to do something I think would be simple. I'd like to read the input of a electret microphone board and update the Adafruit 24-segment LED Bar Graph. I got each individual item working perfectly: I can read the input of the microphone on the analog pin and I can update the LED bar graph using I2C.
The issue occurs when I tried to combine the two concepts. When the bard graph gets updated, the analog input reads HIGH (1023) and never changes. I used my standard debug method and commented out code until the problem went away, so I've narrowed down the issue to a single line of code (right at the end). When the bar.writeDisplay is called the analog input perpetually reads 1023.
If I comment out that one line of code and re-upload my sketch the readings (in the Serial Monitor) are as expected (lower when its quiet and higher when its loud).
Under the hood Adafruit is using the Wire library.
I'm no good at wiring diagrams, but here's what I have:
RoboDyn Mega 2560 Pro (Embed) 5V, Gnd, SDA (20), SCL (21) to the LED Backpack 5V, Gnd, Out (A15/69)
That said, I'm relatively confident this is not a wiring problem as everything works until the software gets ahold of it.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
Adafruit_24bargraph bar = Adafruit_24bargraph();
int pin = 69;
unsigned int sampleWindow = 50; // millis
unsigned int maxScale = 24;
void setup() {
Serial.begin(9600);
bar.begin(0x70); // pass in the address
}
void loop() {
unsigned long startMillis = millis(); // Start of sample window
unsigned int peakToPeak = 0; // peak-to-peak level
unsigned int sample;
unsigned int signalMax = 0;
unsigned int signalMin = 1024;
while (millis() - startMillis < sampleWindow) {
sample = analogRead(pin);
if (sample < 1024) { // toss out spurious readings
if (sample > signalMax) {
signalMax = sample; // save just the max levels
}
else if (sample < signalMin) {
signalMin = sample; // save just the min levels
}
}
}
peakToPeak = signalMax - signalMin;
int displayPeak = map(peakToPeak, 0, 1023, 0, maxScale); // map 1v p-p level to the max scale of the display
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);
}
//bar.writeDisplay(); // <------- THIS LINE
}
}
UPDATE: It appears to be something with the way Adafruit uses the Wire library. I have a similar problem when I use the Adafruit 7-segment library, when I use their MCP23017 library.
But it is wiring related too. If I uncomment the commented out line above but disconnect the I2C device the analog input starts working again.
One more thing I've discovered: it depends on how many lights are lit on the I2C board. Once all the lights are lit, the analog pin reads full. When only a couple of lights are lit, the values are lower. It is like the voltage going into the mic is higher when the lights are brighter.
For curiosity sake, I tried the same thing on a different Arduino (Adafruit Feather 32u4) with the same result (so it isn't my Arduino).