Things used in this project
|Software apps and online services:|
|Hand tools and fabrication machines:|
The electromagnetic force is a powerful ally. It flows through the devices that run our lives. With the right sensor it’s possible to view these invisible forces and harness them for great good (or to let you know when your tea water is ready). Building this project won’t make you a Jedi but it will teach you a thing or two about using the Photon’s ADC to measure electric current of an appliance and it’s DAC to play a WAV audio file through a set of speakers.
Every morning I make hot water for tea or coffee. The first thing I do is set the water on the electric kettle, punch in the desired water temperature then go about the rest of my morning routine. What happens frequently is that I get distracted (by checking email, reading some new thing on the internet, walking the dog, etc…). The hot tea water sits there as I'm distracted and starts cooling off. The kettle keeps the water warm but this can waste quite a bit of electricity. Unfortunately the kettle does not beep or anything like that so have no idea when it’s done. Even if it did beep, I might be in another room and not hear it.
I wanted a way to enhance my tea kettle to notify me when the water is ready. I know that the tea kettle draws a lot of power when it is heating the water (the heating element is 1000W). Based on a previous project I knew it would be possible to sense the tea kettle turning on, heating the water, then turning off. When the element turns off I could sense the transition and trigger something to then let me know my water is ready. I thought it should make some noise I could hear from the other room.
To spice things up and give the project some personality I started to think of this device as a helpful little BB-8. When the kettle water is ready the device plays a chipper BB-8 sound. I found a bunch of BB-8 WAV files here so I had a lot to choose from. Here are links to the files, zipA and zipB.
See it in action!
For this project you will need the following:
- Particle Photon https://store.particle.io
- Current transformer (CT sensor) http://amzn.com/B005CWO5UC
- Four resistors and one capacitor (100 ohm, 2 @ 100k ohm, 10k ohm, 10uF)
- Simple audio amplifier circuit https://www.adafruit.com/products/1712
- Set of speakers https://www.adafruit.com/products/1669
- One (or more) NeoPixels https://www.adafruit.com/products/1312
- 15amp rated appliance cord http://amzn.com/B0022NH41Q
- Project box/enclosure http://amzn.com/B0002BEN9Q
- Breadboard or circuit board (one large one small) https://www.adafruit.com/products/1609
- MicroUSB power adapter https://www.adafruit.com/products/1995
- Crimp connectors for 22-10AWG wire or similar http://amzn.com/B000FPCEM2
- This slick BB-8 decal http://amzn.com/B015KMHYLK
- Hook-up wire, small zip ties, electrical tape, etc
For this project I used the following tools:
- Soldering Iron/station
- 3rd-hand tool
- Hot glue gun
- Hand-held electric drill
- Diagonal cutters
- Saleae Logic Pro 8 (optional, for debugging the analog circuit)
- Screwdriver (various types)
The project has two fairly simple circuits, one for the CT to convert the current in the transformer to a voltage which can be read by the Photon. Another for the Photon to drive the audio circuit and the feedback LED light. Here's what the bread-boarded version of the full circuit looks like.
Here is that same circuit as above. There are not many components. The wiring looks a little complicated but the main challenge is making sure you connected the right wire to the right place. When I first started testing this circuit and the software I put the CT and the current sensing circuit on it's own board (seen above). This was really helpful because it keep the breadboard simple and I could attached long leads to the CT circuit and keep the AC lines far from my DC electronics.
The CT circuit
The parts in the CT circuit are:
- CT (current transformer)
- Appliance cable
- Cable crimps
- Zip ties
- 100 ohm resistor
- two 100k ohm resistors
- 10uF capacitor
- Small protoboard
- hook-up wire
First start by prepping the appliance cable. Cut it in half, towards the female end of the cable. Split the wires in the cord and peel away each cable. The goal is to separate out the hot, neutral, and grounded lines so we can crimp them each back together. Before we crimp them back together we'll slip on the CT sensor on the hot line so we can sense the current flowing through here and used by the attached appliance. Here's a helpful diagram I found on which wire is the Hot wire.
Note: If you're new to AC power. It's worth reading up on (google it, there are some great articles out there). You'll want to be very careful to connect everything correctly (e.g. Hot wire to Hot, Neutral to Neutral, Ground to Ground) otherwise bad things can happen (e.g. smoke, fire, electrical damage, etc...). On the appliance cord linked to in the parts list the Neutral wire is ribbed. Once you line up the ribbed cables the other two should line up as well. Check out the photos below. It's much simpler to see than describe.
Once you have the CT installed in the appliance cord. Begin assembling the CT sensing circuit. The protoboard I used has an unusual trace that groups the connection holes in groups of threes (don't ask). The circuit diagram is correct but how you end up laying out the circuits on your protoboard will likely be different than how I did mine. See the photos of the circuit below.
Once you have this mini-circuit assembled you can test it on it's own. I did that using my Saleae Logic Pro (which has an analog sense feature). You won't be able to test this on a standard multimeter. AC current (and the resulting voltage on the sense line of the CT sensor circuit) changes at 60hz which is too fast for most multimeters.
Here's a screen capture of the sensed voltage when I attached and turned on the power to the tea kettle.
The Photon Circuit
On the Photon the circuit uses both DAC pins (DAC, A3) to produce the audio output. The software only supports mono output at this time but I plan on adding stereo support later. Wiring it up to support stereo audio means all I'll have to do is make software changes to support stereo WAV files. These outputs wire in directly to the Adafruit audio amp.
The circuit also uses the D0,D1 to control the audio amp over I2C. This allows enabling/disabling the audio channels to prevent unwanted noise from leaking through to the speakers when sound data is not being sent to the DAC. It also allows us to (in the future) set sound volume/gain/etc... over I2C.
To turn the amp on we'll use the D3 pin. It is tied to ground with a 10k pull-down resistor. This keeps the amp from turning on during power up before the Photon boots. Without this the amp ends up amplifying noise in the circuit.
Pin A0 is used for the ADC. This is connected to sense the voltage on the CT sensor circuit.
The key to making this whole project work is the software that runs on the Photon and the simple python script to pre-process the WAV file.
WAV file processing
There were a few reasons why I needed a python script to pre-process the BB-8 audio file. First, the DAC on the Photon outputs voltage values between 0-3.3V. Wav files are encoded around a zero midpoint. This means that the audio voltage level in the WAV file goes between positive and negative numbers. The script accounts for this and shifts the numbers up so values are all positive and the waveform is preserved. Secondly, the DAC on the Photon is 12bits. Wav files can be encoded in 64/32/16-bit. To account for this the script requires the WAV files to be 16-bit so we can bit shift the values down to 12-bit. The instructions on how to prep the WAV files using Audacity (a free audio editing tool) see the python script. Steps to prep the WAV file are in the comments. Here are some resources on WAV files. See this article on the PCM format, description of PCM, and this one on WAV files in general.
WAV playback and ADC sampling
The Photon does a lot of heavy lifting to both play the audio and also sample the voltage on the CT sensing circuit. To have the Photon do both these things we need to use the IntervalTimer library. Using a timer based approach the Photon can switch between reading the voltage on the ADC and writing a voltage value to the DAC. I've never written code using this type of approach. It was a little intimidating at first. However, it's pretty easy to use and the resulting code is surprisingly simple. See the code in the gists attached to the project.
Building the enclosure
I went with the simple black ABS box for this project. They are cheap and easy to work with. A 3D printed BB-8 head would be a pretty slick enclosure. That was the plan at he beginning. However, I don't own a 3D printer and the design started to become rather complicated with all the speakers and circuit boards and etc... Here's a link to a downloadable 3D shell I built. http://a360.co/214REnw
To build the enclosure you'll need a drill with several drill bits. I used 3/32, 1/16, 1/8 inch bits, also a 1.25 inch hole saw drill bit. It's also helpful to have blue painters tape to apply to the outside of the enclosure to keep from scratching the surface while you work on it (ABS is pretty soft) and to help make visible marks.
Use the drill (and safety classes) to drill out the holes for the appliance cord, the speaker "grills" and the mounting holes for the speakers. For the speaker grill you can just drill random sized and placed holes.
Adding in the components
Adding the components in requires some tape and hot glue. I omitted photos of the circuit assembly because there is not much to it. Since I used the Adafruit 1/4 size breadboard PCB it was a direct mapping of the circuit from the breadboard to the perfboard since they have the same wiring.
I found this project challenging and very rewarding. The Photon has a lot of powerful features and they are pretty easy to use. This was my first project working with a device that needed to produce audio. Also, it was the first time I had to really look at the WAV file format to figure out how to map it to the Photon's DAC. I'd worked with sampling current from a CT sensor in the past but my first time doing it using an interval timer on the Photon (previously I had used an Arduino). Feel free to post questions to the project and I'll be happy to answer them. Watch for future projects involving the Photon and audio!
Appendix: Current Sensing
The following are my notes on how to sense current using a current transformer. So much of what follows I learned from the OpenEnergyMonitor project. It's a great product and there is a wealth of knowledge on their site.
The current sensor is based on the following formula. The current in the primary circuit (Iprimary) multiplied by the transformer turn ratio.
Isecondary = CTturnsRatio X Iprimary
CTturnsRatio = TURNSprimary/TURNSsecondary
Since primary is the live line from the power cord the value for TURNSprimary is 1. There is one "turn" of wire going through the center of the CT coil.
The value for TURNSsecondary is the Turn ratio of the transformer. In this case the the value is 2015. This is designated in the data sheet as Te = Effective turns ratio including losses.
see CR8448-2000-F 50A rating
This means our CTturnsRatio is 1/2015
For an RMS max current of 20A (which is about typical 20A max of any normal household outlet or circuit breaker) the actual peak-to-peak current of the CT would be:
Ip2p = IrmsMax * sqrt(2)
Ip2p = 20A * 1.4142
Ip2p = 28.28A
If we round up to 30A p2p max to be safe we can plug that max P2P current into our CT equation.
Isecondary = 1/2015 x 30
Isecondary = 0.01489A
Isecondary = 14.89mA
Since our AD input on the Photon has a range of 0-3.3V we want to keep the voltage output of the CT circuit between that range. Actually, since the current is AC current, not DC, it will vary between -14.89mA and +14.89mA. Also, this is our MAX current we expect to see. Most appliances operate well below 20A. Here's a great image to reference for what we are trying to build. Ignore the numbers on the image below since those values are for 5V arduino and they make some different assumptions about the max current that will go through the CT. [-[-[source: http://openenergymonitor.org/emon/sites/default/files/Arduino%20AC%20current%20input%20A.png]
We expect to see roughly 30mA swing, peak-to-peak from the CT and we'll need to size our burden resistor on the circuit so that the peak-to-peak voltage stays within the range of the ADC on the Photon (0 - 3.3V). Using Ohm's law V=IR we can figure out what our burden resistor should be to give us a our maximum peak-to-peak (P2P) voltage. Plugging in the numbers we get:
Vmax = Imax x R
Vmax/Imax = R
3.3V/0.02978A = 110.8Ohm
This means to get the maximum range over the 20A current we would want our CT to have a burden resistor at or around 111 Ohms. You would have a difficult time finding an R value of exactly that and most resistors have a %accuracy built in to how they're sized. For this circuit I'll use a 100 Ohm 1/4W Metal Film resistor which has an 1% accuracy. You can get away with your standard carbon film 5% resistor as well. I just happen to have a box of these resistors with sizing from 0- 10M Ohm.
The other resistors we'll need for the circuit are the voltage divider resistors. We'll put these resistors in series between the 0 and 3.3V rails so that the junction in the middle of the two are at 1.65V. This midpoint will be the "zero value" for the CT. Since the current in the CT (thanks to AC current changing direction at 60hz) will cycle from positive to negative this will cause the voltage across to do the same. With a 100 Ohm resistor we can use Ohms Law to figure out what the voltage will be for the current in the positive direction. Plugging in the numbers we have:
Vpos = 0.01489A x 100
Vpos = 1.489V
Since we'd also see that same current in the negative direction...
Vneg = -0.01489A x 100
Vneg = -1.489V
We want to make sure that when the voltage is positive or negative at it's maximum that it's within our 0 - 3.3V range. We take our center voltage of 1.65V and see that 1.65V - 1.489V = 0.161V and 1.65 + 1.489V = 3.139V. So we are well within the range of the ADC and even though we don't hit zero or 3.3V exactly it's fine. We'll loose a little ability to resolve slight changes in power usage of our device but for our purposes this range of 0.161V to 3.139V is acceptable.
With our burden resistor sized and voltage range checked we can pick out our resistor values for the voltage divider. They should be higher resistance, between 10k - 470k Ohm. The higher the resistance the less quiescent or "stand-by" current is used by the circuit. Since our circuit is plugged in to the wall I'll choose a 100k Ohm pair since I have a bunch of this value. And these 100k are not the fancy metal film but the regular old carbon film 5% kind. I measured the Ohm values and found two at 97.5k Ohm and 97.4k Ohm which are close enough. We just want them both to be as close to the same values as they can be.
Sampling the ADC on the Photon
Since the current draw from an appliance is very dynamic and alternating current is involved ( and with how we have designed the power sensing circuit, so is alternating voltage) we cannot simply take a single reading from the analog pin on the Photon. One single reading at a single moment is not enough information to determine what is going on. Even with a constant current draw from the appliance a single reading can vary between 0-3.3v so we need to take many readings at very accurate intervals to get the full picture.
To take many readings in the arduino world most people would rely on a simple loop with a 'delay(x)' call to create the sample interval. This is fine if the arduino is only doing this one thing. When you use delay loops your code is kind of stuck (albeit intentionally) running over those same lines of code again and again. We are going with a slightly different approach. Since sampling the voltages on the ADC pin is only a small part of what our larger project will be doing we will use an interval timer instead. These are actually very simple once you get used to the concept. The photon has many interval timers available ( the are part of the STM chip so there is not an infinite number but plenty for most projects.
The sampling rate for the circuit should be high enough that we can, over the sample period, capture enough of the alternating voltage to produce the max/min voltage values. The circuit does not need to sample continuously. It just has to sample every 250 ms or so, and during that sampling window capture enough to approximate the current draw.
The frequency of our signal is 60hz. This means that one period is ~16ms (1/60sec). If we want 5 full cycles of the signal we would have to capture the signal for 80ms. Grabbing the max/min RMS voltages will give us the values we'll need to determine the current the device is using. The RMS (root mean square) voltage is Irms = Imax/sqrt(2).
I think to keep the software simple that it would be best to set up an interval timer. This timer would fire every X microseconds and capture the voltages. I would also like to store the past Y readings so that at any instant I can request the Vrms. The function to calculated the Vrms would grab the latest Y readings from an array and calculate on the values stored there.
The frequency of AC is 60hz which means our period is 1/60seconds. This comes to ~16.667ms for a complete cycle. If I want 48 samples per cycle I would need a sampling time period of 16.667ms/48 = 0.34722 ms or 347 microseconds. If we sample at 347 uS we will have a 2.88kHz sampling rate. This should be more that adequate to capture the waveform voltages from the CT sensing circuit.
In terms of the storage of the ongoing readings I think a few cycles would be sufficient. If we want three complete waveforms that would be (1/60) X 3 = 0.05 or 50ms. If we capture and store 144 samples that should be sufficient.
Python WAV processing code
Did you replicate this project? Share it!I made one
Love this project? Think it could be improved? Tell us what you think!