8 bit byte array to float - Spectrum Shield - LED Wall

Hi everyone,

I was hoping I wouldn't be asking for help so quickly in to my project. Last week I didn't even know what an Arduino was, this week I have got this far but have an issue. I know my code is terrible, I hope that I can grow it as the months go on and fine tune it. However, I have hit a wall for the next step of my project.

I have an array called Byte that takes the EQ bands from sound and put them in 0 to 7 of the byte called Band. I would really like these to be a float so I can multiply them up to 4095 for my LEDs. I have looked for about 4 hours but have move ZERO paces forward. Can anyone help? Even just point me in the right direction?

Thank you in advance.

//    ------------                                  ---u----
//    ARDUINO   13|-> SCLK (pin 25)           OUT1 |1     28| OUT channel 0
//              12|                           OUT2 |2     27|-> GND (VPRG)
//              11|-> SIN (pin 26)            OUT3 |3     26|-> SIN (pin 11)
//              10|-> BLANK (pin 23)          OUT4 |4     25|-> SCLK (pin 13)
//               9|-> XLAT (pin 24)             .  |5     24|-> XLAT (pin 9)
//               8|                             .  |6     23|-> BLANK (pin 10)
//               7|                             .  |7     22|-> GND
//               6|                             .  |8     21|-> VCC (+5V)
//               5|                             .  |9     20|-> 2K Resistor -> GND
//               4|                             .  |10    19|-> +5V (DCPRG)
//               3|-> GSCLK (pin 18)            .  |11    18|-> GSCLK (pin 3)
//               2|                             .  |12    17|-> SOUT
//               1|                             .  |13    16|-> XERR
//               0|                           OUT14|14    15| OUT channel 15
//    ------------                                  --------

//LCD Function	LCD Pin	Arduino
//VSS	1	GND
//VDD	2	+5V
//VO	3	10k – 20k Potentiometer
//RS	4	Pin 2
//RW	5	GND
//Enable	6	Pin 6
//D0	7	Not needed for 4-Bit
//D1	8	Not needed for 4-Bit
//D2	9	Not needed for 4-Bit
//D3	10	Not needed for 4-Bit
//D4	11	Pin 7
//D5	12	Pin 8
//D6	13	Pin 12
//D7	14	Pin 14 which is A0
//A (Backlight +)	15	+4.2V
//K (Backlight -)	16	GND


#include <Tlc5940.h>
#include <LiquidCrystal.h>


float SpectrumLeft[7];
float SpectrumRight[7];
byte Band; //this is what the shield spectrum reader uses when it reads each frequency and then plugs it into SpectrumLeft[]


LiquidCrystal lcd(2, 6, 7, 8, 12, 14); //create the lcd variable


void setup () {

//Spectrum Shield  
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT); 
//Spectrum Shield init and reset 
  digitalWrite(4,LOW);  //pin 4 is strobe on shield
  digitalWrite(5,HIGH); //pin 5 is RESET on the shield
  digitalWrite(4,HIGH);
  digitalWrite(4,LOW);
  digitalWrite(5,LOW);
  
//LCD init + reset
//  lcd.clear();                    //clear the LCD during setup
//  lcd.begin(16,4);                //define the columns (16) and rows (4)
  
//init TLC chip + reset
  Tlc.init(4095);
  Tlc.clear(); 
  Tlc.update();

//Serial init for troublehsooting of input data
   Serial.begin(9600);
}



void loop () {
  readSpectrum();
//  writeLCD();
      writeTLC();  
  }
  
//Write Spectrum Values to LCD screen  
void writeLCD(){
  lcd.setCursor(0,1);            //move the cursor to the 2nd line
  lcd.print(SpectrumLeft[0]);          //print...
  lcd.setCursor(0,2);            //move the cursor to the 2nd line    
  lcd.print(SpectrumLeft[1]);
  lcd.setCursor(3,1);            //move the cursor to the 2nd line  
  lcd.print(SpectrumLeft[2]);
  lcd.setCursor(3,2);            //move the cursor to the 2nd line  
  lcd.print(SpectrumLeft[3]);
  lcd.setCursor(6,1);            //move the cursor to the 2nd line  
  lcd.print(SpectrumLeft[4]); 
  lcd.setCursor(6,2);            //move the cursor to the 2nd line  
  lcd.print(SpectrumLeft[5]);
  lcd.setCursor(9,1);            //move the cursor to the 2nd line  
  lcd.print(SpectrumLeft[6]);
      delay(250); 
      lcd.clear();                   //clear LCD, since we are still on 2nd line... 
}
  
//Read Spectrum Shield, put values in SpectrumLeft[BAND] 
void readSpectrum() {
  // Band 0 = Lowest Frequencies.
  for(Band=0;Band <6; Band++){
    SpectrumLeft[Band] = analogRead(0); //left 
    digitalWrite(4,HIGH);  //Strobe pin on the shield
    digitalWrite(4,LOW);
    
      for(int i = 0; i < 6; i++)

       //Drop value down, get rid of shit  
    if (SpectrumLeft[Band] < 19)
    {
    SpectrumLeft[Band] = 0;
    }
    
    Serial.println(SpectrumLeft[1]);
    }
}
    
void writeTLC(){
  
Tlc.set(1, SpectrumLeft[0]*256);

Tlc.set(5, SpectrumLeft[2]*256); 

Tlc.set(7, SpectrumLeft[4]*256); 

Tlc.set(11, SpectrumLeft[5]*256);
//Tlc.set(5, SpectrumLeft[4]);
//Tlc.set(6, SpectrumLeft[5]);
Tlc.update(); 

}

I would really like these to be a float so I can multiply them up to 4095 for my LEDs.

No, sorry, don't follow that argument.

Please use code tags for code, not quote tags.

Apologies, I have amended that.

I could probably explain the laws of thermodynamics better than I can explain this, I shall try my up most to convey my problem. When I read SpectrumLeft[Band] in the monitor I get a full number without a decimal point. I have been trying to figure out how I change this number to a decimal so I can multiply it up to 4095 for my LEDs. At the moment I can't get anything higher than the value 45. The plan is to get everything working in a rag tag manner then hopefully improve the code over the months.

I hope I have explained that a little bit better.

I could probably explain the laws of thermodynamics better than I can explain this

You can't win.
You can't break even.
You can't quit the game.
(And the Zeroth Law - you have to play the game)

What sort of range of values do you start with?

hehe maybe I should have thought about the second law when I said to myself I don't need a resistor on my TLC chip.

Standing i.e no music running through the shield I hit around < 4 on each of the seven bands.

Playing music I hit < 34 on each band, nothing more. This is with volume on full pelt, I guess my only aim is to somehow get these values up to 4095. Is there anything you could suggest?

I tried: map() - Arduino Reference

Using band = map(band,0, 40, 100, 4095);

But this didn't seem to have the desired effect, I placed this inside the ReadSpectrum function.

Well, first, the code could use some work. Let's dig into that:

//Read Spectrum Shield, put values in SpectrumLeft[BAND] 
void readSpectrum() {
  // Band 0 = Lowest Frequencies.
  for(Band=0;Band <6; Band++){
    SpectrumLeft[Band] = analogRead(0); //left 
    digitalWrite(4,HIGH);  //Strobe pin on the shield
    digitalWrite(4,LOW);
    
      for(int i = 0; i < 6; i++)

       //Drop value down, get rid of shit  
    if (SpectrumLeft[Band] < 19)
    {
    SpectrumLeft[Band] = 0;
    }
    
    Serial.println(SpectrumLeft[1]);
    }
}

You have 7 bands, and you're setting 0 through 5 in your for loop. That should be 0-6.

Next, within your for loop, you have another for loop that tries to filter out values beneath a threshold, and thus needlessly grooms the array contents 7 (well, six...) times per cycle. Don't do that. Just check for the threshold during each reading. Check it:

void readSpectrum() {
  uint8_t  i;
  for (i = 0; i < 7; i++) {
    SpectrumLeft[i] = analogRead(0);
    
    // Filter out values beneath a threshold
    if (SpectrumLeft[i] < 19) SpectrumLeft[i] = 0;
    
    // Strobe shield pin
    digitalWrite(4, HIGH);
    digitalWrite(4, LOW);
  }
}

Also, I see you're using Serial.println() to print the value in the second band. Is that what you intended? (Just showing that something is being read, and using band 1 as an arbitrary band to use?)

Alright, now let's address the signal readings...

Scaling an integer value that is too low only gives you really poor resolution, and will be highly susceptible to noise. Converting an integer to a float does not improve this situation any, it's just a less efficient way to produce the same poor results. Try outputting a sine wave (use a tone generator from your PC or phone) at 1kHz at full volume, then use a simple test sketch to see what you get:

void setup () {
  Serial.begin(9600);
  
  // Reset MSGEQ7 chips
  pinMode(PIN_RESET, OUTPUT);
  digitalWrite(PIN_RESET, HIGH);
  digitalWrite(PIN_STROBE, LOW);
  digitalWrite(PIN_RESET, LOW);
}

void loop () {
  uint16_t band[7];
  uint8_t i;
  
  // Read analog values and print them to serial console
  for (i = 0; i < 7; i++) {
    // Read value
    band[i] = analogRead(PIN_OUT);
    
    // Strobe
    digitalWrite(PIN_STROBE, HIGH);
    digitalWrite(PIN_STROBE, LOW);
    
    // Print reading
    Serial.print(band[i]);
    Serial.print("  ");
  }
  
  // End line
  Serial.println();
  
  delay(50);
}

Add your pin constants and see how that works for you. You should get a high value for the band(s) closest to 1kHz (or whatever your tone frequency is), and the ones farthest from the tone frequency should have low values. If you're still getting low values on the bands where you should get a strong signal, you need to increase the audio gain being sent to the MSGEQ7 ICs. If you don't have a way to do that from your source device, you'll need to build an op-amp amplifier circuit on the breadboard area of the shield.