Categories
Making

Recovering an old terrarium

My second terrarium experiment was a rework of a terrarium that Audra made during an education retreat a number of years back. It had completely died off, even before our recent moves, and needed a major overhaul.

This has done quite well, needing only minor maintenance. I will feature a video of this one in an upcoming post.

Categories
Making

Terrariums: Distracting hobby, or mental health exercise? Both?

During the Spring of 2021 as COVID still raged, I wasn’t getting out much. Between significant computer screen time and evening Netflix couch time, I knew that I had to force myself off of the machines and back into something more natural.

Many years ago, during a trip to Chicago, Audra got me a very nice terrarium container made in Poland. My green thumb was focused for years on growing hot peppers outdoors. I didn’t spend as much time on indoor plants, except for my many clippings of Pothos (aka Devil’s Ivy). The terrarium container was never properly used, and found its way into storage. Thankfully, it survived several moves, waiting for the day when it would have a proper place to display.

A few Google and YouTube searches turned up plentiful resources on terrarium builds. The most helpful resource by far has been the YouTube channel SerpaDesign, run by a guy named Tanner in the Pittsburgh area. Aside from bringing an artistic sensibility to everything he does, I found Tanner’s site most helpful because he’s in a similar climate and uses the same type of resources I can access near Philly. And yes, there’s some irony here in the desire to get away from screens, only to turn to YouTube to get up to speed on a new hobby.

Later I’ll note a few other resources, but for now I want to get into showing some things I’ve done.

First up is the “Chicago Terrarium”. This actually went through two iterations so far, the first of which didn’t look very good and only lasted a couple weeks before I wanted to redo it using things I learned online.

The current iteration of the “Chicago Terrarium” uses a combination of local moss, store-bought plants, and locally sourced rocks. I decided to remove the jade buddha because he didn’t look natural in this setting. The springtails came from an Ebay vendor, and the isopods came from local parks.

Following Tanner’s advice, I made a very good false bottom with store-bought aquarium rocks from Lowe’s. I kind of have a problem buying rocks when I can get them from nature, but for this first build I wanted it to be as clean as possible.

The false bottom also uses carbon fiber screen (Lowe’s) and activated charcoal (Ebay). I’m using Serpa’s typical substrate mix of sphagnum moss, sand, orchid bark and sometimes coconut fiber. For this first build, I used some indoor potting soil I already had on hand.

If a terrarium is made correctly, it should not need a lot of maintenance. But one of the highlights of my day right now is looking in on these little worlds and seeing what’s happening with them. Not only does this get me away from the computer, it gets me outside a bit more as I search for moss or other elements to incorporate.

I suppose like anything else you enjoy, terrariums can become addictive. The “Chicago Terrarium” was successful enough that I started looking for other containers to try.

The one thing I’ve noticed about the terrarium enthusiasts is that they seem to fall into three categories. Tanner, who seems to fall in the middle, is very thoughtful about what he does and approaches things with a bit more of a plan and an eye for aesthetics.

Others – particularly some of the terrarium builders from Japan who incorporate bonsai techniques – are even more detailed and show an amazing level of artistry and complexity. The other end of the spectrum are those that just grab whatever is in their backyard, toss it in a jar, and hope for the best with little thought! All of these approaches have their charm.

In future posts, we will take a look at my other creations, and I’ll share some other things I’ve learned along the way.

Coming soon…

Home Goods Tree Scene
IKEA Cookie Jar
IKEA Mason Jar
Joanne’s Terrarium Scene
Reconditioned snake tank!

And maybe a few other experiments!

Categories
Making

Soundcraft Notepad Mixer Repair

Categories
Making Portfolio Project

JD Teensy Breakout V1

Teensy is a popular microcontroller ecosystem that I’ve highlighted on my site before. There are already a number of breakout shields on the market for most of the Teensy models. I’ve tried several, and written about them here.

Teensy 3.2

The breakout boards that I’ve tried were either overbuilt with way more functionality than I required, or too basic, not offering what I needed for my projects. After considering a few ways to approach this, I made a physical prototype for connecting some sensors.

A few months prior to this, my father was transitioning from acid-etched circuit boards to computer designed boards using Eagle. He hadn’t sent his board off for manufacturing yet, so this was a good time to combine efforts and save on shipping if I could get my own board designed. I thought it would be good to use the same program so we could learn about it together. Unfortunately, couldn’t get Eagle to run on my laptop due to a video issue, so I opted for Circuit Maker.

First concept drawing (bottom view)

For about two weeks, I learned how to pull off my design successfully and pass the QC process within Circuit Maker and the online manufacturer I selected (PCBWay in China). On one level the process is very much like desktop publishing in that you have many layers to manage and very fine tolerances down to the fraction of a millimeter. On another level this was a completely different world for me and I definitely learned a lot.

As usual, taking breaks was a good idea throughout the process. I often found myself having an idea about how to make an improvement after some time away. One frustrating part was that PCBWay doesn’t give you all errors at once when you go through their QC process. They tell you about one error at a time, and with the time delay between here and China, that can be somewhat grueling. But with ample help from Youtube and some forums I got through the major hurdles, and in the end I was able to go with a lot of default settings in Circuit Maker. I know a lot of people swear by Eagle, but I am pretty used to Circuit Maker now and will likely use it again.

I used Otherplan as a supplemental check to see if the build files would translate properly. My dad was also able to check my design in a different board viewer. All of the activity on my board project prompted my dad to finish his design, and we were able to ship everything together, saving on shipping. Then we waited… to make sure we didn’t just create a bunch of funky coasters!

After about two weeks, our order came. I couldn’t have been more pleased. The board looks great, and functions electrically the way it should. Like anything you do for the first time, there are always some improvements to make, so I am sketching out V2.0. I’ve worked the board into my project for now, and will be selling the rest on Tindie.com if anyone is interested.


This was a very fun process, and I already have ideas for a completely different board I’d like to make in addition to a revision of this one. My dad’s board is awaiting testing, and we’ll know before long how his design went. Hopefully it was just as successful and I can post an update soon!

Categories
Making

Adafruit TS2012 Amp

This is a rather old project meant as a supplement to other things I was working on in the audio realm.

Adafruit notes:

As of May 23, 2016 we’ve updated this breakout to use the TPA2012 rather than the TS2012. This is an overall-equivalent part with slightly less power output. You can use the two interchangeably for 99% of projects. The TS2012 has been discontinued!”

This is a super simple kit that barely warrants mention on my project page, except for some of the additional mods and interconnections I tried to prepare this amp for best us in my projects.

The first is the speaker enclosure, made with a shipping box and speakers from Adafruit:

The original intent was to make this modular for easy connection for testing audio projects. But I wasn’t happy with the mechanics of the pin interface, and particularly the stereo jacks I got which have an odd pinout and barely work on a breadboard. Somewhat discouraged I let this sit for some time before coming back to it. It was only after I found the Sparkfun Audio Jack Breakout that I was able to get this into better mechanical working order.

Here I also have the power connected, which is the second part of the problem… this board needs 5V on its own and most of my projects also need 5V of their own power, or 3.3V regulated. So the next step is to make a self-contained power supply for this and my Teensy sound projects so I can run everything off of a single adapter.

Categories
Making

Teensy Breakout by Tall Dog

March 3, 2018

I found Daniel Gilbert’s Teensy 3.2 Breakout (Revision D) on Tindie during a web search while working on my Teensy Audio project. The breakout board was out of stock, so I put myself on the wait list immediately. As soon as they were available a few weeks later, I ordered two – one for prototyping and one for potential permanent install. The boards arrived fairly quickly and are of great quality and design.

I know that is it always a good idea to read instructions a couple of times, especially for somewhat specialized stuff like this. This was even more important in this case because I did not plan on using the board 100% exactly as originally proposed. I wanted to use longer pins to allow insertion into a Teensy audio board.

Like other users I had some confusion about the VIN VUSB cut that you need to make on the Teensy, but a quick email to Daniel got me on the right track (see photos below). My only real challenge with this build was the 14-pin double row header. While the instructions say to not worry about lining it up too much, this really does need to line up perfectly with the 5-pin header above it or the Teensy and Breakout wont sandwich together. Luckily, with some foresight I avoided a major issue by using a female header to hold everything in place. In the end I actually had more trouble from the A11,A10,AREF,VUSB header, but with a little gentle bending got everything together.

The 14-pin header soldering area is tight once the 5 pin header is installed. I have a variable soldering iron, but even the conservative setting I typically use was a bit high for working in this area. I had one problematic pin where some plastic melted causing the pin to slide all over the place. At one point I considered scrapping the whole header, but I was able to salvage it after taking a break.

Good light and a magnifying glass are *extremely* helpful here. This was my first time working with the 14-pin right angle header design that connects to pads and to conventional pins. Even for an experienced builder may grow impatient with this. Take breaks!

Altogether the build took me 2 hrs. That was after reading the instructions 3 times in separate sittings. When you consider the cost of this board ($12), the Teensy ($20) and your time, you don’t want to mess up. After I was done, all pins tested fine and I now have a great board that is perhaps too good to use for some projects! This breakout offers more functionality at your fingertips than most people would use in small projects.

Categories
Making

Linksprite LED Matrix

February 24, 2018

The LinkSprite is an 8 x 8 LED matrix that can be used when you need something more sophisticated than a single LED to give feedback. It also opens up the world of creating letters, numbers and basic shapes.

Extremely well documented, the Linksprite is very easy to get going – although, as I post this, the documentation site is down! I’ve had this unit for a few years, having only tried a basic sketch to spell out my name using this sketch:

 unsigned char i;
 unsigned char j; 
/*Port Definitions*/
int Max7219_pinCLK = 10;
int Max7219_pinCS = 9;
int Max7219_pinDIN = 8;
 
unsigned char disp1[38][8]={
{0x3C,0x8,0x8,0x8,0x8,0x8,0x48,0x30},//J
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x41,0x22,0x14,0x8,0x8,0x8,0x8,0x8},//Y
};

void Write_Max7219_byte(unsigned char DATA) 
{ 
 unsigned char i;
 digitalWrite(Max7219_pinCS,LOW); 
 for(i=8;i>=1;i--)
 { 
 digitalWrite(Max7219_pinCLK,LOW);
 digitalWrite(Max7219_pinDIN,DATA&0x80);// Extracting a bit data
 DATA = DATA<<1;
 digitalWrite(Max7219_pinCLK,HIGH);
 } 
}

void Write_Max7219(unsigned char address,unsigned char dat)
{
 digitalWrite(Max7219_pinCS,LOW);
 Write_Max7219_byte(address); //address,code of LED
 Write_Max7219_byte(dat); //data,figure on LED 
 digitalWrite(Max7219_pinCS,HIGH);
}
 
void Init_MAX7219(void)
{
 Write_Max7219(0x09, 0x00); //decoding :BCD
 Write_Max7219(0x0a, 0x03); //brightness 
 Write_Max7219(0x0b, 0x07); //scanlimit;8 LEDs
 Write_Max7219(0x0c, 0x01); //power-down mode:0,normal mode:1
 Write_Max7219(0x0f, 0x00); //test display:1;EOT,display:0
}
 
void setup()
{
 pinMode(Max7219_pinCLK,OUTPUT);
 pinMode(Max7219_pinCS,OUTPUT);
 pinMode(Max7219_pinDIN,OUTPUT);
 delay(50);
 Init_MAX7219();
}
 
void loop()
{ 
 for(j=0;j<38;j++)
 {
 for(i=1;i<9;i++)
 Write_Max7219(i,disp1[j][i-1]);
 delay(500);
 } 
}

That was 2014. With my return to the Linksprite in 2018, I found it is even easier when you reference one of several LED Matrix builders available online.

Aside from getting familiar with the MAX7219 chip which does all the heavy lifting, I found the Linksprite to be very good for studying coding in general.  I thought maybe I’d work with it for a couple hours and get bored, but it became the focus of much of my weekend experiments as I tried different things.

There are a few behaviors to consider, and some concepts you must master for the Linksprite to work. The most important is arrays, which are used to store the various codes for the images. I use the term “images” here loosely, as what you can create with 8×8 LEDs/pixels is limited. Speed and intensity parameters also come into play, and its interesting how many ways you can tackle adjusting these parameters for different effects.

Using a tilt switch, I created two sets of behaviors. One just scrolls through some arrow shapes using a long-ish method of coding.

The second uses an array and some variables to create the appearance of a moving arrow (which is nothing more than a visual trick). Both behaviors show an increase in light intensity.

I tried a number of ways to load the images and change the intensity at the same time. I tried two FOR loops running in parallel, and a FOR within a FOR. Usually I ended up with intensity changing all at once, and sometimes stopping the motion in the process. The solution here is one of many potential options, but worked the best out of what I tried.

/* JJD 2/24/18 - 2/25/18
 * Matrix HEX code from https://xantorohara.github.io/led-matrix-editor
 * 
 * Linksprite LED Matrix v1.0 (MAX7219)
 * https://www.sparkfun.com/products/retired/11861
 * http://linksprite.com/wiki/index.php5?title=LED_Matrix_Kit
 * http://store.linksprite.com/max7219-8x8-red-dot-led-matrix-kit/
 * 
 * Tested with Redboard
 * Intensity of lights change along with animation, but there are a few ways to do this.
 * Not all of them work the same way. Method here gives smoothest transitions.
 * 
 * */

#include <LedControl.h>

int CLKPIN = 10;
int CSPIN = 9;
int DINPIN = 1;
int TILT = 13;
int buttonState = 0; // Variable for reading button
int arrowDelay = 1000;
int arrowToshow = 0;

// https://xantorohara.github.io/led-matrix-editor
const uint64_t IMAGES[] =
 {
 0x081c3e7f1c1c1c1c, // DOWN 0
 0x0010307fff7f3010, // RIGHT 1
 0x1c1c1c1c7f3e1c08, // UP 2 
 0x00080cfefffe0c08, // LEFT 3
 };

//DOWN ARROW ANIMATION
const uint64_t ARROWS[] = {
 0x081c3e7f1c1c1c1c,
 0x1c3e7f1c1c1c1c00,
 0x3e7f1c1c1c1c0000,
 0x7f1c1c1c1c000000,
 0x1c1c1c1c00000000,
 0x1c1c1c0000000000,
 0x1c1c000000000000,
 0x1c00000000000000,
 0x0000000000000000,
 0x0000000000000008,
 0x000000000000081c,
 0x0000000000081c3e,
 0x00000000081c3e7f,
 0x000000081c3e7f1c,
 0x0000081c3e7f1c1c,
 0x00081c3e7f1c1c1c
};

const int IMAGES_LEN = sizeof(IMAGES)/8;

LedControl display = LedControl(DINPIN, CLKPIN, CSPIN);

void setup(){
 pinMode(TILT, INPUT);
 display.clearDisplay(0);
 display.shutdown(0,false);
 display.setIntensity(0,5);
}

void displayImage(uint64_t image)
{
 for (int i = 0; i < 8; i++) {
 byte row = (image >> i * 8) & 0xFF;
 for (int j = 0; j <8; j++) {
 display.setLed(0,i,j,bitRead(row,j));
 }
 }
}

void loop() {

// Read the state of button or tilt
 buttonState = digitalRead(TILT);

// Remember that images are numbered starting at 0,1,2,3... etc
 /* Set the brightness of the display. void setIntensity(int addr, int intensity); 
 * Params:
 * addr the address of the display to control
 * intensity the brightness of the display.
*/
 if (buttonState == HIGH) {
 display.setIntensity(0,0);
 displayImage(IMAGES[3]);
 delay(500);
 display.setIntensity(0,1);
 displayImage(IMAGES[2]);
 delay(500);
 display.setIntensity(0,2);
 displayImage(IMAGES[1]);
 delay(500);
 display.setIntensity(0,3);
 displayImage(IMAGES[0]);
 delay(500);
 display.setIntensity(0,4);
 displayImage(IMAGES[3]);
 delay(500);
 display.setIntensity(0,5);
 displayImage(IMAGES[2]);
 delay(500);
 display.setIntensity(0,6);
 displayImage(IMAGES[1]);
 delay(500);
 display.setIntensity(0,7);
 displayImage(IMAGES[0]);
 delay(500);
 display.setIntensity(0,8);
 displayImage(IMAGES[3]);
 delay(500);
 display.setIntensity(0,9);
 displayImage(IMAGES[2]);
 delay(500);
 display.setIntensity(0,10);
 displayImage(IMAGES[1]);
 delay(500);
 display.setIntensity(0,11);
 displayImage(IMAGES[0]);
 delay(500);
 display.setIntensity(0,12);
 displayImage(IMAGES[3]);
 delay(500);
 display.setIntensity(0,13);
 displayImage(IMAGES[2]);
 delay(500);
 display.setIntensity(0,14);
 displayImage(IMAGES[1]);
 delay(500);
 display.setIntensity(0,15);
 displayImage(IMAGES[0]);
 delay(500);
 
 } else {
 for (int arrowToshow = 0; arrowToshow < 15; arrowToshow++)
 // the 15 here refers to the 16 arrows (0-15) in the array above. Could also make this a variable like IMAGES_LEN
 
 {
 static int count = 0; // setting this for use as intensity, initialize only once via static
 display.setIntensity(0,count); 
 displayImage(ARROWS[arrowToshow]); // use value from FOR loop to assign the arrow image from the array
 delay(arrowDelay); 
 count ++; // increment the intensity
 if (count > 16) // limit intensity to unit threshold 0-16
 {
 count = 0;
 }
 } // close 1st FOR

} // END ELSE
} // END MAIN LOOP

This was a lot of fun and gave me some ideas for how to work this into some of my other projects. One could set a arrow to flash down/up when a temperature reaches too low/high. These LEDs are very bright and could be seen from far away if necessary.

Of course, since these came out in 2012/2014, many more sophisticated LED and NeoPixel devices are available. There’s still lots to learn from even a small 8×8 matrix – time well spent!

Categories
Making

Button Board v1.0

This idea came about from needing LEDs, buttons, trim pots and switches on hand to do quick tests on various devices. Most of the time, I just needed something to test an audio trigger or response from a sensor.

All too often, the item I needed wouldn’t be where I needed it. I often do work away from my main electronics bench, so I thought it would be a good idea to have some sort of modular device that included all the basics for testing. Enter the “Button Board”.

This is version 1.0. A number if improvements need to be made. I thought the double header would be helpful. It wasn’t. Besides being underutilized, it ate up more space than needed. It’s also only obvious to me how the ground/hot connections should be made. There are some simple hidden capabilities that I thought of only as I was building it from my very simple drawing. I’m going to use this for a while and then maybe make another one that is more refined.

Categories
Making

ZX and Ultrasonic Sensing

February 16, 2018

After making some advances with audio board selection and programming, it was time to go through my parts supply and explore various sensors to see how they could be employed.

First up was the ZX Distance and Gesture Sensor made by Sparkfun. I have the original version which is now retired. Following the hookup guide, things were easy enough to get going.

This sensor uses infrared (IR) beams to place objects. As Sparkfun note, “The ZX Sensor is a touchless sensor that is capable of looking for simple gestures in the air above the sensor (e.g. swipe left or swipe right). Additionally, the sensor can also recognize the distance of an object away from the sensor at distances up to about 12 inches (30 cm), referred to as the “Z” axis, and the location of the object from side to side across the sensor in about a 6 inch (15 cm) span, referred to as the “X” axis.”

This has some very similar capability to the Sparkfun APDS-9960 RGB and Gesture Sensor, though a key difference is that it requires 3.3 –  5V power, but 5V gives better range according to Sparkfun. Oddly, there is no “down” gesture, which the APDS-9960 does have. I found the response a bit less immediate than I would like for some things, so haven’t worked this into a project yet.

HC-SR04 Ultrasonic Distance Sensor Module

I’ve had the common HC-SR04 sensor sitting around for years, exploring it early in my Arduino learnings. I probably got mine from Adafruit, but I see they no longer carry it. Sparkfun does, and these sensors are pretty easy to find elsewhere, being a staple in the robotics community.

I chose to use a Pro Mini as the main board here because it would mirror the size of the project I have in mind. Setup was fairly easy, though I did have some issues with my library. Eventually I landed on the one from Martinsos on GitHub, though there are others out there that may be more suitable depending on the application.

After basic tests, I wanted to add some LEDs and found a similar idea from Instructables, so integrated that code. From there, I wanted to incorporate my Adafruit FX Sound Board project and trigger it from the ultrasonic sensor. This was actually a dry run for a similar idea I have for a Particle Photon project, but I wanted to have a proof of concept first.

In the pictures there is a little red PCB on an orange breadboard between the two projects. This is because I thought a logic converter would be needed, but in the end it was not. For one thing, the Adafruit FX Sound Board has a built in regulator for the inputs. So there was no benefit to overbuilding with the converter.

I also couldn’t get it to work anyway – though this was probably user error. Everything worked with the LEDs, but as soon as I tried triggering the soundboard, I either saw repeated triggering (bad) or only got the intended results with what I saw as some backwards wiring. After telling my dad about this, he set me straight with a simple transistor approach that did the trick. “Transistor BASE goes to Mini OUTPUT. COLLECTOR goes to sound board input pin. EMITTER goes to ground. Probably both ground of Mini and ground of soundboard should connect together.”

So the projects are now connected, with an object triggering a sound as it passes the sensor. Final code below. In many ways this is still rather overbuilt (compared to Teensy), but could still be fun to use for Halloween 2018.

/*
JJD 2/16/18 HC-R04 with Pro Mini 5V
Uses Library from
https://github.com/Martinsos/arduino-lib-hc-sr04/blob/master/examples/simple/simple.ino


Sensor is initialized by creating instance of class UltraSonicDistanceSensor and providing trigger and echo pins:
UltraSonicDistanceSensor sensor(triggerPin, echoPin);.

Then, to measure the distance, you just call measureDistanceCm(), which will return distance in centimeters (double).
If distance is larger than 400cm, it will return negative value.

LED code inspired by
http://www.instructables.com/id/Simple-Arduino-and-HC-SR04-Example/

*/

#include <HCSR04.h>
#define LED_1 10
#define LED_2 11

// Initialize sensor that uses digital pins 13 and 12.
int triggerPin = 13;
int echoPin = 12;

//UltraSonicDistanceSensor distanceSensor(triggerPin, echoPin); // this line not really needed if declaring INTs above

void setup () {
 Serial.begin(9600); // We initialize serial connection so that we could print values from sensor.
 pinMode (LED_1, OUTPUT);
 pinMode (LED_2, OUTPUT);
}

void loop () {
 long duration, distance;
 digitalWrite(triggerPin, LOW);
 delayMicroseconds(2);
 digitalWrite(triggerPin, HIGH);
 delayMicroseconds(10);
 digitalWrite(triggerPin, LOW);
 duration = pulseIn(echoPin, HIGH);
 distance = (duration/2) / 29.1;
 if (distance < 6) { // This is where the LED On/Off happens JJD X cm to act as switch for whatever
 digitalWrite(LED_1,HIGH); // When the LED_1 condition is met, the LED_2 LED should turn off
 digitalWrite(LED_2,LOW);
}
 else {
 digitalWrite(LED_1,LOW);
 digitalWrite(LED_2,HIGH);
 }
 if (distance >= 200 || distance <= 0){
 Serial.println("Out of range");
 }
 else {
 Serial.print(distance);
 Serial.println(" cm");
 }
 delay(500);
}
Categories
Making

Sparkfun APDS-9960 RGB and Gesture Sensor

The Sparkfun APDS-9960 RGB and Gesture Sensor is a fairly low-cost ($15) option for hands-free control of all kinds of things. I’ve had this sitting around for a while waiting to be integrated into a project, but I wanted to explore it on its own before making that leap.

For the size, this is a sophisticated sensor, with capability to do proximity, gesture (left/right, up/down, near/far), color sensing and some other options. My initial interest was gesture sensing for a Teensy project, but I chose to explore this sensor on the Sparkfun ESP8266 Thing and Pro Mini 3.3V boards first, just to become familiar with the code.

The trickiest part of my initial tests were the interrupt settings. I ran into issues on the Sparkfun ESP8266 Thing where I’d get a successful sensor initialization, but no gestures. I had better luck with the Pro Mini, though still had some issues with gesture sensing and it was much easier to get Proximity working (shown below).

Here’s the code for the LED proximity threshold test based on Shawn Hymel’s original sensor test sketch:

#include <Wire.h>
#include <SparkFun_APDS9960.h>

// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint8_t proximity_data = 0;
int LED_PIN = 3; // JJD LED for if then

void setup() {

pinMode(LED_PIN,OUTPUT); //configure LED_PIN as OUTPUT 
 digitalWrite(LED_PIN, LOW); // set LED off
 
 // Initialize Serial port
 Serial.begin(9600);
 Serial.println();
 Serial.println(F("------------------------------------"));
 Serial.println(F("SparkFun APDS-9960 - ProximitySensor"));
 Serial.println(F("------------------------------------"));
 
 // Initialize APDS-9960 (configure I2C and initial values)
 if ( apds.init() ) {
 Serial.println(F("APDS-9960 initialization complete"));
 } else {
 Serial.println(F("Something went wrong during APDS-9960 init!"));
 }
 
 // Adjust the Proximity sensor gain
 if ( !apds.setProximityGain(PGAIN_2X) ) {
 Serial.println(F("Something went wrong trying to set PGAIN"));
 }
 
 // Start running the APDS-9960 proximity sensor (no interrupts)
 if ( apds.enableProximitySensor(false) ) {
 Serial.println(F("Proximity sensor is now running"));
 } else {
 Serial.println(F("Something went wrong during sensor init!"));
 }
}

void loop() {
 
 // Read the proximity value
 if ( !apds.readProximity(proximity_data) ) {
 Serial.println("Error reading proximity value");
 //digitalWrite(LED_PIN, LOW); JJD LED TEST
 } else {
 //Serial.print("Proximity: ");
 //digitalWrite(LED_PIN, HIGH); JJD LED TEST
 //Serial.println(proximity_data);
 }

// JJD Section 2/10/18 to set LED on/off at threshold
 if ( proximity_data < 100 ) {
 digitalWrite(LED_PIN, LOW);
 Serial.print("LED OFF, Proximity under 100: ");
 Serial.println(proximity_data);
 } else {
 digitalWrite(LED_PIN, HIGH);
 Serial.print("LED ON!! Proximity over 100: ");
 Serial.println(proximity_data);
 }
 
}

Gestures took some more tries, with a complete refresh of my test code, but eventually it worked (below).

While testing gestures, I tried to include some code to turn an LED on/off. This seemed to slow things down and didn’t work as well as I’d hoped. Response was a bit sluggish, probably because of the delay I used in gesture routine. Even after I took out the LED code, I thought the gestures responded a bit sluggishly.

I’m still not 100% sure why I found so many conflicting tutorials on the interrupt settings.

attachInterrupt(0, interruptRoutine, FALLING);
attachInterrupt(digitalPinToInterrupt(interruptPin), interruptRoutine, FALLING);

Setting that aside, I worked the proximity sensor into a Teensy project to control audio volume and that worked great. I’d like to leave that intact, so I’m going to order another sensor to dedicate to troubleshooting this further. Next step is to a) refine gesture response and b) see if both gesture and proximity can be used from same sensor. Combining them from the same sensor seems feasible, but involves more than just calling the Proximity and Gesture functions in the same sketch. Sparkfun provided some guidance:

“…the gesture function runs off of the proximity function (pages 9-17; the diagrams on 9 & 15 might be more helpful to visualize). You would probably have to internally call the register addresses for that proximity data (page 26).”

So there’s much more to explore!

/****************************************************************

2/9/18 JJD Reworking with SparkFun ESP8266 Thing WRL-13231 (not Dev Thing)
 2/11/18 JJD Pro Mini tests WORKING

APDS-9960 RGB and Gesture Sensor
 Based on Shawn Hymel @ SparkFun Electronics May 30, 2014
 https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor

Tests the gesture sensing abilities of the APDS-9960. Configures
 APDS-9960 over I2C and waits for gesture events. Calculates the
 direction of the swipe (up, down, left, right) and displays it
 on a serial console.

To perform a NEAR gesture, hold your hand
 far above the sensor and move it close to the senasor (within 2
 inches). Hold your hand there for at least 1 second and move it
 away.

To perform a FAR gesture, hold your hand within 2 inches of the
 sensor for at least 1 second and then move it above (out of
 range) of the sensor.

Hardware Connections:

IMPORTANT: The APDS-9960 can only accept 3.3V!

Arduino Pin APDS-9960 Board Function

3.3V VCC Power
 GND GND Ground
 A4 SDA I2C Data
 A5 SCL I2C Clock
 2 INT Interrupt

Resources:
 Include Wire.h and SparkFun_APDS-9960.h

Developed in Arduino 1.0.5, revised by JJD 1.8.5
 Tested with SparkFun Arduino Pro Mini 3.3V
 ****************************************************************/

#include <Wire.h>
 #include <SparkFun_APDS9960.h>
 //#include <ESP8266WiFi.h>

// Pins
 #define APDS9960_INT 2 // Needs to be an interrupt pin
 #define APDS9960_SDA A4 // I2C Data Must use A for Analog
 #define APDS9960_SCL A5 // I2C Clock Must use A for Analog

// Constants

// Global Variables
 SparkFun_APDS9960 apds = SparkFun_APDS9960();
 int isr_flag = 0;
 const byte interruptPin = 2;
 int LED_PIN = 3;

void setup() {
 Wire.begin(); //Start I2C with pins defined above
 pinMode(APDS9960_INT, INPUT);
 pinMode(LED_PIN,OUTPUT);
 digitalWrite(LED_PIN, LOW);

// Initialize Serial port
 Serial.begin(9600);
 Serial.println();
 Serial.println(F("--------------------------------"));
 Serial.println(F("SparkFun APDS-9960 - GestureTest"));
 Serial.println(F("--------------------------------"));

// Initialize interrupt service routine
 attachInterrupt(0, interruptRoutine, FALLING);
 // attachInterrupt(digitalPinToInterrupt(interruptPin), interruptRoutine, FALLING); // JJD interrupt

// Initialize APDS-9960 (configure I2C and initial values)
 if ( apds.init() ) {
 Serial.println(F("APDS-9960 initialization complete"));
 } else {
 Serial.println(F("Something went wrong during APDS-9960 init!"));
 }

// Start running the APDS-9960 gesture sensor engine
 if ( apds.enableGestureSensor(true) ) {
 Serial.println(F("Gesture sensor is now running"));
 } else {
 Serial.println(F("Something went wrong during gesture sensor init!"));
 }
 }

void loop() {
 //digitalWrite(LED_PIN, LOW);
 if( isr_flag == 1 ) {
 detachInterrupt(0);
 handleGesture();
 isr_flag = 0;
 attachInterrupt(0, interruptRoutine, FALLING);
 }
 }

void interruptRoutine() {
 isr_flag = 1;
 }

void handleGesture() {
 if ( apds.isGestureAvailable() ) {
 switch ( apds.readGesture() ) {
 case DIR_UP:
 //digitalWrite(LED_PIN, HIGH);
 Serial.println("UP");
 break;
 case DIR_DOWN:
 //digitalWrite(LED_PIN, HIGH);
 Serial.println("DOWN");
 break;
 case DIR_LEFT:
 //digitalWrite(LED_PIN, HIGH);
 Serial.println("LEFT");
 break;
 case DIR_RIGHT:
 //digitalWrite(LED_PIN, HIGH);
 Serial.println("RIGHT");
 break;
 case DIR_NEAR:
 //digitalWrite(LED_PIN, HIGH);
 Serial.println("NEAR");
 break;
 case DIR_FAR:
 //digitalWrite(LED_PIN, HIGH);
 Serial.println("FAR");
 break;
 default:
 Serial.println("NONE");
 digitalWrite(LED_PIN, HIGH);
 delay(100);
 digitalWrite(LED_PIN, LOW);
 }
 }
 }