[Release] HubDuino v1.1.4 - Hubitat to Arduino / ESP8266 / ESP32 / ThingShield Integration (ST_Anything)



So, I did a little digging into the analogReference() call. It appears to be valid only for real Arduino boards, not the ESP8266 or ESP32. So, is it safe to assume you're using an Arduino MEGA or similar?

One way to approach this is to create a second C++ constructor which is only compiled into the code if the board is one that supports the analogReference() call. This requires the use of #if conditional compilation statements.

You might also be able to simply call the analogReference() call in the sketch's setup() routine. That really does seem to be the simplest solution. No other code changes are required.


Appears that this will do it, and yes, my target application is on a MEGA.

I spent some time on a Mega outside the ST_Anything environment to compare stability of analogRead results when power supply source changes. The signal input voltage was independent of Mega supply voltage (not ratiometric referenced to Vin). When using analogReference(DEFAULT), changing from a 9V wall-wart to USB power and back caused a repeatable 1.9% shift in the analogRead results. Changing to analogReference(Internal1V1) resulted in no shift at all when changing the power source. This confirms the usefulness of the internal reference. It appears to be more independent of supply voltage changes.

The DEFAULT reference worked fine for ratiometric inputs that were also referenced to Vin.

My particular use case is not ratiometric, and a 1.9% shift is 0.25 volts. This is about equal to the delta I am trying to recognize to set a notice that the security panel has dropped off AC power and is running on backup battery. Using the internal reference voltage will solve my problem.

Some things I learned about changing the reference voltage:

  1. After the analogReference() command, analogRead(0) command is required to actually change the reference.
  2. After the analogRead(0) call that changed the reference, it takes 5ms for the reference to settle before an accurate analogRead call can be performed.
  3. if any support libraries are using Ax pins for a device(Seeed TFT screen is one example), it is possible they use the default reference, and will malfunction if you do not set the reference back to DEFAULT when finished with reads using INTERNAL1V1.


Here is another very useful tip which I am sure you have already read, but it is worth noting... (taken from Arduino Reference)

Notes and Warnings

After changing the analog reference, the first few readings from analogRead() may not be accurate.

Don’t use anything less than 0V or more than 5V for external reference voltage on the AREF pin! If you’re using an external reference on the AREF pin, you must set the analog reference to EXTERNAL before calling analogRead() . Otherwise, you will short together the active reference voltage (internally generated) and the AREF pin, possibly damaging the microcontroller on your Arduino board.

Alternatively, you can connect the external reference voltage to the AREF pin through a 5K resistor, allowing you to switch between external and internal reference voltages. Note that the resistor will alter the voltage that gets used as the reference because there is an internal 32K resistor on the AREF pin. The two act as a voltage divider, so, for example, 2.5V applied through the resistor will yield 2.5 * 32 / (32 + 5) = ~2.2V at the AREF pin.


That complication is why I chose the internal reference. Since I have chosen roughly 0-20V as my full scale input range, a voltage divider consisting of external resistors is required. I do not want to add additional resistors to protect Aref.

Related to simplifying things, I was able eliminate the low pass filter I had been using between the voltage divider and the analog input pin. I thought I was chasing noise on the input signal, but it appears to have been noise on Aref when using the default reference. The signal looks a lot cleaner now that I am using the internal reference.

I also have concluded that it is not necessary to build precision voltage dividers to make the digital values from analog read match theoretical calculation. The internal reference is not exactly 1.1V, so calibration of the input is required in software even if the voltage divider is perfect. If it needs to be calibrated anyway, there's nothing gained from making the voltage divider perfect. That translates to using cheaper and fewer resistors.

So far I have used a linear fit when calibrating analog inputs, and it is always a compromise balancing error across the input range. This investigation led me to discover your polynomial fit arguments in PS_Voltage. That might lead to an interesting experiment on best method for determining the polynomial coefficients.


Dan, When I went to my stock of ethernet shields to put together another Mega based Hubduino, I found all I had on hand were W5200 based shields. These seem to work fine with your W5100 focused code which appears to call the standard Arduino Ethernet library. When looking at the standard Arduino Ethernet library, I saw that it supports W5100, W5200 and W5500. What is your reason for maintaining a separate implementation for W5500 which calls Ethernet2? Is it just that you developed the W5500 code before the Ethernet library had universal function?


Yes. When i developed the W5500 solution, there were two libraries. I wasn’t aware that Arduino had merged these all into a single library. Thanks for the heads up.


I might be mistaken about the W5200 working ok with your W5100 library. Before I noticed the claim of universal function for the Arduino Ethernet library, I had built a W5200 ST implementation using the Seeed EthernetV2_0 library called from a modified version of your SmartThingsEthernetW5500 library. I am certain that combination works.

After that success, I read about the universal function of the Arduino Ethernet library and proceeded to setup using your SmartThingsEthernetW5100 library. I thought it was working with the W5200 shield, but it is not. Switching back to my custom ST W5200 library delivers good function. Not sure how I convinced myself the ST W5100 code was working with the 5200 shield. I do not see a version of Ethernet library in your Github repository, so I assume I am running the standard Arduino Ethernet library that is included with version 1.8.8 of the IDE. More tinkering is required.


Hey Dan. I got the board lockup again and I'm definitely thinking that has something to do with the sketch on the board because after having to do a hard power-reset on he hub, I can no longer even ping the board that is locked up. It's not that HE can't connect with it, I don't think anything can connect with it. Any ideas what could be causing it to lockup like that? if it's actively sending something and waiting for an ack or something?
I may just go and get some cheap wifi plugs and hook those up to the power supplies for my boards so I can reset them that way.


I feel your pain, Ryan. I have had a lockup or two on my Hubitat Hub. When it happens, my HubDuino boards also get locked up and require a power cycle to reset them. This is on and Arduino Mega 2560 with a W5500 Ethernet Shield, as well as a NodeMCU ESP8266. I don’t know what causes the lock up. Maybe we could try to utilize the watchdog feature of the ESP8266 to automatically reset the MCU if it detects a lockup?

That’s the only idea I can think of. It probably makes good sense to see if the watchdog feature would work. I am just worried about any ‘normal’ blocking calls that might inadvertently trigger the watchdog.


You genius must be rubbing off or transferring by osmosis or something because I was thinking the same thing. Unfortunately, me poking around would probably do more harm than good. :stuck_out_tongue:

How long is your longest blocking call? The software wdt in the esp class is configurable and could be set longer than your longest blocking call. It should be possible, at least from what I have read and my limited knowledge of the structure of the Hubduino libraries. Because of the structuring of the libraries though (which I totally understand is the only thing that makes the system as a whole so modular and adaptable to every scenario) is a big hindrance to anyone with only a novice skill-set making any modifications. I've tried before and I also miss a function somewhere or don't realize the implications of what appears to be a small change. So, I don't know how much help I'm going to be.

I was also wondering if we might actually be stuck in some type of loop on the board. Since we are only seeing this failure when we have to pull the power on the hub due to a lock-up, is it possible that the board is stuck waiting for some type of acknowledgement from the hub that it will never receive since it is locked up and being forced to reset? I'm not familiar enough with the low-level communication between the board and the hub to answer that question but I see that not infrequently in my line of work.

Now that I have a better handle on OmniThing though, I was going to look at possibly porting a couple of boards over to that system. Given your knowledge of how Hubduino and OmniThing operate and the failure mode we are observing here (being caused after a hard power-reset) do you think that OmniThing would be susceptible to the same type of failure.

The one thing I wish even more than being able to fix this easily is being able to reproduce the problem easily! I hate to keep pulling the power on my hub to create the failure because every time you do that you're increasing the chances it won't come back on. And I REALLY don't want to press my luck. If the no-stick hub were a little cheaper I'd consider getting one as backup/testing but $80 is a little steep given my limited use for it. Maybe someday when I get better at Groovy. :smiley:

All that said, I'm more than willing to help test anything you come up with? I have a whole bunch of extra boards (D1 mini's, NodeMCU, and Feather Huzzah) and sensors of different flavors so I could set a few up to run bench-top for long-term stability testing. Other than being a sounding board, I'm afraid that's all I have to offer. I still have much to learn. :bowing_man:


I'm observing some odd behavior with the servo. I'm utilizing the detachAfterMove parameter because my servo likes to sit and buzz incessantly. Unfortunately when power is removed, the servo defaults back to the initial starting angle of 90 degrees (level 50). Is there a way around this?

Edit: Not actually related to detachAfterMove. It's reverting to default position without that parameter set also.

Edit2: Seems to be related to the addition of the switch parameters. Removing the start position from the sketch and utilizing only the on/off works fine. But using the dimmer always reverts to whatever the start position is.


Instead of yanking the power out of the Hubitat Hub, I wonder if simply pulling the Cat5 cable would reproduce the HubDuino lockup? I may try that later on my development HE hub.

I’m not sure whether or not OmniThing would suffer from the same issue.

As for using the Arduino Watchdog, I have a NodeMCU ESP8266 running in my office with just changes to the sketch to enable the watchdog timer. I use the 8 second timeout because I couldn’t think of a reason not to. I am concerned that a system with a large number of devices defined will execute longer than 8 seconds when a Refresh occurs. I will probably need to add a watchdog timer reset within the ST_ Anything library code to prevent inadvertent resets.

I just need to find some time to do some testing. Also, since the watchdog timer uses an interrupt, we need to make sure it is compatible with all devices that might also need to use interrupts.


The only way I could think that it would reset itself to the default servo position is if your MCU is resetting itself (or experiencing power blips.) A marginal power supply could cause this.


Hmmmmm.... I've got it plugged into the PC, but I'll check my connections.


What is powering the servo motor? The typical PC USB port isn’t very powerful. Also, if the servo motor is being powered by the MCU, you may be starving the MCU for power.

If you have the Arduino IDE Serial Monitor window open, you should easily be able to see if the MCU is resetting.


It's just a test servo, so there's no load - I would think the PC USB port would be okay, but maybe not. I pulled this MCU out of a set of blinds that have been paired with SmartThings for the past year. It's been wall-powered and the MCU is delivering the power. Not ideal, but it's been okay. I'll go try it with the wall adapter and see.


I have 4 servos in my house controlling blinds. In all of the horizontal blinds I am running the servo directly off the 5v power supply not off the boards 5v pin. Depending on the board, that pin is usually limited to an amp rating well below that of the servo. You might get it to start moving but when it locks up, it's going to reset the board.

The one exception to this are my vertical blinds because that servo barely has to do any work to move the blinds at all. So it doesn't pull as much juice.

For my living room blinds, which are 8 feet wide, I actually got a stronger all-metal servo which requires 7v so I'm using a 12v supply and 2 buck converters, one set to 7v and the other to 5v.

But I would definitely not power them off the board. You're going to need at least an amp and your board (or your PC's usb port) won't supply that.

Which brand of NodeMCU do you have? I have had 3 different brands and one of them would reset if I tried to power barely anything off the 5v pin. So, it can be dependent on the particular board as well.


Just noticed I had the board IP set the same as my illuminance sensor board downstairs, which might be some of the problem. :man_facepalming:


So power supplies though. Yeah, I need to do that. I imagine the servos will run a lot more elegantly as well instead of coughing and sputtering.


I went through the same problem when I was originally setting up mine. If you are using a sketch that has a lot of "waits" in it, like the esp8266 blinds on the ST forum, a wonkey power supply will work because it's moving the blinds so bloody slowly. But as soon as I moved my blinds over to the Hubduino library, I had to get better power supplies. But I also notice that my blinds close a lot tighter. I could never close them down before cause they wouldn't close tight enough. Now, I can.