SPI issue between FFT and Digipot

Status
Not open for further replies.

dsparks

Well-known member
I have a Teensy 3.1 (not the latest teensy duino version or arduino IDE) Running 1.0.6. It is connected to an audio board.

I have successfully gotten the FFT to analyze my incoming analog signal coming from my own made preamp. The preamp has a digipot on it that I control via the Teensy. I have the digipot assigned to the MOSI & SCLK pins of the audio board and it works accordingly by its self.

Once I apply both the FFT operation and the digipot operation, they stop working.

Any help on figuring out a solution to this would be helpful.


Thank you!
 
I have the digipot assigned to the MOSI & SCLK pins of the audio board and it works accordingly by its self.

Once I apply both the FFT operation and the digipot operation, they stop working.

Please follow the forum rule!

But my blind guess is perhaps you're also using the SPI from the audio lib, and the digipot code isn't properly using SPI transactions. But that's just a blind guess.... since I can't see your code that reproduces the problem, so I'm just guessing it might have this conflict.
 
Sorry, I forgot to post the code. Here it is.


#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

const int myInput = AUDIO_INPUT_LINEIN;


AudioInputAnalog audioInput;
AudioAnalyzeFFT1024 myFFT;
AudioOutputI2S audioOutput;

AudioConnection patchCord1(audioInput, 0, myFFT, 0);

AudioControlSGTL5000 audioShield;

byte dpotaddress = 0x11; //set address for digipot
int dpotCS= 5; //digipot slave select pin


void setup() {

AudioMemory(12);

audioShield.enable();
audioShield.inputSelect(myInput);
audioShield.volume(0.5);


myFFT.windowFunction(AudioWindowHanning1024);


SPI.setMOSI(7);
SPI.setSCK(14);

digitalPotWrite(150);


}

void loop() {
float n;
int i;

if (myFFT.available()) {
// each time new FFT data is available
// print it all to the Arduino Serial Monitor
Serial.print("FFT: ");
for (i=0; i<40; i++) {
n = myFFT.read(i);
if (n >= 0.01) {
Serial.print(n);
Serial.print(" ");
} else {
Serial.print(" - "); // don't print "0.00"
}
}
Serial.println();
}
}


int digitalPotWrite(int potV)
{
digitalWrite(dpotCS, LOW);
SPI.transfer(dpotaddress);
SPI.transfer(potV);
digitalWrite(dpotCS, HIGH);
}


Thanks for the help.
 
My apologies.

I found my error. Thats why its bad to code late at night without sleep. lol

I left out the:

pinMode (dpotCS, OUTPUT);

SPI.begin();

And so it cause things to stop.

All good now. So far.
 
Well when I combine the two to also include audio output, it fails now! As long as I dont try to set the digipot and comment out the SPI lines of code, the audio comes out ok and the FFT works as well. Please help

NOTE: Using 96mhz setting with Arduino IDE 1.6.5 - teensyduino 1.24

// FFT Test

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>


AudioInputAnalog adc1;
AudioOutputI2S i2s1;
AudioAnalyzeFFT1024 fft1;
AudioConnection patchCord1(adc1, 0, fft1, 0);
AudioConnection patchCord2(adc1, 0, i2s1, 0);
AudioConnection patchCord3(adc1, 0, i2s1, 1);

AudioControlSGTL5000 audioShield;

byte dpotaddress = 0x11; //set address for digipot
int dpotCS= 5; //digipot slave select pin
float level[19];

int mgain = 150;

void setup() {

Serial.begin(9600);

// Audio connections require memory to work. For more
// detailed information, see the MemoryAndCpuUsage example
AudioMemory(12);

// Enable the audio shield and set the output volume.
audioShield.enable();
audioShield.volume(0.9);

// Configure the window algorithm to use
fft1.windowFunction(AudioWindowHanning1024);

pinMode (dpotCS, OUTPUT);

pinMode (A2, INPUT);

SPI.begin();
SPI.setMOSI(7);
SPI.setSCK(14);

delay(5000);

digitalPotWrite(200);

Serial.println("OK");


}


void loop() {

if(fps>500) {
if (mgain > 253) { mgain = 150; }

digitalPotWrite(mgain);

mgain++;
fps = 0;

}



if (fft1.available()) {

level[0] = fft1.read(0) * 100;
level[1] = fft1.read(1) * 100;
level[2] = fft1.read(2, 3) * 100;
level[3] = fft1.read(4, 6) * 100;
level[4] = fft1.read(7, 10) * 100;
level[5] = fft1.read(11, 15) * 100;
level[6] = fft1.read(16, 22) * 100;
level[7] = fft1.read(23, 32) * 100;
level[8] = fft1.read(33, 46) * 100;
level[9] = fft1.read(47, 66) * 100;
level[10] = fft1.read(67, 93) * 100;
level[11] = fft1.read(94, 131) * 100;
level[12] = fft1.read(132, 184) * 100;
level[13] = fft1.read(185, 257) * 100;
level[14] = fft1.read(258, 359) * 100;
level[15] = fft1.read(360, 511) * 100;


for (int i=0; i<16; i++) {

Serial.print(level);
Serial.print(",");

}

Serial.print(" ---- ");
Serial.println(mgain);


}


}


int digitalPotWrite(int potV)
{
digitalWrite(dpotCS, LOW);
SPI.transfer(dpotaddress);
SPI.transfer(potV);
digitalWrite(dpotCS, HIGH);
return false;
}
 
WMXZ,

Could you please explain that in a little more detail as it would pertain to my code please?

Im not sure why I would need transactions, as the only device that Im aware of using the SPI is my digipot. Unless there is some hidden SPI action going on with the audio board to operate.

Thank you!
 
I tried to reproduce your issue using the code from msg #5, but it does not compile. I get:

sketch_nov30b.ino: In function 'void loop()':
sketch_nov30b.ino:60:7: error: 'fps' was not declared in this scope
'fps' was not declared in this scope

Indeed, there's no definition of that variable anywhere in the code you posted.

First, before you post again, test with the latest Teensyduino. Let's not waste precious time over issues that may have already been fixed. Always confirm your problem happens with the latest stable release.

If so, please post a complete program which demonstrates your problem. If I can copy the code into Arduino and reproduce your issue, odds are very good I'll find a solution/workaround or fix whatever is wrong. But if you do not post a complete program, instead you'll get a message from me much like this one, which doesn't help you very much!
 
Sorry for the poor example.

I have upgraded to Arduino IDE 1.6.6 and Teensyduino 1.26

Have updated all the libraries to their current versions.

When running the code below, which I have stripped out all of the FFT code, to simplify things, it fails to produce any output to the line out.

I also noticed, the LED (pin13) does go bright just after booting then turns off. I can also hear little clicks every time the digipot cycles through to increase the gain by one during the loop I have set up for testing. And when I comment out the SPI code (SPIbegin, SETmosi, SETsck, digitalPotWrite), the LED(pin13) on the teensy turns on and fades slightly as the audio signal passes through and out to the line out. I have also tested with and without all of the libraries included in the code directly as mentioned above (Audio.h , Wire.h , SPI.h , SD.h , SerialFlash.h)

This is not my first use of the Teensy , Audioboard, or Arduino coding. In fact I have lots of projects using them and operating fine within the older version stack. So jumping to the new versions has proven buggy in my experience. Any further help is appreciated. Thank you!


Code:
#include <Audio.h>
#include <SPI.h>


AudioInputAnalog         adc1;        
AudioOutputI2S           i2s1;         

AudioConnection          patchCord2(adc1, 0, i2s1, 0);
AudioConnection          patchCord3(adc1, 0, i2s1, 1);

AudioControlSGTL5000 audioShield;

byte dpotaddress = 0x11;  //set address for digipot
int dpotCS= 5;  //digipot slave select pin
int mgain = 150;

void setup() {

  Serial.begin(9600);

  AudioMemory(12);
  audioShield.enable();
  audioShield.volume(0.9);


  pinMode (A2, INPUT);

// set the slaveSelectPin as an output:
  pinMode (dpotCS, OUTPUT);
  pinMode (dpotCS, HIGH);
  // initialize SPI:
  SPI.begin();
  SPI.setMOSI(7);
  SPI.setSCK(14);

  digitalPotWrite(200);

  Serial.println("OK");

  
}

elapsedMillis fps;

void loop() {

  if(fps>500) {
    if (mgain > 253)  { mgain = 150; }

   digitalPotWrite(mgain);

    mgain++;
    fps = 0;
  
  }


Serial.print("GAIN: ");
Serial.println(mgain);

}


int digitalPotWrite(int potV)
{
  //SPI.beginTransaction();
  SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
  digitalWrite(dpotCS, LOW);
  SPI.transfer(dpotaddress);
  SPI.transfer(potV);
  digitalWrite(dpotCS, HIGH);
  SPI.endTransaction();
  return false;
}
 
Change this:

Code:
  SPI.begin();
  SPI.setMOSI(7);
  SPI.setSCK(14);

to this:

Code:
  SPI.setMOSI(7);
  SPI.setSCK(14);
  SPI.begin();

If you look at any of the examples which access the SD card, you'll see these SPI.setMOSI and SPI.setSCK are always used before SPI.begin. They must be configured before the SPI library initializes, because SPI reconfigures the MOSI, MISO and SCK pins in SPI.begin(). Two of those pins are needed for I2S communication to the audio shield. If SPI reconfigures those pins, they stop talking I2S and all communication with the SGTL5000 chip is lost.

Also, delete the pinMode line. It's not causing this problem, but you shouldn't enable the digital input if the pin has analog voltage.

So jumping to the new versions has proven buggy in my experience.

I'm pretty sure you can see this wasn't a bug in any version of Teensyduino.
 
Thank you very much!

By "buggy", I didnt mean to insult the cleanliness of the code within your and every one elses work. Just meant getting my setup to work with the new versions has not been without incident.

I couldnt really find any documentation or info on the fact that the SPI.begin had to take place afterwards. But makes sense now.

I have the FFT code working with the test code now as well. The gain is being adjusted as hoped.

Now to move on to the final code. Which combines a lot of other moving pieces. Im sure I'll be back for some more help.

Again, thank you very much!
 
Status
Not open for further replies.
Back
Top