0

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?

5
  • Did you try successive readings every 100 to see if it changes? Commented Nov 29, 2017 at 22:08
  • Hi! Yes. The code shows the loop (I've adjusted it from every 100 cycles to every cycle...with no changes in behavior). The values do change as I turn the Pot (when I comment out the fht_mag_octave() line, but i get gibberish otherwise. This tells me that the Pot pin is set up correctly, and that the core ADC calls are working. The ONLY variable is fht_mag_octave()
    – buzzandy
    Commented Nov 30, 2017 at 4:57
  • I meant repeat consecutive A2 only Commented Nov 30, 2017 at 5:46
  • @TonyStewart, You are a genius! That worked. I just added a duplicate A2 read right after, and the results of the 2nd read were spot on! What do you think the cause is? And why wouldn't just adding a delay before the 1st call have solved it?
    – buzzandy
    Commented Nov 30, 2017 at 17:36
  • I have no idea of cause, I am glad my intuition was correct. Only the OEM knows for sure. Commented Nov 30, 2017 at 17:46

1 Answer 1

1

Thanks to @TonyStewart for suggesting that I just do a successive A2 read.

I modified the code by just repeating the A2 read. b1 is the first read, and b2 is the 2nd read.

  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

  Serial.print("b1: ");
  Serial.print(brightness);

  while (!(ADCSRA & 0x10)); // wait for adc to be ready
  ADCSRA = 0xf5; // restart adc 
   m = ADCL; // fetch adc data
   j = ADCH;
   brightness = (j << 8) | m; // form into an int

  Serial.print("   b2: ");
  Serial.println(brightness);

And the readout looks good. B1 is now legible, but incorrect/low. B2 looks accurate and scales all the way to 1024 as I wanted.

b1: 0   b2: 688
b1: 0   b2: 739
b1: 0   b2: 816
b1: 20   b2: 915
b1: 118   b2: 1016
b1: 152   b2: 1023
b1: 172   b2: 1023
b1: 165   b2: 1023
b1: 180   b2: 1023
b1: 188   b2: 1022
b1: 184   b2: 931
b1: 127   b2: 713
b1: 0   b2: 615
b1: 0   b2: 532
b1: 0   b2: 436
b1: 0   b2: 327
b1: 0   b2: 304
b1: 0   b2: 452

I'm still curious about the reasoning behind this...but I'm glad that there is a solution, and not one that is too painful.

1
  • I was experiencing something similar, adding a delay solved the issue (?), no idea why. Later trying other things I realized that if you print a number before all of this, the output will be correct (??!). So I have in my setup function this: // trick to 'clean and set' Serial printer to avoid // printing weird characters instead of numbers Serial.println(0);
    – mayo
    Commented Sep 30, 2021 at 19:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.