I have been playing with the FHT library and have run into an interesting issue with fht_mag_octave()
disrupting the output of my ADC actions. Running on a MEGA ADK.
The idea is that I'm using FHT to read in the microphone input into A0, but also occasionally checking A2 pot to adjust the volume/brightness of the of the overall FastLED strip.
Here is the code in question... it's barebones. Just the standard FHT loop and then, every 100 loops, it checks A2 for the brightness setting.
#include <FastLED.h>
#define LED_PIN 6
#define BRIGHTNESS 200
#define LED_TYPE WS2811
#define COLOR_ORDER GRB
#define NUM_LEDS 16
CRGB* const leds(NUM_LEDS);
#define LOG_OUT 1 // use the log output function
#define OCTAVE 1 // // Group buckets into octaves (use the log output function LOG_OUT 1)
#define OCT_NORM 0 // Don't normalise octave intensities by number of bins
#define FHT_N 128 // set to 128 point fht
#include <FHT.h> //
void setup() {
Serial.begin(9600);
delay(1000);
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
FastLED.setBrightness (BRIGHTNESS);
// TIMSK0 = 0; // turn off timer0 for lower jitter (commented this out b/c I think this interferes with FastLED)
ADCSRA = 0xe5; // set the adc to free running mode (0b11100101), prescalar=32 for higher ADC clock freq
ADMUX = 0x40 | (0 & 0x07); // use adc0 (0b1000000)
DIDR0 = 0x01; // turn off the digital input for adc0
}
int counter = 0;
void loop() {
while (1) { // reduces jitter
cli(); // UDRE interrupt slows this way down on arduino1.0
for (int i = 0 ; i < FHT_N ; i++) { // save 128 samples
while (!(ADCSRA & 0x10)); // wait for adc to be ready in binary 0010000 (look for ADC Interrupt flag to be set to 1)
ADCSRA = 0xf5; // restart adc (in binary 11110101...http://www.robotplatform.com/knowledge/ADC/adc_tutorial_2.html)
byte m = ADCL; // fetch adc data
byte j = ADCH;
int k = (j << 8) | m; // form into an int
k -= 0x0200; // form into a signed int
k <<= 6; // form into a 16b signed int
fht_input[i] = k; // put real data into bins
}
fht_window(); // window the data for better frequency response
fht_reorder(); // reorder the data before doing the fht
fht_run(); // process the data in the fht
fht_mag_octave();
// fht_mag_log();
// every 100th loop, adjust the volume accourding to the value on A2 (Pot)
if (counter > 10) {
ADMUX = 0x40 | (2 & 0x07); // set admux to look at Analogpin A2
while (!(ADCSRA & 0x10)); // wait for adc to be ready
ADCSRA = 0xf5; // restart adc
byte m = ADCL; // fetch adc data
byte j = ADCH;
int brightness = (j << 8) | m; // form into an int
// brightness = map(brightness, 0, 1023, 0, 255);
Serial.print("b: ");
Serial.println(brightness);
FastLED.setBrightness (brightness);
ADMUX = 0x40 | (0 & 0x07); // set admux back to look at A0 analog pin (to read the microphone input
counter = 0;
}
counter++;
sei();
}
}
Here's the output as shown (basically, it's outputting nonsense, non-int
values):
b: ⸮
b: ⸮
b:
b:
b: ⸮
b: ⸮
b:
b: ⸮
b: ⸮
b:
b: ⸮
b: ⸮
b: ⸮
b:
b: ⸮
b: ⸮
b:
b: ⸮
b: ⸮
b:
If I comment OUT the fht_mag_octave
line and uncomment fht_mag_log()
, here is the output (which looks right as I turn the Pot pin):
b: 0
b: 0
b: 0
b: 0
b: 0
b: 9
b: 35
b: 38
b: 48
b: 85
b: 143
b: 171
b: 188
b: 204
b: 224
b: 245
b: 280
b: 332
The issue is that the A2 value "brightness" does not read properly if I use fht_mag_octave()
. If I comment out only the fht_mag_octave()
line, it works perfectly. I can also use fht_mag_log
instead, and it works fine.
This makes me think that there is something that fht_mag_octave()
does something that interferes with the ADC registers.
Any ideas?