Automation Hat readings different between method

Hi,

When I was trying to ‘capture’ my doorbell button press using an input, I got some strange signals. Sometimes my code said that the bell was pressed while nothing was going on, so I started to look at the readings. Instead of using the digital input, I now used the analog input.

The strange thing I noticed, is when using the methods to directly read an input like ‘automationhat.input.three.is_on()’ or ‘automationhat.analog.three.read()’ I get a different reading then when using ‘input.read()’ or ‘analog.read()’. See my simple test program below and some output snippets:

#!/usr/bin/env python

import time

import automationhat

x = 0

if automationhat.is_automation_hat():
    automationhat.light.power.write(1)

while True:
    print(x)
    print(automationhat.input.read())
    print(automationhat.analog.read())
    print(automationhat.analog.three.read())
    time.sleep(0.5)
    x = x + 1


27
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
0.05
28
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
-0.06
29
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.06, ‘two’: 0.03, ‘one’: 0.03}
4.42
30
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
0.03
31
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
0.03
32
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
-0.03
33
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
0.03
34
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.54, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
4.44
35
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
0.05
36
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: -0.02, ‘two’: 0.03, ‘one’: 0.03}
0.08
37
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.54, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
0.03
38
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
0.06
39
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
0.05

170
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: -0.05, ‘two’: 0.03, ‘one’: 0.03}
0.08
171
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
-0.02
172
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: 0.11, ‘two’: 0.03, ‘one’: 0.03}
-0.05
173
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
4.47
174
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: 0.06, ‘two’: 0.03, ‘one’: 0.03}
0.0
175
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
0.0
176
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
0.06
177
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
0.03
178
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.58, ‘three’: -0.02, ‘two’: 0.03, ‘one’: 0.03}
0.06
179
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
0.0
180
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
0.02

205
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.03, ‘two’: 0.03, ‘one’: 0.03}
0.06
206
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: -0.02, ‘two’: 0.03, ‘one’: 0.03}
0.06
207
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
4.42
208
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.09, ‘two’: 0.03, ‘one’: 0.03}
-0.05
209
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.57, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
-0.05
210
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.54, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
0.0

223
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: -0.03, ‘two’: 0.03, ‘one’: 0.03}
0.08
224
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.09, ‘two’: 0.03, ‘one’: 0.03}
0.03
225
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.03}
4.45
226
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.56, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
-0.05
227
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.05, ‘two’: 0.03, ‘one’: 0.03}
0.0
228
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: 0.0, ‘two’: 0.03, ‘one’: 0.05}
-0.03
229
{‘three’: 0, ‘two’: 0, ‘one’: 0}
{‘four’: 0.55, ‘three’: -0.03, ‘two’: 0.03, ‘one’: 0.03}
0.09

What you see happening is that when reading all analog inputs at once, they array shows a value that I would expect as nothing was connected just two wires (one on Hat 5V and one on ADC input 3) which where NOT connected. But when reading analog three directly, I sometimes get a high value (4.xx). Similar behavior was found when reading the digital input. Sometimes it unexpectedly reported 1 (high) or true when using ‘is_on()’.

Does anyone have a clue why/how this happens? For now I stick with reading all inputs at once and use the result array, but as the library provides nicer functions for this I would expect it to work the same.

I’d guess that it’s because the switch is “floating” when it’s not pressed. This essentially means when you try to read it, you’ll get basically random readings from the ADC, because it’s grounded when the switch isn’t pressed. The input looks like it’s reading correctly, and it’s the correct thing to use for your application. I believe they have pull resistors to stop the input from floating.

Thx for the quick response.I guessed already it had to do with something like that, but I am not really an electronics guy (yet :) ) I find it difficult to think of a good solution.

At the moment I ‘countered’ the floating values in code like this:

#!/usr/bin/env python

import time

import automationhat

x = 0
bel = False

if automationhat.is_automation_hat():
    automationhat.light.power.write(1)
    automationhat.analog.three.auto_light(False)

while True:
    if automationhat.analog.three.read() > 4.8:
        time.sleep(0.15)
        if automationhat.analog.three.read() > 4.8:
            automationhat.analog.three.light.on()
            time.sleep(0.15)
            if automationhat.analog.three.read() > 4.8:
                print(str(x) + ' Bel!')
                bel = True
            else:
                automationhat.analog.three.light.off()
    else:
        if bel:
            bel = False
            automationhat.analog.three.light.off()
            print(str(x) + ' Bel released!')
    time.sleep(0.2)
    #print(x)
    x = x + 1

Which seems to work nicely (and with visual feedback using the led :) ). But I would rather have used a digital input as in this use-case it basically is just an On/Off situation and it would keep the analog input free for real readings.

As you can see in the simple drawing, there is no ‘ground’, not even a wire to the ‘gnd’ of the Automation Hat. Should I have a wire between the blue line and the ‘gnd’ of the Automation Hat? Does it make sense to make an actual ‘ground’ connection between the Automation Hat and a real earth ground? Would that mean a wire from the ‘gnd’ to the real ground?

(I might have to do some reading/training into basic electronics maybe :) )

For that circuit you need a small resistor connected between the ADC3 input and the negative/zero-volts point on the HAT. Ground in this case is the zero-volt rail of the HAT.

A resistor anywhere in the range of 1k ohms to 22k ohms would do nicely - the value is not specific - it is only there to “pull down” the ADC input to - yes “Ground” - when the doorbell is not pressed.
Testing an unpressed doorbell will then show zero volts.
Pressing the doorbell will “fight” the resistor and raise the ADC input to the supplied 5 volts.

Note when pressing the doorbell the 5 volt supply will be connected across this resistor - if the value is too low then the resistor may warm a little during pushes. A 1k resistor will only draw 5 mA and will never warm up.

Thank you @neilman. I spent some time reading up on the ‘floating ground’ issue as @sandyjmacdonald referenced and indeed I have to put in a resistor. Didn’t have one lying around (yet, now underway) so haven’t tried it, but quite confident it will work. Actually I will move back to using the digital input instead of the ADC.

But I also found that the Pi is equipped with build-in resistors that just need to be activated, so in my scenario I should be able to ‘just’ activate the internal pull-down resistor for the specific pin. If I would use digital input 3, that is Pin 21 using the GPIO library (and looking at the the library init.py code), and provide ‘pull_up_down=GPIO.PUD_DOWN’ during initialization. Not sure yet how to do that :) but will see if I can get that in somehow.

I will report my progress…

Excellent - learning all the time :-)

Ok, got it working :) Learned a lot. Also found this article very useful.

Indeed the Pi’s internal resistors can be used to ‘fix’ the problem (which wasn’t a problem but just me being a n00b here). To be able to do it nicely within my code, I made some small changes to the Automationhat library which add the ability to activate the internal resistor for the input port. Now the code is really simple :)

#!/usr/bin/env python

import time

import automationhat

automationhat.input.three.resistor(automationhat.PULL_DOWN)

if automationhat.is_automation_hat():
    automationhat.light.power.write(1)

while True:
    if(automationhat.input.three.is_on()):
        print("Bell pressed!")
    time.sleep(0.2)

I created a pull request to add this ability. Hopefully it gets through :) Not having to use an external resistor (and having to solder, etc.) but wire simple things like my doorbell directly makes using Automationhat even simpler. At least I am happy with it ;)

Consider this ‘problem’ closed/solved.

1 Like

Really glad you got it working and that you learnt something along the way! Phil will take a look at your PR for the pull resistors but, at first glance, it looks like a really useful and neat addition to the library. :-)