I am having issues connecting a second Qwiic keypad to a Qwiic MP3 Trigger to play more sound files
The first keypad has its address unchanged as 0x4B
The second keypad address has been changed to 0x4A by soldering the ADR jumper
All three boards addresses are confirmed using I2C scanner example.
My sketch will work correctly with a single keypad connected, but add the second and all goes dead.
What am I missing to be able to have two keypads accessing the MP3 Trigger?
Can you please provide pictures of your setup and detailed pictures of the modified board?
And one more of the MP3 Trigger with 4 buttons attached
Here is the code I have been modifying to try and make this work.
Using only keypad1 statements I can make this sketch work with either keypad added to the circuit one at a time.
But when I add in the Keypad2 statements and add a second keypad to the circuit, they are both non responsive.
/*
Controlling the Qwiic MP3 Trigger with I2C Commands
By: Nathan Seidle
SparkFun Electronics
Date: January 12th, 2019
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
This example shows how start the MP3 Trigger library using a different wire port (ie, Wire1, etc).
This is handy if you need to connect *a lot* of Triggers and have multiple Wire ports on your dev platform.
Feel like supporting open source hardware?
Buy a board from SparkFun! https://www.sparkfun.com/products/15165
Hardware Connections:
Plug in headphones
Make sure the SD card is in the socket and has some MP3s in the root directory
Don't have a USB cable connected right now
If needed, attach a Qwiic Shield to your Arduino/Photon/ESP32 or other
Plug the Qwiic device onto an available Qwiic port
Open the serial monitor at 9600 baud
*/
#include <Wire.h> //Needed for I2C to Qwiic MP3 Trigger
#include "SparkFun_Qwiic_Keypad_Arduino_Library.h"
#include "SparkFun_Qwiic_MP3_Trigger_Arduino_Library.h" //http://librarymanager/All#SparkFun_MP3_Trigger
MP3TRIGGER mp3;
const byte mp3InterruptPin = 4; //Any GPIO will work. Connect to the INT pin on Qwiic MP3 Trigger
KEYPAD keypad1; //Create instance of this object
const byte interruptPin = 2; // digital pin 2 = INT0, but we will use "digitalPinToInterrupt(interruptPin)" to convert
KEYPAD keypad2; //Create instance of this object
const byte interruptPin2 = 6; //digital pin 3 = INT0, but we will use "digitalPinToInterrupt(interruptPin)" to convert
volatile boolean buttonAvailable = false; // used to keep track if there is a button on the stack
// needs to be "volatile" because it's updated by interrupt.
void setup(void)
{
Serial.begin(9600);
Serial.println("Qwiic MP3 Trigger Rebel Station");
Wire.begin(); //Compilation will fail here if your platform doesn't have multiple I2C ports
Wire.setClock(400000); //MP3 Trigger supports higher I2C rates
if (mp3.begin(Wire) == false)
{
Serial.println("MP3 Trigger does not appear to be connected. Please check wiring. Freezing...");
while (1);
}
if (keypad1.begin() == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
if (keypad2.begin(Wire, 0x4A) == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
{
Serial.println("Keypad does not appear to be connected. Please check wiring. Freezing...");
while (1);
}
Serial.print("Initialized. Firmware Version: ");
Serial.println(keypad1.getVersion());
}
void loop(void)
{
keypad1.updateFIFO(); // necessary for keypad to pull button from stack to readable register
char button = keypad1.getButton();
if (button == -1)
{
Serial.println("No keypad detected");
delay(1000);
}
else if (button != 0)
{
if (button == '1') mp3.playTrack(1); //Begin playing the first track on the SD card
if (button == '2') mp3.playTrack(2);
if (button == '3') mp3.playTrack(3);
if (button == '4') mp3.playTrack(4);
if (button == '5') mp3.playTrack(5);
if (button == '6') mp3.playTrack(6);
if (button == '7') mp3.playTrack(7);
if (button == '8') mp3.playTrack(8);
if (button == '9') mp3.playTrack(9);
if (button == '0') mp3.playTrack(10);
if (button == '#') Serial.println();
else if (button == '*') Serial.print(" ");
else Serial.print(button);
}
{
keypad2.updateFIFO(); // necessary for keypad to pull button from stack to readable register
char button2 = keypad2.getButton();
if (button2 == -1)
{
Serial.println("No keypad detected");
delay(1000);
}
else if (button2 != 0)
{
if (button2 == '1') mp3.playTrack(1); //Begin playing the first track on the SD card
if (button2 == '2') mp3.playTrack(2);
if (button2 == '3') mp3.playTrack(3);
if (button2 == '4') mp3.playTrack(4);
if (button2 == '5') mp3.playTrack(5);
if (button2 == '6') mp3.playTrack(6);
if (button2 == '7') mp3.playTrack(7);
if (button2 == '8') mp3.playTrack(8);
if (button2 == '9') mp3.playTrack(9);
if (button2 == '0') mp3.playTrack(10);
if (button2 == '#') Serial.println();
else if (button2 == '*') Serial.print(" ");
else Serial.print(button2);
}
//Do something else. Don't call your Keypad a ton otherwise you'll tie up the I2C bus
delay(25); //25 is good, more is better
}
}
/code]
Does the Keypad2 work by itself with out the first one attached?
To answer your question, yes and no.
I have found that if I connect the Keypad2 0x4A (the jumper ADR) by itself to the BlackBoard and the MP3 Trigger ,
that the sketch will initialize and the keypad responds by pressing keys,
THEN and only then if I add the second keypad1 in hot (as in not resetting the Blackboard) the second keypad1 will also respond by pressing ITS keys.
and all works as intended, this is Great, except not practical to be adding second keypad after everthing is up and running.
It does not work in reverse however, meaning, if I start with the 0x4B (factory normal) keypad1 by itself, that the sketch does NOT initialize and does not respond to the sketch and adding the second keypad2 does not respond either.
also starting with BOTH keypads in the circuit to begin with will not work , as stated before. Which is what I really want to happen.
Thanks
Dan
I think your issue might be in four areas:
I would leave the clock set at the default. I am not sure how well the AtTiny handles the “Fast” I2C protocol/speeds.
Wire.setClock(400000); //MP3 Trigger supports higher I2C rates
I would add a short delay between initializing the connection to each device. (200ms should be more than enough… It’ll also give the modified keypad time to reconfigure itself after power up.)
If the delay and clock speed changes don’t help. I would double check that bridged jumper. I don’t remember how the firmware operated, but if that soldering isn’t completely connected, it might be causing that keypad to occasionally not be configured to the alternate address. You may also need to increase the delay… I don’t remember how long it takes the AtTiny to recognize the address jumper and reconfigure to be at a different I2C address.
I believe your project is getting stuck in this section of the code. Once it can’t find the 0x4A device, it sits in a while infinite loop. I would use while instead of if so that the code keeps attempting to connect to the device.
if (keypad2.begin(Wire, 0x4A) == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
{
Serial.println("Keypad does not appear to be connected. Please check wiring. Freezing...");
while (1);
}
(i.e. You might be seeing the single error statement (stuck in the infinite loop). Changing it to a while condition, the error statement will repeat and the microcontroller will reattempt to connect to the device at 0x4A. )
Thank you so much Santa Impersonator! for your suggestions and most importantly your willingness to reach out and respond.
I was able to update my sketch with your recommendations and glad to say its working just as I wanted.
Thank you again for your help.
Here is all that I changed, removed the two “if” statements and replaced with “while” and added the delay(200) between them. I did not have to change the clock speed and my solder joint is secure.
while (keypad1.begin() == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
delay (200);
while (keypad2.begin(Wire, 0x4A) == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A)./code]
Anyone wanting to use two or more Qwiic Keypads to trigger the Qwiic MP3 Trigger here is a working Sketch.
/*
Controlling the Qwiic MP3 Trigger with I2C Commands
By: Nathan Seidle
SparkFun Electronics
Date: January 12th, 2019
License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).
This example shows how start the MP3 Trigger library using a different wire port (ie, Wire1, etc).
This is handy if you need to connect *a lot* of Triggers and have multiple Wire ports on your dev platform.
Feel like supporting open source hardware?
Buy a board from SparkFun! https://www.sparkfun.com/products/15165
Hardware Connections:
Plug in headphones
Make sure the SD card is in the socket and has some MP3s in the root directory
Don't have a USB cable connected right now
If needed, attach a Qwiic Shield to your Arduino/Photon/ESP32 or other
Plug the Qwiic device onto an available Qwiic port
Open the serial monitor at 9600 baud
*/
#include <Wire.h> //Needed for I2C to Qwiic MP3 Trigger
#include "SparkFun_Qwiic_Keypad_Arduino_Library.h"
#include "SparkFun_Qwiic_MP3_Trigger_Arduino_Library.h" //http://librarymanager/All#SparkFun_MP3_Trigger
MP3TRIGGER mp3;
const byte mp3InterruptPin = 4; //Any GPIO will work. Connect to the INT pin on Qwiic MP3 Trigger
KEYPAD keypad1; //Create instance of this object
const byte interruptPin = 2; // digital pin 2 = INT0, but we will use "digitalPinToInterrupt(interruptPin)" to convert
KEYPAD keypad2; //Create instance of this object
const byte interruptPin2 = 6; //digital pin 3 = INT0, but we will use "digitalPinToInterrupt(interruptPin)" to convert
volatile boolean buttonAvailable = false; // used to keep track if there is a button on the stack
// needs to be "volatile" because it's updated by interrupt.
void setup(void)
{
Serial.begin(9600);
Serial.println("Qwiic MP3 Trigger Rebel Station");
Wire.begin(); //Compilation will fail here if your platform doesn't have multiple I2C ports
Wire.setClock(400000); //MP3 Trigger supports higher I2C rates
if (mp3.begin(Wire) == false)
{
Serial.println("MP3 Trigger does not appear to be connected. Please check wiring. Freezing...");
while (1);
}
while (keypad1.begin() == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
delay (200);
while (keypad2.begin(Wire, 0x4A) == false) // Note, using begin() like this will use default I2C address, 0x4B.
// You can pass begin() a different address like so: keypad1.begin(Wire, 0x4A).
{
Serial.println("Keypad does not appear to be connected. Please check wiring. Freezing...");
while (1);
}
Serial.print("Initialized. Firmware Version: ");
Serial.println(keypad1.getVersion());
}
void loop(void)
{
keypad1.updateFIFO(); // necessary for keypad to pull button from stack to readable register
char button = keypad1.getButton();
if (button == -1)
{
Serial.println("No keypad detected");
delay(1000);
}
else if (button != 0)
{
if (button == '1') mp3.playTrack(1); //Begin playing the first track on the SD card
if (button == '2') mp3.playTrack(2);
if (button == '3') mp3.playTrack(3);
if (button == '4') mp3.playTrack(4);
if (button == '5') mp3.playTrack(5);
if (button == '6') mp3.playTrack(6);
if (button == '7') mp3.playTrack(7);
if (button == '8') mp3.playTrack(8);
if (button == '9') mp3.playTrack(9);
if (button == '0') mp3.playTrack(10);
if (button == '#') Serial.println();
else if (button == '*') Serial.print(" ");
else Serial.print(button);
}
{
keypad2.updateFIFO(); // necessary for keypad to pull button from stack to readable register
char button2 = keypad2.getButton();
if (button2 == -1)
{
Serial.println("No keypad detected");
delay(1000);
}
else if (button2 != 0)
{
if (button2 == '1') mp3.playTrack(1); //Begin playing the first track on the SD card
if (button2 == '2') mp3.playTrack(2);
if (button2 == '3') mp3.playTrack(3);
if (button2 == '4') mp3.playTrack(4);
if (button2 == '5') mp3.playTrack(5);
if (button2 == '6') mp3.playTrack(6);
if (button2 == '7') mp3.playTrack(7);
if (button2 == '8') mp3.playTrack(8);
if (button2 == '9') mp3.playTrack(9);
if (button2 == '0') mp3.playTrack(10);
if (button2 == '#') Serial.println();
else if (button2 == '*') Serial.print(" ");
else Serial.print(button2);
}
//Do something else. Don't call your Keypad a ton otherwise you'll tie up the I2C bus
delay(25); //25 is good, more is better
}
}
/code]
No problem, glad you were able to get your project working!