Multiple GPIO buttons and Thermostat

761 views
Skip to first unread message

Bradley Nelson

unread,
Jan 18, 2015, 5:36:16 PM1/18/15
to web...@googlegroups.com
Hi all,  I've been spinning my tires on this little project for quite a while. I've googled and youtubed all over and have come up unsuccessful.  I'm just going to throw out what I'm trying to do and am grateful for any direction or feedback I can get.

Overview ---  My goal is a simple interface that allows "click" control of 3 GPIO pins. Just simple Low/High clicking action.   Then I also have two temp sensors I'm using as thermostat.  I want to be able to select Auto or Manual.  If manual, just a simple "Low/High" button for each heater. If auto, then I want to input the threshold temp for each sensor.  Also, display current temp for each sensor. 

  Does that make sense? Simple?   
 
  I worked through some of the tutorials on WebIOPi, but can't even make a second button to control a second pin.  I copy all the code, initialize the pin in the config, etc. But the button doesn't work.  How do I simply make a page with 3 buttons for 3 different IO pins?  That would be a good start.  

  Then some tips on the thermostat would be so great! I'm sure it's been done many times. 

Thanks for any help!!

Toshi Bass

unread,
Jan 19, 2015, 6:31:30 AM1/19/15
to web...@googlegroups.com
Hi Bradley

First make 3 buttons to control 3 gpio's say 23, 24, & 25 your index.html needs to look like this:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content = "height = device-height, width = 420, user-scalable = no" /> 
<title>WebIOPi | Demo</title>
<script type="text/javascript" src="/webiopi.js"></script>
<script type="text/javascript">
webiopi().ready(function() {

webiopi().setFunction(23, "out"); //
webiopi().setFunction(24, "out"); // See Note*
webiopi().setFunction(25, "out"); //

var content, button;
content = $("#content");
// create a "button" labeled Button 1 for GPIO 23
button = webiopi().createGPIOButton(23, "Button 1");
content.append(button); // append button to content div

// create a "button" labeled Button 2 for GPIO 24
button = webiopi().createGPIOButton(24, "Button 2");
content.append(button); // append button to content div

// create a "button" labeled Button 3 for GPIO 25
button = webiopi().createGPIOButton(25, "Button 3");
content.append(button); // append button to content div

webiopi().refreshGPIO(true);
});
</script>
<style type="text/css">
button {
display: block;
margin: 5px 5px 5px 5px;
width: 160px;
height: 45px;
font-size: 24pt;
font-weight: bold;
color: black;
}
input[type="range"] {
display: block;
width: 160px;
height: 45px;
}
.LOW {
background-color: Pink;
}
.HIGH {
background-color: LimeGreen;
}
</style>
</head>
<body>
<div id="content" align="center"></div>
</body>
</html>

_________________________________

This will give you 3 buttons on your webpage which when pressed will toggle gpio's 23, 24 & 25 

Note* At the moment there is no python script necessary, however when you start to use a python script its best to set up the functions of gpio's 23, 24 & 25 to output in the python script and remove the 3 lines setting up the functions from this index.html file.(Because when you start webiopi - script.py will run before your index.html file so the gpio's may get used there before your web page loads if you get my meaning)
_________________________________

Hope that gives you a start, for temperature you need to import the sensors into your python script (you didn't say what type) and use macros for your auto/manual function and to display the temperatures on your web page, there are loads of examples here, just search "display temp"

Toshi

Bradley Nelson

unread,
Jan 20, 2015, 1:14:34 PM1/20/15
to web...@googlegroups.com
Toshi, thanks for you help! This gives me a great start.

One small issue though - this has happened previously as well.  It appears I have a floating pin or something. I changed the code you gave me to control pins 2,3,4.  2 and 3 always work great, but now and then 4 becomes unresponsive. Or the button will randomly light up or turn off, but the actual pin doesn't go high or low. 

I even noticed the issue sometimes on the default GPIO control that comes with WebIOPi. A couple of the pins randomly blink on and off. 

Any ideas?

Toshi Bass

unread,
Jan 20, 2015, 3:23:47 PM1/20/15
to web...@googlegroups.com
Sorry I have no idea which pins you are calling "control pins 2,3,4"  are you talking about GPIO or perhaps an attached extender like MCP23017 I am a bit confused ?

Toshi

Bradley Nelson

unread,
Jan 20, 2015, 7:43:05 PM1/20/15
to web...@googlegroups.com
Yeah, GPIO pins 2,3,4 instead of the ones you put in your code.  I think I figured it out though. I put the temp sensors on GPIO 4 and then I'm using GPIO 2,3, and 17 for the buttons.

Toshi Bass

unread,
Jan 21, 2015, 8:47:54 AM1/21/15
to web...@googlegroups.com
I must apologies, I am so used to not seeing/using GPIO 2,3 & 4 the reason is as follows:

GPIO 2 and GPIO 3 are used for the i2c bus if in future you think to plan adding i2c sensors or gpio expanders you should not use these 2 gpio's
  
GPIO 4 as you have mentioned is used by the 1 wire bus if you plan to add any 1 wire sensors or gpio expanders you should not use this gpio

GPIO 7, 8 ,9, 10 & 11 are used for the SPI bus, smaller numbers of sensors / gpio expanders for this bus, but again don't use these gpio's  if you plan to use say a piface expansion board for example

A good rule of thumb is use gpio's in this order - general gpio's are  17 22 23 24 25 27 then use 18 then 7 8 9 10 11 and finally if your sure you don't need 1 wire - 4 then - 2 & 3.

When you add a one wire and or i2c sensor you will see the the gpio's logo change on the GPIO-header web page like attached (that's why I was confused) :


Note* gpio 4 is the only gpio you can use for 1 wire, however it is possible to add a i2c - 1 wire bus master module (or build your own) here is an example https://www.abelectronics.co.uk/products/3/Raspberry-Pi/27/1-Wire-Pi obviously this free's up gpio 4 to use.

Toshi
Captured.JPG

Bradley Nelson

unread,
Jan 24, 2015, 7:54:33 PM1/24/15
to web...@googlegroups.com
Thanks Toshi, that's good to know on the GPIOs.  I did get the DS18b20s going on GPIO 4 and works great in Devices Monitor. 

I've been reading tons of threads on the DS18B20. Seems like everyone is doing something just a little different.  Forgive my newness - most of my experience is in Arduino.  Maybe I'm missing the big picture of how things work, but is there a simple way to pull in the Temp from the sensor and turn GPIO on and off based on the temp?  Seems like they're are many ways to do it - hard to pick one way not knowing if it will work for all features.

Bradley Nelson

unread,
Jan 24, 2015, 7:56:24 PM1/24/15
to web...@googlegroups.com
Sorry, I feel like you answer the same questions over and over... 

Bradley Nelson

unread,
Jan 24, 2015, 8:26:15 PM1/24/15
to web...@googlegroups.com
yeah, I try tinkering with other's code, but whenever I tell WebIOPi to load an external script, it breaks...  I don't know enough to diagnose. So many layers going on.

Toshi Bass

unread,
Jan 25, 2015, 4:14:08 AM1/25/15
to web...@googlegroups.com
Hi Bradley

Yes there are a few ways try this one ( I ran this code and it works so if you have a problem then my guess would be something wrong with the path you specified in the config that loads the script.

The following script assumes you called your 2 DS18B20 sensors Temp0 and Temp1 in the config file (if you called them something else then its probably best to rename the sensors in the config file then it will be easier to debug if the code does not work)

I think the python code speaks for its self, but if there is anything you don't get, ask !  (incidentally I post this python code here because you could have problems with properties if I attach the file, so just copy and paste it into your script.py (if that's a problem for you and your using windows just down load the free program WinSCP)  however that wont happen with the attached index.html file.)

#!/usr/bin/python
# Toshi Bass
# Python 3.2 Raspbian (Wheezy)

# Imports
import webiopi
import os
import sys
import subprocess
import time

# Enable debug output
webiopi.setDebug()
from webiopi.utils.logger import info

# Retrieve GPIO lib
GPIO = webiopi.GPIO

from webiopi import deviceInstance
Temp0 = webiopi.deviceInstance("Temp0")
Temp1 = webiopi.deviceInstance("Temp1") 

LED1  = 23
heat0 = 24
heat1 = 25

##################################################################
# Called by WebIOPi at script loading
##################################################################

def setup():
    webiopi.debug("Script with macros - Setup")
    GPIO.setFunction(23, GPIO.OUT)
    GPIO.setFunction(24, GPIO.OUT)
    GPIO.setFunction(25, GPIO.OUT)

##################################################################
# Setup Globals
##################################################################


##################################################################
# Setup Vars
##################################################################

temp0 = "%.2f" % (Temp0.getCelsius())
temp1 = "%.2f" % (Temp1.getCelsius())

heat_setpoint = 60

##################################################################
# Define Functions
##################################################################

def switch():

    global heat_setpoint,temp0,temp1,heat0,heat1

    if int(float(temp0)) < heat_setpoint:
        GPIO.digitalWrite(heat0, 1)
    else:
        GPIO.digitalWrite(heat0, 0)  

    if int(float(temp1)) < heat_setpoint:
        GPIO.digitalWrite(heat1, 1)
    else:
        GPIO.digitalWrite(heat1, 0)  


##################################################################
# Looped by WebIOPi
##################################################################

def loop():

# Toggle LED each 4 seconds
    value = not GPIO.digitalRead(23)
    GPIO.digitalWrite(23, value)
    print()
    print("_______________watch_dog",int(value))
    print()

    switch()


    webiopi.sleep(4)

##################################################################
# Called by WebIOPi at server shutdown
##################################################################

def destroy():
    webiopi.debug("Script with macros - Destroy")
    GPIO.setFunction(23, GPIO.IN)
    GPIO.setFunction(24, GPIO.IN)
    GPIO.setFunction(25, GPIO.IN)

##################################################################
# Macros
##################################################################

@webiopi.macro
def get_temp(arg0,arg1):
    global temp0,temp1

    print(temp0,temp1)
    return("%s %s" % (temp0,temp1))

################################################################## 


After you past in the the python code into script.py and move the attached index.html into the same folder, start webiopi in debug mode   sudo webiopi -d -c /etc/webiopi/config   to be able to see any errors etc stop with   ctrl c

Hope it helps

Toshi

index.html

Bradley Nelson

unread,
Jan 25, 2015, 3:31:10 PM1/25/15
to web...@googlegroups.com
Wow! Toshi, I really appreciate your time. 

Everything loads properly. I switched the getCelsius to getFarenheit and it's working.  The only thing that doesn't work is refreshing the Temp data. The temperatures only update when WebIOPi is restarted.  What would cause that?   Also, none of the default WebIOPi apps will load when I go to their path    app/devices-monitor

Toshi Bass

unread,
Jan 26, 2015, 4:53:03 AM1/26/15
to web...@googlegroups.com
Yes your right if you think about what the code is doing, it gets the initial temperatures in setup vars section but never updates them, now you see why its important to spend time testing your code, clearly you need to add a couple of lines in your code to refresh the global temperatures temp0 & temp1.. because there global values you could add the lines in any of the following :
 
In the loop                            < refresh every-time the loop loops 
In the def switch()                 < every time switch() is called
In the macro                         < ever time the get_temp macro is called 

So thinking about it if you go for in the macro you will only refresh when you have your web page open, not good because you want to switch heat all the time based on the temperature so I would go for in def switch() like:

def switch():
    global heat_setpoint,temp0,temp1,heat0,heat1
    temp0 = "%.2f" % (Temp0.getCelsius())
    temp1 = "%.2f" % (Temp1.getCelsius()) 

    if int(float(temp0)) < heat_setpoint:
        GPIO.digitalWrite(heat0, 1)
    else:
        GPIO.digitalWrite(heat0, 0)  

    if int(float(temp1)) < heat_setpoint:
        GPIO.digitalWrite(heat1, 1)
    else:
        GPIO.digitalWrite(heat1, 0)  

or in the loop

to solve the path issue next line after imports try adding :

sys.path.append("/home/pi/xxxxxxxi/xxxxxxx") # were x is the path to script.py

Toshi

Toshi Bass

unread,
Jan 26, 2015, 4:38:09 PM1/26/15
to web...@googlegroups.com
Hi Bradley

Had a play with your temperature set points this afternoon result attached

Toshi
index.html
script.py

Ed Lentz

unread,
Apr 3, 2016, 8:57:55 PM4/3/16
to WebIOPi
Hi I just installed this and it is working fine.  How can I change this all over to Fahrenheit?

Thanks

Toshi Bass

unread,
Apr 3, 2016, 11:18:43 PM4/3/16
to WebIOPi

Just replace every instance of Celsius with Fahrenheit for example ....

(Temp0.getCelsius()) becomes (Temp0.getFahrenheit())

Ed Lentz

unread,
Apr 3, 2016, 11:24:56 PM4/3/16
to WebIOPi

Thanks Toshi but how does that work out with the set temp?   Or am I missing something.   Does the temp set update only change the base temp?   I noticed that there was a setting for the temp to start out at.   The setting goes from -10 to +30 or there abouts.   If the base temp was 20 then the "swing" of the temp settings would be 10 to 50.  Is that right

Thanks

On Apr 3, 2016 11:18 PM, "Toshi Bass" <toshib...@gmail.com> wrote:

Just replace every instance of Celsius with Fahrenheit for example ....

(Temp0.getCelsius())  becomes  (Temp0.getFahrenheit())

--
You received this message because you are subscribed to the Google Groups "WebIOPi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webiopi+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Toshi Bass

unread,
Apr 4, 2016, 8:27:49 AM4/4/16
to WebIOPi
In script.py

Just replace every instance of Celsius with Fahrenheit for example ....

(Temp0.getCelsius())  becomes  (Temp0.getFahrenheit())

also change default setpoints from 20c to 68f or whatever....

temp_set_point0 = 68
temp_set_point1 = 68

In index.html  change range from -10 & 30 to 14 & 86 or whatever.... 

// setup Temperature dropdown variable range
$(function(){
     var $select = $(".30");
     for (i=14;i<=86;i+=.5){
if (i[0]==.5) {i[0] = i[0]+"0"};
         $select.append($('<option>').val(i).html(i))
     }
});

If you want to loose the .5 increment use...

// setup Temperature dropdown variable range
$(function(){
     var $select = $(".30");
        for (i=14;i<=86;i++){
         $select.append($('<option>').val(i).html(i))
     }
});

To answer your next question before you ask, add the following in script,py to retain you new setpoint values even when you reboot your pi....

Add to the list of imports....

import pickle

replace....

temp_set_point0 = 68
temp_set_point1 = 68

with..

##################################################################
# Retrieve saved Vars
##################################################################

global temp_set_point0,  temp_set_point1
try:
    inFile = open('/home/pi/webiopi/myproject/saveVars.txt', 'rb') # substitute myproject for your working directory
    newList = pickle.load(inFile)
    inFile.close()
    temp_set_point0,temp_set_point1 = newList
    print()
    print("Retreve SaveVars ",newList)
    print()
except Exception as e:
    print (e)
    print("Unable to access saveVars file")
    print("Loading initial temp_set_points instead")
    pass
    temp_set_point0 = 68
    temp_set_point1 = 68
    print(" temp_set_points = ",temp_set_point0, temp_set_point1)


Add following in def destroy():

##################################################################
# Called by WebIOPi at server shutdown
##################################################################

def destroy():
    webiopi.debug("Script with macros - Destroy")

    # SaveVars
    global temp_set_point0temp_set_point1
    useList = [temp_set_point0, temp_set_point1]
    print()
    print("SaveVars ",useList)
    print()
    outFile = open('/home/pi/webiopi/myproject/saveVars.txt', 'wb') # substitute myproject for your working directory
    pickle.dump(useList, outFile)
    outFile.close()

    # Reset GPIO functions
    GPIO.setFunction(switch1, GPIO.IN)
    GPIO.setFunction(switch2, GPIO.IN)
    GPIO.setFunction(LED1, GPIO.IN)
    GPIO.setFunction(Timed_switch, GPIO.IN)

Clearly on the first use there will be no existing saveVars.txt file so the script will be Loading initial ,temp_set_point0, temp_set_point1 instead when the script shutsdown the saveVars.txt file will be made and subsequent restarts will use the last saved values.

Ed Lentz

unread,
Apr 4, 2016, 8:34:26 AM4/4/16
to WebIOPi
Thanks Toshi!  I really appreciate all the help.  I will make the changes this evening.

--
You received this message because you are subscribed to the Google Groups "WebIOPi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webiopi+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--

Ed

Ed Lentz

unread,
Apr 4, 2016, 9:48:02 PM4/4/16
to WebIOPi
The changes work as advertised!  Thanks Toshi.  Is there a way to add in some hysteresis?  Or using DS182 sensors they will add in some of that?

Thanks very much
--

Ed

Михаил Иванов

unread,
May 6, 2016, 9:18:01 AM5/6/16
to WebIOPi
Port GPIO is in control and thermostat mode. How to lock the mouse control button in the thermostat mode?

Михаил Иванов

unread,
May 13, 2016, 1:18:23 AM5/13/16
to WebIOPi
I would like to repeat the question.
Output GPIO can operate in the control mode and the mode of the thermostat. How to make what would be in the thermostat mode button only shows the state of output (ON/OFF), and output can not be controlled by the mouse?

Pete Dudash

unread,
May 13, 2016, 10:18:18 AM5/13/16
to WebIOPi

Just disable the button property using jQuery: $("#btn_ID").prop("disabled",true);
Check out this quick jsFiddle for an example.

Michael

unread,
May 15, 2016, 1:45:20 AM5/15/16
to WebIOPi
Perhaps I am wrong to explain :(
GPIO outputs are controlled manually or automatically (timer, thermostat). In automatic mode, you need to block the output control of the mouse. But the condition of this output should be shown (red / green)

Reply all
Reply to author
Forward
0 new messages