Waveshare MCP23017 Expansion Board wiring with Teensy 3.6

Status
Not open for further replies.

massahwahl

Active member
Hoping to get some help on how to properly wire this expansion board I am trying to use: https://www.waveshare.com/wiki/MCP23017_IO_Expansion_Board

I have power going to it but I cant find any information regarding how to wire it with the Teensy. I have the SCL and SDA connected to SCL0 and SDA0 while using 3.3v for power. I am trying to wire up some buttons to it and when I have a button connected to PA7 pin and ground on that set of pins I get nothing from the serial monitor using their example code:

Code:
// Install the LowPower library for optional sleeping support.
// See loop() function comments for details on usage.
//#include <LowPower.h>

#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp;

byte ledPin= LED_BUILTIN;

// Interrupts from the MCP will be handled by this PIN
byte arduinoIntPin=24;

// ... and this interrupt vector
byte arduinoInterrupt=1;

volatile boolean awakenByInterrupt = false;

// Two pins at the MCP (Ports A/B where some buttons have been setup.)
// Buttons connect the pin to grond, and pins are pulled up.
byte mcpPinA=7;
byte mcpPinB=15;

void setup(){

  Serial.begin(9600);
  Serial.println("MCP23007 Interrupt Test");

  pinMode(arduinoIntPin,INPUT);

  mcp.begin();      // use default address 0
  
  // We mirror INTA and INTB, so that only one line is required between MCP and Arduino for int reporting
  // The INTA/B will not be Floating 
  // INTs will be signaled with a LOW
  mcp.setupInterrupts(true,false,LOW);

  // configuration for a button on port A
  // interrupt will triger when the pin is taken to ground by a pushbutton
  mcp.pinMode(mcpPinA, INPUT);
  mcp.pullUp(mcpPinA, HIGH);  // turn on a 100K pullup internally
  mcp.setupInterruptPin(mcpPinA,FALLING); 

  // similar, but on port B.
  mcp.pinMode(mcpPinB, INPUT);
  mcp.pullUp(mcpPinB, HIGH);  // turn on a 100K pullup internall
  mcp.setupInterruptPin(mcpPinB,FALLING);

  // We will setup a pin for flashing from the int routine
  pinMode(ledPin, OUTPUT);  // use the p13 LED as debugging
  
}

// The int handler will just signal that the int has happen
// we will do the work from the main loop.
void intCallBack(){
  awakenByInterrupt=true;
}

void handleInterrupt(){
  
  // Get more information from the MCP from the INT
  uint8_t pin=mcp.getLastInterruptPin();
  uint8_t val=mcp.getLastInterruptPinValue();
  
  // We will flash the led 1 or 2 times depending on the PIN that triggered the Interrupt
  // 3 and 4 flases are supposed to be impossible conditions... just for debugging.
  uint8_t flashes=4; 
  if(pin==mcpPinA) flashes=1;
  if(pin==mcpPinB) flashes=2;
  if(val!=LOW) flashes=3;

  // simulate some output associated to this
  for(int i=0;i<flashes;i++){  
    delay(100);
    digitalWrite(ledPin,HIGH);
    delay(100);
    digitalWrite(ledPin,LOW);
  }

  // we have to wait for the interrupt condition to finish
  // otherwise we might go to sleep with an ongoing condition and never wake up again.
  // as, an action is required to clear the INT flag, and allow it to trigger again.
  // see datasheet for datails.
//  while( ! (mcp.digitalRead(mcpPinB) && mcp.digitalRead(mcpPinA) ));
//  // and clean queued INT signal
//  cleanInterrupts();
}

// handy for interrupts triggered by buttons
// normally signal a few due to bouncing issues
//void cleanInterrupts(){
//  EIFR=0x01;
//  awakenByInterrupt=false;
//}  

/**
 * main routine: sleep the arduino, and wake up on Interrups.
 * the LowPower library, or similar is required for sleeping, but sleep is simulated here.
 * It is actually posible to get the MCP to draw only 1uA while in standby as the datasheet claims,
 * however there is no stadndby mode. Its all down to seting up each pin in a way that current does not flow.
 * and you can wait for interrupts while waiting.
 */
void loop(){
  
  // enable interrupts before going to sleep/wait
  // And we setup a callback for the arduino INT handler.
  attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
  
  // Simulate a deep sleep
  while(!awakenByInterrupt);
  // Or sleep the arduino, this lib is great, if you have it.
  //LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
  
  // disable interrupts while handling them.
  detachInterrupt(arduinoInterrupt);
  
  if(awakenByInterrupt) handleInterrupt();
}

I am only using the first interrupt pin on the board wired to pin 24 but even uploading the sketch gets nothing to the serial monitor at all, not even the set up message.
 
Before getting to interrupts, it may be simpler to first try it without low power stuff or interrupts.

First try Examples -> Wire -> Scanner, load it, bring up the serial monitor, and run it. If it hangs that is an indication that you need pull-up resistors. You would attach one end of a resistor to the Teensy SCL pin (A5/19) and the other end of the resistor to the ground pins. You would attach one end of a second resistor to the Teensy SDA pin (A4/18) and the other end to the ground. Typically, you would use 2.2K resistors on Teensy, but you could use higher values.

If the Scanner runs but does not print anything finding a device, that means you haven't hooked up the device properly. It should show a device with address 0x20 by default (and up to 0x27, depending on the solder jumpers set).

Once the device is recognized, then try Examples -> MCP23017 -> Toggle and hook up a LED with a resistor to pin 0 of the MCP23017 and ground. The LED should flash on/off in 1/10 second intervals.

Then try the other two tests.
 
Thanks Michael,

Scanner is showing that it found the expander and I have been able to flash the LED with the adafruit script as well. Had not considered that my issue was with the interrupts, are they handled different on the Teensy?
 
Thanks Paul! That did get the serial monitor to work, still not getting anything when I press the button though
 
still not getting anything when I press the button though

Maybe try MichaelMeissner's suggestion. First get a LED to blink, which is a lot easier to troubleshoot than input mode and interrupts.


Once the device is recognized, then try Examples -> MCP23017 -> Toggle and hook up a LED with a resistor to pin 0 of the MCP23017 and ground. The LED should flash on/off in 1/10 second intervals.

Then try the other two tests.

If this doesn't work either, maybe something is wrong with the wiring? We can help more if you show us photos of how you actually connected the wires.

But do try the LED blink *before* adding the complexities of interrupts.
 
Maybe try MichaelMeissner's suggestion. First get a LED to blink, which is a lot easier to troubleshoot than input mode and interrupts.




If this doesn't work either, maybe something is wrong with the wiring? We can help more if you show us photos of how you actually connected the wires. But do try the LED blink *before* adding the complexities of interrupts.

I replied to Michaels suggestion right before you had replied, I have been able to do both, it does register as being connected with the scanner sketch and the LED will blink as well. I am using simple arcade buttons so the positive pin is connected to the PA7 pin on the expander and the negative pin of the button is connected to the ground pin on the PA header if that helps.
 
Before getting to interrupts, it may be simpler to first try it without low power stuff or interrupts.

First try Examples -> Wire -> Scanner, load it, bring up the serial monitor, and run it. If it hangs that is an indication that you need pull-up resistors. You would attach one end of a resistor to the Teensy SCL pin (A5/19) and the other end of the resistor to the ground pins. You would attach one end of a second resistor to the Teensy SDA pin (A4/18) and the other end to the ground. Typically, you would use 2.2K resistors on Teensy, but you could use higher values.

If the Scanner runs but does not print anything finding a device, that means you haven't hooked up the device properly. It should show a device with address 0x20 by default (and up to 0x27, depending on the solder jumpers set).

Once the device is recognized, then try Examples -> MCP23017 -> Toggle and hook up a LED with a resistor to pin 0 of the MCP23017 and ground. The LED should flash on/off in 1/10 second intervals.

Then try the other two tests.
Accidentally deleted my reply when i was trying to edit it.... what it said was that I can confirm both of thsoe tests were successful. Multimeter shows the button is working correct and takes the pin to ground when pressed but Multimeter on the interrupt pin of the teensy and ground shows 3.3 at rest and goes bananas when i press the button. Cant figure out why that is happening. Here is the current code:

Code:
// Install the LowPower library for optional sleeping support.
// See loop() function comments for details on usage.
//#include <LowPower.h>

#include <Wire.h>
#include <Adafruit_MCP23017.h>

Adafruit_MCP23017 mcp;

byte ledPin=LED_BUILTIN;

// Interrupts from the MCP will be handled by this PIN
byte arduinoIntPin=24;

// ... and this interrupt vector
byte arduinoInterrupt=1;

volatile boolean awakenByInterrupt = false;

// Two pins at the MCP (Ports A/B where some buttons have been setup.)
// Buttons connect the pin to grond, and pins are pulled up.
byte mcpPinA=6;
byte mcpPinB=15;

void setup(){
    while (!Serial) ; 
  Serial.begin(9600);
  Serial.println("MCP23007 Interrupt Test");

  pinMode(arduinoIntPin,INPUT);

  mcp.begin();      // use default address 0
  
  // We mirror INTA and INTB, so that only one line is required between MCP and Arduino for int reporting
  // The INTA/B will not be Floating 
  // INTs will be signaled with a LOW
  mcp.setupInterrupts(true,false,LOW);

  // configuration for a button on port A
  // interrupt will triger when the pin is taken to ground by a pushbutton
  mcp.pinMode(mcpPinA, INPUT);
  mcp.pullUp(mcpPinA, HIGH);  // turn on a 100K pullup internally
  mcp.setupInterruptPin(mcpPinA,FALLING); 

  // similar, but on port B.
  mcp.pinMode(mcpPinB, INPUT);
  mcp.pullUp(mcpPinB, HIGH);  // turn on a 100K pullup internall
  mcp.setupInterruptPin(mcpPinB,FALLING);

  // We will setup a pin for flashing from the int routine
  pinMode(ledPin, OUTPUT);  // use the p13 LED as debugging
  
}

// The int handler will just signal that the int has happen
// we will do the work from the main loop.
void intCallBack(){
  awakenByInterrupt=true;
}

void handleInterrupt(){
  
  // Get more information from the MCP from the INT
  uint8_t pin=mcp.getLastInterruptPin();
  uint8_t val=mcp.getLastInterruptPinValue();
  Serial.print("Interrupted by");
  
  // We will flash the led 1 or 2 times depending on the PIN that triggered the Interrupt
  // 3 and 4 flases are supposed to be impossible conditions... just for debugging.
  uint8_t flashes=4; 
  if(pin==mcpPinA) flashes=1;
  if(pin==mcpPinB) flashes=2;
  if(val!=LOW) flashes=3;

  // simulate some output associated to this
  for(int i=0;i<flashes;i++){  
    delay(100);
    digitalWrite(ledPin,HIGH);
    delay(100);
    digitalWrite(ledPin,LOW);
  }

  // we have to wait for the interrupt condition to finish
  // otherwise we might go to sleep with an ongoing condition and never wake up again.
  // as, an action is required to clear the INT flag, and allow it to trigger again.
  // see datasheet for datails.
  while( ! (mcp.digitalRead(mcpPinB) && mcp.digitalRead(mcpPinA) ));
  // and clean queued INT signal
 // cleanInterrupts();
}

// handy for interrupts triggered by buttons
// normally signal a few due to bouncing issues
//void cleanInterrupts(){
//  EIFR=0x01;
//  awakenByInterrupt=false;
//}  

/**
 * main routine: sleep the arduino, and wake up on Interrups.
 * the LowPower library, or similar is required for sleeping, but sleep is simulated here.
 * It is actually posible to get the MCP to draw only 1uA while in standby as the datasheet claims,
 * however there is no stadndby mode. Its all down to seting up each pin in a way that current does not flow.
 * and you can wait for interrupts while waiting.
 */
void loop(){
  
  // enable interrupts before going to sleep/wait
  // And we setup a callback for the arduino INT handler.
  attachInterrupt(arduinoInterrupt,intCallBack,FALLING);
  
  // Simulate a deep sleep
  while(!awakenByInterrupt);
  // Or sleep the arduino, this lib is great, if you have it.
  //LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
  
  // disable interrupts while handling them.
  detachInterrupt(arduinoInterrupt);
  
  if(awakenByInterrupt) handleInterrupt();
}
 
Status
Not open for further replies.
Back
Top