Teensy 3.5 with MIKROE-506 (WM8731)

Status
Not open for further replies.

dassismiranda

New member
I'm trying to make teensy 3.5 record audio with MIKROE-506 however what I get is only a big hiss, as I'm not very knowledgeable and I'm still learning, I believe I'm putting pinouts in the wrong places. Can anybody help me ?


What followed was this

// Mikroe Teensy 3.1
// ------ ----------
// SCK 9
// MISO 13
// MOSI 22
// ADCL ??
// DACL 23
// SDA 18
// SCL 19
// 3.3V +3.3V
// GND GND
 
First, thanks for your support.

I make the connection of ADCL to pin 23. But, still getting only hiss noise when i use the Recorder.ino from the Exemples. See the code below:


Code:
// Record sound as raw data to a SD card, and play it back.
//
// Requires the audio shield:
//   http://www.pjrc.com/store/teensy3_audio.html
//
// Three pushbuttons need to be connected:
//   Record Button: pin 0 to GND
//   Stop Button:   pin 1 to GND
//   Play Button:   pin 2 to GND
//
// This example code is in the public domain.

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

// GUItool: begin automatically generated code
AudioInputI2S            i2s2;           //xy=105,63
AudioAnalyzePeak         peak1;          //xy=278,108
AudioRecordQueue         queue1;         //xy=281,63
AudioPlaySdRaw           playRaw1;       //xy=302,157
AudioOutputI2S           i2s1;           //xy=470,120
AudioConnection          patchCord1(i2s2, 0, queue1, 0);
AudioConnection          patchCord2(i2s2, 0, peak1, 0);
AudioConnection          patchCord3(playRaw1, 0, i2s1, 0);
AudioConnection          patchCord4(playRaw1, 0, i2s1, 1);
AudioControlWM8731master     wm8731;     //xy=265,212
// GUItool: end automatically generated code

// For a stereo recording version, see this forum thread:
// https://forum.pjrc.com/threads/46150?p=158388&viewfull=1#post158388

// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord = Bounce(0, 8);
Bounce buttonStop =   Bounce(1, 8);  // 8 = 8 ms debounce time
Bounce buttonPlay =   Bounce(2, 8);


// which input on the audio shield will be used?
const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;


// Use these with the Teensy Audio Shield
//#define SDCARD_CS_PIN    10
//#define SDCARD_MOSI_PIN  7
//#define SDCARD_SCK_PIN   14

// Use these with the Teensy 3.5 & 3.6 SD card
#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

// Use these for the SD+Wiz820 or other adaptors
//#define SDCARD_CS_PIN    4
//#define SDCARD_MOSI_PIN  11
//#define SDCARD_SCK_PIN   13


// Remember which mode we're doing
int mode = 0;  // 0=stopped, 1=recording, 2=playing

// The file where data is recorded
File frec;

void setup() {
  // Configure the pushbutton pins
  pinMode(0, INPUT_PULLUP);
  pinMode(1, INPUT_PULLUP);
  pinMode(2, INPUT_PULLUP);

  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(60);

  // Enable the audio shield, select input, and enable output
  wm8731.enable();
  wm8731.inputSelect(myInput);
  wm8731.volume(0.5);

  // Initialize the SD card
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here if no SD card, but print a message
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
}


void loop() {
  // First, read the buttons
  buttonRecord.update();
  buttonStop.update();
  buttonPlay.update();

  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
    Serial.println("Record Button Press");
    if (mode == 2) stopPlaying();
    if (mode == 0) startRecording();
  }
  if (buttonStop.fallingEdge()) {
    Serial.println("Stop Button Press");
    if (mode == 1) stopRecording();
    if (mode == 2) stopPlaying();
  }
  if (buttonPlay.fallingEdge()) {
    Serial.println("Play Button Press");
    if (mode == 1) stopRecording();
    if (mode == 0) startPlaying();
  }

  // If we're playing or recording, carry on...
  if (mode == 1) {
    continueRecording();
  }
  if (mode == 2) {
    continuePlaying();
  }

  // when using a microphone, continuously adjust gain
  if (myInput == AUDIO_INPUT_MIC) adjustMicLevel();
}


void startRecording() {
  Serial.println("startRecording");
  if (SD.exists("RECORD.RAW")) {
    // The SD library writes new data to the end of the
    // file, so to start a new recording, the old file
    // must be deleted before new data is written.
    SD.remove("RECORD.RAW");
  }
  frec = SD.open("RECORD.RAW", FILE_WRITE);
  if (frec) {
    queue1.begin();
    mode = 1;
  }
}

void continueRecording() {
  if (queue1.available() >= 2) {
    byte buffer[512];
    // Fetch 2 blocks from the audio library and copy
    // into a 512 byte buffer.  The Arduino SD library
    // is most efficient when full 512 byte sector size
    // writes are used.
    memcpy(buffer, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    memcpy(buffer+256, queue1.readBuffer(), 256);
    queue1.freeBuffer();
    // write all 512 bytes to the SD card
    elapsedMicros usec = 0;
    frec.write(buffer, 512);
    // Uncomment these lines to see how long SD writes
    // are taking.  A pair of audio blocks arrives every
    // 5802 microseconds, so hopefully most of the writes
    // take well under 5802 us.  Some will take more, as
    // the SD library also must write to the FAT tables
    // and the SD card controller manages media erase and
    // wear leveling.  The queue1 object can buffer
    // approximately 301700 us of audio, to allow time
    // for occasional high SD card latency, as long as
    // the average write time is under 5802 us.
    //Serial.print("SD write, us=");
    //Serial.println(usec);
  }
}

void stopRecording() {
  Serial.println("stopRecording");
  queue1.end();
  if (mode == 1) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
    }
    frec.close();
  }
  mode = 0;
}


void startPlaying() {
  Serial.println("startPlaying");
  playRaw1.play("RECORD.RAW");
  mode = 2;
}

void continuePlaying() {
  if (!playRaw1.isPlaying()) {
    playRaw1.stop();
    mode = 0;
  }
}

void stopPlaying() {
  Serial.println("stopPlaying");
  if (mode == 2) playRaw1.stop();
  mode = 0;
}

void adjustMicLevel() {
  // TODO: read the peak1 object and adjust sgtl5000_1.micGain()
  // if anyone gets this working, please submit a github pull request :-)
}

I can't find the problem.

When i use the WavFilePlayer.ino work perfectly.

Best regards
 
I looked into this today. The WM8731 inputSelect() function was never implemented, so even though everything else was working, you couldn't actually tell the chip to actually give you the input signal.

Here's a fix.

https://github.com/PaulStoffregen/Audio/commit/e83ddeefdd03a90180857ecd66783c12bf686164

DSC_0108_web.jpg
 
Last edited:
Hi,

Paul, is you board run in Slave or Master mode? Because I heard that the MIKROE-506 is intended to be used as a master device (due to the cristal in-chip). I see no visible desoldering/modification on your board, so I presume you run it Master. Maybe I'm wrong...

I ask this because I recently own a very similar board using the WM8731, the audioinjector (https://www.kickstarter.com/project...r-zero-sound-card-for-the-raspberry-p?lang=fr), formerly designed for use with raspberry pi zero. The design looks interesting and compact, good for prototyping future projects.

Have you any advice about using this one with the teensy regarding your experience with the MIKROE ?

I've already check the pins mapping for compatibility, all seems 100% OK.

Cherrz
 
is you board run in Slave or Master mode?

In this case, Teensy runs in I2S slave mode.

For most other chips, Teensy would run in I2S master mode. Teensy does support both modes, but when Teensy runs in slave mode using other inputs or outputs (like the ADC & DAC pins on Teensy) tend to have trouble. You can combine those non-I2S inputs & outputs with I2S master mode, but usually not with slave mode I2S.

The other caveat of slave mode is all the code still expects 44.1 kHz sample rate. With master mode, Teensy controls the timing so you always get correct tones and speeds. I2S slave mode does not "learn" the external timing. It assumes the timing is the same 44.1 kHz Teensy would have used in master mode.


Have you any advice about using this one with the teensy regarding your experience with the MIKROE ?

Yes, I put the advice info in the comments of the example sketch:

https://github.com/PaulStoffregen/A...reTesting/WM8731MikroSine/WM8731MikroSine.ino

In Arduino, with a Teensy board selected in Tools > Boards, you can open example this by clicking File > Examples > Audio > HardwareTesting > WM8731MikroSine.

Check out the comments about which crystal to use for 44.1 kHz sample rate...
 
Check out the comments about which crystal to use for 44.1 kHz sample rate...

Thanks a lot, It seems clear to me now.
On my board (audioinjector) I've a 12 mhz cristal, not 12.288 nor 11.2896. It's a bit strange choice for this design but maybe it's normal. I'll test it first with the stock cristal to see what it return. Then, for proper work (and tone), I'll change the cristal for a 11.2896, but I don't have theses right now.

Alternatively, I've heard that removing the cristal is also possible, by configuring the Teensy as a Master device that generate the clock. Is that right?
 
Yes, years ago I did use I2S master mode with a modified Mikro 506. I didn't document the mods, but as I recall (from years ago) removing the crystal was necessary and an extra wire was needed for MCLK.

What exactly you would need to do with that audioinjector board, I can not say. I really don't use WM8731 much, other than the MikroE-506 is the hardware I use for testing Teensy's support for I2S slave mode.
 
Status
Not open for further replies.
Back
Top