I stumble out to my cafe area (originally designed to be a dining area, I’m sure) first thing each morning to make coffee. As I step up to the counter, a localized spotlight turns on so I can see what I’m doing, even though the overhead light is behind me so that the counter where I’m working in in shadow.  That’s done by the smarthome node that handles the cafe area.

I was in my office at the bookcase one evening and the room wasn’t overly bright. I thought “I could use more light so I can better see the books.” It occurred to me that I had just the thing. I decided to extract the relevant part of my node design into a standalone auto-light.

I hacked it up on a piece of perfboard in about half an hour. I love prototyping on this stuff. It’s just holes, bit there is a tinned pad on each side of the board and the holes are plated through. It provides lots of options for mounting components and is available in various sizes. I buy it via Amazon.

IMG_1144

IMG_1145

I used a Trinket M0 because it’s small and cheap, and because I had some laying around. My current nodes use an ATMEGA328P and I could have done the same here and used an Arduino ProMini (I have a drawer full of those) but it wouldn’t have been much cheaper, and would have been larger.

The neopixel strip has it’s contacts sweat soldered onto tinned holes in the perfboard: the front 3 holes the front of the A and T rows.  The VX53L0X breakout is mounted by using the usual male header strip, and plugging it into a matching strip of stacking headers, the legs of which have been bent 90 degrees so that the body lays against the perfboard. This lets the breakout hang down at 90 degrees to the main board, pointing out and away.  The whole thing can them be mounted with the NeoPixels facing down and the sensor pointing out.

The circuit is simple (so simple I didn’t bother with a schematic or breadboarding before soldering it up): an output to control a small NeoPixel strip, and an I2C proximity sensor. It’s an application perfectly suited to a Trinket. Since I plan to run this off a 9v battery or a wall wart like you’d use with an Arduino UNO, I added a power port and 5v regulator. The TO-220 7805 is bulky, but the NeoPixels do draw a bit of power. But most of all I had a drawerfull just sitting there and they’re easier to use on perfboard than the SMT version.

Untitled_Artwork

The code is straight forward, and mostly copied from Adafruit’s examples.  The only fancy part is the bit that requires 3 consecutive in/out-of-range readings before it will switch on/off. I didn’t originally have that but found that the light flickered between on & off when you were just at 500mm away. If you want to adjust the behaviour, just change those numbers to what you want.

Source is below, but first here it is in action.

My next step will be to make a custom PCB for it, as well as a 3D printable case for easy mounting.

/*
    Copyright 2017 Dave Astels

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the
   "Software"), to deal in the Software without restriction, including
   without limitation the rights to use, copy, modify, merge, publish,
   distribute, sublicense, and/or sell copies of the Software, and to
   permit persons to whom the Software is furnished to do so, subject to
   the following conditions: 

   The above copyright notice and this permission notice shall be included
   in all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
*/

#include 
#include 


#define HYSTERESIS (3)      // number of required consecutive same readings
#define DISTANCE (500)      // at what distance do the lights turn on, in mm
#define PIXEL_COUNT (8)     // how many pixels in the strip
#define NEOPIXEL_PIN (1)    // pin the NeoPixels are on


uint8_t hys_count = 0;
bool light_state = false;

Adafruit_VL53L0X prox_sensor;
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);


void setup() 
{
  pixels.begin();
  pixels.show();
  for (int i = 0; i < PIXEL_COUNT; i++) {
    pixels.setPixelColor(i, 64, 64, 64);
    pixels.show();
    delay(100);
    pixels.setPixelColor(i, 0, 0, 0);
    pixels.show();
  }

  if (!prox_sensor.begin()) {
    while(1) {
      pixels.setPixelColor(0, 64, 0, 0);
      delay(500);
      pixels.setPixelColor(0, 0, 0, 0);
      delay(500);
    }
  }
}


void fill(uint8_t r, uint8_t g, uint8_t b)
{
  for (int i = 0; i < PIXEL_COUNT; i++) {     
    pixels.setPixelColor(i, r, g, b);   
  }   
  pixels.show(); 
} 

void toggle_if_ready(bool test, bool new_state, uint8_t r, uint8_t g, uint8_t b)
{   
  if (test) {     
    hys_count = 0;     
    light_state = new_state;   
  }    
  if (hys_count > HYSTERESIS) {
    fill(r, g, b);
  } else {
    hys_count++;
  }
}


void loop() 
{
  VL53L0X_RangingMeasurementData_t measure;
    
  prox_sensor.rangingTest(&measure, false)

  if (measure.RangeStatus != 4) {
    if (measure.RangeMilliMeter < DISTANCE) {
      toggle_if_ready(!light_state, true, 128, 128, 128);
    } else {
      toggle_if_ready(light_state, false, 0, 0, 0);
    }
  }
    
  delay(100);

}

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s