Can't get Qwiic MP3 trigger working with Microbit

Sorry for the crosspost, but I figured that this might be a better place to get help.

I have a micro:bot kit, and am trying to connect a Qwiic MP3 trigger to it over I2C. I am using the MakeCode editor.

IMG_4748.jpg

The SD card on the MP3 trigger is loaded with files T001.mp3 through T010.mp3, as well as F001.mp3 through F010.mp3.

I can play the manual triggers fine by connecting ground to the various breakouts, so I know it is reading the SD card correctly, and receiving power over the I2C bus.

However, it is not responding to I2C commands.

Here is the Javascript code, below. It is sending 110,2,2 to address 55 (or 0x6e, 0x02, 0x02 to address 0x37), which I would expect to play F002.mp3.

Any thoughts on what I am doing wrong?

input.onButtonPressed(Button.A, function () {

basic.showIcon(IconNames.Yes)

pins.i2cWriteNumber(

55,

110,

NumberFormat.UInt8LE,

true

)

pins.i2cWriteNumber(

55,

2,

NumberFormat.UInt8LE,

true

)

pins.i2cWriteNumber(

55,

2,

NumberFormat.UInt8LE,

false

)

basic.showIcon(IconNames.No)

})

basic.showIcon(IconNames.Happy)

basic.forever(function () {

})

Hi gpvillamil,

Unfortunately, we do not have much information to help you out here since the guide and examples for the Qwiic MP3 Trigger are written for use with Arduino and we can’t really help debug custom code like this. That said, I have a couple of suggestions that might help.

It might be that you are sending the I2Cwrite commands too quickly either after the Qwiic MP3 Trigger is turned on. The [Arduino Library handles that for you but if you’re writing custom code like this, you’ll need to include a 2-second delay from power-up before sending I2C commands. Similarly, try adding a delay to wait 50ms between I2C commands.

Aside from these suggestions, I am not sure what else would be causing the issue.](GitHub - sparkfun/SparkFun_Ublox_Arduino_Library: Library to control UBX binary protocol and NMEA over I2C on Ublox GPS modules)

Got it, thanks.

The 50 msec delay might be the solution. I’ll try it later today.

I am triggering the sound via a button press, so I was aware of the 2 second delay and waiting. However I did not try the delay between commands.

There are no examples of the I2C feature in MakeCode, which has made things harder!

I noticed that you were triggering them from a button press after my first response so it most likely is not related to that. The delay in between writes might help since it’s not having time to interpret the first string before the second is sent.

I found that issue regarding I2CWrite and Read when I was looking into this and there is not much out there aside from pre-made functions in MakeCode packages like the one we have for the motor:bit. I will do a bit more searching and ask around the building to see if anyone else has some input here.

Otherwise, even though it will probably be more hassle than it is is worth since it looks like you are trying to incorporate this with our motor:bit kit, it may be a better option to try getting it to work with MicroPython. There is some very thorough documentation of using MicroPython with the micro:bit [here that could help you get started if you wanted to go down that rabbit hole.](I²C — BBC micro:bit MicroPython 1.1.1 documentation)

A quick update. I spoke with one of our engineers who is working on some micro:bit things and we are pretty sure it is related to the missing delays in between your commands. You are using the correct format for the messages with unsigned 8-bit and the Qwiic MP3 Trigger is just using standard I2c communication so nothing else seems off here. You could try switching the repeated option to false and see if that changes anything. I would need to test this here to confirm since I have not really played around with the I2C Write function in MakeCode.

If you have a logic analyzer handy, that might help you identify what is going on with your data and clock lines to see where the bus is getting hung up. If I were to guess, I would imagine you would see some clock stretching happening from the MP3 Trigger that is preventing the micro:bit from sending new pulses on that line.

No joy.

Tried inserting 50msec and 100 msec pauses, and tried setting the repeat flags true, true, false and false, false, false.

The few examples I’ve found, by taking apart libraries, use i2c Write Buffer (https://makecode.microbit.org/reference … ite-buffer) - however, it seems like the documentation is a little out of sync with the MakeCode editor as it actually exists.

Would a Bus Pirate be able to listen in to the signals coming FROM the Micro:bit?

input.onButtonPressed(Button.A, function () {

basic.showIcon(IconNames.Yes)

pins.i2cWriteNumber(

55,

110,

NumberFormat.UInt8LE,

true

)

basic.pause(100)

pins.i2cWriteNumber(

55,

2,

NumberFormat.UInt8LE,

true

)

basic.pause(100)

pins.i2cWriteNumber(

55,

2,

NumberFormat.UInt8LE,

false

)

basic.showIcon(IconNames.No)

})

basic.showIcon(IconNames.Happy)

pins.digitalWritePin(DigitalPin.P0, 0)

basic.forever(function () {

})

Here’s where I am now (still not working)

input.onButtonPressed(Button.A, function () {

basic.showIcon(IconNames.Yes)

buf.setNumber(NumberFormat.UInt8LE, 0, 0x6e) // write register

buf.setNumber(NumberFormat.UInt8LE, 1, 1) // play file

buf.setNumber(NumberFormat.UInt8LE, 2, 2) // play the 3rd file

pins.i2cWriteBuffer(deviceID, buf, false)

basic.showIcon(IconNames.No)

})

let deviceID = 0

basic.showIcon(IconNames.Happy)

deviceID = 55

let buf = pins.createBuffer(3)

buf.setNumber(NumberFormat.UInt8LE, 0, 0x6e) // write register

buf.setNumber(NumberFormat.UInt8LE, 1, 7) // set the volume

buf.setNumber(NumberFormat.UInt8LE, 2, 31) // set it to maximum

pins.i2cWriteBuffer(deviceID, buf, false)

basic.forever(function () {

})

Hi gpvillamil.

A Bus Pirate can listen to the I2C bus and allow you to send data to the Qwiic MP3 Trigger for testing. Another excellent (and inexpensive) tool for viewing data over the I2C bus is our [USB Logic Analyzer A tool like that will allow you to see exactly what’s going on over the bus so you can spot where you might have an error in your code.

I’m not exactly sure how to code this in Makecode if if it’s possible to code it, but what you need to do to play track one on the Qwiic MP3 Trigger is send the following in this order:

  • I2C start bit
  • - Write to address 0x37 (Devices I2C address)
  • - Write 0x01 (command for play track)
  • - Write 0x01 (track number to play)
  • - I2C stop bit
  • The Arduino code below will play track one. You might try adapting it to MakeCode and see if that works.

    #include <Wire.h>;
    
    void setup() 
    {
    Wire.setClock(100000);         //Slow the bus down to standard mode. 
    Wire.beginTransmission(0x37);  //Start bit + Qwiic MP3 Trigger address
    Wire.write(0x01);              //Command to play a track
    Wire.write(0x01);              //Track number to play
    Wire.endTransmission();        //Stop bit
    }
    
    void loop() 
    {
      // put your main code here, to run repeatedly:
    }
    

    The screen grab in the file below will show the actual data over the bus.

    Qwiic MP3 Trigger play track 1.zip (41.3 KB)

    If you’re able to reproduce those transmissions on the micro:bit, you should be good to go. Unfortunately I don’t know enough about the micro:bit or Make Code to help with the code needed to do this. It’s likely a library may be needed in Make Code to accomplish this with blocks.](https://www.sparkfun.com/products/15033)

    OK getting somewhere. Using MicroPython, the scan shows a device at address 55. I know it is the MP3 trigger because it disappears from the scan when disconnected. However, asking it to report its status returns 0.

    i2c.scan()

    [25, 30, 55, 89]

    i2c.write(0x37,b’\0x6E\0x10’,repeat=False)

    i2c.read(0x37,1)

    b’\x00’

    i2c.write(0x37,b’\0x10’,repeat=False)

    i2c.read(0x37,1)

    b’\x00’

    i2c.write(0x37,b’0x6F’,repeat=False)

    i2c.read(0x37,1)

    b’\x00’

    i2c.write(0x37,b’\0x6E\0x10’,repeat=False)

    i2c.write(0x37,b’\0x6F’,repeat=False)

    i2c.read(0x37,1)

    b’\x00’

    TS-Mark:
    Otherwise, even though it will probably be more hassle than it is is worth since it looks like you are trying to incorporate this with our motor:bit kit, it may be a better option to try getting it to work with MicroPython. There is some very thorough documentation of using MicroPython with the micro:bit [here that could help you get started if you wanted to go down that rabbit hole.
    [/quote]](I²C — BBC micro:bit MicroPython 1.1.1 documentation)

    Wait, you don’t need to send the Write register after the address?

    So you are sending 0x01 0x01 to address 0x37 directly, you don’t need to send 0x6e 0x01 0x01?

    TS-Chris:
    Hi gpvillamil.

    A Bus Pirate can listen to the I2C bus and allow you to send data to the Qwiic MP3 Trigger for testing. Another excellent (and inexpensive) tool for viewing data over the I2C bus is our [USB Logic Analyzer A tool like that will allow you to see exactly what’s going on over the bus so you can spot where you might have an error in your code.

    I’m not exactly sure how to code this in Makecode if if it’s possible to code it, but what you need to do to play track one on the Qwiic MP3 Trigger is send the following in this order:

  • I2C start bit
  • - Write to address 0x37 (Devices I2C address)
  • - Write 0x01 (command for play track)
  • - Write 0x01 (track number to play)
  • - I2C stop bit
  • The Arduino code below will play track one. You might try adapting it to MakeCode and see if that works.

    #include <Wire.h>;
    

    void setup()
    {
    Wire.setClock(100000); //Slow the bus down to standard mode.
    Wire.beginTransmission(0x37); //Start bit + Qwiic MP3 Trigger address
    Wire.write(0x01); //Command to play a track
    Wire.write(0x01); //Track number to play
    Wire.endTransmission(); //Stop bit
    }

    void loop()
    {
    // put your main code here, to run repeatedly:
    }

    
    
    
    The screen grab in the file below will show the actual data over the bus.
    
    Qwiic MP3 Trigger play track 1.zip
    
    
    
    If you're able to reproduce those transmissions on the micro:bit, you should be good to go. Unfortunately I don't know enough about the micro:bit or Make Code to help with the code needed to do this. It's likely a library may be needed in Make Code to accomplish this with blocks.
    [/quote]</QUOTE>](https://www.sparkfun.com/products/15033)

    Here’s where my question comes from. The screen grab you sent shows this:

    However, in the hookup guide, here’s an example of sending a command to the MP3 trigger:

    And an example of reading status:

    SparkFun_Qwiic_MP3_Trigger_-_Read_ID.jpg

    In the examples from the hookup guide, it looks like you send the write register 0x6E first, before the instructions. Then to read status it looks like you send 0x6E 0x10 0x6F and then get 0x39 back - or am I reading this incorrectly?

    Update: ok it looks like I am reading this incorrectly. 0x37 with 0 in the high bit is 0x6E and with a 1 is 0x6F. So the Write / Read functions should take care of this given a 7 bit address, right?

    This Python command would work (except it doesn’t!):

    i2c.write(0x37,b’\0x10’,repeat=False)

    i2c.read(0x37,1)

    b’\x00’

    Progress!

    The code below will play the second file on the MP3 trigger when the button is pressed. However, it will only do it once.

    Pressing the button again will lead to a low crackling sound.

    Power-cycling the micro:bit and starting over will play the file when the button is pressed.

    Is there some kind of “rewind” that is necessary?

    input.onButtonPressed(Button.A, function () {

    basic.showIcon(IconNames.Yes)

    buf.setNumber(NumberFormat.UInt8LE, 0, 1)

    buf.setNumber(NumberFormat.UInt8LE, 1, 2)

    pins.i2cWriteBuffer(deviceID, buf, false)

    basic.showIcon(IconNames.No)

    })

    let deviceID = 0

    basic.showIcon(IconNames.Happy)

    deviceID = 55

    let buf = pins.createBuffer(2)

    buf.setNumber(NumberFormat.UInt8LE, 0, 7)

    buf.setNumber(NumberFormat.UInt8LE, 1, 31)

    pins.i2cWriteBuffer(deviceID, buf, false)

    basic.forever(function () {

    })

    OK! Working now!

    Thank you for all your help!

    Something to take note of:

    PLAY_FILENUMBER 0x02 works correctly.

    PLAY_TRACK 0x01 only plays once.

    The blocks-based functions don’t work, but the i2cWriteBuffer function does work.

    input.onButtonPressed(Button.A, function () {

    basic.showIcon(IconNames.Yes)

    buf.setNumber(NumberFormat.UInt8LE, 0, 2)

    buf.setNumber(NumberFormat.UInt8LE, 1, songNum)

    pins.i2cWriteBuffer(deviceID, buf, false)

    songNum = songNum + 1

    if (songNum > 10) {

    songNum = 1

    }

    basic.showIcon(IconNames.No)

    })

    let deviceID = 0

    let songNum = 0

    songNum = 1

    basic.showIcon(IconNames.Happy)

    deviceID = 55

    let buf = pins.createBuffer(2)

    buf.setNumber(NumberFormat.UInt8LE, 0, 7)

    buf.setNumber(NumberFormat.UInt8LE, 1, 31)

    pins.i2cWriteBuffer(deviceID, buf, false)

    basic.forever(function () {

    })

    Awesome! Great work on this! I am sure this thread will come in handy for other users trying to get I2C commands for this or other boards working with some “raw” MakeCode/Javascript instead of using a MakeCode package.

    Also, if you or others are interested in learning, we just posted a new tutorial on how to create a MakeCode package for micro:bit [here.

    Let us know if you run into any other issues or have any other questions about the Qwiic MP3 Trigger and we would be happy to help.](https://learn.sparkfun.com/tutorials/how-to-create-a-makecode-package-for-microbit)

    I’m really excited that this is working!

    Even though the i2c.writeBuffer function is not available in the Blocks environment, if you write it in Javascript you can still roundtrip back to the Blocks mode and keep working there. So potentially a teacher could distribute those snippets and students can still use it as a play sound abstraction.

    I’ll take a look at the article, perhaps I can package up the functions to drive the MP3 trigger.

    TS-Mark:
    Awesome! Great work on this! I am sure this thread will come in handy for other users trying to get I2C commands for this or other boards working with some “raw” MakeCode/Javascript instead of using a MakeCode package.

    Also, if you or others are interested in learning, we just posted a new tutorial on how to create a MakeCode package for micro:bit [here.

    Let us know if you run into any other issues or have any other questions about the Qwiic MP3 Trigger and we would be happy to help.
    [/quote]](https://learn.sparkfun.com/tutorials/how-to-create-a-makecode-package-for-microbit)