Hackster is hosting Hackster Holidays, Ep. 5: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Friday!Stream Hackster Holidays, Ep. 5 on Friday!
Chris-topher Slater
Published © CC BY-NC-SA

"Brew Home" Hydrometer

Designing a "Brew Home" distributed brewing system.

IntermediateWork in progress2 hours19,684
"Brew Home" Hydrometer

Things used in this project

Hardware components

ESP8266 ESP-01
Espressif ESP8266 ESP-01
×1
GY-521 MPU-6050 3 Axis Gyroscope + Accelerometer Module For Arduino
This project is flexible enough to use with any I2C accelerometer with integrated temperature probe.
×1
PreForms
I used a spent WhiteLabs Yeast container.
×1
LIPO 14500 battery
×1

Software apps and online services

Node-RED
Node-RED
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

Battery clip and stand for ESP&MPU

I used pink ABS. I had to fiddle with the size a bit to allow for ABS Shrinkage. You might have to adjust it for PLA, so it fits the preform tube.

Schematics

Schematic

Wire the ESP8266 to the MPU-6050 and battery with a diode as a voltage limiter.

Code

PinkHydrometer

Arduino
This is the Arduino code.
//based on  Basic ESP8266 MQTT example


#include <ESP8266WiFi.h>
#include <PubSubClient.h>
byte sleepTimeS = 5; // Deep sleep time in seconds


//For MPU650
#include<Wire.h>
const int MPU_addr = 0x68; // I2C address of the MPU-6050
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ, hold;
// data
const char* color = "HYDRO-Pink";
const char* pub1 = "Hydro/Pink/TILT"  ;  //send angle
const char* pub2 =  "Hydro/Pink/TEMP" ;  //send temperature
const char* sub1 =  "Hydro/Pink/TARE" ;  //recieve tare switch position
const char* sub2 =  "Hydro/Pink/BATT" ;  //recieve battery Saver Value
String keeper;


// Update these with values suitable for your network.

const char* ssid = "YourSSID";
const char* password = "YourWIFIPassword";
const char* mqtt_server = "YourMQTTServerAddress";// no :1883

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50]; //tilt
char msg2[50]; //temp
//char Tilt[10];
int Tilt = 0;
int calibrateValue = 0;
byte SwitchPos;
float KeepTime = 0;
String SetTime;
String message;
void setup_wifi() {

  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}


void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = color;
    //clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      // Once connected, publish an announcement...

      //Duplicate these as needed
      client.publish(pub1, "0"); //Set up Publising  for each value
      client.publish(pub2, "0");
      // ... and resubscribe
      client.subscribe(sub1);  //Set up Subscription for each value
      client.subscribe(sub2);



    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  Wire.begin(2, 0); //nodeMCU D2,D1   8622-01 2,0
  Serial.begin(115200);
  Serial.println("Initializing I2C devices...");
  //pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
}

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  long now = millis();
  if (now - lastMsg > 2000 + KeepTime) { //2 seconds as a buffer
    lastMsg = now;
    getTemp();
    long now = millis();


    if (SwitchPos == 0) { // Implament Tare value
      Tilt =  Tilt - calibrateValue;
      //Serial.println("                    Switch 0 ");
      //Serial.println (Tilt);
    }

    snprintf (msg, 75, "%ld", Tilt);
    Serial.print("Tilt message: ");
    Serial.println(msg);
    client.publish(pub1, msg);     // Publish Tilt


    Serial.print("Temp message: ");
    snprintf (msg2, 75, "%ld", Tmp);
    client.publish(pub2, msg2);    // Publish Temp
    Serial.println(msg2);
    delay(300);
  }
}


void callback(String topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) { // Used to concatanate the message
    message += (char)payload[i];
  }
  keeper = message;    //Store the message
  message = "";        //Clear the buffer
  Serial.println(keeper); //debug chcek for data captured


  if (topic == sub1) {  //Tare Switch data
    // Switch on the LED if an 1 was received as first character
    if (keeper == "1") { //Tare Position
      digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
      // but actually the LED is on; this is because
      // it is acive low on the ESP-01)
      calibrateValue = Tilt; //Store data to find a zero point.
      if (calibrateValue < 0) {
        calibrateValue = 0;
      }
      SwitchPos = 1; //elimiate taring a tare value
      Serial.print("calabrating");
    }
    if (keeper == "0") { //Tare Position
      digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
      SwitchPos = 0;
      Serial.print("                         callValue        ");
      Serial.println(calibrateValue);
    }
  }


  if (topic == sub2) {  // Battery Saver data
    KeepTime = keeper.toInt();
    KeepTime = KeepTime * 3600000; // scale microseconds to hours
    Serial.print("                                               KeepTime  =  ");
    Serial.println(KeepTime);
  }
}

void getTemp() {
  //int Tmp=0;
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
  AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
  //Tmp = Tmp / 340.00 + 33.6; //equation for temperature in degrees C from datasheet 340/36.53
  //Tmp = Tmp * 1.8 + 32;   //convert to F   Comment out for C
  Tilt = AcX / 100;
  Serial.print("AcX = "); Serial.print(AcX / 100);
  //Serial.print(" | AcY = "); Serial.print(AcY);
  //Serial.print(" | AcZ = "); Serial.print(AcZ);
  Serial.print(" | Tmp = "); Serial.println(Tmp);
  //  snprintf (msg, 75, "%ld", Tmp);
  //client.publish(pub2, msg);//
  delay(300);



}

NodeRED Pink Hydrometer

JSON
This is the hydrometer code. The labels are pretty self explanatory.
[{"id":"ec2c35bb.3da2e8","type":"tab","label":"Pink-Hydrometer"},{"id":"8b7e6712.79f978","type":"mqtt out","z":"ec2c35bb.3da2e8","name":"Tare Light","topic":"Hydro/Pink/TARE","qos":"1","retain":"","broker":"90df1d9a.a10478","x":508,"y":214,"wires":[]},{"id":"d59e1e05.bacc68","type":"ui_switch","z":"ec2c35bb.3da2e8","name":"Tare Switch","label":"Run<--->Tare","group":"66f07b35.87d77c","order":6,"width":"6","height":"1","passthru":true,"topic":"Hydro/Pink/TARE","style":"","onvalue":"1","onvalueType":"str","onicon":"","oncolor":"","offvalue":"0","offvalueType":"str","officon":"","offcolor":"","x":214,"y":204,"wires":[["8b7e6712.79f978"]]},{"id":"6c294ad9.ee030c","type":"mqtt in","z":"ec2c35bb.3da2e8","name":"TIlt value","topic":"Hydro/Pink/TILT","qos":"0","broker":"90df1d9a.a10478","x":105,"y":85,"wires":[["488000cb.18762","9900b60b.560e3"]]},{"id":"488000cb.18762","type":"ui_text","z":"ec2c35bb.3da2e8","group":"66f07b35.87d77c","order":8,"width":"4","height":"1","name":"Raw TILT","label":"RawTILT","format":"{{msg.payload}}","layout":"row-left","x":325,"y":74,"wires":[]},{"id":"9959d18a.ccf4d8","type":"mqtt in","z":"ec2c35bb.3da2e8","name":"TempIn","topic":"Hydro/Pink/TEMP","qos":"0","broker":"90df1d9a.a10478","x":90,"y":320,"wires":[["65e40397.2ce244","57b709db.8c93b8"]]},{"id":"8a27144c.f7373","type":"ui_text","z":"ec2c35bb.3da2e8","group":"66f07b35.87d77c","order":1,"width":"4","height":"1","name":"Temp","label":"Temp","format":"{{msg.payload}}","layout":"col-center","x":523,"y":305,"wires":[]},{"id":"9900b60b.560e3","type":"range","z":"ec2c35bb.3da2e8","minin":"0","maxin":"170","minout":"1.0","maxout":"2.0","action":"scale","round":false,"name":"Aproximate Gravity","x":357,"y":129,"wires":[["aad315dc.42ef18","cf00eeec.d6069"]]},{"id":"aad315dc.42ef18","type":"ui_text","z":"ec2c35bb.3da2e8","group":"66f07b35.87d77c","order":2,"width":"4","height":"1","name":"Aprox Grav","label":"Aprox Grav","format":"{{'%.2f'|sprintf:msg.payload}}","layout":"col-center","x":594,"y":73,"wires":[]},{"id":"65e40397.2ce244","type":"range","z":"ec2c35bb.3da2e8","minin":"-6800","maxin":"3200","minout":"51","maxout":"111","action":"scale","round":true,"name":"","x":270,"y":298,"wires":[["8a27144c.f7373","db27a217.a5d848"]]},{"id":"cf00eeec.d6069","type":"ui_chart","z":"ec2c35bb.3da2e8","name":"GravChart","group":"66f07b35.87d77c","order":3,"width":"8","height":"5","label":"Gravity","chartType":"line","legend":"false","xformat":"dd HH:mm","interpolate":"bezier","nodata":"Waiting for data","ymin":"1","ymax":"2","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"x":627,"y":133,"wires":[[],[]]},{"id":"54a86820.4276a8","type":"mqtt out","z":"ec2c35bb.3da2e8","name":"Battery","topic":"Hydro/Pink/BATT","qos":"1","retain":"","broker":"90df1d9a.a10478","x":473,"y":429,"wires":[]},{"id":"7c76ec68.cbec84","type":"ui_numeric","z":"ec2c35bb.3da2e8","name":"Battery Saver","label":"Battery Saver - 30 min ---> 24 Hours","group":"66f07b35.87d77c","order":5,"width":0,"height":0,"passthru":true,"topic":"Hydro/Pink/Batt","format":"{{value}}","min":0,"max":"24","step":"1","x":149,"y":447,"wires":[["54a86820.4276a8"]]},{"id":"2d72dadf.ed7326","type":"ui_text","z":"ec2c35bb.3da2e8","group":"16a93edd.d73581","order":0,"width":"8","height":"1","name":"","label":"Turn tare switch ON, wait for numebrs to settle then turn switch OFF.","format":"{{msg.payload}}","layout":"row-spread","x":314,"y":529,"wires":[]},{"id":"57b709db.8c93b8","type":"ui_text","z":"ec2c35bb.3da2e8","group":"66f07b35.87d77c","order":7,"width":"4","height":"1","name":"","label":"RawTemp","format":"{{msg.payload}}","layout":"row-center","x":278,"y":256,"wires":[]},{"id":"db27a217.a5d848","type":"ui_chart","z":"ec2c35bb.3da2e8","name":"TempChart","group":"66f07b35.87d77c","order":4,"width":0,"height":0,"label":"Temperature ","chartType":"line","legend":"false","xformat":"dd HH:mm","interpolate":"linear","nodata":"Waiting for data","ymin":"50","ymax":"85","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"x":525,"y":363,"wires":[[],[]]},{"id":"90df1d9a.a10478","type":"mqtt-broker","z":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willRetain":"false","willPayload":"","birthTopic":"","birthQos":"0","birthRetain":"false","birthPayload":""},{"id":"66f07b35.87d77c","type":"ui_group","z":"","name":"PinkHydromiter","tab":"7a76f6fd.2207d8","order":2,"disp":true,"width":"8"},{"id":"16a93edd.d73581","type":"ui_group","z":"","name":"Setup in pure water","tab":"7a76f6fd.2207d8","order":1,"disp":true,"width":"8"},{"id":"7a76f6fd.2207d8","type":"ui_tab","z":"","name":"Hydrometers","icon":"dashboard","order":2}]

Credits

Chris-topher Slater

Chris-topher Slater

2 projects • 10 followers
Technology Teacher Chesapeake VA. Play with Home automation.

Comments