Digital Value off/on switch doesn't update

Hi,

I have written a piece of python code which is not optimized at all.The code controls the status of 20 switches (off=0/on=2). I’m using the mqtt api to connect to Cayenne. Here is the code:

import cayenne.client #Cayenne MQTT Client 
from time import sleep
from gpiozero import Button
button1=Button(14) # Declaring button pin 14
button2=Button(15) # Declaring button pin 15
button3=Button(18) # Declaring button pin 18
button4=Button(23) # Declaring button pin 23
button5=Button(24) # Declaring button pin 24
button6=Button(25) # Declaring button pin 25
button7=Button(8) # Declaring button pin 8
button8=Button(7) # Declaring button pin 7
button9=Button(12) # Declaring button pin 12
button10=Button(16) # Declaring button pin 16
button11=Button(20) # Declaring button pin 20
button12=Button(21) # Declaring button pin 21
button13=Button(2) # Declaring button pin 2
button14=Button(3) # Declaring button pin 3
button15=Button(4) # Declaring button pin 4
button16=Button(17) # Declaring button pin 17
button17=Button(27) # Declaring button pin 27
button18=Button(22) # Declaring button pin 22
button19=Button(10) # Declaring button pin 10
button20=Button(9) # Declaring button pin 9


# Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
MQTT_USERNAME  = "x"
MQTT_PASSWORD  = "x"
MQTT_CLIENT_ID = "x"

client = cayenne.client.CayenneMQTTClient()

client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)

def send_on1():
  client.virtualWrite(8, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 8
  print("Button pressed\n")

def send_off1():
  client.virtualWrite(8, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 8
  print("Button released\n")

def send_on2():
  client.virtualWrite(10, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 10
  print("Button pressed\n")

def send_off2():
  client.virtualWrite(10, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 10
  print("Button released\n")

def send_on3():
  client.virtualWrite(12, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 12
  print("Button pressed\n")

def send_off3():
  client.virtualWrite(12, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 12
  print("Button released\n")

def send_on4():
  client.virtualWrite(16, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 16
  print("Button pressed\n")

def send_off4():
  client.virtualWrite(16, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 16
  print("Button released\n")

def send_on5():
  client.virtualWrite(18, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 18
  print("Button pressed\n")

def send_off5():
  client.virtualWrite(18, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 18
  print("Button released\n")

def send_on6():
  client.virtualWrite(22, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 22
  print("Button pressed\n")

def send_off6():
  client.virtualWrite(22, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 22
  print("Button released\n")

def send_on7():
  client.virtualWrite(24, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 24
  print("Button pressed\n")

def send_off7():
  client.virtualWrite(24, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 24
  print("Button released\n")

def send_on8():
  client.virtualWrite(26, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 26
  print("Button pressed\n")

def send_off8():
  client.virtualWrite(26, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 26
  print("Button released\n")

def send_on9():
  client.virtualWrite(32, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 32
  print("Button pressed\n")

def send_off9():
  client.virtualWrite(32, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 32
  print("Button released\n")

def send_on10():
  client.virtualWrite(36, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 36
  print("Button pressed\n")

def send_off10():
  client.virtualWrite(36, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 36
  print("Button released\n")

def send_on11():
  client.virtualWrite(38, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 38
  print("Button pressed\n")

def send_off11():
  client.virtualWrite(38, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 38
  print("Button released\n")

def send_on12():
  client.virtualWrite(40, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 40
  print("Button pressed\n")

def send_off12():
  client.virtualWrite(40, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 40
  print("Button released\n")

def send_on13():
  client.virtualWrite(3, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 3
  print("Button pressed\n")

def send_off13():
  client.virtualWrite(3, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 3
  print("Button released\n")

def send_on14():
  client.virtualWrite(5, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 5
  print("Button pressed\n")

def send_off14():
  client.virtualWrite(5, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 5
  print("Button released\n")

def send_on15():
  client.virtualWrite(7, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 7
  print("Button pressed\n")

def send_off15():
  client.virtualWrite(7, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 7
  print("Button released\n")

def send_on16():
  client.virtualWrite(11, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 11
  print("Button pressed\n")

def send_off16():
  client.virtualWrite(11, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 11
  print("Button released\n")

def send_on17():
  client.virtualWrite(13, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 13
  print("Button pressed\n")

def send_off17():
  client.virtualWrite(13, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 13
  print("Button released\n")

def send_on18():
  client.virtualWrite(15, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 15
  print("Button pressed\n")

def send_off18():
  client.virtualWrite(15, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 15
  print("Button released\n")

def send_on19():
  client.virtualWrite(19, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 19
  print("Button pressed\n")

def send_off19():
  client.virtualWrite(19, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 19
  print("Button released\n")

def send_on20():
  client.virtualWrite(21, 1, "digital_sensor", "d") #Publish "1" to Cayenne MQTT Broker Channel 21
  print("Button pressed\n")

def send_off20():
  client.virtualWrite(21, 0, "digital_sensor", "d") #Publish "0" to Cayenne MQTT Broker Channel 21
  print("Button released\n")

button1.when_pressed=send_on1 #When button pressed run send_on function
button1.when_released=send_off1 #When button released run send_off function
button2.when_pressed=send_on2 #When button pressed run send_on function
button2.when_released=send_off2 #When button released run send_off function
button3.when_pressed=send_on3 #When button pressed run send_on function
button3.when_released=send_off3 #When button released run send_off function
button4.when_pressed=send_on4 #When button pressed run send_on function
button4.when_released=send_off4 #When button released run send_off function
button5.when_pressed=send_on5 #When button pressed run send_on function
button5.when_released=send_off5 #When button released run send_off function
button6.when_pressed=send_on6 #When button pressed run send_on function
button6.when_released=send_off6 #When button released run send_off function
button7.when_pressed=send_on7 #When button pressed run send_on function
button7.when_released=send_off7 #When button released run send_off function
button8.when_pressed=send_on8 #When button pressed run send_on function
button8.when_released=send_off8 #When button released run send_off function
button9.when_pressed=send_on9 #When button pressed run send_on function
button9.when_released=send_off9 #When button released run send_off function
button10.when_pressed=send_on10 #When button pressed run send_on function
button10.when_released=send_off10 #When button released run send_off function
button11.when_pressed=send_on11 #When button pressed run send_on function
button11.when_released=send_off11 #When button released run send_off function
button12.when_pressed=send_on12 #When button pressed run send_on function
button12.when_released=send_off12 #When button released run send_off function
button13.when_pressed=send_on13 #When button pressed run send_on function
button13.when_released=send_off13 #When button released run send_off function
button14.when_pressed=send_on14 #When button pressed run send_on function
button14.when_released=send_off14 #When button released run send_off function
button15.when_pressed=send_on15 #When button pressed run send_on function
button15.when_released=send_off15 #When button released run send_off function
button16.when_pressed=send_on16 #When button pressed run send_on function
button16.when_released=send_off16 #When button released run send_off function
button17.when_pressed=send_on17 #When button pressed run send_on function
button17.when_released=send_off17 #When button released run send_off function
button18.when_pressed=send_on18 #When button pressed run send_on function
button18.when_released=send_off18 #When button released run send_off function
button19.when_pressed=send_on19 #When button pressed run send_on function
button19.when_released=send_off19 #When button released run send_off function
button20.when_pressed=send_on20 #When button pressed run send_on function
button20.when_released=send_off20 #When button released run send_off function
  
while True:
  client.loop()

Everything works fine, but sometimes the value of the status gets stuck in Cayenne dashboard. For example if my switch is off, it still shows its on. I’m not sure if my problem is the python code which I’ve written, or there is a bug in system. Thanks for your help in advance.

I have not tried the gpiozero library, but I can say for sure that most libraries have issues with buttons because of bounce. What kind of button are you using? If that’s not the issue we’ll keep digging. For now I’d add in a print statement every time you expect to see something happen when you press a button and test it thoroughly on the local level to see if it reacts the way you think it should. If it does then there’s an issue after the packets leave your Pi.

Hi @adam,
Thanks for your help. I’m actually not using any buttons, I’m just touching the bare wires together. When the system loads without any buttons touching, some buttons on the dashboard show a green button with a value of 0 and a few show green with a value of 1. Keep in mind that no wires are touching. Then after I connect a couple of wires, they start working as usually, but once in a while the button shows the connected value but the wires aren’t connected.
I went ahead and tried the print statement locally and the results were perfect. I think the packets aren’t being delivered to Cayenne.

@rushtkb
i am not a expert in python but give this a try and let me know.

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

if (GPIO.input(18) == GPIO.LOW):
print (“Button pressed”)
client.virtualWrite(8, 1, “digital_sensor”, “d”) #Publish “1” to Cayenne MQTT Broker Channel 8
sleep(5)

Looks like the library you are using sets the internal pull-ups, so I’m not sure what would be causing that. I’ll give it a try later and see what happens.

Ok, I’m going to give this a try and let you know. Thanks!

Yeah if you can try it and see if you get the same results, I would truly appreciate it.

I have tried this early version of the library and I had the same problems in the back, so I let this library out of my use. Now when I read this post, I browse the documentation and found that if the pin is set with the class button of that library, there is a couple of configurations for pullup and bounce parameters.

class gpiozero.Button(pin, pull_up=True, bounce_time=None)

So can you try to change the default configuration?

• pull_up (bool) – If True (the default), the GPIO pin will be pulled high by default.
In this case, connect the other side of the button to ground. If False, the GPIO pin
will be pulled low by default. In this case, connect the other side of the button to 3V3.

Thanks for the help @ognqn.chikov, So let me get this clear before I do anything. You are saying that I should hook up all my 20 buttons like so:
1 leg to the ground, and the other to 3.3 v?
And then call the pull_up function for every button and set a random gpio for them as the first parameter?

I think the same as you, and this is how I understand this when I read if from the documentation. But you can try with one button, not with all of them? Just with one for testing?

In section 11.1 Button is described:

http://gpiozero.readthedocs.io/en/stable/api_input.html

@rushtkb the solution i gave earlier did u had a go at it?
it works by pulling up the GPIO pin and when button is pressed it is connected to ground.
connect 1 leg of button to GPIO pin and other to ground.

So it is similar to what is written in the documentation ?

its similar but different library.

Yeah I tried this:
import cayenne.client cayenne MQTT Client
from time import sleep

Cayenne authentication info. This should be obtained from the Cayenne Dashboa$

MQTT_USERNAME = “x”
MQTT_PASSWORD = “x”
MQTT_CLIENT_ID = “x”

client = cayenne.client.CayenneMQTTClient()

client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)

import RPi.GPIO as GPIO
from time import sleep # this lets us have a time delay (see line 12)
GPIO.setmode(GPIO.BCM) # set up BCM GPIO numbering
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP) # set GPIO 25 as input

if (GPIO.input(25)==GPIO.LOW): # if port 25 == 1
print “Port 25 is 1/GPIO.HIGH/True - button pressed”
client.virtualWrite(22, 1, “digital_sensor”, “d”)
else:
print “Port 25 is 0/GPIO.LOW/False - button not pressed”
sleep(2) # wait 0.1 seconds

The terminal print was working, but I couldn’t get the vertualWrite to change the status of my widget. The client was getting connected, but no luck on updating the status. Let me know if you see any errors.

you dint include client.loop() and give this a try if it changes the status on dashboard.
import cayenne.client #Cayenne MQTT Client
from time import sleep

Cayenne authentication info. This should be obtained from the Cayenne Dashboa$
MQTT_USERNAME = “x”
MQTT_PASSWORD = “x”
MQTT_CLIENT_ID = “x”

client = cayenne.client.CayenneMQTTClient()

client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)

import RPi.GPIO as GPIO
from time import sleep # this lets us have a time delay (see line 12)
GPIO.setmode(GPIO.BCM) # set up BCM GPIO numbering
GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_UP) # set GPIO 25 as input
i=0
timestamp = 0

while True:
client.loop()
if (time.time() > timestamp + 10):
client.virtualWrite(22, i, “digital_sensor”, “d”)
timestamp = time.time()

if (GPIO.input(25)==GPIO.LOW): # if port 25 == 0
print “Port 25 is 0/GPIO.LOW - button pressed”
i = 1

I tried it and now its giving me an error on the time.time() function:
if(time.time()>timestamp +10):
AttributeError: ‘builtin_function_or_method’ object has no attribute ‘time’

sorry add import time

RPI.gpio has got to be the worst library I have used for buttons. To be fair there aren’t many good ones. I have found pigpio to be the best for buttons.

ok now I keep getting disconnected from mqtt client every second or so.

I made a new client and disconnect stopped. The pin was automatically added, but the status is not being updated. its green at all times!