Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 14 of 14

Thread: Teensy 4.1 + MCP23017 examples

  1. #1
    Junior Member
    Join Date
    Aug 2019
    Posts
    11

    Teensy 4.1 + MCP23017 examples

    I'm building a teensy 4.1-based drum machine. It's got quite a few buttons and LEDs so I'm using a few i2c MCP23017 to offload the I/O. It took me WAAAAY too long to get the Teensy 4.1 working with the MCP23017 using interrupts. I had a really hard time finding code examples, especially working out the magic sequence of code that makes the MCP23017 interrupt reset after triggered/processed. There was a bit of discussion on these pjrc forums about it, but nothing that "just worked". Now that I've got it working with and without interrupts I figured I'd make a quick post here. Maybe it will save a future googler the hours I spent figuring out what surely has already been figured out.

    Here are my example projects:

    Without interrupts: https://github.com/nshaver/teensy_mc..._no_interrupts

    Using interrupts: https://github.com/nshaver/teensy_mcp23017_interrupts

    If anyone notices that my "using interrupts" version has any bugs or sees things that coule be improved - feel free to reply here so I'll know. As far as I can tell, it runs very fast and stable. I haven't finished this project yet though. I'll have more confidence in it after the drum machine runs for 24 hours without getting glitchy.

  2. #2
    Junior Member
    Join Date
    Oct 2021
    Posts
    8
    nice work! I wish I had this code about a week ago. I just went through the same thing. It sounds like we are working on similar projects! I just started a drum machine project too! I ended up going the no interrupt route since my drum pads are done with a 4x4 matrix. I found it easier to do that way than use interrupts.

  3. #3
    Junior Member
    Join Date
    Oct 2021
    Posts
    16
    Interesting! One question, though: you are reading the multiplexer in the version without interrupts every loop cycle. Given the speed of the Teensy 4.1, I reckon this will be much too often to only catch button presses. Worse, it will slow down the loop while waiting for the I2C transfer to finish. I would think it will be sufficient to read the multiplexer every 5ms or so and still not miss a beat.
    The interrupt version is much more efficient of course. The button state variable might need to be declared volatile, by the way.

  4. #4
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    I have some loop-counting logic in my examples. When polling every loop the "loops per second" numbers were in the hundreds or low thousands. When using the interrupt it runs at around 8 million loops per second. It's a night and day difference. I think interrupts are definitely worth the trouble, and it's a lot of trouble. You were correct about the button state needing to be volatile.

    Regarding not reading every loop (when not using interrupts), my thinking was this: if I don't read every loop, there's a chance that a button will be both pressed and released before I got around to polling again. In that case I would have missed a button press, and that's pretty much the last thing I want to happen.

  5. #5
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    Quote Originally Posted by rcon View Post
    nice work! I wish I had this code about a week ago. I just went through the same thing. It sounds like we are working on similar projects! I just started a drum machine project too! I ended up going the no interrupt route since my drum pads are done with a 4x4 matrix. I found it easier to do that way than use interrupts.
    Have you done any testing to see how many loop/sec you're able to process? I worry that if I poll too much my Teensy won't also be able to handle the wave generation and effects. I plan on using reverb and that has a pretty big hit on the processor.

  6. #6
    Junior Member
    Join Date
    Oct 2021
    Posts
    16
    Quote Originally Posted by nshaver View Post
    Regarding not reading every loop (when not using interrupts), my thinking was this: if I don't read every loop, there's a chance that a button will be both pressed and released before I got around to polling again. In that case I would have missed a button press, and that's pretty much the last thing I want to happen.
    Yeah, whatever serves your purposes best. I was just calculating that 5ms would cover 200BPS (that is, 12000BPM) - most probably you will not be able to press and release pads that fast. And the 5ms in between are a lot of time for the Teensy to do something different.

  7. #7
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    Quote Originally Posted by Miq58 View Post
    Yeah, whatever serves your purposes best. I was just calculating that 5ms would cover 200BPS (that is, 12000BPM) - most probably you will not be able to press and release pads that fast. And the 5ms in between are a lot of time for the Teensy to do something different.
    Well, for what it's worth I gave the non-interrupt method a try again and polled every 5ms. I'm also keeping up with the LED state of any LEDS that I've turned on or off, so that I never try to turn on an LED that was already on, or off one that was already off. I'm now getting at least 3 million loops/second, even when hitting the buttons crazy fast. This is the most responsive and accurate I've managed to get yet. I'm going to do a little more testing to hit it a button as fast as I can for a good minute or so and see if the Teensy counts as many as I hit. If it does then I think I'm going to call it good enough and switch my methodology to polling instead of interrupts. The interrupts are just more trouble than they're worth. My current setup is with three MCP23017s, one processing 16 button inputs, and the other two processing 32 LED outputs.

    Thanks for all of the suggestions and discussion.

  8. #8
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    I did some testing to see if I'm missing important button presses with the non-interrupt method. Best I can tell, it's fine. I'm going to polling, interrupts are more trouble than they're worth in my current use case. I made a short video of this most recent test:


  9. #9
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    For what it's worth I have updated the code in github for my "no interrupts" version. Link is in first post to this thread.

  10. #10
    Junior Member
    Join Date
    Oct 2021
    Posts
    16
    Glad to hear that. I am at a similar task but have to read many analog inputs in short intervals and I am going to try that by polling as well.

  11. #11
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    Quote Originally Posted by Miq58 View Post
    Glad to hear that. I am at a similar task but have to read many analog inputs in short intervals and I am going to try that by polling as well.
    For what it's worth, I have used CD74HC4067 multiplexers to read lots of pots into a Teensy 4.1 for MIDI controller projects. That has worked ok, but my pot values seem to be jumpy sometimes. I've resorted to doing multiple analogReads (like maybe 3 reads in a row) and then using the last one. I suspect that my hardware design might be lacking, maybe I need a capacitor on my pots or something like that. The multiple analogReads don't seem to slow things down much so I've just gone with that and moved on.

  12. #12
    Junior Member
    Join Date
    Oct 2021
    Posts
    16
    I am about to do exactly the same - MIDI controller, 4067s, resistance values (from FSRs). I had to put an opamp in between to have a low impedance signal at the analog pin, that improved things greatly.

  13. #13
    Junior Member
    Join Date
    Aug 2019
    Posts
    11
    Quote Originally Posted by Miq58 View Post
    I am about to do exactly the same - MIDI controller, 4067s, resistance values (from FSRs). I had to put an opamp in between to have a low impedance signal at the analog pin, that improved things greatly.
    Ah, thanks very much for that tip! I'm seeing quite a bit of hits now that I google for "multiplexer opamp". I'll make use of an opamp on my next multi-pot 4067 project. Did you use a 4072/4 op amp, or something fancier?

  14. #14
    Junior Member
    Join Date
    Oct 2021
    Posts
    16
    I use a MCP6002. I was advised to use that due to the 3V3 voltage I am using in my circuit.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •