SX1509 library interrupt problem

Hi everyone,

I’ve been playing around with the SX1509 library for the last day or so. I gave myself a small week-end challenge which consisted of reading as much HC-SR04 sonars as I can through I2C using the SX1509 as an intermediary. (using this breakout board.)

So far I:

  • Configured half the SX1509 as the HC-SR04 trigger pins
  • Configured the rest as my echo pins.
  • Enabled an interrupt on the echo pin of the sonar I want to read.
  • Use the active-low output interrupt pin of the SX1509 and the pulseIn() function of the Photon to capture the delay/distance of the sonar.

I’ve just started troubleshooting my circuit, however it seems like I’m not getting any echo back from the HC-SR04.
Using a small testbench program, I confirmed the sonar itself works well which means I most likely made a few mistakes along the way.

I’m not too familiar with the I2C protocol and quite unsure about the proper way to drill down to the root cause. I was thinking perhaps the digitalWrite() commands sent through I2C are too slow for the HC SR04 trig signal to properly work? Or maybe I’m not going the right way about reading the SX1509 interrupt with pulseIn()?

  SX1509 io; // Creation of  a an SX1509 object
  /* setup(), loop(), etc... */

      io.digitalWrite(trig_pin, HIGH);
      delayMicroseconds(10);
      io.digitalWrite(trig_pin, LOW);
      duration = pulseIn(D2, LOW);  //Particle's D2 configured as INPUT_PULLUP connected to the SX1509 active-low INT

@mivoel, one thing to remember with I2C is that the bus speed is (by default) 100KHz or 10us per bit. You may want to set the I2C clock to 400KHz to speed things up Depending on the amount of data sent for each GPIO command, there could be a command “lag” of 100us to several hundred microseconds. You will need to consider this in your timing.

Note that the breakout board includes a 10kΩ resistor pulling INT HIGH. So there is no need to use an internal pull-up.

The is a problem with the way you expect the INT* pin to work. The Adafruit guide says “It can be configured to go LOW whenever a pin state changes”. Meaning, it won’t “shadow” the pin state but go LOW when the programmed state occurs. Here is how the INT* pin works:

  1. You enable interrupts for a GPIO pin (RISING, FALLING, CHANGE) using the enableInterrupt(byte pin, byte riseFall) function.
  2. When the GPIO pin state satisfies the interrupt conditions, INT* will be pulled low and stay that way until the interrupt flag is reset using checkInterrupt(int pin) which will reset the interrupt flag if it is set.

So, you will not be able to use pulseIn(). Instead, you will need to set the SX1509 GPIO interrupt to whatever the ping state returns (RISING, FALLING). Once you fire the ping, you will need to start a counter (set starting time in millis() or micros()).

At the next GPIO pin state change (from the ping), INT* will go low. The ISR can then calculate the change in time (from the start time), store it in a global (volatile) variable, read/reset the interrupt flag and reset the “timing started” flag. The interrupt flag reset could also (instead) be done by loop() so that the interrupt is only enabled once the next sensor is selected via the SX1509.

You could easily setup an array of pins and calculated time values to simplify the interaction between loop() and the ISR.

There may be a timing challenge in this entire approach if the sensor ping time is smaller than the I2C transaction time. You will need to work that out.

2 Likes

Thanks! I’ll polish up my knowledge of I2C, review the doc, and give it another go soon. I’ll be wary to add the appropriate delays which takes into account the I2C transaction time.

I remember having some difficulties referencing class variable and using member function as callback functions for an ISR last time I tried. As you suggested using a global (volatile) variable seems to be fairly straightforward. I found that the hard way especially since using wrapper functions / static pointer doesn’t seem to be the recommanded method…. I’m not too experienced with embedded C++ programming, however with such insightful answers this should keep me busy for the next couple days

:clap: Thanks again

2 Likes