Teensy Playing Audio file rejects Pulsein

Status
Not open for further replies.

Blitter

Member
My Teensy 3.1 has a piggybacked Audio Adaptor Board.
The Teensy is powered from a 1A 5V supply to Vin (pin 24), and the same 5V supply is powering a TSOP4856 IR Detector wired pin Pin 2.

1) Without trying to read IR via pulseIn, I can play .WAV files from my SD card without error.

2) Without audio playing, I can decode SIRC style pulses (600us on/off) modulated at 56kHz without error.

3) However, if there is a wav file playing, I cannot consistently decode IR pulses and sometimes the Teensy just locks up and I get a solid "beeeeeee" tone in the headphones. More often than not, pulseIn misses at least half of the pulses sent. I think the audio playback takes more clock cycles and "busy time" that won't allow Pulsein to run properly. I'd sure love to be able to play .WAVs while the Teensy looks for pulses and sends pulses, and looks for serial, all at the same time. Does anyone know if there is a fix, or am I just stuck?

Audio playback is boilerplate, lifted from Paul's WavFilePlayer example from the Audio library.
My IR code is sprinkled in for seasoning.

Code:
// Audio
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playWav1;       //xy=154,78
AudioOutputI2S           i2s1;           //xy=334,89
AudioConnection          patchCord1(playWav1, 0, i2s1, 0);
AudioConnection          patchCord2(playWav1, 1, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=240,153
// GUItool: end automatically generated code

int received[19];               


void setup()
{
  // IR INPUT INIT  
  pinMode(2, INPUT);  

  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(5);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.50);  // HEAPHONES

  // Set Pin Overrides
  SPI.setMOSI(7);
  SPI.setSCK(14);

  if (!(SD.begin(10))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}  

void loop()
{
  
  if (!playWav1.isPlaying())
  {
     playFile("SDTEST1.WAV");
  }
  
  CheckForIR();
}  

void playFile(const char *filename)
{
    Serial.print("Playing file: ");
    Serial.println(filename);

      // Start playing the file.  This sketch continues to
      // run while the file plays.
      playWav1.play(filename);

      // A brief delay for the library read WAV info
      delay(5);
}

void CheckForIR()
{
  int error = 0;
 
  if(digitalRead(2) == LOW)  
  {   
     received[0] = 0;

    // Get the Header pulse, and wait until it is done.
    while(digitalRead(2) == LOW){}
    
    for(int i = 1; i < 18; i++)  
    { 
      received[i] = pulseIn(2, LOW, 5000);  
    }
  }
}
 
I suspect the Audio library takes too many dedicated clock cycles to play nice with other clock-dependent operations. The three I2S clock signals (LRCLK @ 44.1 kHz, BCLK @ 1.41 MHz and MCLK @ 11.29 MHz) should have been my first evidence of this. ;)

Breaking out the audio functions to a serial-addressed Teensy+Audio Board+2W amp "module" might be the best bet.
 
It's probably the SD card access; but yes, the audio library is stealing too many ticks.

I can't recommend setting up interrupts with the current IR code, this will break the audio playback instead.

. Do you have to play audio from the SD card? Playing it from sketch or from spi flash would probably fix this.

another option would be to rewrite the IR pickup code to run an interrupt which fires 18 times to pick up the IR data.
 
Or find a lib which is able to receive ir in interrupt.
You could try mine, but its needs some tuning for the protocol you use. Is easy, but you need to know the protocol in detail.
I use it for my webradio, it receives data over wlan (uart 2 mbps), decodes mp3, plays it and updates the display with fft.
Receiving ir with this lib has no negative effect...
 
Those clocks are the issue. The problem is the audio library is running a bunch of stuff every 3 ms. When reading the SD card, it can consume about 1 ms or more, depending on the performance of your card. During that time, your CheckForIR() function can't run.

As a first step, you might try using the IRremote library. It uses an interrupt which runs regularly, rather than a function like CheckForIR. The IRremote interrupt should be able to interrupt the audio processing code, so there's a good chance it might just work.

If not, you could try building something with IntervalTimer. However, if you go down that path, you have to avoid spending any significant length of time inside your interrupt. It can't call a function like pulseIn(), which waits for a long time for the entire pulse. Instead, you'll have to read the pin, add the bit into a buffer or shift into a 32 bit int or something. Then have the main program look at all those readings and do something with them. If you had the IntervalTimer run every 100 us, then 32 bits collected would be 3.2 ms, which is longer than the audio update period, so you'd be sure to be able to "see" the result from your main program between the audio updates every 3 ms. That's quite a bit of coding to do, and something similar already exists inside IRremote, so I'd try to use the library first.
 
Thanks Guys. I can see from Ken's IRremote library, that it will ultimately be the direction to go. Being able to read pulses on interrupt is far more efficient than my current polling-type method.

Polyphonic sound is a goal, and the Teensy + SGTL5000 is a hard-to-beat combination ($34 for the pair). Using this dedicated "Sound Teensy" will allow me to queue sound effects in its ample memory, and layer in background music & narration WAVs read from SD as needed.

Teensy-to-Teensy communication over Serial2 (thanks for those back-side pads, Paul) will serve to trigger, with a quick pin-to-pin connection for lightning-fast triggering of the in-memory sound effects.

After working with the Teensy for only a couple of weeks, the limited Arduino Nano and Pro seem downright primitive by comparison.
 
After working with the Teensy for only a couple of weeks, the limited Arduino Nano and Pro seem downright primitive by comparison.

Glad it's working out so well.

Please help spread the word, if you can. I think a lot of people have a concept of what microcontroller can and can't do, which doesn't factor in the tremendous possibilities of these newer 32 bit chips when using well designed libraries.
 
Please help spread the word, if you can.
Will do! I already have one "convert" that was lamenting the SRAM ceiling on his current crop of Nanos. I think the attractive price - and the fact that you don't have to unplug your serial lines just to program it - will help win over the rest.
 
Status
Not open for further replies.
Back
Top