Raspberry Pi PWM AC Light Dimmer

Required for this project is a Raspberry Pi Zero W or Raspberry Pi 3 Model B+ (other models, like the Raspberry Pi 3 Model A+, may also work), compatible power supply, buttons, 5 volt relay switches, solder and soldering gun, cables/wires, circuit board, a basic understanding of the HTTP (Hypertext Transfer Protocol), the Python programming language and the Linux operating system.

This tutorial assumes the use of Windows 10.

Setup the Raspberry Pi

If the Raspberry Pi's Raspbian OS is already installed and configured, skip this section.

  1. Download and install SD Card Formatter for Windows; download from sdcard.org.
  2. Quick format the Raspberry Pi's micro SD card.
  3. Download and install Win32 Disk Imager; download from sourceforge.net.
  4. Download Raspbian Lite from raspberrypi.org.
  5. Install Raspbian Lite image using Win32 Disk Imager.
  6. Install micro SD card and boot Raspberry Pi device.
  7. Login as: pi, password: raspberry
  8. Configure Raspbian by issuing a sudo raspi-config command from the command line prompt.
    1. Under Network Options, setup wireless networking.
    2. Under Interface Options, enable SSH.
    3. Under Localization Options, configure the keyboard.
    4. Under Advanced Options, expand filesystem.
    5. Reboot.
    6. Login.
  9. Issue a sudo apt-get update && sudo apt-get upgrade command to update the system.
  10. To access the Raspberry Pi file system over the network from a Windows machine, install Samba.
    1. Issue a sudo apt-get install samba samba-common-bin command at the command line.
    2. Issue a sudo nano /etc/samba/smb.conf command to edit the samba configuration.
      1. Go to the end of the file and enter this text on new lines:
        [user_pi]
        comment=User Pi
        path=/home/pi
        browseable=yes
        writeable=yes
        only guest=no
        create mask=0777
        directory mask=0777
        public=yes
        guest ok=yes
        
      2. Hit CTRL+X to exit.
      3. Save the file when prompted.
    3. Issue a sudo chmod 0777 /home/pi command at the command line.
    4. Reboot.
    5. Login.
  11. Type python at the command prompt. Python version 2.x should be in use.

Program the Raspberry Pi

circuit diagram under construction.

Python Coding

import os
import RPi.GPIO as GPIO
import SimpleHTTPServer
import SocketServer
import urlparse
import time

GPIO.setmode(GPIO.BOARD) # set GPIO numbering mode
GPIO.setup(12,GPIO.OUT) # 12 pin for recessed lighting
pwm = GPIO.PWM(12,140) # pin 12 uses PWM, 140 Hz
pwmval = 0
pwm.start(pwmval) # start the pwm at zero percent

fan_state = GPIO.IN
fan_light_state = GPIO.IN

def build_html_page():
	form_fields = "<fieldset><legend>recessed lighting</legend>"
	i = 100
	while(i >= 0):
		s = str(i)
		form_fields += "<input onclick='this.form.submit()' type=radio name=pwm id=pwm" + s + " value=" + s
		if(pwmval==i):
			form_fields += " checked"
		form_fields += " /><label for=pwm" + s + ">" + s + "%</label>"
		if(i):
			form_fields += "<br />"
		i -= 10
	form_fields += "</fieldset><fieldset><legend>ceiling fan</legend><input onclick='this.form.submit()' type=radio name=fan id=fanon value=" + str(GPIO.OUT)
	if(fan_state==GPIO.OUT):
		form_fields += " checked"
	form_fields += " /><label for=fanon>on</label><br /><input onclick='this.form.submit()' type=radio name=fan id=fanoff value=" + str(GPIO.IN)
	if(fan_state==GPIO.IN):
		form_fields += " checked"
	form_fields += " /><label for=fanoff>off</label></fieldset><fieldset><legend>ceiling fan light</legend><input onclick='this.form.submit()' type=radio name=fanlight id=fanlighton value=" + str(GPIO.OUT)
	if(fan_light_state==GPIO.OUT):
		form_fields += " checked"
	form_fields += " /><label for=fanlighton>on</label><br /><input onclick='this.form.submit()' type=radio name=fanlight id=fanlightoff value=" + str(GPIO.IN)
	if(fan_light_state==GPIO.IN):
		form_fields += " checked"
	form_fields += " /><label for=fanlightoff>off</label></fieldset>"
	c = float(os.popen("vcgencmd measure_temp").readline().replace("temp=","").replace("'C","").replace("\n","")) # get cpu temp
	if(c >= 70):
		color = "#f00";
	else:
		color = "#00f";
	f = 1.8 * c + 32;
	return str("""<!DOCTYPE html>
	<html>
		<head>
			<style>
				input, label {
					margin:7px;
				}
				fieldset {
					border:1px solid #ccc;
				}
			</style>
			<title>Living Room</title>
			<meta name="viewport" content="width=device-width" />
			<meta http-equiv="refresh" content="30; url=/" />
		</head>
		<body>
			<div style='margin-top:25px;text-align:center;'>
				<div style='text-align:left;margin:auto;border:1px solid #ccc;width:200px;padding:7px;'>
					<form method=POST action='/'>
					""" + form_fields + """
					</form>
				</div>
			</div>
			<div style='text-align:center;color:""" + color + """;margin-top:20px;'>CPU temp: """ + str(f) + """'F</div>
	</body></html>""");

class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
	def __init__(self,req,client_addr,server):
		SimpleHTTPServer.SimpleHTTPRequestHandler.__init__(self,req,client_addr,server)

	def do_POST(self):
		global pwm
		global pwmval
		global fan_state
		global fan_light_state
		post_body = self.rfile.read(int(self.headers['Content-Length']));
		qs = dict(urlparse.parse_qs(post_body)) # returns a dictionary
		if(qs.get("pwm") != None):
			pwmnew = int(qs.get("pwm")[0])
			if(pwmnew > pwmval):
				i = 1
			else:
				i = -1
			while(pwmval != pwmnew):
				pwmval += i
				pwm.ChangeDutyCycle(pwmval)
				time.sleep(.01)
		if(qs.get("fan") != None):
			fan_state = int(qs.get("fan")[0])
			GPIO.setup(7,fan_state) # 7 pin for ceiling fan
		if(qs.get("fanlight") != None):
			fan_light_state = int(qs.get("fanlight")[0])
			GPIO.setup(18,fan_light_state) # 18 pin for ceiling fan light
		self.send_response(200)
		self.send_header("Content-type", "text/html")
		html = build_html_page()
		self.send_header("Content-length", len(html))
		self.end_headers()
		self.wfile.write(str.encode(html))

	def do_GET(self):
		self.send_response(200)
		self.send_header("Content-type", "text/html")
		self.send_header("Cache-control", "no-store")
		self.send_header("Pragma", "no-cache")
		html = build_html_page()
		self.send_header("Content-length", len(html))
		self.end_headers()
		self.wfile.write(str.encode(html))

PORT = 8000
httpd = SocketServer.TCPServer(("0.0.0.0", PORT), Handler)
httpd.serve_forever()

GPIO.cleanup()