Laat ik even vooraf erbij vermelden dat dit mijn allereerste RPI project is waar ik de GPIO gebruik in combinatie met python. Zowel de taal als GPIO zijn voor mij nieuw.
Mijn projectje
Ik wil onze WTW die je aanstuurt met een drie-standen-schakelaar gaan aansturen via domotica in combinatie met de fysieke schakelaar. De regels zijn relatief simpel: als de fysieke schakelaar gebruikt wordt dient die instelling altijd de huidige stand te vervangen. Als via een web-request een stand wordt ingesteld dan wordt dat de stand totdat ofwel de fysieke knop gebruikt wordt of er een nieuwe web-request wordt gedaan.
De reden voor het gebruiken van een webrequest is simpel: ik heb alles via Homey draaien en een GET request is de makkelijkste route in dit geval.
Theorie aanpak
Mij leek het gebruik van een raspberry pi in combinatie met een relais bordje de beste route. Het relais bordje gebruik ik om de 12V signalen van de WTW te schakelen. De fysieke standen schakelaar koppel ik aan GPIO pinnen. Met python en Flask maak ik een app waar ik de events afvang van de GPIO input pins en de GET requests en bob is je oom.
De werkelijkheid
In mijn tests werkte het geheel perfect, tot ik de standen schakelaar in gebruik nam. Want wat ik nu zie gebeuren is dat ongeacht de stand het bijbehorende event de hele tijd opnieuw blijft triggeren.
/f/image/MdCUXLYM1pirbX0eTE4XluXC.png?f=fotoalbum_large)
De knop staat toch echt stil, dus waarom blijft dat event de hele tijd opnieuw komen? Ik heb al geprobeerd om de aansturing te doen op basis van pull-down en ook pull-up. Uiteindelijk maakt het geen verschil.
Natuurlijk heb ik ook gemeten hoeveel volt er op de pin staat bij een actieve stand (0,1V bij pull-down situatie) en volgens mij zit het altijd ver genoeg af van de grenzen voor de rizing danwel falling edge.
Wat natuurlijk ook anders is ten opzichte van mijn testopstelling is dat er natuurlijk langere draden in gebruik zijn. Tussen de rpi en de standenschakelaar zit een CAT5 netwerk kabel waar vier paren zijn gemaakt voor de vier mogelijke signalen. Drie paren voor de standen en een extra paar voor de filter LED, deze is nu niet in gebruik.
Ik doe vast vanalles fout. Aangezien het geheel keurig werkt zodra ik de schakelaar er tussenuit laat en met kabeltjes direct op de GPIO header werk lijkt het me duidelijk dat het te maken heeft met de schakelaar en/of de draadlengte. De schakelaar en de draad ga ik niet zomaar even vervangen dus ik hoop dat er een oplossing mogelijk is in de code of door een schakeling tussen te voegen.
De laatste versie van mijn code:
Mijn projectje
Ik wil onze WTW die je aanstuurt met een drie-standen-schakelaar gaan aansturen via domotica in combinatie met de fysieke schakelaar. De regels zijn relatief simpel: als de fysieke schakelaar gebruikt wordt dient die instelling altijd de huidige stand te vervangen. Als via een web-request een stand wordt ingesteld dan wordt dat de stand totdat ofwel de fysieke knop gebruikt wordt of er een nieuwe web-request wordt gedaan.
De reden voor het gebruiken van een webrequest is simpel: ik heb alles via Homey draaien en een GET request is de makkelijkste route in dit geval.
Theorie aanpak
Mij leek het gebruik van een raspberry pi in combinatie met een relais bordje de beste route. Het relais bordje gebruik ik om de 12V signalen van de WTW te schakelen. De fysieke standen schakelaar koppel ik aan GPIO pinnen. Met python en Flask maak ik een app waar ik de events afvang van de GPIO input pins en de GET requests en bob is je oom.
De werkelijkheid
In mijn tests werkte het geheel perfect, tot ik de standen schakelaar in gebruik nam. Want wat ik nu zie gebeuren is dat ongeacht de stand het bijbehorende event de hele tijd opnieuw blijft triggeren.
/f/image/MdCUXLYM1pirbX0eTE4XluXC.png?f=fotoalbum_large)
De knop staat toch echt stil, dus waarom blijft dat event de hele tijd opnieuw komen? Ik heb al geprobeerd om de aansturing te doen op basis van pull-down en ook pull-up. Uiteindelijk maakt het geen verschil.
Natuurlijk heb ik ook gemeten hoeveel volt er op de pin staat bij een actieve stand (0,1V bij pull-down situatie) en volgens mij zit het altijd ver genoeg af van de grenzen voor de rizing danwel falling edge.
Wat natuurlijk ook anders is ten opzichte van mijn testopstelling is dat er natuurlijk langere draden in gebruik zijn. Tussen de rpi en de standenschakelaar zit een CAT5 netwerk kabel waar vier paren zijn gemaakt voor de vier mogelijke signalen. Drie paren voor de standen en een extra paar voor de filter LED, deze is nu niet in gebruik.
Ik doe vast vanalles fout. Aangezien het geheel keurig werkt zodra ik de schakelaar er tussenuit laat en met kabeltjes direct op de GPIO header werk lijkt het me duidelijk dat het te maken heeft met de schakelaar en/of de draadlengte. De schakelaar en de draad ga ik niet zomaar even vervangen dus ik hoop dat er een oplossing mogelijk is in de code of door een schakeling tussen te voegen.
De laatste versie van mijn code:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
| import RPi.GPIO as GPIO from flask import Flask, render_template, request import logging from time import sleep app = Flask(__name__) logging.basicConfig(filename='record.log', level=logging.DEBUG, format=f'%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s') app.logger.info('App started') GPIO.setmode(GPIO.BCM) # Create a dictionary called pins to store the pin number, name, and pin state: inputpins = { 19 : {'name' : 'GPIO 19'}, 16 : {'name' : 'GPIO 16'} } # Set each pin as an output and make it low: for pin in inputpins: GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.input(pin) pins = { 20 : {'name' : 'GPIO 20', 'state' : GPIO.LOW}, 21 : {'name' : 'GPIO 21', 'state' : GPIO.LOW}, 26 : {'name' : 'GPIO 26', 'state' : GPIO.LOW} } # Set each pin as an output and make it low: for pin in pins: GPIO.setup(pin, GPIO.OUT) GPIO.output(pin, GPIO.LOW) # WTW standen # L L G # | | | # 1 0 0 # 2 1 0 # 3 0 1 def set_level(): if GPIO.input(19) == 0: print('Input 19 is low') app.logger.info('Input 19 is low') GPIO.output(20, GPIO.LOW) GPIO.output(21, GPIO.HIGH) GPIO.output(26, GPIO.LOW) if GPIO.input(16) == 0: print('Input 16 is low') app.logger.info('Input 16 is low') GPIO.output(20, GPIO.HIGH) GPIO.output(21, GPIO.LOW) GPIO.output(26, GPIO.LOW) if GPIO.input(16) == 1 and GPIO.input(19) == 1: print('Input 16 and 19 are high') app.logger.info('Input 16 and 19 are high') GPIO.output(20, GPIO.LOW) GPIO.output(21, GPIO.LOW) GPIO.output(26, GPIO.HIGH) def my_callback(channel): sleep(0.2) print('Callback function triggered by pin ' + str(channel) + ', setting level') app.logger.info('Callback function triggered, setting level') set_level() GPIO.add_event_detect(19, GPIO.BOTH, callback=my_callback, bouncetime=100) GPIO.add_event_detect(16, GPIO.BOTH, callback=my_callback, bouncetime=100) set_level() @app.route("/") def main(): # For each pin, read the pin state and store it in the pins dictionary: for pin in pins: pins[pin]['state'] = GPIO.input(pin) # Put the pin dictionary into the template data dictionary: templateData = { 'pins' : pins } # Pass the template data into the template main.html and return it to the user return render_template('main.html', **templateData) @app.route("/release") def release(): print('Release triggered') app.logger.info('Release triggered') set_level() # For each pin, read the pin state and store it in the pins dictionary: for pin in pins: pins[pin]['state'] = GPIO.input(pin) # Put the pin dictionary into the template data dictionary: templateData = { 'pins' : pins } # Pass the template data into the template main.html and return it to the user return render_template('main.html', **templateData) # The function below is executed when someone requests a URL with the pin number and action in it: @app.route("/<changePin>/<action>") def action(changePin, action): print('Pin change requested') app.logger.info('Pin change requested') # Convert the pin from the URL into an integer: changePin = int(changePin) # Get the device name for the pin being changed: deviceName = pins[changePin]['name'] # If the action part of the URL is "on," execute the code indented below: if action == "on": # Set the pin high: for pin in pins: if pin == changePin: GPIO.output(pin, GPIO.HIGH) else: GPIO.output(pin, GPIO.LOW) # Save the status message to be passed into the template: message = "Turned " + deviceName + " on." if action == "off": GPIO.output(changePin, GPIO.LOW) message = "Turned " + deviceName + " off." # For each pin, read the pin state and store it in the pins dictionary: for pin in pins: pins[pin]['state'] = GPIO.input(pin) # Along with the pin dictionary, put the message into the template data dictionary: templateData = { 'pins' : pins } return render_template('main.html', **templateData) if __name__ == "__main__": app.run(host='0.0.0.0', port=80, debug=True) |
To be determined...