arduinoFFT.h code breaking switch case/ button For guitar tuner

Hi,
I've been having problems with using the following section of code within a switch case.
The full code without comments is as follows.

#include <arduinoFFT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
#define SAMPLES 128
#define SAMPLING_FREQUENCY 660
arduinoFFT FFT = arduinoFFT();
unsigned int samplingPeriod;
unsigned long microSeconds;
double vReal[SAMPLES];
double vImag[SAMPLES];
const int E4 = 280.41; //Avergae Piezo value for E4
const int B = 213.30; //Avergae Piezo value for B
const int G = 164.76; //Avergae Piezo value for D
const int D = 125.15; //Avergae Piezo value for D
const int A = 92.23; //Avergae Piezo value for A
const int E = 70.71; //Avergae Piezo value for E4
const int led_yellow = 9;
const int led_green = 10;
const int led_red = 11;
const int led_E4 = 6;
const int led_B = 5;
const int led_G = 4;
const int led_D = 3;
const int led_A = 2;
const int led_E = 1;
const int buttonPin = 0;
int buttonState;
int string = 0;
int prestate = 0;
double peak = FFT.MajorPeak(vReal, SAMPLES, SAMPLING_FREQUENCY);

void setup() {
  Serial.begin(115200);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;);
  }
  delay(2000);
  display.clearDisplay();
  pinMode(led_yellow, OUTPUT);
  pinMode(led_green, OUTPUT);
  pinMode(led_red, OUTPUT);
  pinMode(led_E4, OUTPUT);
  pinMode(led_B, OUTPUT);
  pinMode(led_G, OUTPUT);
  pinMode(led_D, OUTPUT);
  pinMode(led_A, OUTPUT);
  pinMode(led_E, OUTPUT);
  pinMode(buttonPin, INPUT);
  digitalWrite(buttonPin, HIGH);
  digitalWrite(led_E4, HIGH);
  digitalWrite(led_yellow, HIGH);
  digitalWrite(led_green, HIGH);
  digitalWrite(led_red, HIGH);
  digitalWrite(led_E4, HIGH);
  digitalWrite(led_B, HIGH);
  digitalWrite(led_G, HIGH);
  digitalWrite(led_D, HIGH);
  digitalWrite(led_A, HIGH);
  digitalWrite(led_E, HIGH);
}
void loop() {

  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && prestate == 0) {

    string++;

    if (string > 5) {
      string = 0;
    }

    prestate = 1;

  } else if (buttonState == HIGH) {

    prestate = 0;
  }

  switch (string) {

    case 0:
      display.clearDisplay();
      samplingPeriod = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
      digitalWrite(led_E4, HIGH);
      digitalWrite(led_E, LOW);
      display.setTextSize(1);
      display.setTextColor(WHITE);
      display.setCursor(0, 0);
      display.println("E String");
      display.display();
      delay(500);

      for (int i = 0; i < SAMPLES; i++) {
        microSeconds = micros();

        vReal[i] = analogRead(A0);

        vImag[i] = 0;
      }
      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      //peak = 70.71; //Avergae Piezo value for E
      display.clearDisplay();
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("E String");

      display.setTextSize(1);
      display.setCursor(0, 32);
      display.println(peak);
      display.display();
      delay(500);


      if (((E - 5) <= peak) && (peak <= (E + 5))) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Tuned");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_green, LOW);


      } else if ((E - 5) > peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Flat");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_yellow, LOW);

      } else if ((E + 5) < peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Sharp");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_red, LOW);

      }
      delay(250);
      digitalWrite(led_green, HIGH);
      digitalWrite(led_yellow, HIGH);
      digitalWrite(led_red, HIGH);
      break;

    case 1:
      display.clearDisplay();
      samplingPeriod = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
      digitalWrite(led_E, HIGH);
      digitalWrite(led_A, LOW);
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("A String");
      display.display();
      delay(500);

      for (int i = 0; i < SAMPLES; i++) {
        microSeconds = micros();

        vReal[i] = analogRead(A0);

        vImag[i] = 0;
      }
      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      //peak = 92.23; //Avergae Piezo value for A
      display.clearDisplay();
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("A String");

      display.setTextSize(1);
      display.setCursor(0, 32);
      display.println(peak);
      display.display();
      delay(500);

      if ((A - 5) <= peak && peak <= (A + 5)) {
        // if sample is between +5hz or -5hz it is considered in tune
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Tuned");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_green, LOW);


      } else if ((A - 5) > peak) {

        // if sample is more than 5Hz lower it is condidered flat
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Flat");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_yellow, LOW);

      } else if ((A + 5) < peak) {

        // if sample is more than 5Hz higher it is condidered sharp
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display Peak frequency
        display.println("Sharp");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_red, LOW);

      }
      delay(250);
      digitalWrite(led_green, HIGH);
      digitalWrite(led_yellow, HIGH);
      digitalWrite(led_red, HIGH);
      break;

    case 2:
      display.clearDisplay();
      samplingPeriod = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
      digitalWrite(led_A, HIGH);
      digitalWrite(led_D, LOW);
      display.setTextSize(1);
      display.setCursor(0, 0);
      // Display static text
      display.println("D String");
      display.display();
      delay(500);

      for (int i = 0; i < SAMPLES; i++) {
        microSeconds = micros();

        vReal[i] = analogRead(A0);

        vImag[i] = 0;
      }

      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      //peak = 125.15; //Avergae Piezo value for D
      display.clearDisplay();

      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("D String");

      display.setTextSize(1);
      display.setCursor(0, 32);
      display.println(peak);
      display.display();
      delay(500);

      if ((D - 5) <= peak && peak <= (D + 5)) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Tuned");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_green, LOW);


      } else if ((D - 5) > peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Flat");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_yellow, LOW);

      } else if ((D + 5) < peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Sharp");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_red, LOW);

      }
      delay(250);
      digitalWrite(led_green, HIGH);
      digitalWrite(led_yellow, HIGH);
      digitalWrite(led_red, HIGH);
      break;

    case 3:
      display.clearDisplay();
      samplingPeriod = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
      digitalWrite(led_D, HIGH);
      digitalWrite(led_G, LOW);
      display.setTextSize(1);
      display.setCursor(0, 0);
      // Display static text
      display.println("G String");
      display.display();
      delay(500);

      for (int i = 0; i < SAMPLES; i++) {
        microSeconds = micros();

        vReal[i] = analogRead(A0);

        vImag[i] = 0;
      }

      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      //peak = 125.15; //Avergae Piezo value for G
      display.clearDisplay();

      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("G String");

      display.setTextSize(1);
      display.setCursor(0, 32);
      display.println(peak);
      display.display();
      delay(500);

      if ((G - 5) <= peak && peak <= (G + 5)) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Tuned");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_green, LOW);


      } else if ((G - 5) > peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Flat");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_yellow, LOW);

      } else if ((G + 5) < peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Sharp");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_red, LOW);

      }
      delay(250);
      digitalWrite(led_green, HIGH);
      digitalWrite(led_yellow, HIGH);
      digitalWrite(led_red, HIGH);
      break;

    case 4:
      display.clearDisplay();
      samplingPeriod = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
      digitalWrite(led_G, HIGH);
      digitalWrite(led_B, LOW);
      display.setTextSize(1);
      display.setCursor(0, 0);
      // Display static text
      display.println("B String");
      display.display();
      delay(500);

      for (int i = 0; i < SAMPLES; i++) {
        microSeconds = micros();

        vReal[i] = analogRead(A0);

        vImag[i] = 0;
      }

      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      //peak = 213.30; //Avergae Piezo value for B
      display.clearDisplay();
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("B String");

      display.setTextSize(1);
      display.setCursor(0, 32);
      display.println(peak);
      display.display();
      delay(500);

      if ((B - 5) <= peak && peak <= (B + 5)) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Tuned");
        display.display();
        delay(500);
        display.clearDisplay();

      } else if ((B - 5) > peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Flat");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_yellow, LOW);

      } else if ((B + 5) < peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("sharp");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_red, LOW);

      }
      delay(250);
      digitalWrite(led_green, HIGH);
      digitalWrite(led_yellow, HIGH);
      digitalWrite(led_red, HIGH);
      break;

    case 5:
      display.clearDisplay();
      samplingPeriod = round(1000000 * (1.0 / SAMPLING_FREQUENCY));
      digitalWrite(led_B, HIGH);
      digitalWrite(led_E4, LOW);
      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("E4 String");
      display.display();
      delay(500);

      for (int i = 0; i < SAMPLES; i++) {
        microSeconds = micros();

        vReal[i] = analogRead(A0);

        vImag[i] = 0;
      }

      FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
      FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);
      //peak = 280.41; //Avergae Piezo value for E4
      display.clearDisplay();

      display.setTextSize(1);
      display.setCursor(0, 0);
      display.println("E4 String");

      display.setTextSize(1);
      display.setCursor(0, 32);
      // Display Peak frequency
      display.println(peak);
      display.display();
      delay(500);

      if ((E4 - 5) <= peak && peak <= (E4 + 5)) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Tuned");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_green, LOW);


      } else if ((E4 - 5) > peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        display.println("Flat");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_yellow, LOW);

      } else if ((E4 + 5) < peak) {
        display.setTextSize(1);
        display.setCursor(0, 16);
        // Display static text
        display.println("Sharp");
        display.display();
        delay(500);
        display.clearDisplay();
        digitalWrite(led_red, LOW);
      }
      delay(250);
      digitalWrite(led_green, HIGH);
      digitalWrite(led_yellow, HIGH);
      digitalWrite(led_red, HIGH);
      break;
  }
}

The code is functional without the following lines

FFT.Windowing(vReal, SAMPLES, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(vReal, vImag, SAMPLES, FFT_FORWARD);
FFT.ComplexToMagnitude(vReal, vImag, SAMPLES);

by replacing this declaring "peak" the average reading of the sensor for that string the code functions as intended.

peak = 125.15; //Avergae Piezo value for G

I have changed the compiler to display all warnings and no errors are returned only " Low memory available which I believe is the cause of the problem. For reference, I am using an Arduino UNO R3.

Any advice on fixing this would be greatly appreciated, many thanks.
Adam

Hello, do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation for your ask).

Did you really mean greater than?

is where you should. Do as it says.

Looks like you may have tried to post all your code using the </> button in the button bar in the window where you write your post, but missed where it said to do!

Also, before you paste your code using that method, it would be good to use the autoformat tool in the IDE to put it into a format that makes it easy (er) to read.

Oh, and welcome to the community!

a7

thanks will update the post now

Have updated post with the correct version of code

thanks post has been updated

OK, thanks.

But you need to post all the code, a complete sketch that compiles even if it doesn't yet do what you want.

Just taking a quick low level peek at what you did post, right away I see this


        vImag[i] = 0;
        // imaginary value will always equal 0

        (micros() < (microSeconds + samplingPeriod))
        //wait till all samples are taken
        ; 

Which when manually formatted to a common standard is the same as

        vImag[i] = 0;

        (micros() < (microSeconds + samplingPeriod)); 

(I and others will often just ignore comments, they can vary from misleading to useless, not saying yours are, but that's why I stripped them here)

Which is the same as

        vImag[i] = 0;

yes, that 2nd line of code is a way to do… nothing but spend a little time calculating something, then throwing it away.

Welcome to C/C++ - totally possible to say something the compiler has no trouble with but doesn't do what you want or even anything.

So…

In the IDE preferences turn up all compiler warnings, it is possible (likely, but not 100 %) that the compiler might warn you about something sketchy in your sketch.

Verify (compile) the program and look through the warnings to see if there are many of this kind of thing, and begin trying to eliminate all warnings.

TBH once I hit that, I stopped, wrote this and will wait for you next posting in which we hope to see the entire program, don't try to help by isolating or briefing it in any way.

a7

But that doesn't look like the code you posted before, so now my comment doesn't make sense, so...I'll leave this topic now.

Good luck.

Thanks for the feedback have altered the code and post based on your advice. If any more insight can be proved on the matter would be greatly appreciated.

The above line is the only place where peak is calculated, I don’t see how it can compile, but even if it does, it does not get calculated again ever.

So it is no surprise that printing it to the LCD doesn’t work.

Did you write this code, or use some code you found to make a larger program?

A common noob mistake is to think that such a line of code creates some kind of active relationship between peak and the expression on the right hand side of the equal sign, so it becomes a shorthand for the expression. That’s not how it works.

I’m not saying you have made that mistake, but TBH I can’t see how this code woukd function.

And there are still nonsense lines

 microSeconds = micros();

microSeconds doesn’t appear to be used; what is your understanding of the purpose of that line?

I didn’t mean to tell you to strip your own comments, I only did that earlier to show what the compiler ended up seeing.

I’m unable to work the code much because of all the libraries. Post the lines of compiler output that describe your memory use. Using most of the memory is not necessarily a problem.

Now I ask what exactly you mean that the posted code you “adjusted” is broken. I have inferred that it compiles, but doesn’t print correct values.

Please supply a link to the source(s) of your inspiration for the code.

Also refrain from editing earlier posts beyond typos… it kinda makes trash of the thread because the later posts will now be referring to content that is not what it was when they were written. Potentially confusing.

a7

Hello adampayne
I´ve made a low lwvel flight about the sketch and following questions arose:

  • Did you code the sketch for yourself?
  • Did you made any tests during the development times?
  • Why some some variable intializations match not to the datatyp declarated?
  • Why the cases carrying magic numbers?
  • Why do you uses ELSE/IF instead of nested SWITCH/CASE?
  • Why the sketch contain 37 calls of the delay() function in range of 250msec to 2500msec?
  • Do you will run a RT-FTT ?

Take some time, study the IPO model and cleanup the sketch. Sometimes the usage of the enum and array instructions, and some other C++, are very very useful to code a human readable sketch, too.
Have a nice day and enjoy coding in C++.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.