Darian Johnson
Published © CC BY-NC

Compost Professor DIY Hardware (Alexa Version)

This is an easy do it yourself version of the Compost Professor that integrates with Alexa.

IntermediateFull instructions provided16 hours1,158
Compost Professor DIY Hardware (Alexa Version)

Things used in this project

Hardware components

Thermistor
I used a thermistor I got off Amazon, but any epoxy coated resistor will work. You'll just need to know the resistance and the Beta Coefficient. If you're ordering from Adafruit, then you can just get part 372. (Note - you'll need a larger hole in the probe if you use this version)
×1
DFRobot Capacitive Moisture Sensor
×1
adadfruit Adafruit Feather M0 WiFi - ATSAMD21 + ATWINC1500
The attached code works with the custom featherwing, however, the ESP32 should work as well. You'll need to write your own code, but the footprint will work. ESP32 is about $15 cheaper.
×1
Texas Instruments TPL5111 (low power timer)
×1
Custom fabricated PCB
OSH Park Custom fabricated PCB
I used OshPark for my boards, but you can use any PCB shop... or make it yourself
×1
Assorted resistors
×1
5 pin weatherproof connector
Needed if you plan to use the 3D printer version (listed below in options)
×1
3D Printed components or tupperware container
×1
Lipo battery
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Hot glue gun (generic)
Hot glue gun (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

3D components for Compost Professor

You'll need this printed in ASA for actual long term use in compost.

Screws for 5 pin connector

You'll need two. You'll also need rubber O rings. I suggest you print at 107-109% scale.

Schematics

Board for Feathering

I used Oshpark to print.

Schematic for Featherwing

Modified from the schematic of the Adafruit Proto Featherwing

Code

Compost Professor DIY Code

Arduino
/***************************************************
  Compost Professor DIY Version

  Created 2018-09-06
  http://compostprofessor.com

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


#include <SPI.h>
#include <WiFi101.h>
#include <WiFiMDNSResponder.h>
#include <ArduinoHttpClient.h>
#include <NTC_Thermistor.h>
#include <ArduinoJson.h>
#include "settings.h"


const int ledPin = 6; // LED pin for connectivity status indicator

char mdnsName[] = "wifi101";

WiFiServer server(80);
// Create a MDNS responder to listen and respond to MDNS name requests.
WiFiMDNSResponder mdnsResponder;

char serverAddress[] = "api.compostprofessor.com";
int port = 443;

//WiFiClient wifi;
WiFiSSLClient wifi;
HttpClient client = HttpClient(wifi, serverAddress, port);
int status = WL_IDLE_STATUS;
String response;
int statusCode = 0;

//Define inputs and outputs
const int moisturePowerPin = 12;
const int moisturePin = A0;
const int thermistorPin = A1;
const int photoTransistorPin = A2;
const int redPin = 5; //RGB ~3.3V ; 20ma
const int greenPin = 10;
const int bluePin = 11;
const int donePin = A5; //6;

volatile int rVal = 0; //RGB ~3.3V ; 20ma
volatile int gVal = 0;
volatile int bVal = 0;

volatile boolean resetWifi = false;


//Settings for Measurements
const int numSamples = 5;
int sampleDelay = 10; //in Milliseconds

//Thermistor settings
uint16_t samples[numSamples];
int seriesResistor = 10000;
int thermistorNominal = 10000;
int temperatureNominal = 25; //degrees Celcius
int bCoef = 3435; //: Beta coefficient (or constant) of the thermistor (will be documented with the thermistor, typically 3380, 3435, or 3950)
NTC_Thermistor* thermistor = NULL;

//Moisture settings
const int AirValue = 520;
const int WaterValue = 260;


//Photoresistor settings


//Values To Send Via API; values are -1 unless a measurement is made
float batteryValue = -1;
int moistureValue = -1;
int lightValue = - 1;
float temperature = - 1;

void setup() {
  delay(5000);
  Serial.begin(19200);

  //Initialize Pins
  pinMode(vBattPin, INPUT);
  pinMode(moisturePin, INPUT);
  pinMode(moisturePowerPin, OUTPUT);
  //pinMode(photoTransistorPin, INPUT);
  pinMode(thermistorPin, INPUT);
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(donePin, OUTPUT);

  digitalWrite(donePin, LOW);

  //Set-up Thermistor
  thermistor = new NTC_Thermistor(
    thermistorPin,
    seriesResistor,
    thermistorNominal,
    temperatureNominal,
    bCoef,
    numSamples,
    sampleDelay
  );


  //Set-up Wifi Chip
  WiFi.setPins(8, 7, 4, 2);

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    //Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }



  // configure the LED pin for output mode
  pinMode(ledPin, OUTPUT);

  // Start in provisioning mode:
  //  1) This will try to connect to a previously associated access point.
  //  2) If this fails, an access point named "wifi101-XXXX" will be created, where XXXX
  //     is the last 4 digits of the boards MAC address. Once you are connected to the access point,
  //     you can configure an SSID and password by visiting http://wifi101/
  WiFi.beginProvision();

  while (WiFi.status() != WL_CONNECTED) {
    // wait while not connected

    // blink the led to show an unconnected status
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
    delay(500);
  }

  // connected, make the LED stay on
  digitalWrite(ledPin, HIGH);

  server.begin();

  // Setup the MDNS responder to listen to the configured name.
  // NOTE: You _must_ call this _after_ connecting to the WiFi network and
  // being assigned an IP address.
  if (!mdnsResponder.begin(mdnsName)) {
    //Serial.println("Failed to start MDNS responder!");
    while (1);
  }



  String values = "volume=" + String(volume) + "&enclosure=" + String(enclosure) + "&battery=" + String(getBattery()) +
                  "&batteryNominal=" + String(batteryNominal) + "&sunLight=" + String(getLight()) + "&compostMoist=" + String(getMoisture()) + "&zipCode=" + String(zipcode) + "&compostTemp=" + String(getThermreading());

  client.beginRequest();
  client.post("/CompostProfessorDIY_Analyze?" + values);
  client.sendHeader("X-Api-Key", apikey);
  client.endRequest();

  // read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();
  delay(3000);

}



void loop() {

  digitalWrite(donePin, HIGH);
  delay(100);

}


// Should be called in the loop function and it will take care if connecting.
void printWiFiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}


//Interrupts

void resetWifiFunc() {
  resetWifi = true;
};

float getThermreading(void) {
  const double fahrenheit = thermistor->readFahrenheit();
  //Serial.print("Temperature: ");
  // Serial.println(String(fahrenheit) + " F");

  return fahrenheit;

}

int getMoisture(void)
{

  digitalWrite(moisturePowerPin, HIGH);
  delay(sampleDelay);

  int intervals = (AirValue - WaterValue) / 3;
  int soilMoistureValue = 0;

  for (int i = 0; i < numSamples; i++) {

    soilMoistureValue = soilMoistureValue + analogRead(moisturePin);
    delay(sampleDelay);
  }

  soilMoistureValue = soilMoistureValue / numSamples;

  //Serial.println("Moisture volt");
  //Serial.println(soilMoistureValue);

  int calcSensorValue = 0;

  if (soilMoistureValue < WaterValue) {
    //Serial.println("Puddle");
    calcSensorValue = 100;
  }
  else if (soilMoistureValue > WaterValue && soilMoistureValue < (WaterValue + intervals))
  {
    //Serial.println("Very Wet");
    calcSensorValue = 70;
  }
  else if (soilMoistureValue > (WaterValue + intervals) && soilMoistureValue < (AirValue - intervals))
  {
    //Serial.println("Wet");
    calcSensorValue = 50;
  }
  else if (soilMoistureValue < AirValue && soilMoistureValue > (AirValue - intervals))
  {
    //Serial.println("Dry");
    calcSensorValue = 30;
  }
  else {
    //Serial.println("Bone Dry");
    calcSensorValue = 0;
  }

  //Serial.print("Moisture is: ");
  //Serial.println(calcSensorValue);
  digitalWrite(moisturePowerPin, LOW);

  return calcSensorValue;

}

float getBattery(void)
{
  float measuredvbat = analogRead(vBattPin);
  measuredvbat *= 2;    // we divided by 2, so multiply back
  measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
  measuredvbat /= 1024; // convert to voltage
  //Serial.print("VBat: " ); Serial.println(measuredvbat);
  return measuredvbat;
}

float getLight(void) {


  float photocellReading = analogRead(photoTransistorPin);
  float photocellVoltage = 3.3 * (10000 / (10000 + photocellReading));

  //Serial.print("Analog reading = ");
  //Serial.println(photocellReading);     // the raw analog reading

  //Serial.print("Photocell voltage = ");
  //Serial.println(photocellVoltage);     // the raw analog reading

  return photocellVoltage;

}

Settings code

Arduino
const char apikey[] = "APIKEY";
const int vBattPin = A7; //Cortex M0 Feather - this is the #9 GPIO pin
const char zipcode[] = "5digitzipcode";
//const int vBattPin = A13; //ESP32 Feather

//Compost Unit Specifications
const char enclosure[]= "open"; //open if the compost unit is open to elements, enclosed if the unit is enclosed (e.g. a tumbler)
const float batteryNominal = 3.7;

//use these units if the compost is a square/rectange bin
const int unitHeight = 36; //(units in inches)
const int unitWidth = 36; //(units in inches)
const int unitLenght = 36; //(units in inches)

const int volume = unitHeight*unitLenght*unitWidth;

//use these units if the compost is in a cylinder container
//const int unitHeight = 36; //(units in inches)
//const int unitRaduis = 36; //(units in inches)
//const int volume = (3.14*unitRaduis^2)*unitHeight

Credits

Darian Johnson

Darian Johnson

8 projects • 139 followers
Technologist. Music lover. Fitness enthusiast. Movie buff. Fan of sci-fi and comic books.

Comments