Build Log for March 4th and 5th (3D Model of Camera Mount)


, , , , ,

Customer Check-In

These images were taken at 5 minute intervals.  I tried a new way to mount the camera using…wait……that’s right DUCK TAPE!

OOPS – the duck tape quickly gave way…the camera drops…then the LED turns off.  But it does show most of the plants and what they are up to.  At this point I am not focusing on their health as much as I am on fixing any challenges with the Leaf Spa implementation.  I am fairly happy with the growth of the basil and thyme.  However, I am concerned with the health of the other plants.  I plan to research this after I get the camera mounted the way I want.

Time Lapse

Good better best  This is a late added feature – and it shows.  Challenges:

  • Did not design a mount and explore the best camera angles during the design stage of the Grow Chamber.  At this point, I will make a mount but it will not be ideal.
  • O Snap! does not automatically download the images, make a time-lapse movie, or upload to YouTube.  To do this, I have to remove the camera.
  • O Snap! has an easy way to set a time interval or to shoot during time of day.  I would like to control via when the LED is ON or OFF.  I.e.: if the LED is ON, take the shot.  If not, don’t.

What I love about O Snap! is it gives me a very good feeling for what I want out of taking pictures of plants in the Leaf Spa.  It works well enough for this prototype and I have clear ideas on how I can evolve when/if I decide to right a custom app for an iPhone or Android phone.

My next attempt at mounting the iPhone camera within the Grow Chamber is to create and 3D print a mount. I’ll do what I did with the fan and drill holes in the LED shelf.  

Designing a Mount

I’m going to design a mount for the iPhone I have in Fusion 360.  I will need

  • a Fusion 360 model of the iPhone 4S (model A1387).  
  • Fusion 360 Design 

I’m printing out the three bodies:


I used the iPhone 3D model done by Amit Kumar located at this web link. I decided for this attempt to go with a simple design that includes a camera grip (yellow), wedge (light blue), and fastener (purple).  I’ll glue these together after checking the wedge angle and fastener depth + bolt hole location.

To fasten the camera holder to the leaf shelf, I will draw to holes and feed these bolts through the holes and the holes on the plastic fastener:


 I found these bolts in my husband’s toolbox:


ummm….yah…a pretty big mess… :-).  I am ecstatic to use bolts that have been kicking around.

Note: I find fastening a 3D printed object onto the Leaf Spa to be challenging.  The simplest is to do what I’ve done here – which is to find a bolt with a nut that allows the shelf + plastic to fit the bolt and then be tightened by the nut.  This way, the plastic does not participate in the threading/tightening of bolt-to-nut.  I apologize if my terminology for this stuff is off.  I’m new to building stuff that requires bolts.

The 3d Printed fan mount + CO2 tube holder that is hanging on the other side of the Leaf Spa is fastened by screwing the bolt into holes in the plastic. This is too feeble for long term stability – although working find for now.

Here are other ways I explored to fasten a mount:

  • Heat-set threaded inserts as recommended by MatterHackers on this web post



I’m still printing out the pieces…and well..with 3D printing….it takes longer than I typically expect it should….so..time to practice patience. 

Good better best Supports should be used when printing out the camera grip.


Build Log for March 3rd and 4th (First Run Results and Time Lapse)

Customer Check-in

I’m trying out O Snap! on an old iPhone.

I put the iPhone right on the Grow Chamber’s leaf shelf.  I set the timer to go off once an hour.  Within the O Snap! app I created a .mov and shared it on YouTube.  Not that great, but it’s a start.  I’ll try mounting the iPhone on the LED shelf.

First Run

I imported the log file into the 3/2/2017 sheet of the Test Run Log Files spreadsheet.

The run starts at 12:40:20 3/2/2017 (row 5).  


Expected:  Readings every 2 minutes

Simpson DOH Not As Expected

debug = 0;  
globalSettings.secsBtwnReadings = (debug == 1) ? 60 : 2 * 60; 

Readings were taken every minute.

WhyCat Why?

The firmware’s logic is to use what is stored in the EEPROM unless the writeCheck value changes.

  if (globalSettings.writeCheck != eepromWriteCheck) {

but in resetGlobalSettings(), I am using DEBUG to change global settings values:

void resetGlobalSettings() {
  bool debug = true;
#ifndef DEBUG
  debug = false;
  DEBUG_PRINTLNF("In resetGlobalSettings()");
  globalSettings.writeCheck = eepromWriteCheck;
  globalSettings.secsBtwnReadings = (debug == 1) ? 60 : 2 * 60;  //if in debug mode, make the period between readings short.
  globalSettings.targetCO2Level = 1200;
  globalSettings.amtSecsWaterPumpIsOn = (debug == 1) ? 5 :  60; //amount of seconds for pump to be ON.
  globalSettings.secsBetweenTurningPumpON = (debug == 1) ? 60 :  15 * 60; //# secs between turning pump ON.
  globalSettings.hourToTurnLightOff = 0; //Turn light off at midnight.
  globalSettings.hourToTurnLightOn = 4; //Turn light on at 4AM.
  eeprom_write_block(&globalSettings, (void *)0, sizeof(globalSettings)); //write settings to eeprom

The reason I used EEPROM to store global settings was the earlier thought I would allow the user to change global settings on the fly through a UI (either Internet or buttons).  Right now, I do not allow user input.  I could remove the code to EEPROM, but instead I added:

#ifdef DEBUG
#define eepromWriteCheck 0x1234
#define eepromWriteCheck 0x5678

This way, the write check bytes in EEPROM will change when the definition of DEBUG changes.


Expected: if readings < 1200ppm, add CO2.

ChallengesBringOpportunitesYIPPEE! Worked as Expected

void adjustCO2() {
  if (fLEDon) {
    int CO2Value = takeCO2Reading();
    if (CO2Value > 0 && CO2Value <= 1200) { // -1 is returned if the sensor isn't working correctly.
      //Got a good reading that is below 1200 ppm so turn on the CO2.  It is assume the valve is opened just
      //a little bit. Leave the valve on for less time as the value gets closer to 1200
      int nSecondsValveIsOpen = 0;
      CO2Value < 800 ? nSecondsValveIsOpen = 10 : nSecondsValveIsOpen = 5;
      digitalWrite(CO2Pin, ON);
      Alarm.timerOnce((const unsigned long)nSecondsValveIsOpen, turnCO2Off);
    } else {
      DEBUG_PRINTLNF("The LED is off - no need to adjust");


Expected: LEDs should be off for four hours between 12AM and 3:59:59 AM.

ChallengesBringOpportunitesYIPPEE! Worked as Expected

  • The  LEDs are turned on after the 3 minute warm up at 12:43:20.  
  • The LEDs are turned off at 0:00:00  
  • The LEDs are turned back on at 4:00:00

2nd Run

I deleted the log file from the SD card, put the SD Card back into the Arduino, and uploaded the updated code.  

ChallengesBringOpportunitesYippee!  All Worked as Expected

I decided to adjust the amount of time the CO2 regulator is on to a little higher:

      CO2Value < 800 ? nSecondsValveIsOpen = 13 : nSecondsValveIsOpen = 8 

3rd Run

I let the system run from 12PM to close to 4AM.    I :

  • expect no CO2 to be released between 12AM and 3:59AM.
  • am interested in the temperatures at night.
  • want to fix any other issues shown by the data.

CO2 Off Based on LED ON/OFF

ChallengesBringOpportunites YIPPEE!  As Expected.  No CO2 is released between 12AM and 3:59AM.

Differences in LED ON vs. LED OFF Measurements

I took the average of measurements when the LED was ON and when it was OFF.  Another variable is we turn the heat off at night.  The indoor temperature goes from 21.11˚C during the day to 15.56˚C during the night.  Here are the averages for the 3/3/2017 – 3rd Run:

Lights ON    
Average Temp Avg Humidity Avg CO2
29.88 35.76 1267.16
Lights OFF    
18.76 56.31 313.05

The average measurements are what I expected.  Close to ambient CO2, a higher humidity. The higher humidity makes sense because when the LED is off, respiration should increase relative to transpiration.

Additional Issues

Bug in Adjusting the CO2 Code

Simpson DOHMy code was incorrect in the case the MH-Z16 CO2 sensor couldn’t take a reading (i.e.: returned -1).  I updated the adjustCO2() function to:

void adjustCO2(int CO2Value) {
  if (fLEDon) {
    if (CO2Value < 0) { // The MH-Z16 returns a -1 when it couldn't get a valid reading.
      DEBUG_PRINTLNF("Could not get a valid CO2 reading - no adjustment made");
    if (CO2Value <= 1200) {
      //Got a good reading that is below 1200 ppm so turn on the CO2.  It is assume the valve is opened just
      //a little bit. Leave the valve on for less time as the value gets closer to 1200
      int nSecondsValveIsOpen = 0;
      CO2Value < 800 ? nSecondsValveIsOpen = 13 : nSecondsValveIsOpen = 8;
      digitalWrite(CO2Pin, ON);
      Alarm.timerOnce((const unsigned long)nSecondsValveIsOpen, turnCO2Off);
  }else {
      DEBUG_PRINTLNF("The LED is off - no adjustment made");    


Leak 1

hmmm….looks like there is a small leak:

Pasted Image 3 3 17 10 51 AM

I’m noticing drips coming from a drip irrigation bib.

I fixed this leak by spreading silicone over the hole.  


The challenge is getting the silicone to the hole since at this point the hose is within a tight space on top of the gutters and below the plant’s shelf.

Leak 2

Fixing Leak 1 led me to find leak 2.

Pasted Image 3 4 17 12 51 PM 

Time Lapse

As shown by the 3 frame Youtube video under Customer Check-In, I ran my first test of producing a time lapse movie.

I used an old iPhone I found kicking around our house, loaded O Snap! as well as the WiFi transfer extension pack…although I’m not sure I need the extension pack for what I ultimately ended up doing, which was to upload the time lapse movie to YouTube.

First Attempt – Camera Sitting On Leaf Shelf

I’m trying to figure out the best placement of the camera.  In the first attempt, I placed the camera on the leaf shelf.  This gives a lilliputian’s view but not even close to a best placement.  For my second attempt, I will shorten the time between taking an image to 5 minutes.  For the second attempt, I will mount the camera on the LED shelf.

Well…hmmm…I’m on my third attempt..more on this in another log!  For now, time to go.



Build Log for March 1st and 2nd (Moving Day!)



Customer Check-In



 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

The lettuce and kale are starting to show growth.  The rest seems to be growing well.  Although the leaves look a bit yellow which makes me think they need a stronger nutrient mix.  Pretty soon I’ll be moving them into their new Leaf Spa home.

Sensor Puck

Hmmm…seems I didn’t save the last layout I did in Kicad.  So I redid this and sent the SensorPuck Kicad layout to OSHPark.  It is so easy!  I don’t even have to generate Gerbers.  Just upload the GrowChamberSensorPuck.kicad_pcb file.  This link goes to the specific check-in of the Kicad files that were part of what I am calling the “A” build.  Hopefully I won’t need to go to “Z” before I get the board working….

I’m still waiting for the CCS811 from Digikey.  I got mail about a month ago the shipment should be 2/28…time to check on that.  DRAT…now it is sometime in May.  Hmm…I’ll just wait for now.  I guess all the chips are going into cell phones?

Moving In

ChallengesBringOpportunitesA YIPPEE MOMENT!  I moved the plants into their new home.  I

  • cut clone collars I got awhile back in half and put them around each of the plants.  My intent is to keep light off the rock wool.  The enemy of the Leaf Spa is the algae that grows within the nutrient bath – either within the Coleman reservoir or on or around the rock wool.  
  • put an air pump within the reservoir to increase the amount of oxygen in the bath.  Roots need to breath!
  • updated theLeafSpa.ino to handle #define DEBUG correctly 
  • set up the nutrient bath with Jack’s Hydro feed with an EC of 3mS/cm and pH of 6.1.
…and BOOYAH..moved the plants into their new home with the theLeafSpa.ino firmware doing it’s thing.  I’ll check the log file tomorrow to see how well the measurements and relays are working.

How Do They Look?

I want to enjoy the visual experience of growing plants.   I just recently decided to include a way to take time lapse photos of the plants growing within the Grow Chamber and upload them somewhere (TBD) to make a time lapse movie.  This way I can get a visual on growth as well as challenges shown by viewing the plants.  To do this, I will repurpose an older iPhone we have kicking around the house.  The app I will be using is OSnap!. Things I need to do:

  • Get the old iPhone charged up and running OSnap!.
  • Get an iPhone camera mount and figure out how to attach to the Grow Chamber.  I ordered this one.  I’ll see if it works.

Build Log for February 28th (Test Run)

Customer Check-In


 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

Ooh! Starting to see roots:


Open Source

The Arduino code – TheLeafSpa.ino –  I used for this post is located at this GitHub location.


ChallengesBringOpportunites Yippee!

Logfile Results

The Leaf Spa doesn’t have a UI.  Rather, I log readings and actions onto a file on the SD Card (I went over what I’m doing code wise in this post)  I’m getting expected results when testing the Grow Chamber.  Here is a snapshot of some of the data logged:


Feeding the CSV file into a Google Spreadsheet, here is a partial table:

Row ID Date Time Temp (˚C) Humidity CO2 PPM
51 2/28/2017 9:53:00      
9 2/28/2017 9:53:00      
51 2/28/2017 9:53:20      
9 2/28/2017 9:53:20      
10 2/28/2017 9:56:20      
3 2/28/2017 9:56:20      
0 2/28/2017 9:56:20 22.7 54.7 379
5 2/28/2017 9:56:20      
1 2/28/2017 9:56:20      
2 2/28/2017 9:56:25      
6 2/28/2017 9:56:30      
0 2/28/2017 9:57:20 22.5 54.6 1077
5 2/28/2017 9:57:20      
1 2/28/2017 9:57:20      
6 2/28/2017 9:57:25      
2 2/28/2017 9:57:25      
0 2/28/2017 9:58:20 22.8 54.7 1253

I added the header to the file.

Row ID

The RowID comes from the logRow_t enum in TheLeafSpa.ino 

enum logRow_t {
  SensorData,   //0
  PumpOn,       //1
  PumpOff,      //2
  LEDOn,        //3
  LEDOff,       //4
  CO2On,        //5
  CO2Off,       //6
  CardInserted, //7
  CardRemoved,  //8
  WarmupStart,  //9
  WarmupEnd,     //10
  Settings_V1 = 51 //51 will be the number used to identify the logfile contains sensor readings and actions
                //based on globalSettingsV1_T variables
} ;

back to the rows on the spreadsheet above.   The first two rows point to a start that was quickly abandoned.  This points out the log file appends new entries.  My intent with not deleting an older run is to favor the person who takes the SD Card out to read from a Mac/PC the ability to delete older results.

Starting with the third row, the 51 for the row type points to a row about the version of settings used:

void writeSettingsVersionToLogFile() {
  File logFile = openFile();
  if (!logFile) {
    DEBUG_PRINTLNF("Could not write settings data. Log File could NOT be opened!");
  } else {
    String settingsString = String(20);
    settingsString = String(Settings_V1) + ",";
    settingsString += getDateTimeString() ;
    DEBUG_PRINTF("Settings String: ");

Row ID 9 lets us know The Leaf Spa’s firmware is warming up.  This is to accommodate the three minutes of warmup discussed on the wiki page for the Grove CO2 Sensor.  The time the date/time the firmware starts warming up is 9:53:20 on February 28, 2017.  Row ID = 10 (warmup is finished) has a time stamp of 9:56:20 – three minutes after the start of warm up.

Row ID=3 lets us know the LEDs were turned on immediately after warm up.  The firmware logic:

void turnLightOnOrOff() {
  //light is off between 00:00:00 and 3:59:59
  if ( (hour() >= globalSettings.hourToTurnLightOff) && (hour() < globalSettings.hourToTurnLightOn) ) {
  } else {

uses the settings for the hours the lights should be on or off to determine if the LED should be on or off when the firmware starts up.  This sets up the photoperiod. 

Row ID 0 is a sensor reading.  For now, no action is taken based on the readings for temperature and humidity.  Action is taken based on the CO2 level.  If the CO2 level is below 1200 ppm, the firmware will turn on the CO2 tank’s valve and CO2 will be released into the Grow Chamber.  It is assumed the valve is at a low level.

void adjustCO2() {
  if (fLEDon) {
    int CO2Value = takeCO2Reading();
    if (CO2Value > 0 && CO2Value <= 1200) { // -1 is returned if the sensor isn't working correctly.
      //Got a good reading that is below 1200 ppm so turn on the CO2.  It is assume the valve is opened just
      //a little bit. Leave the valve on for less time as the value gets closer to 1200
      int nSecondsValveIsOpen=0;
      CO2Value < 800 ? nSecondsValveIsOpen=10 : nSecondsValveIsOpen=5;
      digitalWrite(CO2Pin, ON);
      Alarm.timerOnce((const unsigned long)nSecondsValveIsOpen, turnCO2Off);
    } else {
      DEBUG_PRINTLNF("The LED is off - no need to adjust");

Row ID 1 and 2 show when the water pump was turned on and off.  

  globalSettings.amtSecsWaterPumpIsOn = (DEBUG == 1) ? 5 :  60; //amount of seconds for pump to be ON.
  globalSettings.secsBetweenTurningPumpON = (DEBUG == 1) ? 60 :  30 * 60; //# secs between turning pump ON.

The settings vary depending if the firmware is running in debug mode.  This test was run in debug mode.


…so …yah…I’m happy with the results.  It’s almost time to give the plants a new home!

Build Log for February 27th

Customer Check-In


 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

I finally got around to replacing the lettuce and kale.  The two lower stevia plants don’t look very strong.  Hmmm…I’ll watch these two and plant two more.

Thanks To Those That Went Before

Vesta Stoudt – Your story on the invention of duck/duct tape is truly inspirational.  Thank you for your invention.  Thank you for showing us that each of us can make a major impact…we just need to find a challenge we care about and a way to think about what we can do.  YOU ARE INSPIRATIONAL.

When in Doubt, Duck Tape


Well the Grow Chamber has become my much loved yet ugly baby.  Now, replete with duck tape sealing the bottom.  This should stop the CO2 from leaking out when adjusting the CO2 level to ~ 1200ppm.

Next Up – the Reservoir Lid

All is working.  It is almost time for the Leaf Spa’s GRAND OPENING.  Before that, I need to put the lid on the reservoir.  I was overly exuberant drilling holes early on:


The original holes are not located in the right spots.  Also, I need to add a hole for the air pump tube and the water pump power cord.

Here is the new lid with reservoir in place:


Let the Testing Begin!

Interesting…as I added more logging, avrdude kindly pointed this out to me:

avrdude: verifying …
avrdude: verification error, first mismatch at byte 0x7800
0xff != 0x1b
avrdude: verification error; content mismatch

avrdude done. Thank you.

I’m pretty sure what was happening was a depletion of SRAM (Adafruit has a great description of Arduino’s SRAM).  I didn’t spend much time fixing.  Rather, I removed some of the Strings I planned to write.  I also added this function:

int availableMemory() {

    int size = 1024; // Use 2048 with ATmega328

    byte *buf;


    while ((buf = (byte *) malloc(–size)) == NULL)





    return size;

to DebugLib. I needed to add #includesince the availableMemory() function uses Arduino types and constants.


So right now I’m in the middle of testing…more tomorrow.

Build Log for February 26th (Fixing Leaks)

Customer Check-In


 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

Pardon the red light. The Mars Hydro lighting dominated this part of my kitchen on this overcast day.  Plants are growing.  Some not as well as I hoped.  The basil is looking the best.  Got awhile before there are strong enough roots to transplant to the Grow Chamber.  I STILL haven’t replanted lettuce and kale.  I WILL DO THIS TODAY :-).

Fixing Leaks

WhyCat Another skill I do not have enough practice at is dealing with plumbing leaks.  How would a skilled plumber that comes highly recommended by their customers handle these leaks?

I designed the Base so the reservoir can be pumped out by switching the valve and turning the spigot on:

NewImage                             NewImage

My plan is to replace the nutrient bath once a week.  To do this, I wanted to make it as easy as possible to do so.

While emptying the reservoir, I observed leaks:

NewImage          NewImage

Here’s my knowledge evolution on stuff that puts two pieces of PVC together:

  • PVC cement (the purple stuff in the picture) as noted by the Natural Handyman: [PVC Cement] is designed to “weld” two mating pieces of PVC… for example a pipe and a coupling of some kind. It does not bridge gaps like an adhesive, but instead partially softens and dissolves the pipe, making for a permanent connection between the two parts. Once set… usually within a minute… the joint is beyond permanent!
    • I was using PVC cement both for “welding” of two pipes and also as a sealant.  As stated – PVC Cement is not a sealant.
  • PVC sealant.  I’ve tried several silicone varieties.  My latest favorite is this one.
Put PVC cement around end caps that I had not sealed because I wanted to be able to get inside the gutters.  This fixed the leaks shown on the right hand image.  Put sealant around both the end caps for good measure as well as the leak shown in the left hand image.  This fixed the leak.  I detected one small leak around an end cap where I’ll apply more sealant:
That’s it for leaks – at least for now :-). 


Build Log for February 25th (Update on Relay Box)


, , , , ,

Customer Check-In


 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

Still haven’t planted the lettuce or kale.  The cubes are getting a small amount of algae as the nutrient mix I put on them gets exposed to the stronger light.  This is not uncommon.  I’m ignoring the algae for now because at this level it does not (caveat: I’m no expert) choke off the plants from getting their food (AKA nutrients – I like thinking of the plants as getting a wonderful meal carefully crafted….).

Thanks to Those That Went Before

Home Depot – For having an employee like Ken.  Ken deserves a moment of respect and grateful appreciation from customers (like me) who he has helped.  When I go to Home Depot’s electronics aisle, I am relieved when I see Ken (he isn’t there every time I go). Ken has MEGA years electronics experience and is the type of person who listens to what I am trying to do then suggest Home Depot products that best meet the need at the lowest price.  Ken has an awesome background story about why he is working at Home Depot.  Ken smiles and is always kind.  Take THAT machine learning replacements that don’t need to concern themselves with providing a home for their families (ah, but I diverge…although from talking to other home depot employees, unfortunately they cannot afford housing in our neighborhood even with a $15 minimum wage…is there an app for that?  An app that gets these folks a life where “…the pursuit of happiness” is integrated into their pay so they can afford housing?).  THANK YOU KEN.  I did the minimal I can do – I sent a comment from the Home Depot web site letting them know I shop at Home Depot instead of Lowes because of you.

Here is the email I got back from Home Depot:


Thank you for contacting The Home Depot and sharing your wonderful experience with Ken!

Outstanding Customer Service is a cornerstone of The Home Depot and we are so excited to hear first-hand how much this means to our customers.

I have created Customer Care Case #05359597 with all the information that you have provided. This will be shared with the store leadership so that they may share in our celebration of this great news!

Thank you for taking the time out of your busy day to reach out to us, and thank you for being a customer of The Home Depot!


Team Customer Care

The Home Depot Email Response Team


SparkX – for publishing the schematic and layout of their CCS811 breakout board (GitHub location).  It is not just a copy and paste exercise for me.  I learned from the techniques used both in building the schematic as well as the layout. 

Levitron – for providing a video on installing the wires of a wall socket (receptacle). The video can be found on this Home Depot page. The tip about inserting the cane of the wire clockwise into the screw makes a lot of sense…but I didn’t think to do this before watching the video.

The Relay Box

Simpson DOHDOH – I didn’t understand how to wire the AC side of the Relay Box – specifically, I (and this is dumb, I know) thought each wall socket would connect to a different relay.  Meaning I could use a 2-gang setup as I noted in this post.  Um…no…each wall socket goes to one relay. Um..yah…duh…so I redid the wiring and replaced the 2-gang box with a 3-gang box and face plate:


(Update 2/28/2017)

WhyCat When I went to the the circuit design above, I first tried to remove the metal tabs but was unable to.As I bumbled around, I found this Electrical 101 post on split receptacles.  


OOh – Now I know what I have been calling a wall socket is most referred to as a receptacle in the world of the electrician.  Knowing this really helped Google searches on this stuff :-).

Good better best I’ll try this split (duplex) receptacle from Home Depot the next time I build a multi receptacle relay box.


The color coding refers to the Arduino wire colors.

ChallengesBringOpportunitesYIPPEE! The good news is all tests – water pump, CO2 adjustment, LED lights on/off – worked.  I tested theLeafSpa Arduino code for turning the water pump and LED on/off.  I wanted to better understand the settings for adjusting the CO2.  So I ran a separate CO2 adjustment test.  One thing I learned was my current design for the Grow Chamber cover leaks more CO2 than it probably should.  It is not a lot, but will mean more CO2 will be released than needed.  My next step will be to duck tape down the cover.  However, I want to see about putting the panels back on the Base before I do that.

Wire Gauge

WhyCatHMMMM… One (of the many things 🙂 ) thing I lacked knowledge of was outlet wiring.  Wiring AC demands a higher respect than wiring up a prototype using an Arduino.  Taking a step back, these are my AC relay wiring notes to myself:

  • use the rule of thumb I received from hansmoman when I posted a question about wiring to the /r/AskElectronics subreddit:
House wiring is 14 gauge for 15 amp circuits, 12 gauge for 20 amp. If you are making a “general purpose” switched outlet I would avoid the 18 gauge for safety reasons since it could potentially be overloaded. Stranded or solid makes no difference electrically in this application. Solid may be easier since stranded wires can fray when you try to connect them to the screw terminals. Be sure to use an appropriately rated relay for 15+ amps as well.Keep in mind if you install this in the wall it will be against code and if your house burns down the insurance will not cover it.

This is the advice I used for this build of the relay box.  Umm…look how stiff the 14 AWG wire is:
it was difficult to fit all the wiring and bend to the screws on the wall sockets.
  • But then – when I look at LED wiring, the AWG gauge is the smaller 18 AWG gauge.  So I will end up using this rule of thumb:
Figure out the maximum current draw and using wiring that can conservatively handle the amount of current.

But how much current does each of these (LED lights, water pump, CO2 regulator) draw?

How Much Current?

I’m going to explore using my trusty Kill A WATT meter.  

Measuring the current using the Kill A Watt meter,


I created this spreadsheet (google docs link – go to the Amps needed sheet):

Power Sink Amps Appliance
water pump 0.1 Active Aqua Submersible Water Pump, 160 GPH
CO2 solenoid 0.04 ProLabs CO2 Regulator w/ Solenoid Valve
LEDs 0.85 The Leaf Spa BoM

 Let’s say they are all on at the same time.  The total current = 0.1 + 0.04  +0.85 = .99A.  1A.  Clearly, these appliances don’t draw what an appliance in a house – like a toaster, microwave, or tea kettle – might gobble up.  Looking up the amount of current load the different gauged wires can handle, for future builds I will use an 18 AWG wire like this one.

Sensor Puck Layout

Moving over to the Sensor puck…

As I was doing the layout, I really liked the jumper done for determining which I2C address in SparkX’s layout (GitHub location)  to use:

Here is the layout as I currently have it:


The outline is 1” x 1”.

The next step is to print out the front layer layout.  I do this through the print (not plot) option:


which creates this:


The next step is to print out this page and map the actual parts to the pads.  This will check whether the footprints I am using (particularly for the CCS811 and Si7006) are correct.


And that is it for today.



Build Log for February 23rd


Customer Check-In


 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

The plants like the new lighting.  As more mature leaves (past the cotyledon) started to appear, I started feeding them the leafy plant nutrients I discussed in this blog post at a strength of ~ 1/10 the EC value of basil (using info on my First Grow spreadsheet).  I haven’t added back the lettuce and kale plants I managed to destroy.

Growth Sensor Puck


Updated Schematic and BoM

I took SparkX’s CCS8 Eagle Schematic/Layout (GitHub location) to a Kicad evolution of the Growth Sensor Puck schematic (GitHub location).  The “big” difference is the inclusion of the Si7006.  I ran makedigikeyBOM (ooh – it worked AND I found a “bug” in the jellybean parts file!):

Reference Value Quantity Manf Part # Digikey Part # 1 10 100 1000 Qty Avail Link
R4,R5 100K 2 ERJ-6GEYJ104V P100KACT-ND 0.1 0.025 0.01 0.00451 523146
U1 Si7006 1 SI7006-A20-IM 336-3124-ND 2.08 2.08 1.7372 1.56551 2158
R7 10K 1 C0805JR-0710KL 311-10KARCT-ND 0.1 0.016 0.0066 0.00297 2775278
C2 1u 1 TMK212BJ105KG-T 587-1291-1-ND 0.16 0.115 0.0541 0.03139 231010
C1 .1u 1 CL21F104ZBCNNNC 1276-1007-1-ND 0.1 0.029 0.0128 0.00718 1016710
U2 CCS811 1 CCS811CT-ND CCS811CT-ND 12.76 10.073 7.1632 7.1632
R1,R2,R3 4K7 3 RC0805FR-074K7L 311-4.70KCRCT-ND 0.1 0.019 0.0077 0.00345 2362052

Looking through my box-o-parts (I standardize on 0805 when possible):


Besides the CCS811 and Si7006, I do not have 4K7 resistors.  I added these to my current Digikey backorder for the CCS811 and the Si7006.

PCB Layout

A challenge I have with Kicad is finding footprints when I am in cvpcb.  One example is the footprint for the optional 10k thermistor that has a through hole footprint.  I was challenged to find a tht resistor footprint that had a 2.54mm spacing.


the image is from this data sheet.  So I made my own.  Simple to do but I can’t help thinking I’m wasting my time since these footprints probably exist.


and…yah…i think i wasted my time making the layout (even if it was simple…I certainly am not getting younger 🙂 )…further bumbling within cvpcb lead me to the Socket_Strips library.  Where I associated the optional thermistor with the 1 x 02 straight socket strip with a 2.54 mm pitch.



Design Rules

It would be a D’OH moment if the board was turned back from OSHPark because I did not adhere to their design rules.  It’s been awhile since I sent a PCB to OSHPark so I went back to check OSHPark’s design rules:

  • 6 mil minimum trace width
  • 6 mil minimum spacing
  • at least 15 mil clearances from traces to the edge of the board
  • 13 mil minimum drill size
  • 7 mil minimum annular ring

I discussed what the design rules refer to (e.g.: the term “annular ring” was not a term I was familiar with) in this post.

Based on what I used in the post, here are the design rules I am using for tracks and vias:


That’s as far as I got today…excited to see what I can do tomorrow. 

Build Log for February 21st

Customer Check-In 


 plant key:

genovese basil parsley sweet basil stevia stevia lettuce
genovese basil thyme sweet basil stevia stevia kale

Frustrated Sadly, the lettuce and kale got way to stringy with the previous light I used.  Lesson learned: don’t buy cheap LED desk lamps at Home Depot and use on seedlings.  A PAR ~ 70 is not enough.

I had a Mars Hydro I got awhile back that I’m not using.  


The PAR ranged from ~230 on the edges of the heat mat to ~290 at the center.  Now the seedlings should have enough (PAR) light.


I can’t believe I almost forgot about the PyCom WiPy 2.0 and the expansion board I got from Adafruit last week.  Time to give them a twirl.  The PyCom website is here.  I start with the Pycom documentation.  The first thing I need to do is put headers onto the PyCom so I can fit it in the expansion board.

My goal with paying top $$ for the PyCom through Adafruit included:

  • Supporting Adafruit.  I have received a lot of learning and support love.  From all I can tell, Adafruit treats their employees well – caring more about people than how much can be acquired before we die.
  • Evolving my understanding of micro python based ESP8266 environments on the best made and supported environment (both hardware, IDE, and support).


The PyCom hardware has made a great start at providing an excellent micro python experience.  Yet, there appears to be many areas that I would hope evolve.  I’ve been on projects at this state before and wonder if it is for the same reason: 1) a little bit of “throw something out there before it is polished” to better guide direction based on customer feedback 2) engineers dominate the user experience 3) list of features/testing is more demanding than scheduling truly allows for (taking in the number of folks working on it as well as the Mythical Man Month).  The one I had the hardest time with regards to customer experience was addressing #2.  My take on the reason is an engineer sees delight in figuring out details.  Others might not be as delighted by this but more delighted by saving time and getting to blinking a light or whatever.  Both are valid. This is another thing I love about Adafruit, their leadership executes within the latter camp.  There is empathy for non-engineers – folks like me – the liberal arts crowd…

Challenge with Firmware Upgrade

I went through the firmware upgrade steps and got this dialog:


Homer aargh Failure! is the message?  Yah – no sh*&*&*&*&t. :-).  I…but wait a minute, a little later the documentation states:


Pymakr IDE

Next I installed the Pymakr IDE as recommended by the Getting Started documentation.  Oh my.  Their own IDE?  And here I had a problem with their install experience while they have time to create their own IDE?  What about all the extensible IDEs – like Exclipse, Atom…  Do they really have time to accommodate all the different OSs (e.g.: Mac, Ubuntu, Windows) and the various releases?  All the hardware and software configurations??? WHOA…I was relieved to read in the PyCom forum they are moving away from providing an IDE and moving towards plug-ins.  I’m not knowledgable enough about what this means to my use of PyDev within Eclipse.  I’ll figure this out at some point.


After several reboots and deciding to use the USB over serial, I’m using Pymakr.  I’m able to get commands to execute at the >>> real prompt.

Strange though, for awhile I couldn’t find the board even though I was able to get a connection to Pymakr yesterday.  Of all the gobbly gook things I tried, rebooting (over and over) eventually seemed to work.  I’m currently using Pymakr over USB.

Sensor Puck Layout

On to the sensor puck layout….hold up…Hold up…I just found an offering from SparkX of a CCS811 BoB.  But…sadly, I will not be able to get any…I called Sparkfun support and was told they know of no plans for restocking…. however, the schematic and layout are open source (GitHub location).

I was going to stop working on the Sensor Puck and just use SparkX’s offering.  However, difficulty getting them made me reconsider.  I will evolve the schematic and layout to SparkX’s since Nate has a lot more experience than I do in building PCBs.

That’s it for today.

Update to MakeDigikeyBoM

What MakeDigikeyBoM is

MakeDigikeyBom (GitHub location)  takes the components that are part of a PCB schematic made in Kicad’s eeSchema and creates a CSV file that has the digikey part number information for quantities where the minimum order is 1.  This CSV file can then be loaded into an app like Google spreadsheets.  Here is a the Google spreadsheet that originated from the GrowChamberSensorPuck project (GitHub location):

Reference Value Quantity Manf Part # Digikey Part # 1 10 100 1000 Qty Avail Link
C2 4.7u 1 LMK212BJ475KD-T 587-1297-1-ND 0.18 0.128 0.0602 0.03497 216464
R7 100K 1 ERJ-6GEYJ104V P100KACT-ND 0.1 0.025 0.01 0.00451 547481
U1 Si7006 1 SI7006-A20-IM 336-3124-ND 2.08 2.08 1.7372 1.56551 2199
R5,R6 4K7 2 RC0805FR-07100KL 311-100KCRCT-ND 0.1 0.019 0.0077 0.00345 6051592
R4,R1,R2,R3 10K 4 C0805JR-0710KL 311-10KARCT-ND 0.1 0.016 0.0066 0.00297 2786699
C1 .1u 1 CL21F104ZBCNNNC 1276-1007-1-ND 0.1 0.029 0.0128 0.00718 1026228
U2 CCS811 1 CCS811CT-ND CCS811CT-ND 15.5 12.65 9.8038 9.8038
R8 NTC100K 1 NTCS0805E3104FXT BC2562CT-ND 1.1 0.86 0.5823 0.43669 17108

I use the Eclipse/PyDev IDE exclusively to run  Yah…This is ugly compared with running python from the command line.  I do this because my skills in python are at an advanced beginer’s level (at best 🙂 ).  I take advantage of the extensive features such as debugging, setting up input, adding tasks… this IDE offers. 

When it comes to Python, I’m just not ready to take my floaties off.

Steps to Get to the BoM CSV

  • Get the Jellybean parts csv file ready.  The Jellybean parts contains categories of parts (like R for resistors, C for capacitors….) that are referenced within a component’s PN in eeSchema (see the example under the next step where the R5 component’s PN=R).  I start with this jellybean parts file.  I download  this jellybean parts file as a CSV file as a start.  I then renamed it JBParts.csv (just a simple name)…More jellybean parts can be added (or removed).
  • Run bom2csv (discussed here) to create the XML file.  The XML file will have the filename of the Kicad project.  For example, the Kicad project I used was GrowChamberSensorPuck (GitHub location).  This means the bom2csv’s output XML filename will be GrowChamberSensorPuck.xml.  The created file contains an XML tree for each component.  The important fields are the ref, value, and PN fields.  These must be filled for each component in eeSchema.  The images below point out part numbers can be either Jellybean parts, manufacturer part numbers, or X (for exclude this component from the BoM).
Example Component Property Dialog Box
Example Output: Jellybean Part
In the case of this component, it is a jellybean part.  (“PN”<R>). 
Example Output: Specific Component
This example has a specific manufacturer’s part number.
Example Output: Exclude Component
By saying the name of the part number is X, this component is excluded from the BoM.
  • Set the variables up within the Eclipse/PyDev environment.  As I noted in this post, there are three important user inputs:
    • The full name of the bom2csv file.  In my current example, the full name I will use:


    • The full name to the jellybean parts file.  I will use:  /Users/margaret/Documents/LettuceBuddyHW/LadyBugHydro/TheHerbSpa/GitHub/Kicad/JBParts.csv
    • The file folder where the MadeDigikeyBOM.csv will be written. I will use: /Users/margaret/Documents/LettuceBuddyHW/LadyBugHydro/TheHerbSpa/GitHub/Kicad/

To set the variables up, I’ll go into the debug/run configurations within the Eclipse/PyDev IDE:

Pasted Image 2 20 17 5 38 AM



Then I run MakeDigikeyBOM from within Eclipse.  This creates the MadeDigikeyBOM.csv which I then import into a Google spreadsheet.


Well…MakeDigikeyBOM works for now… As I continue to use this BoM creation tool, I am sure I’ll come back to evolving the code and documentation.  For now, if you are interested, look at the code at this GitHub location.  I tried to document the code with ample information to know the intent of each section.