GPIO output changes state on Device Disconnect

Hi All,

I’ve got an ImpC001-US dev board setup in the lab. GPIO PinD is configured as an Output and is connected to a 3.3Vdc Opto-isolated relay board linked here.

While sitting here in the lab (we have poor cellular reception in here), I’ve noticed that the relay chatters open and closed very quickly every time the Imp disconnects and reconnects (as seen in my IDE log file):

|2019-08-15T14:34:43.589 -04:00|[Status]|Device disconnected|
|2019-08-15T14:34:43.588 -04:00|[Agent]|Device c001xxxxxxxxxxxxx is not connected|
|2019-08-15T14:34:43.705 -04:00|[Agent]|Device c001xxxxxxxxxxxxx is connected|

It’s pretty important in my application that this relay does not change states unless the user sends the command via the Agent. Is there any code I can add to help ensure it does not change state due to a network error?

EDIT: I’ve seen the relay chatter occur without a matching Device Disconnected event in the log, so it might be an incorrect conclusion that it is due to a network error!

I put a scope probe on PinD output (blue trace) and waited for my relay to chatter off/on (i.e. set my trigger to 3Vdc falling edge on PinD). Noticed that the voltage drops to 2.8Vdc for about 9ms. I also monitored the incoming 5Vdc (red trace) that powers the board to see if I was getting a drop in voltage for some reason at that time. Seems to be very steady ~5Vdc throughout the entire event.

Interesting; if a single pin is doing that, then I’m pretty sure you will see 3v3 dropping at the same time (a high GPIO is essentially just connected to 3v3).

How is the VCC of the relay board being supplied? From the imp PSU?

Oh hang on, I know what this is… sorry, not had enough coffee today obviously!

At any build & run/VM restart, all GPIOs are tristated. What you’re seeing is the GPIO tristating, then being re-configured and driven by your code.

In the event of a longer disruption (eg OTA OS update) you’ll see the same - the GPIO will be tristated during the upgrade period, as your code is not running at that time.

There are a couple of ways to address this:

  • Use a flip-flop to latch the state. Here you would connect the flip-flop’s D line to an imp GPIO (this sets the next desired state), then the CLK line to another imp GPIO, which you’d drive high then low to clock the new D state through to the Q pin. You would put a pull-down resistor on the CLK line to ensure it stayed stable unless it was driven. As long as the flip-flop has power, the state on the Q pin will be preserved.

  • Use a bistable relay. These relays hold an on or off state permanently, and use two control signals - one which, when pulsed high, will turn the relay on, and another which, when pulsed high, will turn the relay off. There are a number of relays on amazon which are not latching, but this one is the real deal: … the relay coil is 12v, but the control signals just feed a transistor via a 1k resistor, so will likely work fine (3.3v drive, 0.7v Vbe, 1k resistor = 2.6mA base current so with Hfe of even 30 you’ve got plenty to switch the relay). The great thing here is that no power is required to preserve state - even after a power outage, if the switch was ON, it’ll be ON as the power comes back up.

Do you have 12v anywhere around? There are lower voltage latching relays, I just couldn’t find one on amazon with a quick search.

Awesome - thanks for the clues on what is happening. I think we can come up with a solution to solve this once we spin our own boards; I wanted to make sure I was seeing something expected here.

My 3.3Vdc relay is getting it’s VCC power from a 3.3V pin on the dev board.

The latching relay would be really nice, except we need our relay to fall back to the open state if there’s ever a power failure.

These boards will be powered by a 12Vdc battery (the starter battery on a gas generator) so I’m using a 12Vdc to 5Vdc step-down to power the board.

Thanks for the help Hugo!

There are “fake” latching relays, which toggle state when you close two pins, eg - these will open on a power failure - but there are a couple of issues with these:

  • there’s no indication of what voltage is exposed on the toggle input
  • you can’t tell if the relay is off or on at any time

Ah, just found this:

They appear to be using an MCU instead of a flip-flop (!!!) but this has SET and RST connections, which is what you want; the only worry I have here is that you pull these inputs down to set or reset (fine) but I don’t know what they’re pulled up to.

Worth buying one and checking this with a meter. There’s definitely an LDO on board to run the MCU, but I suspect it’s a 5v one, meaning you’d really want a couple of N-FETs to deal with the higher voltage (gate driven by imp, source to GND, drain to the SET or RST pin).

I don’t get it. Why is this imp experiencing VM restarts when it disconnects/reconnects?

You may well still need the extra circuitry Hugo describes, to keep the relay stable during “Build & Run” and during OS updates – but your relay shouldn’t be chattering when neither of those things is happening. Is your code restarting at those times – perhaps due to a Squirrel runtime error?


Hi Peter - I’ve done some further testing. It turns out that the real culprit here is my 12VDC to 5VDC USB converter I’m using. Link here. It’s rated for 3A, just like the 120Vac power supply that comes with the Imp boards, but we are dealing with a sketchy Chinese supply off of Amazon here…

The issue goes away completely if I use the Imp-provided 120Vac to 5Vdc supply.

Measuring the input voltage of the USB pins, I get around 4.9 to 4.8 Vdc with the Imp-provided supply. My Chinese 12-to-5Vdc supply appears to be outputting 5.1 to 5.2 Vdc. Does the Imp dev board have a rated max input voltage? I would think it could handle that, but maybe it’s causing an overvoltage situation somewhere on the board?

The timing with the network disconnect/reconnect may have been a red herring, but not totally sure yet.

I started monitoring a 3.3V supply pin on the Imp board with the o-scope. It seems to be dipping down to 2.5V every time the relay is dropping out. If I set my scope to trigger on a drop of the 3.3v supply, it’s actually occurring quite often. What would cause the 3.3 supply to be dropping out so frequently?

I don’t think my code should be restarting ever; it’s pretty simple.

#require "HTS221.device.lib.nut:2.0.1"

// Globals
sensor <- null;
old_UI_relay_state <- null;
old_xfer_state <- null;
dataPayload <- {};
UI_relay_state <- 0;
UI_relay_close_time <- 0;

// Configure I2C bus and sensors
local i2c = hardware.i2cKL;
sensor = HTS221(i2c, 0xBE);

// Set DIO pins
local utility_interrupt_relay = hardware.pinD;
local xfer_state = hardware.pinE;

// Sends data to the Agent whenever input changes state.
function inputHandler() {
    // Read UI Relay state (virtual state based on GPIO output status)
    // This means the imp has received the command and turned on relay output
    dataPayload.UI_relay_state <- UI_relay_state;
    // Read Transfer state
    local inverse_state = == 0 ? 1:0;
    dataPayload.xfer_state <- inverse_state;    
    // Compare current state to old state. If different, send data to Agent
    if ((UI_relay_state != old_UI_relay_state) || (dataPayload.xfer_state != old_xfer_state)) {
        old_UI_relay_state = dataPayload.UI_relay_state;
        old_xfer_state = dataPayload.xfer_state;
        server.log(format("Transfer Input State: %d", dataPayload.xfer_state));
        server.log(format("UI Relay State: %d", dataPayload.UI_relay_state));

// Configure the pins
utility_interrupt_relay.configure(DIGITAL_OUT, 0);
xfer_state.configure(DIGITAL_IN_PULLDOWN, inputHandler);

// Turns on/off UI relay if the agent sends a Power On/Off command
function UI_relay_Handler(state) {
    local str = format("Recieved a UI Relay command from agent: %d", state);
    utility_interrupt_relay.write(state);  // set state of pin
    UI_relay_state = state; // Copy state into relay state variable
    inputHandler(); // Run the input handler function to check for change

// Read all sensor data
function readSensorData() {
    // Get the sensor data
    local reading =;
    // Generator max run time failsafe here?
    if (UI_relay_state == 1) {
       UI_relay_close_time += 1; 
    // Add the temperature using Squirrel’s 'new key' operator
    dataPayload.temp <- reading.temperature * 1.8 + 32;
    dataPayload.humid <- reading.humidity;
    // Check again in 10 seconds
    imp.wakeup(10.0, readSensorData);

// Function to send data to the agent
function sendData(data) {
    agent.send("reading", data);
    server.log("sent a reading to the agent");

// whenever we get a "power" message, run the powerHandler function 
agent.on("power", UI_relay_Handler);

// Start the data read loop function

// Read the input state on first run.

Is there a way to see that if it is occurring?

Well, I believe I solved it. It was a case of Read the Freakin Manual.

Looks like the PMU was enabling current limiting, since the 12Vdc to 5Vdc converter has no D+/D- data lines, and I had not bridged W1. Not sure what the default current limit is when it sees no D+/D- data, but it must be low enough to drop the 3.3V supply to 2.7V during cellular transmissions.

I bridged W1 and have not had a 3.3v drop or a relay chatter since.

Ah yes, the default limit is 500mA and especially with other things powered from the imp 3.3v you’re taking a lot out of the available current. That makes total sense now :slight_smile:

While it is nice that it is working now, I’m still a little surprised that it was drawing more than 500mA. The 3.3V relay was always on, so no inrush or change of state was going on. The relay is pulling 96mA, and that is the only thing we have connected to the Imp at this time. That leaves over 400mA just for imp-related processes. Is that typical?

For short peaks, sure. See the datasheet - up to 570mA just on VMOD when the PA is on at a high power level.

The imp itself (on 3v3) will be taking much less, but cell radios still have high current peaks. In Europe it can be up to 2.4A when on a 2G network for bursts as they can transmit at +33dBm.