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

I'm not understanding something about the sensor objects and calling class functions by name.

In my setup I have
static st::IS_Button sensor2(F("button1"), PIN_BUTTON_1, 3000, LOW, true, 500);
st::Everything::addSensor(&sensor2);
st::Everything::initDevices();

but when I get to my loop and try the following...

void loop()
{

st::Everything::run();

ledState = digitalRead(PIN_LED);
if (&sensor2->getStatus()) {
digitalWrite(PIN_LED, ledState ? HIGH : LOW);
}
}

....I get 'sensor2' was not declared in this scope. Sorry to be such a novice, but what should I be doing to use the sensor object to call the various class public functions?

The much better place to execute code like you've shown above would be in the "callback()" routine. That routine is called each time the microcontroller sends an update to Hubitat. The name/value text pair is available to parse and then perform whatever other code you'd like.

The specific error your experiencing is due to the fact that the scope of the 'sener2' variable is only valid within the setup() routine. In order to use it within the loop() routine, you'll need to create a global pointer variable outside of both the setup() and loop() routines.

Something like

st::IS_Button* ptrSensor2;

then add to the end of the setup() routine something like

ptrSensor2 = &sensor2;

Then, in the loop() routine use the following syntax

ptrSensor2->getStatus()

Hope that makes sense!

Hi there,
I'm embarking on adding meter readings (gas, water, elec) to HE, so that I can decide what to do with my PV generation, spot water leaks etc etc.
I'm using an ESP8266 with an LM393 to count meter pulses.
I tried with Tasmota which was looking good, but hit a wall (see Creating a power meter by counting pulses with LM393 and Tasmota - #2 by jamesxheath and [RELEASE] Tasmota for HE - Auto-detecting Tasmota drivers + Tasmota firmware 7.x/8.x for HE (for use with Tuya, Sonoff and other ESP devices) - #586 by jamesxheath).
Then @peterbrown77.pb reminded me about HubDuino - of course!! I already have that set up for a load of DS18B20 temp sensors.
I'm working on getting the pulsecounter working, but have hit an issue - I don't think the ESP8266 is getting data to the HE - the child device hasn't been created, and the logs show nothing interesting other than an error:

dev:13222022-04-02 10:03:05.155 debugdescription= 'mac:500291FE6C30, ip:c0a85619, port:1f9a, headers:SFRUUC8xLjEgMjAwIE9LDQo=, body:'
dev:13222022-04-02 10:03:05.091 debugUsing ip: 192.168.86.25 and port: 8090 for device: 1322
dev:13222022-04-02 10:03:05.089 debugExecuting 'sendEthernet' refresh
dev:13222022-04-02 10:03:05.088 debugExecuting 'refresh()'
dev:13222022-04-02 10:03:05.086 infoSending REFRESH command to Arduino, which will create any missing child devices.
dev:13222022-04-02 10:03:05.035 infoEnabling Debug Logging for 30 minutes
dev:13222022-04-02 10:03:05.002 infoSetting DNI = C0A85619
dev:13222022-04-02 10:03:05.000 infoArduino IP Address = 192.168.86.25, Hub Port = 8090
dev:13222022-04-02 10:03:04.998 infoHub IP Address = 192.168.86.20, Hub Port = 39501
dev:13222022-04-02 10:03:04.996 infoExecuting 'updated()'
dev:13222022-04-02 10:00:55.044 errorjava.lang.NullPointerException: Cannot execute null+900000 on line 414 (method checkHubDuinoPresence)

which I think is because the Hubduino parent has never received data, so doesn't have a time stamp to work out the presence from.
In my arduino code I am using the identical settings to my other devices, with the exception of the reserved IP for the 8266 (which I've checked is correct).

The arduino serial monitor is behaving a bit oddly (weird non ascii chars):

Enter the following three lines of data into ST App on your phone!

localIP = 192.168.86.25
serverPort = 8090
MAC Address = 500291FE6C30
SSID = xxxxx
PASSWORD = xxxx
hubIP = 192.168.86.20
hubPort = 39501
RSSI = -64
hostName = ESP8266-500291FE6C30
SmartThingsESP8266WiFI: Intialized
Disabling ESP8266 WiFi Access Point
ArduinoOTA Ready
IP addr�.'�ʒr���r²r��j
ArduionOTA Host NU: ESP8266-500291FE6C30
Every-�: init ended
Everything: Free RAM = 48536
Everything: adding sensor named power1
Everything:V� O�ª��ja�^�4�*�''J��ZAeWk�� started
Everything: Free RAM = 48536
Everything: Sending: power1 0
Everything: initDev�,ցY�)VHEverything: Free RS' j
Everything: Free Ram = 47936
Everything: Sending: ower1 48

(I have obfuscated the Wifi details - they are correct)

It suggests that it is trying to send data, though should I worry about the line:

Disabling ESP8266 WiFi Access Point

This ESP8266 and the pulse counter worked perfectly on Tasmota - I could see everything over Tasmota's webUI - I just couldn't get the data to appear in HE

Help!!

James

Thanks Dan! The example you gave helps a lot.

One quick follow-up question: I'm more concerned about when Hubitat sends something to the microcontroller, is callback() still the appropriate place to put the code or is their a better place?

Greg

Hmm... Stand down on this for a moment...
I had another 8266 lying around, so I gave that a try, and it works.
Slightly worryingly though - I've not updated the IPs in the code yet, so I'm a little surprised it works.....
I'm trying to get the settings right, but I have a rubbish DHCP server (Google Wifi - great consumer device, but terrible for managing IP allocation, looking at devices etc).

1 Like

There is a much better place for 'sniffing' the incoming data.

In the setup() routine in the sketch, simply make the following change. Or, if you want both a SEND and a RCVD callback, simply create a new callbackRcvd() function and assign that function to the callOnMsgRcvd pointer below.

  //Initialize the optional local callback routine (safe to comment out if not desired)
//  st::Everything::callOnMsgSend = callback;
  st::Everything::callOnMsgRcvd = callback;

So I have no idea what went wrong earlier - I'm blaming the Google Wifi - it's really hard to see what devices have what IPs and what their MACs are.

But I'm up & running with a watts figure, derived from counting the 1 Wh pulses from the meter for one minute & multiplying by 60.

The next desires are:
1/ possibly improve accuracy by timing the interval between a number of pulses and reporting based on that - currently max accuracy is 60W. Though TBH this may not be worth doing.
2/ reporting the actual Energy consumption by passing over the pulse count. This would probably mean storing it in flash so it persisted over power cycles.
3/ expanding to water - I know Hubduino has a water meter set up for analogue, so I ought to be able to use that in conjunction
4/ expanding to GAS - I could just use this, and convert from m3 of gas to kW...

@ogiewon - has anyone done any of these before? I am not a great coder, and whilst I can tell that the architecture of Hubduino is very elegant & flexible, it is (currently at least) a little beyond my understanding. I'm willing & keen to give it a go though!

James

Have you looked at the ST_Anything PS_PulseCounter device? It is actually designed to handle higher frequency pulses that I am guessing your meter is providing, but it may be useful.

//******************************************************************************************
//  File: PS_PulseCounter.h
//  Authors: Dan G Ogorchock & Daniel J Ogorchock (Father and Son)
//
//  Summary:  PS_PulseCounter is a class which implements the SmartThings "Power Meter"-style device capability.
//			  It inherits from the st::PollingSensor class.  The current version uses a digital input to measure the 
//			  the number of counts between polling intervals.  At the polling interval, the pulse count is converted
//			  to engineering units via a linear conversion (engUnits = slope x counts + offset).
//
//
//			  Create an instance of this class in your sketch's global variable section
//			  For Example:  st::PS_PulseCounter sensor3(F("power1"), 60, 5, PIN_PULSE, FALLING, INPUT_PULLUP, 1.0, 0);
//
//			  st::PS_PulseCounter() constructor requires the following arguments
//				- String &name - REQUIRED - the name of the object - must be in form of "power1", "power2", etc...
//				- int interval - REQUIRED - the polling interval in seconds
//				- int offset - REQUIRED - the polling interval offset in seconds - used to prevent all polling sensors from executing at the same time
//				- byte pin - REQUIRED - the GPIO Pin to be used as an digital input (Hardware Interrupt)
//				- byte inttype - REQUIRED - which type of Arduino interrupt to trigger the ISR (RISING, FALLING, CHANGE)
//				- byte inputmode - REQUIRED - Mode of the digital input Pin (INPUT, INPUT_PULLUP)
//				- float cnvslope - REQUIRED - Conversion to Engineering Units Slope
//				- float cnvoffset - REQUIRED - Conversion to Engineering Units Offset

Hi Dan, yes that's what I've got working.
It's doing the job, I'm hoping to work out how to extend it. I'll likely come back with questions....

1 Like

Got it. That helps a lot. I'm a coding noob, but it's starting to come together a bit for me now.

Just to add, Hubduino is an amazing asset, especially to DIYers like myself. Thank you for it and for all your dedication to the community.

1 Like

I've set one of these up & it's working OK on D7, using a falling edge trigger.
I've tried adding a 2nd on D4 (I'm fairly sure I read somewhere that the ESP8266 only had 2, though a quick google suggests they are on every pin other than 16?) and both readings go awry - they seem to average themselves.
I also saw odd behaviour from the blue LED on the board - with only D7 working it stays on the whole time. When I added D4 it flashed in time with the pulse on D4.
Any suggestions for which pins I should use if I want to use multiple pins?
Might it be interference from one to another? these are only pulsing 80 times a minute or less. I've added some small capacitors in case, and I've enabled INPUT_PULLUP.
I'm wondering about adding some debounce in code in case that helps.
I'd like to run four from one device, but if I have to use an ESP8266 per meter that's OK.

@ogiewon I could do with a quick bit of guidance...
I'm getting on nicely working on modifying PS_PulseCounter to my needs, though it's extending my programming knowledge to cover Classes!
It's given me insight in to the issue I described in the post above.
If I create two instances of PS_PulseCounter:

 static  st::PS_PulseCounter  sensor1(F("power1"), 5, 0, D3, FALLING, INPUT_PULLUP, 1.0, 0.0);
 static  st::PS_PulseCounter  sensor2(F("power2"), 5, 2, D4, FALLING, INPUT_PULLUP, 1.0, 0.0);

They look to me to be sharing the interrupt, or possibly the m_nCounts variable, meaning that I don't get a meaningful value out of either.
Is there something special I should be doing - using specific pins, something else?
Or does the ESP8266 only support one interrupt? I'm new to this!
Ideally I'd like to run 4 of these counters from one ESP8266, but if I have to use one for each that's not the end of the world.

Thanks,

James

Yes, you are correct. The Interrupt Service Routine (ISR) and the m_nCounts variable are being shared amongst all instances of the PS_PulseCounter class. This was done as the ISR could not access the variable otherwise.

You could try to create three more versions of the PS_PulseCounter class, called something like PS_PulseCounter2, PS_PulseCounter3, and PS_PulseCounter4. In each of them, rename both the isrPulse() routine and m_nCounts variable accordingly, and change all references to both within the new .h and .cpp files as well.

It's worth a try, in order to use more than one PS_PulseCounter on a single microcontroller. Just be aware that I am not sure if this will work or not. It may work on some microcontrollers but not on others due to hardware Interrupt limitations.

Thanks - I'll give that a try, then likely give up and just buy a few more ESP8266s!
I did try and implement this:

which looks very neat, but is unfortunately a little beyond my expertise, and I hit issues I couldn't resolve.

I wonder if Bluetooth Arrival Sensor exist for Hubduino?
And if doesn't how easy to add or develope one?

It does not exist.

Please explain exactly how you would envision this working? It might be easy… or it may be challenging. Need some details to understand the requirements and do some analysis.

@ogiewon - that worked a treat! not the nicest code, but I'm fine with it - thanks so much! Have you got patreon or similar so I can send you a beer?
My next step is to add sending of total counts since power on, to allow me to graph hourly, daily, weekly consumption etc.
Would you suggest modding the classes to send two bits of data (I had a look at PS_TemperatureHumidty), or just using the "generic" class, and a global variable for each to transfer the data? I don't think you've sent "Wh" or "kWh" in any of the classes.

I am thinking about Arrival Sensor similar to Samsung Zigbee Arrival Sensor
(already discontinued) but based on Cellphone Bluetooth BLE used as a
Presence Device plus ESP as a Presence Sensor.
When cellphone(s) connects to the ESP8266 (or ESP32) via Bluetooth the HE
gets a Switch On event or whatever what could be used as a Trigger for RM.

Interesting idea... :thinking: I have never messed around with BLE. I am pretty sure one would need to use an ESP32 as the ESP8266 does not support BLE, IIRC.

Do you have any example Arduino sketches for the ESP32 that demonstrate this functionality? (i.e. the ability to detect a specific device has been connected via BT.)

Yes, you are 100% correct. It must be ESP32

This is not an Arduino sketch but rather ready to go ESpresence project:

I was/am thinking to try it "as is" but it does not directly integrates with HE.
I don't want to mess up with all other required components in order to get
it working with HE. Unfortunately I am not a SW guru but I am thinking it
could be not a big deal for experts like you to put together all components.
Hubduino already exist. It is very well structured and easy to use.
I guess (amd I hope), ESpresence has a BLE Presence Sensor ready to go.
So maybe it is not a big deal to create a Hubduino BLE Presence Sensor.
I am sure, the HE community will like it a lot.
I will be a first one to try it immediately and help to debug.