Sunday, January 13, 2013

Automatic Bathroom Fan Switching

It's been a long time since my last post, but I have a legitimate excuse! I bought a house and have been moving in and getting the place comfortable. Then the Christmas holiday came, and I had to move more stuff from my parents' house, then I bought a car so I'll have something to drive while I tear my truck apart. Maybe I'll have pictures of the house and the car in a later post. For now, I must document my first house-related project.

What I wanted was a way to have the bathroom fans run for a set amount of time after I was done taking a shower in order to suck the humidity out and prevent mold from growing in the bathroom (a serious concern in South Florida, which is already a substantially humid area). My options were either turn the fan off when leaving the bathroom and risk high humidity levels, or leave the fan on and waste energy. I figure there was a solution for me out there.

I decided I could program an ATtiny45 to do this job. My goal originally was for the microcontroller to measure how long I had the lights on, and turn the fan on and leave it on for an appreciable amount of time after I turned the light out. It took me a while to hammer out the program, but I learned all about Interrupt Service Routines and some of the registers while I was doing the coding.


I used an old cell phone charger to get 5V DC from the 120 AC in the gang box. Luckily the electricians who wired my house ran the neutral to the gang box as well, otherwise this project would have been shot. Without the neutral wire, this would have tripped the house-wide GFCI every time the light or the fan in the bathroom was switched on. That would have been inconvenient. Additionally, using the cell phone charger is great for power efficiency; when neither the light nor the fan is on, I do not have the tools sensitive enough to measure how much power it uses (meaning less than 5 mW are consumed when it is idling). When both are on, the whole thing uses only about 3.5 watts (but presumably saves me a lot of money over simply leaving the fan on).

I used timer interrupts to crudely measure how long the light had been on, and a rising edge interrupt on  one of the pins to toggle the fan (in case it was on, turn it off if you wanted, or vice versa). I decided on 90 seconds for the light to be on before the fan gets turned on (to allow for bathroom activities that are NOT showers) and an hour and a half of fan run time after the light turns off.


Trying to squeeze everything into the gang box without making too many modifications. I had to trim two of the wires down that lead to the fan, which hopefully won't be that hard to fix if I ever decide to sell the house and take this monstrosity with me.



Hooking up the switch for the light, which now no longer switches 120V AC. It now is only a logic switch for the microcontroller to tell the program to turn the relay on that is connected to the light. I wanted to use some of the original hardware though.


(Almost) finished. Those two wires will be attached to the toggle button for the fan. For now it works just fine without. I'm planning on using some bondo to modify another face plate to accept the new switch. The best part about this project is that now that I am done, I allowed myself to buy the parts from Digikey that I need to build something I've wanted to build for a long time. I had to finish this one first before starting on it though, and everyone knows how much I disapprove of programming. So I had to give myself some incentive. But hey!


Sunday, October 14, 2012

Listen to the Radio from ANYWHERE

Since I moved to South Florida I've noticed that there aren't any appropriate radio stations anywhere down here. They're all mindless Clear Channel-type Top 40 or country stations. Unacceptable. There weren't this many country stations when I lived in South Carolina or Tennessee. Anyway! I thought maybe I could build a radio that would get radio stations from far away, and it would let me listen to independently-owned and happily non-country stations 105.5 The Bridge from Charleston and Lightning 100 from Nashville.

My idea was to interface a parallel port port in a computer to a set of buttons. Each button would launch Firefox which would then load the online stream of one of these stations. The computer controlling it would be headless and hidden, so the visible hardware would look and perform just like a regular radio. The only downside to this is that I can't get 95.7 The Ride out of Charlotte with this build because they don't have an online stream anymore.

At boot, the computer executes a script that starts a C program called "launcher". The C program is necessary to take control of the printer port, and therefore it must be run as root. To allow the computer to execute the script as root, I added the following line to the sudoer's file with the command "sudo visudo":

ALL    ALL = (root) NOPASSWD: /home/bryan/programs/radio/launcher

The script is very simple:

#!/bin/bash
sudo /home/bryan/programs/radio/launcher

I also ran "chmod 755 startup.sh" on the script to make it executable. Next is the C program that will actually handle the parallel port and launch the browser when a button press is detected:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#include <time.h>

#define base 0x378 // printer port base address
#define status 0x379 //printer port status register

//Define button push events. Status register default 0x78 = 0b01111000. 
#define PUSH1 0x70 //0x70 = 0b01110000
#define PUSH2 0x68 //0x68 = 0b01101000

int A=1;
int lastA=0;
int B=1;
int lastB=0;
int regval=0;
int lastregval=1;

int main(int argc, char **argv) {
  //make sure the program has access to the parallel port
  if (ioperm(base,1,1))
   fprintf(stderr, "Couldn't get the port at %x\n", base), exit(1);
  if (ioperm(status,1,1))
   fprintf(stderr, "Couldn't get the port at %x\n", status), exit(1);

  //write 0b00000001 to the output lines to get +5V for the switches
  outb(1, base);

  while(1) { //run forever
  //print status register if and only if it changes
/*    regval=inb(status);
    if(regval != lastregval) {
      printf("%x\n",regval);
      lastregval=regval;
    } */

    if (inb(status)==PUSH1 && A!=lastA) {
      //enable other button pushes
      B++;
//      printf("button 1 pushed!\n");
      //call script
      system("/bin/bash /home/bryan/programs/radio/script1.sh");
      //disable a second button 1 push event to debounce and to
      //prevent closing of browser and opening the same page it was on
      A=lastA; 
    }

    if (inb(status)==PUSH2 && B!=lastB) {
      //enable other button pushes
      A++;
//      printf("button 2 pushed!\n");
      system("/bin/bash /home/bryan/programs/radio/script2.sh");
      //disable a second button 2 push event to debounce and to
      //prevent closing of browser and opening the same page it was on
      B=lastB;
    }
  }
}


No problem. I complied it using "gcc -O launcher.c -o launcher". Compiling with these options is necessary for proper functionality of the parallel port.

This program only handles two stations now but it could be expanded for more if 95.7 WXRC ever decided to have an online stream again. I believe the next step is to program this on my Raspberry Pi when it gets here, and install it in the radio that I have that has been the subject of previous posts on this blog. I think I could rewire the memory buttons on the radio to be inputs to the Pi and have the radio display "105.5" or "100.1" on its LCD. This has some potential! If anyone has some tips on how I can be a better programmer, I am open to those suggestions. I'm an engineer, not a computer scientist.


Sunday, August 12, 2012

Halon Alarm

I found this halon alarm in the garbage a long, long time ago and I finally have some time to goof off. Believe it or not, this relates to my ongoing solar panel build. To build a maximum power point tracking circuit will require the construction of a special switch mode power supply topology, and since I have never built even a simple switch mode power supply, I figure I could get some experience with one before moving on to the complicated stuff.


The halon alarm consists of two modules, a bell and a strobe light. They are wired in parallel and accept a 24V DC power source. Since 24V systems are less common than 12V systems (and I may install this in a vehicle in the future) I attempted to build a 12V DC to 24V DC boost converter, with varying degrees of success.

A brief explanation of boost converters: a transistor is used to rapidly switch power flowing through an inductor. The rapid switching action exploits an inductor's resistance to changes in current. When the current flow to an inductor is switched off, a voltage spike occurs as the inductor attempts to keep current flowing through it at the same rate. By charging a capacitor with this voltage spike, a DC voltage greater than the input voltage can be obtained. Before transistors (and before they became cost-effective to mass produce) DC-DC conversion was either expensive, impractical, unreliable, or some combination of those three. This is why the power grid is alternating current, as it is much easier to change the voltage levels using AC than with DC.

The first step is actually the most difficult: creating a circuit that will switch the power transistor. For a power supply like this, the switching action must happen many thousands of times per second. PWM is often the best option for rapid transistor switching, so for this I used a 555 timer chip wired to produce a 28 kHz square wave. The output of the timer was attached to the gate of an IRF510 MOSFET. The rest of the power supply is comparatively easy to build.


This is the point that I had some difficulties. Switch mode power supplies can be very particular. The duty cycle of the signal that switches the transistor must be precise, as this directly controls the output voltage. The other quirk with these circuits is that the output voltage tends to be dependent on the load that is connected to them. Without a load, the voltage (on this circuit anyway) tended to "run away", growing higher and higher until I realized something catastrophic was about to happen, at which point I turned it off. This contrasts to a linear voltage regulator, which (while it wastes about 70% of the input power) will have a relatively stable output voltage regardless of load.

Another point I would like to make here is that this design does not include any feedback on the output voltage. I designed it for 12V input and 24V output but "really" what it does is double the input voltage. If I put 5V input it will output 10V, and (theoretically, although it would burn up first) a 100V input would produce a 200V output. The alarm is rated for 20-24VDC (and I'm assuming a little above that as well) so as long as the 12V source is fairly constant (a car battery, etc) then this shouldn't be a problem, and keeps the design simple.

The other major difficulty is managing the power spikes inherent in the design. On computer power supplies, the electrical noise and harmonics that are produced are dramatic. Most are required to have special filters on them to prevent them from harming a power utility's power factor and voltage waveforms (compact fluorescent bulbs produce a similar amount of noise but are not required to have as strict of filtering, which causes problems). So anyway, it turns out that I melted through two ground wires because of this.


Notice the bubbles on the white wire. Whoops. The circuit draws 100 mA on average, but this doesn't necessarily account for the spikes that the inductor causes.

Once I got everything straightened out I tested the alarm (very, very briefly) in my apartment with numerous cloths wrapped around the bell. I didn't want to remove the bell for fear that I would damage the striking mechanism. Once I was sure everything was in working order, I drove far away to test it more thoroughly.


If you look closely during and after the test, you will see that I melted through the orange ground wire. When I build this circuit in a permanent manner (not on the breadboard) I will be using much heavier gauge wire. I also plan on enclosing the circuit within the junction box that houses the strobe light.

You will also notice that the strobe light is noticeably not strobing. I am currently working on repairing this. I'm not sure how successful I will be, but it would be nice if it worked too. Updates on that will follow.



MEANWHILE! I got around to repairing an old set of Pioneer headphones I commandeered from my dad when I was younger, in an effort to reduce the number of times either one of my parents accused me of listening to my CD player too loud while we were on car trips. The effort was largely in vain. But the headphones needed some TLC (and one of the ears wasn't working any way) so I finally took them all apart, soaked them in acetone to clean them up, rewired the malfunctioning speaker, and hot-glued the ear pads on (the plastic that was supposed to hold them on had broken off). Then I used some WD-40 to clean up the leftover residue from the duct tape that was holding them together. Viola! A brand new set of headphones that I can use with my piano to keep the neighbors happy.



Thanks for all the free stuff, Dad!

UPDATES

I built a permanent version of the boost converter and put it inside the strobe light housing. Pictures! The inductor is a 1mH 0.8A high-current choke that I had laying around. I believe an inductor of this size is overkill. So it goes. Also, I used a IRF530 MOSFET driven by a 555 timer. The capacitor values are not as important.


All the capacitors are there because I didn't have one that was the right value, so I paralleled them up to get the capacitance I needed.


Installed, complete with fuse. Now I just need to fix the strobe light and I'll be in business!


This was the extent of this project's damage. The white wire I bubbled up while I was still figuring out the ins and outs of SMPS design, the orange one is the wire I melted through during the test that I recorded in the video above. You can watch it melt if you look real closely.

Saturday, July 21, 2012

Holy oscilloscope, Batman!

I bought an analog Hewlett-Packard oscilloscope today. It was designed in the 70s, built in 1985, and decommissioned by the US Navy in 1993. Still going strong apparently. It's about two feet long (which is not evident in the picture, but it does not fit on my recliner). I don't have any test leads yet, but this is one of the two tools I needed to start working on switch-mode power supplies. It also makes me feel like I'm back in my Circuits I class with lab equipment that rarely worked. Hopefully this will go better!

Sunday, July 1, 2012

Outlet Control Pictures


I took some pictures while I was making a permanent enclosure for my web-controlled power outlets. These are going in the kitchen and are attached to the old Gateway that plays my fridge music and serves up my tunes. I made it work in a way that each plug on the outlet can be independently controlled.

 

 Oh, and I used a ton of hot glue to seal everything up...

 



I took 12V DC control wiring from the IDE drives' power wires and ran it out of the front of the computer.



Very professional!




New update relating to my lamp: I was successfully able to install a webcam and set it up to monitor the lamp. This is more of a temporary solution until I can learn Python.

Any way! I installed a program called "streamer" which can do many things, including take a JPEG picture from a webcam. Then I wrote a script to run this program every second.

#!/bin/sh
while [ true ] do 
 streamer -s 640x480 -f jpeg -o /var/www/images/snapshot.jpeg 
 sleep 1
done

The picture gets rewritten every time it runs. That way the web server doesn't need to think about which picture to show. Now I need to execute this program as root at boot time. I added a line to the /etc/init.d/rc.local file:

/home/bryan/streamer &

Hooray! This method obviously takes quite a bit more system resources. If this was something that people would look at all the time, maybe it would be a good method, but I'll maybe use this once a week, so hopefully when I learn Python I'll figure out a way to execute the "streamer" program once when the page is requested.

Saturday, June 23, 2012

Desk Lamp Web Control

Once I got the web server working from the last post, it was time to get the parallel port to do something useful. As its first task, I decided to hook it up to my desk lamp so that anyone in the world could turn the light in my apartment on and off. If you would like to try it yourself (and my computer is on), go to http://108.233.132.201/.

THIS IS IMPORTANT: I can't tell who is turning my lamp on and off yet. So! If you're going to play around with it, please let me know who you are. Phone/text/email/facebook are all acceptable, or just leave a comment below.

I used an AC adaptor I had laying around (from my kitchen light switch mod from two and a half years ago) to get 12V DC for the relay. When I actually hook this up in the kitchen, I plan on splicing in to the old Gateway's power supply to get the 12V. I tied the output ground from the power supply to the 0V pins of the parallel port and put an LED in to let me know when I had the device powered up. Next I wired up a TIP31 NPN bipolar junction transistor. The base was attached to one of the parallel pins, the collector was attached to the relay coil (I also put an LED here just for peace of mind), and the emitter was attached to ground. And that's it! Once I get this in the kitchen (and wired up properly, i.e. not with live 120AC wires taped to terminals) I'll post a video of it in action. 

An overview of the setup. Parallel port on the left, electronics in the middle, AC adaptor, relay, and the lamp's plug on the upper right.


A close-up of the electronics. The IC on the right is a 555 timer that's not being used. 

Everything together including the lamp. 

My not-quite-up-to-code wiring, which shows how I fed the 120V AC from the wall, through the adaptor, through the relay, and to the lamp. Not super safe but I won't leave it plugged in until I build a more permanent enclosure for it.


Also I promise I had this idea before this episode of the Big Bang Theory aired. WHAT A COINCIDENCE! This is what I felt like though. Then it was creepy when people started turning my lamp on and off.

Tuesday, June 19, 2012

Progress on the "Turing" Slow Cooker

I have successfully managed to control the pins on a parallel (printer) port over the internets. I now document my efforts.

I already have this working on my personal desktop (which is apparently old enough to still have a parallel port in it?). For the purposes of writing this without flaws, I will be re-creating my work on the old Gateway in the kitchen, mostly using SSH. As of this writing, the computer is running Ubuntu 12.04 with LXDE.

First, I installed the apache2 webserver.

sudo apt-get install apache2

Next, I need to modify apache to run CGI scripts. This is much easier than everyone else on the internet seems to think. First, open /etc/apache2/apache2.conf with your favorite text editor and add the following line above  
ErrorLog ${APACHE_LOG_DIR}/error.log:

ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ 

Now it is time to get dirty. I used www.epanorama.net/circuits/parallel_output.html as a primer. It is full of spelling and grammar mistakes (and a few coding mistakes) but it's legible and helpful. Any way, the default web page that apache serves is /var/www/index.html. Mine looks like this:

<html>
<head>
<title>Parallel port controlling test page</title>
</head>
<body>
<h1>Parallel port controlling test page</h1>
<p>
<form action="/cgi-bin/lpton.cgi" method="get" name="on">
<input type=submit value="Set all data pins high">
</form>
<p>
<form action="/cgi-bin/lptoff.cgi" method="get" name="off">
<input type=submit value="Set all data pins low">
</form>
<p><img src="pic.png">
<p>
</body>
</html>


The picture was to double-check to make sure apache was serving more than just index.html because at first I had problems serving the CGI scripts. Any way! Now we need to get those CGI scripts written. I use two, in this example, one to set all the data pins on the parallel port high (turn things on) and one to set them all low (turn them off). I started off in ~/programs with two C programs.


lptoff.c:
include
#include
#include
#include
#include


lpton.c:
#include
#include
#include
#include
#include


I compiled the programs:

gcc -O lptoff.c -o lptoff
gcc -O lpton.c -o lpton 


Then I moved the programs to the /usr/sbin/ directory and gave them root access. This means that every time these programs are called they run as root automatically, even if the user who executes the programs does not have root privileges. This may seem like bad practice, but the reason for this is that writing to the parallel port requires root. This seems unavoidable. Just make sure the program won't get stuck in an infinite loop or it will be difficult to stop it. Any way...

sudo cp lptoff /usr/sbin/
sudo cp lpton /usr/sbin/
cd /usr/sbin
sudo chmod +s lptoff
sudo chmod +s lpton


The next step is to write CGI scrips that tell apache to run these two programs. They will be placed in the /usr/lib/cgi-bin/ directory. There are two buttons in this example, so there are two CGI scripts:

lptoff.cgi:
#!/bin/sh
# Parallel port CGI script
#
# Send HTTP headers
echo Content-type: text/html;charset=ISO-8859
echo
# Do the controlling
/usr/sbin/lptoff
# Output web page data
echo ""
echo "Parallel port controlled
"
echo "Go back to controlling page"
echo ""
#


lpton.cgi:
#!/bin/sh
# Parallel port CGI script
#
# Send HTTP headers
echo Content-type: text/html;charset=ISO-8859
echo
# Do the controlling
/usr/sbin/lpton
# Output web page data
echo ""
echo "Parallel port controlled
"
echo "Go back to controlling page"
echo ""
#


That's all! Again, credit where credit is due, most of the pages came from http://www.epanorama.net/circuits/parallel_output.html#webcontrol, and I modified the rest to suit my needs. This blog is primarily a way that I can keep track of what I do, and that is what I have done. Hooray science!

A video of it in action:




UPDATE: Actually a lot of this code is messed up because it's almost impossible to post code with this blog publisher's web software. So if anyone REALLY WANTS the files, maybe I'll make them available for download from my server. Also. You'll need to make the .cgi files executable! This is important otherwise you'll get a "INTERNAL SERVER ERROR!!!!!11" error when you try to run this. Do sudo chmod +x on the files and you'll be fine.