Henmulator

From RAWiki
Revision as of 17:45, 18 December 2016 by Ahoussney (Talk | contribs) (Code)

Jump to: navigation, search
Jacob Springs and Agronimo's prototype Henmulator arduino controlled incubator


The Henmulator (hen emulator) is Agronimo and Jacob Springs Farm's incubator for Jacob Springs poultry programs. It was the inaugural project to incorporate open source hardware and software into useful farm devices.

Earlier versions

Mike Soltys' engineering class at the University of Colorado created the first version of the henmulator - found here. It was a plywood box with an arduino system controlling temperature and turning off the egg turner after 18 days of incubation. The project was never entirely working but it was an important step in developing the henmulator.

Enclosure

drawing of freezer that became the henmulator

The henmulator enclosure is an old upright freezer that stopped working a few months before the henmulator project began. It's internal volume is around 16 cubic feet (450 li) It was modified by removing the built-in shelves, cutting a window and vents into the door and re-trimming the interior of the door, painting the door yellow and adding draw latches. The latches were added because the door failed to seal after it was modified. Andre recommends not removing the magnetic seal of freezers while modifying them because it's difficult to reinstall them exactly flat making a good seal difficult. (This particular freezer door, however, had prior issues with the seal being fully shut anyway.)

Working parts

Temperature controls

The henmulator heater is a bank of 5 light bulbs in a fixture that was salvaged from a dumpster in a demolition site. It was re-wired so that two sets of two bulbs function in series. Equipped with 100 watt incandescent bulbs the total wattage is 300 watts since four bulbs (the ones in series) are operating at half power and one at full power. If any one of the bulbs burns out the wattage is reduced to 200 watts and if any two burn out the wattage will be 100 watts. See also incubation#bulbs in series

Air circulation

lower, outlet fan blows air over the heating elements and the humidifier package

Two 110v fans salvaged from microwave ovens circulate the air in the Henmulator, on at each end of a duct that pulls air from the (inside) top of the enclosure and pushes it out at the bottom across the heating element. Andre estimates that one fan would probably suffice.

Humidity controls

The Henmulator as originally built was equipped with a home humidifier purchased at a thrift store that was controlled by the arduino via a relay. Plans are in process to replace this with a USB powered floating humidifier purchased online for less than $10, the advantage of this is that it makes the relay unneeded, although there are concerns about longevity.

Rotation

overlapping gears reduce the rotation of the microwave motor. The gears were laser cut using 1/4" clear acrylic.
Rotation on the henmulator is handled by a gear system that is driven by a 2.5 RPM AC motor, pulled from an old microwave oven. By overlapping to sets of gears with a ratio 6:1, the rotation is slowed to approximately 4 rotations per hour.

Electrical wiring

The Henmulator essentially has two sets of wiring: the 5V DC microcontroller circuit, which reads data from the sensor and controls the temperature and humidity relays; and the fan and gear circuit, which run off a separate plug connected to 120V AC wall power. Most of the wiring was run through existing conduits in the freezer housing.

Control system

A block diagram schematic of the henmulator control system wiring.
The original control system used an arduino pro mini with a HTU21D humidity and temperature sensor and two relays.

In fall 2016, Andre rebuilt the control system using a Photon by Particle. This time the humidity and temperature sensor is a AM2302

One relay controls a group of 5 incandescent light bulbs (for temperature) and the other controls the humidifier.

Henmulator bb.jpg

Code

The code to run the Henmulator is relatively simple- temperature and humidity thresholds are defined within the code, then the relays are activated when the readings are below the threshold. The original code can be found here.

Code needs to be modified to add the following features:

  • Error Alerts: Push notifications to a smartphone app under the following conditions:
    • If there are no recent temp/humidity readings i.e. the sensor is disconnected or broken
    • If readings are significantly outside of the parameters or for too long i.e. the humidifier is out of water or the bulbs are burnt out
    • App should be able to tell if entire system is not responding as in a power failure
  • Next level stuff:
    • Build app to display current readings
      • temp
      • humidity
      • relay states
    • Build app to switch between programs:
      • General poultry
      • Waterfowl and other (see incubation
      • Cheese programs
      • Salami programs
    • Alert when a batch reaches a milestone (such as a hatching is imminent or a cheese needs to be turned or a salami is reader for mold inoculation)

The updated code is here:




// Henmulator Code version 2.3
// This #include statement was automatically added by the Particle IDE.
#include "PietteTech_DHT/PietteTech_DHT.h"

// DHT parameters
#define DHTTYPE  AM2302              // Sensor type DHT11/21/22/AM2301/AM2302
#define DHTPIN   D5                  // Digital pin for communications
#define DHT_SAMPLE_INTERVAL   2000   // Sample every two seconds

// Variables
float temperature;
int humidity;
int blue = D7;
int heater = D1;
int humidifier = D2;
int onTempSet = 50;           //lowest allowable temp in degraas F
int offTempSet = 55;          //highest allowable temp
int onHumidSet = 70;          //how much swing is acceptable?
int offHumidSet = 75;         //(greater tolerance saves the relays)
bool humidifierState;
bool heaterState;

// Declaration
void dht_wrapper();

// Lib Initialize
PietteTech_DHT DHT(DHTPIN, DHTTYPE, dht_wrapper);

// globals
unsigned int DHTnextSampleTime; // Next time we want to start sample
bool bDHTstarted;	            // flag to indicate we started acquisition
int n;                          // counter

void setup() {
    pinMode(blue, OUTPUT);
    pinMode(heater, OUTPUT);
    pinMode(humidifier, OUTPUT);
    DHTnextSampleTime = 0;
    
    //start with everything off
    digitalWrite(heater, LOW); 
    heaterState = false;
    digitalWrite(humidifier, LOW);
    humidifierState = false;
    
}

void dht_wrapper() {
    DHT.isrCallback();
}

const char *onOrOff(bool value) {
    return value ? "ON" : "OFF";
}

void loop()
{
  // Check if we need to start the next sample
  if (millis() > DHTnextSampleTime) {
	if (!bDHTstarted) {		// start the sample
	    DHT.acquire();
	    bDHTstarted = true;
	}

    if (!DHT.acquiring()) {		// has sample completed?

    // get DHT status
    int result = DHT.getStatus();
    int humidity = DHT.getHumidity();
    float tempf = DHT.getFahrenheit();
//    int tempc = DHT.getCelsius();
//    int tempk = DHT.getKelvin();
//    int dp = DHT.getDewPoint();
//    int dpslow = DHT.getDewPointSlow();

    //Turn the built in LED on to indicate publishing
    digitalWrite(blue, HIGH);

    //* Publish readings - uncomment/comment the values you'd like to publish

    Particle.publish("Humidity", String(humidity) + "%");
    Particle.publish("Temperature", String(tempf) + " °F");
    //Particle.publish("Temperature", String(tempc) + " °C");
    //Particle.publish("Temperature", String(tempk) + " °K");
    //Particle.publish("Dew Point", String(dp) + " %");
    //Particle.publish("Dew Point", String(dpslow) + " %");

    //Turn the built in LED off indicate publishing finished
    delay(250);
    digitalWrite(blue, LOW);

    n++;  // increment counter
    bDHTstarted = false;  // reset the sample flag so we can take another
    DHTnextSampleTime = millis() + DHT_SAMPLE_INTERVAL;  // set the time for next sample
    
    if (tempf < onTempSet) {
        digitalWrite(heater, LOW);  //the relays I used are triggerd by a LOW voltage
        heaterState = true;
    }
    
    if (tempf > offTempSet) {
        digitalWrite(heater, HIGH);
        heaterState = false;
    }
    
    if (humidity < onHumidSet) {
        digitalWrite(humidifier, LOW);
        humidifierState = true;
    } 
    
    if (humidity > offHumidSet) {
        digitalWrite(humidifier, HIGH);
        humidifierState = false;
    }
    
    Particle.publish("Relays", "Heater " + String(onOrOff(heaterState)) + ", Humidfier " + String(onOrOff(humidifierState)));
}
}
}