Wire Spy: a home electricity auditing helper

The full paper is available on request (server is not cooperating). Email me: ethan-at-cmu-dot-edu. 

Wire Spy

Advertisements

3-D input device

I mentioned this 3-D capacitive input interface for Arduino (on Instructables.com) in class yesterday. It’s basically one corner of a cube with the 3 sides covered with aluminum foil, attached to the Arduino using shielded cable and a couple of resistors. It claims to report the distance of your hand from each of the three faces of the hemi-cube, so you can those as x, y, z coordinates to control… anything! One idea that springs to mind is setting the R/G/B values for your mood lighting. If it’s accurate enough, you could also try to hack it into your favorite cad program (you *are* already using VR goggles for that, right?)

Electri-critter

Use flow

Use flow

 

The electri-critter is a small robot vehicle that follows the walls in a home and senses electric loads (the current flowing in the power cables). When it approaches a power cable, it clamps its sensor onto the cable and measures the load. Because the current transformer (CT) reports different signal levels depending on the relative orientation of the conductors within the cable, the CT must be rotated around the cable until the best orientation is found. The critter will then be able to sense when the appliance turns on and off, and ideally the size of the load. The critter will eventually traverse the entire house, cataloging as many loads as possible.

 

Alternate version: an augmented reality device which a person uses to move through their house and discover the energy consumption of various devices by turning them off and on. Unlike other similar solutions, it would not require the user to unplug the device or record any numbers, because it would sense induction fields around the device’s cord (or perhaps even further) and measure power consumption using a whole-house energy meter that the device communicates with.

Low-bar target: device can be handheld, manually attached to cord, communicates to central meter and receives accurate power consumption, which it then displays to user.

High-bar target: Device may not need to be attached to cable, but only in vicinity of appliance; device may help direct user (or self) to location of cord; feedback may include on-screen (of PC) time-based graph or representation of whole-house energy consumption with the target appliances portion highlighted; multiple devices all simultaneously communicating with central meter… ?

Skills

  • Signal processing / event detection – to identify relevant transitions from the mobile current sensor
  • Mechanical design and fabrication – to create an integrated hinge actuator and closure sensor 
  • Soldering and circuit testing – to assemble XPort ethernet board
  • LCD interface – to output Watts on mobile sensor

Parts

  • Central electricity metering system (I happen to have a couple installed already)
  • Current transducer (I also have some of these)
  • LCD numeric output (need to purchase multi-digit, or I think Hammerschlag has some one-digit models)  
  • wood/metal/plastic disks, gears, hinges, and such – to make cable-clamping and critter-rotating assembly
  • Network connector for Arduino (I have an Xport Ethernet board, but wireless would be better) – to communicate with central meter
  • Microphone for Arduino – to take user input and describe the appliance which is being used

Timeline

  • Week 1: rough draft of mobile device event detector; serial communication to central meter; attempt to correlate events
  • Week 2: rough draft of current-clamp rotating apparatus; ethernet board for Arduino, and communication code for both ends (sensor andrew?) 
  • Week 3: user interaction on Arduino – indicate power consumption, events detected and displayed, accept user labels for events; attempt to calculate power without central meter, using rotation
  • Week 4: attempt wireless, add PC-based energy consumption display, make device more robust, add autonomous vehicle?

Sketches to come (after scanning)…

    Arduino article in Wired

    The latest issue of Wired Magazine has an article on open-source hardware, focusing on the Arduino and its designers/manufacturers in Italy.

    …the Arduino board is a piece of open source hardware, free for anyone to use, modify, or sell. Banzi and his team have spent precious billable hours making the thing, and they sell it themselves for a small profit — while allowing anyone else to do the same. They’re not alone in this experiment. In a loosely coordinated movement, dozens of hardware inventors around the world have begun to freely publish their specs.

    Sense glove

     

    Fingerless glove with adjustable proximity dector

    Fingerless glove with adjustable proximity dector

    This is an investigation of how we might use interactive technology to extend our senses. I mounted the Arduino (with mini project board) on a wrist brace, along with an ultrasonic range-finder, a custom-built flexible rotary input device, a thermistor (embedded on the inside), an LED, a piezo element and a small pager buzzer. In addition, a thermistor (mounted in soft foam) was connected by a length of flexible cable so that it could be placed in the wearer’s armpit. The Arduino was programmed to periodically “chirp” the piezo with two tones corresponding to the levels of the wearer’s core (armpit) and distal (hand) temperatures. Secondly, when the range-finder detects an object closer than the distance set by the rotary input device, the pager buzzer vibrates and an LED lights up.

     

    Sensors and Arduino mounted on a wrist brace.

    Sensors and Arduino mounted on a wrist brace.

    My first goal was to mount all of the hardware on the glove so that the user experience was unencumbered by any tethering to external components such as the Arduino or battery pack. This required building mounting brackets for the Arduino and battery pack out of popsicle sticks and twine. The mini project board was mounted to the top of the Arduino using another stick to support one side. That stick was further used as a strain-relief for some of the wires, and as a mounting platform for two RJ-11 jacks (salvaged from small inline DSL filters). The rangefinder and rotary input device were fitted with RJ-11 plugs on short tails so they could be securely connected but easily detached. The thermistor was threaded into a channel on the inside of the wrist (which previously held a metal stiffener) and fed through a slit, then sewn into the inside of the glove. The pager buzzer was inserted into the same channel and both sets of wires were run along the outside of the glove to the project board. The rangefinder was glued and wired to a stiff piece of plastic with velcro on the back, to mate with the existing velcro covering the back of the glove. The rotary input device (a small potentiometer with a short length of flexible rubber tubing slid over the knob) was mounted to a clothespin so it could be clipped into position and adjusted until the end was just in reach of the wearer’s fingers.

    Glove mount for Arduino and battery pack
    RJ-11 jacks

    Glove mount for Arduino and battery pack (above) and RJ-11 jacks

    While this configuration allowed the hardware to be fully mounted on the glove, there were several lessons learned:

    • wires must be run so that they allow full movement, including opening and closing the item; in this case, that was complicated by the way the Arduino was mounted on the strap, which ran through grommets so that the apparent length of the strap changed as it was pulled tight. However, if the wires at least ran in the same direction as the strap, it could have been fully loosened without detaching the wires. As it was, I ran the wires in the opposite direction, so there was barely enough slack to loosen the strap enough to remove my hand.
    • comfortable wearables demand much smaller/lighter components, and would benefit from embedded wiring so you can move freely without fear of everything falling apart–ideally the user is thinking about the function of the item, not the implementation.
    • RJ-11 connectors are a little bulky for wearables, but it’s easy to find extension cables; perhaps these connectors are better used for household installations (for example, I don’t use any land-line phones in my house, so the in-wall phone wiring could be used for other purposes, such as a one-wire network.)
    • (and on a related topic) RJ-11 connectors are not consistent about the position of different colors of wire.
    range-finder (upper left), Arduino (upper right), and rotary input

    Side view: range-finder (upper left), Arduino (upper right), and rotary input

    The range-finder presented some challenges when I first began communicating with it through the Arduino. While I could detect objects placed with a few inches of the device, once it was more than about 6 inches away from the nearest object it consistently reported the same distance. Eventually I concluded that the receiver must be “hearing” the transmitter directly, without the signal first bouncing off of any object. I placed a small piece of open-cell foam between the two ultrasonic elements and extending approximately 1/2″ beyond the ends of those elements, which solved the problem. I also had intermittent trouble with the thermistors; the one mounted in the glove seemed to occasionally lose contact with the wearer’s hand (causing a temperature drop), and might have benefitted from some foam placed behind it in the channel to maintain pressure (though this might have caused discomfort if it pressed too hard on the wrong part of the wrist). The thermistor in the armpit sometimes seemed to give erratic readings, which I suspect may have been caused by perspiration on the wearer’s skin shorting the conductors and lowering the resistance. The foam thermistor mount was also a little to thick, and could be uncomfortable in the armpit; again, wearable devices place a high premium on small form-factor.

    Schematic

    Schematic

    Another challenge was how to get enough information to the user through ambient buzzing and beeping. The pager buzzer was supposed to buzz more strongly as it detected objects closer to the glove, but it was difficult to perceive the different levels of buzzing, so the rotary input was used to set a minimum distance threshold. I believe that modulating the buzzer and mapping distance to the rate of buzzing would have been easier to interpret, but I did not test this theory. Similarly, the core-distal chirping did not succeed at giving clear feedback about the relative temperature of the two sensed points. It’s possible that mapping a smaller temperature range to a larger tonal range would make it easier to detect different conditions (chiefly, out-of-norms conditions like too-cold hands). Additionally, since the core temperature is unlikely to change (unless the wearer is getting sick), the tone or tones could simply indicate the difference between core and distal temperatures. Perhaps the first tone could be set to a pre-calibrated “normal” difference, an the second tone could indicate the current difference. Also, mounting the distal temperature sensor on a fingertip rather than the wrist might have exposed it to greater fluctuations and produced a more sensitive indicator, but it seemed awkward to mount on a fingerless “glove”. Perhaps a short study with armpit, wrist, and fingertip temperature sensors could be conducted to establish the relationship between the three.

    Thermistor in foam block (aprox. 1"x1"x4") for armpit-mounting

    Thermistor in foam block (aprox. 1

     

     

    You will be sensed...

    You will be sensed...

    The clearest conclusion from this project is that walking around with a small computer, numerous wires, and assorted strange-looking hardware strapped to one’s wrist and beeping at regular intervals–basically, your typical cyborg getup–is a good conversation-starter. However, it was not clear from the beginning of the project exactly what extra-sensory information was needed and how it would be used, so the project was more of a guided exploration of several interesting pieces of hardware and programming notions.

    View sense_glove code for Arduino

    Sunburn warning indicator

    As someone with fair skin who is prone to sunburns, I would benefit from an early warning system which reminded me when I had spent too much time in the sun. This prototype simply increments a counter at a rate proportional to the light level reported by the photo sensor, then triggers a warning when the counter exceeds a preset level. A two-color LED is used to display the current light level as a range of blue (low light) to red (bright light).

    Planned improvements include:

    • light level floor (no exposure is registered when you are inside)
    • UV-only filter (more accurate measurement of sunlight)
    • adjustable sensitivity (for different skin types)
    • multi-level warning indicator (green/yellow/red)
    • sunscreen mode: sensitivity is divided by the SPF for a few hours
    • decrement the counter when user is out of the sun for a while
    • embed it in a wearable object, such as a pendant

    The wiring schematic is quite simple: the analog input is driven by a voltage divider using a 1kOhm resistor to +5V and a photo sensor to ground. Two PWM “analog” outputs power the 2-color LED (blue/red in this case). The red warning LED is powered by a digital output.

     

    One red LED and one bi-color LED are used as indicators, while a photo-sensitive resistor is the input.

    One red LED and one bi-color LED are used as indicators, while a photo-sensitive resistor provides input.

    Arduino Code

    The code is fairly straightforward: calculate the resistance of the photo resistor using the voltage measurement at the voltage divider, use that to scale the red/blue LED. Add the light level to the exposure counter and set off the warning light if exposure exceeds the threshold.

     

    /*
    sunburn warning
    A photo-resistor is used to detect bright-light situations,
    and a bi-color LED indicates the level of light detected.
    Once the cumulative light exposure passes a set threshold,
    a red warning LED is lit.

    */

    int photoPin = 5; // the photo resistor
    int ledPinRed = 5; // the red half of the LED
    int ledPinBlue = 6; // the blue half of the LED
    int ledPinWarn = 7; // the red warning LED
    int lightLevel; // used to store the current level of light sensed
    int lightAccum = 0; // the accumulated light counter
    int maxLightAccum = 20000; // the warning threshold for the accumulated light counter
    // note that to convert this number to a useful unit like lumen-seconds it is necessary to consider the delay (currently 0.01 sec)
    int ledLevelRed; // level to set the red portion of the bi-color LED
    int ledLevelBlue; // level to set the blue portion of the bi-color LED
    int blinkRate; // not used; early concept was to communicate warning through speed of blinking
    int vIn = 5; // voltage on V+ rail; used to scale the photo resistor reading
    int rBridge = 10000; // rating of the voltage bridge resistor in Ohms
    int rPhoto; // calculated resistance of the photo resistor at each cycle

    void setup(){
    pinMode(ledPinWarn, OUTPUT);
    Serial.begin(9600);
    }

    void loop(){
    /*
    measure light level
    */
    lightLevel = analogRead(photoPin); // get the current voltage at the voltage divider, over a range of 0-1023
    rPhoto = rBridge * ((vIn / lightLevel) - 1); // calculated resistance of photo resistor
    Serial.print("light level: ");
    Serial.print(lightLevel);
    // Serial.print(" = r of ");
    // Serial.println(rPhoto);
    /*
    set bi-color LED levels
    */
    ledLevelRed = map(lightLevel, 1023, 0, 0, 254); // red gets brighter as light level increases; note that resistance decreases as light level increases
    ledLevelBlue = map(lightLevel, 1023, 0, 254, 0); // blue gets dimmer as light level increases; note that resistance decreases as light level increases
    Serial.print(" led level Red: ");
    Serial.print(ledLevelRed);
    Serial.print(" led level Blue: ");
    Serial.print(ledLevelBlue);
    analogWrite(ledPinRed, ledLevelRed);
    analogWrite(ledPinBlue, ledLevelBlue);
    /*
    update accumlated light exposure
    */
    lightAccum = lightAccum + (ledLevelRed);
    Serial.print(" light accum: ");
    Serial.println(lightAccum);
    /*
    set off warning light if exposure level is exceeded
    */
    if (lightAccum > maxLightAccum){
    digitalWrite(ledPinWarn, HIGH);
    }
    delay(10);
    }

    Bike helmet turn signal

    It is dangerous to take your hands off of the handlebars when signaling a turn, so I designed a helmet-mounted turn signal than can be triggered by a small switch. The switch can be mounted on the handlebars or clipped to your wrist so that it dangles within easy reach of your fingers. The signal clips to the strap at the back of the helmet. Since there is not much distance between the left and right sides of the helmet, I used a strip of 6 LEDs that chase from left to right or vice-versa; this is similar to the system that some ambulances use.

     

    Arduino board (center) wired to 3-way switch (top) and strip of 6 LEDs (left)

    Arduino board (center) wired to 3-way switch (top) and strip of 6 LEDs (left)

    Input is from a 3-way toggle switch; center position is “off” and makes no contact with any of the four pins, left and right position are used for left/right turn signal, and those positions make contact with the left and right pairs of contacts, respectively. Each pair of contacts is wired to the +5v rail of the breadboard and to a digital input pin, and those pins are also connected to ground through >1k ohm resistors. There is also a small potentiometer wired to an analog input pin from the middle (variable output) pin, while the other two pins on the pot are wired to ground and +5v, allowing the output pin to range from 0-5v.

    The output to the 6 LEDs is through 6 digital pins, wired through 6 ~1k ohm resistors to the cathodes, while the anodes are wired to ground (would it be possible to use a single 1k ohm resistor between the junction of all the anodes and ground?) Also note that we extend the conductors to the LEDs using an 8-conductor CAT-5 cable with RJ-45 connectors. The jacks are wired to the breadboard at one end using 26-gauge solid-core jumpers which can be press-fit to the jack (no stripping required) and at the other end the LEDs cathodes are directly connected to the RJ-45 jack using the same press-fit connections. This does not give them much stability until they are pressed through the cardboard mounting strip (a more waterproof material would be a better long-term choice). The anodes are twisted together with a jumper which is attached to another pin on the RJ-45 jack; this connection should be strengthened with solder.

     

    connections between LEDs, 3-way switch, and potentiometer and the Arduino's connectors

    connections between LEDs, 3-way switch, and potentiometer and the Arduino

    Arduino code


    /* turn signal
    ripple through a row of LEDs in one of two directions
    speed (aka 1/slowness) is controlled by an analog input
    */
    boolean debug = false; // show debug messages on serial output
    int leftButtonPin = 2; // connect to left side of 3-way switch
    int rightButtonPin = 3; // connect to right side of 3-way switch
    int rowWidth = 6; // number of LEDs
    int firstLedPin = 4; // lowest pin number of LEDs - connect to adjacent pins in ascending order
    int knobPin = 4; // connected to variable pin of potentiometer knob

    int rippleDirection = 1; // can be set to +/- 1 for left-to-right or right-to-left rippling, respectively
    int currentRipplePos = -1; // can be set from 0-(rowWidth-1) to indicate currently "active" LED, or set to -1 to indicate no active LED
    int leftButton; // value read from left button pin; should be LOW or HIGH
    int rightButton; // value read from right button pin; should be LOW or HIGH
    boolean lightState[6]; // zero-indexed array of booleans indicating whether LED at that index should be off (false) or on (true)
    int slowness; // delay per cycle, in milliseconds; set by knob position, scaled between min and max
    int minSlowness = 5; // min delay
    int maxSlowness = 500; // max delay
    boolean justSwitched = false; // flag for the reset actions at the beginning of a left- or right-moving cycle; reset when switch is set to "off"
    unsigned long lastMoveTime = millis(); // reset each time LED position changes
    int rawKnobPos; // analog value of knob pin

    void setup(){
    // set all the LED pins to LOW (off) and digital output mode
    int i;
    for (i = 0; i < rowWidth; i = i + 1) {
    lightState[i] = false;
    pinMode(firstLedPin + i, OUTPUT);
    }
    // for debugging output
    Serial.begin(9600);
    }

    void loop(){
    // read value of knob pin and set slowness to that value, scaled between min and max
    rawKnobPos = analogRead(knobPin);
    slowness = map(rawKnobPos, 0, 1024, minSlowness, maxSlowness);

    // only show debug code when needed, as it adds a delay and limits the min slowness
    if (debug == true){
    Serial.print("current pos: ");
    Serial.print(currentRipplePos);
    Serial.print(" direction: ");
    Serial.print(rippleDirection);
    Serial.print(" rawKnobPos: ");
    Serial.print(rawKnobPos);
    Serial.print(" slowness: ");
    Serial.print(slowness);
    }

    // read button pins and make LEDs ripple if switch is not "off"
    leftButton = digitalRead(leftButtonPin);
    rightButton = digitalRead(rightButtonPin);
    if ((rightButton == HIGH || leftButton == HIGH)){

    if (leftButton ==HIGH){
    if (debug == true){Serial.println(" left button on");}
    rippleDirection = 1; // ripple from left to right
    if (justSwitched == true){ // setup steps for the first cycle after switch moves from off to left
    currentRipplePos = 0; // start with the left-most LED
    justSwitched = false; // don't run setup steps again
    lastMoveTime = millis(); // reset delay timer
    }
    } else {
    if (debug == true){Serial.println(" right button on");}
    rippleDirection = -1; // ripple from left to right
    if (justSwitched == true){ // setup steps for the first cycle after switch moves from off to right
    currentRipplePos = rowWidth - 1; // start with the right-most LED
    justSwitched = false; // don't run setup steps again
    lastMoveTime = millis(); // reset delay timer
    }
    }
    // if switch is in "off" position
    } else {
    currentRipplePos = -1; // no active LED
    justSwitched = true; // ready to run setup steps nect time switched on
    // set all LEDs to LOW (off)
    int j;
    for (j = 0; j lastMoveTime + slowness){
    // reset timer
    lastMoveTime = millis();
    // only make LEDs ripple if they are not set to off (position = -1)
    if (currentRipplePos != -1){
    // toggle the led at the current position; on->off or off->on
    if (lightState[currentRipplePos] == false){
    lightState[currentRipplePos] = true;
    } else {
    lightState[currentRipplePos] = false;
    }

    // if the position is at the end of the row, go to other end
    if (currentRipplePos == (rowWidth - 1) && rippleDirection == 1){
    currentRipplePos = 0;
    } else if (currentRipplePos == 0 && rippleDirection == -1){
    currentRipplePos = rowWidth - 1;
    } else {
    currentRipplePos = (currentRipplePos + rippleDirection);
    }

    }
    // update the LED pins with the new values so the lights go blinky-blinky
    int k;
    for (k = 0; k < rowWidth; k = k + 1) {
    if (lightState[k] == true){
    digitalWrite(firstLedPin + k, HIGH);
    } else {
    digitalWrite(firstLedPin + k, LOW);
    }
    }
    }

    }