Nuances Series #1: Unintentional Spike

This is the first post of a series, the idea is to post about some easy to overlook things while designing and building embedded hardware and applications. This post in particular is about a relay board which is driven over I2C. I was getting unintentional spikes on my load which is connected to the relay.

At office, we are moving from C to C++ and I am new to object oriented programming. Learning theory is all good, but from my experience, we learn something well when we try to use it solve real problems with real constraints. So I started a pet project to build an IoT board based on ESP8266. I know that if I need to get something done, I should aim for MVP (minimum viable product) but this being more of a learning exercise than a project which needs to be completed asap, I started designing a platform independent code base which I would be able to leverage for future projects. (more about this probably in a later blog)

Coming back to the topic, this particular board i am working on,  I have an ESP talking to PCF8574 over I2C and this was driving a 4 channel off-the-market relay board which has an active low input.


In the code, I have a class defined for the PCF8574 over I2C, and I have defined a class for a single channel of relay as well. Since my relay board has control input as active low (when the pin is pulled down the relay is switched on) initially for each relay on the board I had created an object of the relay class which had an inverted output. Meaning, if I set it "On" it will actually pull the I2C pin Low. The thing which I overlooked was in the initialization of the PCF8574 class that I wrote. I initialized all pins with "Low" (set the output value to 0).

The initialization sequence of the board was: first the board comes up, then it will initialize all the buses like PCF8574, CD4051 (i had a CD4051 to multiplex the ADC inputs) etc. Then the IO pins are initialzed, which will specify pins with type (if its a GPIO, over I2C or over CD4051 etc). Then it will initialize all the sensors and actuators which will have one or more pins associated with it . All these happens in a jiffy when the board boots up.

I noticed that the LEDs on the relay board is getting lit for a fraction of a second when the board boots up. I have an LED bulb connected on the load, that stays off during this sequence, at least to my naked eye. I hooked up the relay board to the scope and this is what i saw:


There was a 25ms window when the relay was "On" before it went to its set state. Initially I thought it was bad design of the relay board where if the input is not pulled high at start up the relay turns on. I started debugging by disconnecting the relay board from my ESP-pcf board and powering it up separately, with no connection to the input pins. The relays stayed off at start up. The relay turns on only if you actively pull the input low, meaning only if the input pins are connected to ground will the relays turn on. Then  I realized that the init of the I2C bus is causing the problem. I am writing 0 to each of the PCF pins by setting the initial value to 0 and then immediately setting it to 1 when each of the relay pins are initialized.

This is very easy to overlook on a Solid state relay board since you wont hear a thing while the relay switches on or off. While driving load, this can cause a spike every time power comes back after a power outage. The way I have resolved the problem now is by defining a new constructor for the PCF class which takes an initial value for all pins (in this case 0xff) which will make sure that the PCF is initialized with high on all pins which have relays connected to it.

I am planning to use this with Node Red and Alexa to automate my room. I have all my equipment connected over spike protected UPS, but still, had this gone unnoticed it could have potentially caused a lot of trouble.

Comments

Popular posts from this blog

Weekend Project: Nerf Dart Counter (Ammo Counter)

Exporting Solder mask with untented Vias as SVG from KiCad

No nonsense LPG sensor