DUE playing sound and receiving input at the same time?

Where you put your function definition does not matter.

It does NOT work. I have mistaken the waiting for .wav to finish as a delay. Sorry. I've made an edit right away btw.

So it does not really have 5sec delay - it just waits for .wav to finish (volume was too low and I thought it does work :confused: )

About those serial.prints, did they show you the delay's origin?

It's not a delay sadly. The program (like in the beginning) just waits for .wav to finish and then registers interrupts and goes to the next state. My interruptPins are not working - not interrupting a loop.

You need to declare interruptState as volatile since you are setting it in the ISR. You should also make the variable a single byte so you can access it without having to disable interrupts, make a copy and re-enable interrupts. Then, examine that variable inside your playSound() function and exit early if set

volatile uint8_t interruptState = 0;
...
void interruptToggle() {
  interruptState = 1;
}
...
// Playing assigned filename
void playSound(const char* cName) {
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);


  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
  if ( interruptState ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

Thanks @blh64 I think we're going somewhere.
Oh - the sketch does not play .wav anymore.

It tries to play .wav for a <sec. and interrupts. Serial monitor:

playing 
intro.wav
**beep (interrupt) sound**

Trying to debug and see the place when interrupt occurred:

...
void loop() {
  switch (state) {
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
    //kalba();
      Serial.print("interruptStateA ");
      Serial.println(interruptState);
               if (interruptState == 0) {
              playSound("intro.wav");
      Serial.print("interruptStateB ");
      Serial.println(interruptState);
               }
            else if (interruptState == 0 && isLanguageKey(key)) {
      Serial.print("interruptStateC ");
      Serial.println(interruptState);
                buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      Serial.print("interruptStateD ");
      Serial.println(interruptState);
      if (isKeyPressed()) {
      Serial.print("interruptStateE ");
      Serial.println(interruptState);
                   buttonBeep();
        if (isLanguageKey(key)) {
          processLanguage();
        }
        else {
      Serial.print("interruptStateF ");
      Serial.println(interruptState);
          keypresses[keyCounter] = key;
          keyDial();
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
...

Then loop won't even start intro.wav. Serial monitor:

interruptStateA 1
interruptStateC 1
interruptStateD 1
interruptStateD 1
...
//entering a number
...
5
playing 
ledaiLT.wav
interruptStateD 0
interruptStateD 0
interruptStateD 0

So interruptState somehow got true from the beginning.
But changes to 0 after accessing a wav file.

The system should wait for a language key, not any key. I should only use language keys as interruptPins - but it's a matrix, so it's not possible?
I've tried:

 else if (interruptState == 0 && isLanguageKey(key))

But system just hangs in "interruptStateA 1" in serial monitor.

If you are getting these interrupts without pressing any of the keys - how are your keys wired up? Are those inputs floating? Do you have pull-up or pull-down resistors installed? It is typical to enable internal pullups as well.

How about a schematic?

Sure. Wanted to take a picture, but you can't really see clearly much.
I've wired it according to other instructions provided in this forum. So I don't have push up/down resistors installed.

Keep in mind that "random" interrupt happens only once when just after powering/restarting the system.

EDIT: Unplugging Keypad completely also gives interrupt when starting a system.

Without any external pull-up/pull-down resistors, you need to define all your pins as INPUT_PULLUP.

Oh, that I have...
I thought it should be included in attachInterrupt somewhere.

  pinMode(pin_rows[ROW_NUM], INPUT_PULLUP);
  pinMode(pin_column[COLUMN_NUM], INPUT_PULLUP);

OK - it does work when adding the interruptPin with a physical pull-up resistor!
I've added a simple button to Pin 22 and it interrupts the .wav without any problems :slight_smile: and no random interruptions at the beginning.

...
byte interruptPin = 22;  // your interrupt pin
...
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptToggle, RISING);
...

Wiring same as this: https://roboticsbackend.com/wp-content/uploads/2019/05/schema_interrupt_button_led.png

But it's impractical to have the same wiring for all of 8 pins for a keypad. Probably the problem is in declaring INPUT_PULLUP?

In my situation I only need interruption when selecting a language - when any button in column 4 is being pressed (Buttons A, B, C, D). So in the sketch I only need pin 38 as an interrupt.

attachInterrupt(digitalPinToInterrupt(38), interruptToggle, RISING);

But how wire it? I cannot find an example of wiring a keypad as interrupt. Only a single button (which doesn't help in my example).

Once again, that is NOT how you do it. Those functions take a single pin to work with, not the entire array and using ROW_NUM and COLUMN_NUM as the index is Out of Bounds.
You need to iterate over your array and act on each pin.

for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], INPUT_PULLP);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLP);

Oh, sorry, these were some old lines. I have also tried with this:

  pinMode(52, INPUT_PULLUP);
  pinMode(50, INPUT_PULLUP);
  pinMode(48, INPUT_PULLUP);
  pinMode(46, INPUT_PULLUP);
  pinMode(44, INPUT_PULLUP);
  pinMode(42, INPUT_PULLUP);
  pinMode(40, INPUT_PULLUP);
  pinMode(38, INPUT_PULLUP);

Same result - random interrupts at the beginning.

ALSO - I've read more about random interrupts at the launch of a program. It seems it's a big problem with some Arduino boards.
Normally you would remove interrupt flag like that:

 EIFR = (1 << INTF0); // clear INT0 interrupt flag

But it does not work on DUE. Still searching.

I understood that my Keypad pins don't really deliver anythink usefult on attachInterrupt.
It seems I need a different method to interrupt .wav when 4th row button is being pressed.
From another thread(s):

Owing to the fact that you have to manually cycle through each row (or column, depending on which way you are holding your head at the time) in order to read which keys are pressed there is no way to relate a button to an interrupt.

If anyone has any ideas, please share. I am still searching :slight_smile: I will share it here once found.

It works! I just wanted to share here the solution for future searches. What you need to do is to get the 4th column of 4x4 keypad to work as an interrupt properly:
Set all row pins as output and column pins as input with pullup:

for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

Set row pins to low:
for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW);

Attach the 4th column pin as interrupt:
attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

And of course, fix the syntax overall (it was a bit messy :slight_smile: )
Full sketch:

#include <DAC.h>
#include <SD.h>
#include <SPI.h>
#include <Audio.h>
#include <Key.h>
#include <Keypad.h>

const byte ROW_NUM = 4;
const byte COLUMN_NUM = 4;

int code1 = 12345;  //The code I used, you can change it
int code2 = 45678;  //The code I used, you can change it
int code3 = 78900;  //The code I used, you can change it

int tot, i1, i2, i3, i4, i5;
char c1, c2, c3, c4;

char hexaKeys[ROW_NUM][COLUMN_NUM] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte hookPinA = 23;  // your interrupt pin
byte pin_rows[ROW_NUM] = {52, 50, 48, 46}; //connect to the row pinouts of the keypad
byte pin_column[COLUMN_NUM] = {44, 42, 40, 38}; //connect to the column pinouts of the keypad

Keypad myKeypad = Keypad(makeKeymap(hexaKeys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);

char keypresses[5];
char language;
char key;

volatile uint8_t interruptState = 0;
volatile byte hookOffState = 0;
int keyCounter = 0;

void setup() {
  // debug output at 9600 baud
  Serial.begin(9600);
  SD.begin(10);
  analogWriteResolution(12);

for( int i=0; i< ROW_NUM; ++i) pinMode(pin_rows[i], OUTPUT);
for( int i=0; i< COLUMN_NUM; ++i) pinMode(pin_column[i], INPUT_PULLUP);

for( int i=0; i< ROW_NUM; ++i) digitalWrite(pin_rows[i], LOW); 
 pinMode(hookPinA, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(hookPinA), hookOffToggle, CHANGE);
 attachInterrupt(digitalPinToInterrupt(pin_column[3]), interruptToggle, FALLING);

  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}


int state = 0;
const int STATE_OFF = 0;
const int STATE_IDLE = 1;
const int STATE_LISTEN_KEY = 2;
const int STATE_PLAYER = 3;

bool isLanguageKey(char customKey) {
  return ('A' == customKey || 'B' == customKey || 'C' == customKey || 'D' == customKey);
}

void loop() {
  switch (state) {
    case STATE_OFF:
    //listen for a telephone receiver to be removed
      if (hookOffState == 1) {
        interruptState = 0;
        state = STATE_IDLE;
                      }
               else if (hookOffState == 0) {
               }
        break;
    case STATE_IDLE:
    //listen for a language key. Cannot dial a number before
               if (interruptState == 1) {
         isKeyPressed(); //get the key input
         buttonBeep();
        processLanguage();
        state = STATE_LISTEN_KEY;
               }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
               else {
      playSound("intro.wav");
        }
      break;
    case STATE_LISTEN_KEY:
    //listen for any key
      if (isKeyPressed()) {
        interruptState = 0;
        if (isLanguageKey(key)) {
          buttonBeep();
          processLanguage();
        }
        else  {
          buttonBeep();
          keypresses[keyCounter] = key;
          keyCounter++;
          if (keyCounter > 4) {
            state = STATE_PLAYER;
            //when 5 numbers are pressed - try to open the .wav file
          }
        }
      }
               else if (hookOffState == 0){
                state = STATE_OFF;
               }
      break;
    case STATE_PLAYER:
        //Play the audio and go back to state LISTEN
      calculateAndPlay();
      keyCounter = 0;
      interruptState = 0;
      state = STATE_LISTEN_KEY;
      break;
    default:
      break;
  }
}

void hookOffToggle() {     //detect a telephone receiver to be removed
hookOffState = digitalRead(hookPinA);
}

void interruptToggle() {
    interruptState = 1;
}

bool isKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY;
}

bool langKeyPressed() {
  key = myKeypad.getKey();
  return key != NO_KEY && isLanguageKey(key);
}

void processLanguage() { //press A/B/C/D keys - select 1 out of 4 languages
  keyCounter = 0;
  if (key == 'A') {
    Serial.println("   LT    ");
  }
  if (key == 'B') {
    Serial.println("   EN    ");
  }
  if (key == 'C') {
    Serial.println("   LV    ");
  }
  if (key == 'D') {
    Serial.println("   RU    ");
  }
  language = key;
}


void buttonBeep(){
      for (int j = 0; j < 200; j++) {
        for (int i = 0; i < 200; i++)
          analogWrite(DAC0, i);
        for (int i = 200; i >= 0; i--)
          analogWrite(DAC0, i);
      }
}

void backgroundHumm() {
      for (int j = 0; j < 256; j++) {
        for (int i = 0; i < 256; i++)
          analogWrite(DAC0, j);
          for (int j = 256; j >= 0; j--) {
            for (int i = 256; i >= 0; i--)
          analogWrite(DAC0, j);
      }
  }
}
 
void calculateAndPlay() {
  //if we have 4+1 numbers - proceed
  //the keys pressed are stored into chars I convert them to int then i did some multiplication to get the code as an int of xxxx
  i1 = (keypresses[0] - 48) * 10000;
  i2 = (keypresses[1] - 48) * 1000;
  i3 = (keypresses[2] - 48) * 100;
  i4 = (keypresses[3] - 48) * 10;
  i5 = (keypresses[4] - 48) * 1;  

  tot = i1 + i2 + i3 + i4 + i5;
  if (language == 'A') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLT.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLT.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLT.wav");
    }
    else //if the code is wrong you get a beep and audio message
  {
      playSound("blogasLT.wav");
    }
  }
  if (language == 'B') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiEN.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisEN.wav");
    }
    else if (tot == code3)
    {
      playSound("draugEN.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasEN.wav");
    }
  }
  if (language == 'C') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiLV.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisLV.wav");
    }
    else if (tot == code3)
    {
      playSound("draugLV.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasLV.wav");
    }
  }
  if (language == 'D') {
    if (tot == code1) //if the code is correct you trigger to play .wav
    {
      playSound("ledaiRU.wav");
    }
    else if (tot == code2)
    {
      playSound("zuvisRU.wav");
    }
    else if (tot == code3)
    {
      playSound("draugRU.wav");
    }
    else //if the code is wrong you get a beep and audio message
    {
      playSound("blogasRU.wav");
    }
  }
}

// Playing assigned filename
void playSound(const char* cName) {  
  File myFile = SD.open(cName);
  const int S = 1024; // Number of samples to read in block
  short buffer[S];
  // until the file is not finished
  Serial.println("playing ");
  Serial.println(cName);


  Audio.begin(44100, 200);
  delay(200);
  while (myFile.available()) {
    myFile.read(buffer, sizeof(buffer));
    // Prepare samples
    int volume = 512;
    //max volume 1024
    Audio.prepare(buffer, S, volume);
    Audio.write(buffer, S);
   if ( interruptState ) break;
   else if ( hookOffState == 0 ) break;
  }
  Audio.end();
  myFile.close();
  delay(50);
  DACC->DACC_CHDR = DACC_CHDR_CH1; //disable DAC1
}

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