asafa52
Published © GPL3+

Solar Water Tank Regulator

I use an electric valve, temperature sensors with WiFi connectivity to control and monitor optimal usage of solar energy.

IntermediateShowcase (no instructions)Over 20 days11,748
Solar Water Tank Regulator

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
DS18B20 Programmable Resolution 1-Wire Digital Thermometer
Maxim Integrated DS18B20 Programmable Resolution 1-Wire Digital Thermometer
×1
ESP8266 ESP-12E
Espressif ESP8266 ESP-12E
OEM module; https://www.aliexpress.com/item/ESP8266-ESP-12E-UART-WIFI-Wireless-Shield-Development-Board-Module-For-Arduino-UNO-R3-Mega-3/32657998941.html?spm=a2g0s.9042311.0.0.8VdeO5
×1
Relay (generic)
generic 2 way relay
×1
motorized ball valve
×1

Software apps and online services

ThingSpeak API
ThingSpeak API
Arduino IDE
Arduino IDE

Story

Read more

Schematics

circuit diagram

wire t up

Code

ValveControl_0.4_Beta

C/C++
the whole code. you should add WiFiEsp.h, OneWire.h, DallasTemperature.h libraries.
#include <WiFiEsp.h>
#include <WiFiEspClient.h>
#include <WiFiEspUdp.h>

/********************************************************************/
// First we include the libraries
#include <OneWire.h>
#include <DallasTemperature.h>
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
/********************************************************************/


/********************************************************************/
/*wifi configuration*/
// Emulate Serial1 on pins 6/7 if not present
#ifndef HAVE_HWSERIAL1
#include "SoftwareSerial.h"
SoftwareSerial Serial1(6, 7); // RX, TX
#endif
char ssid[] = "amar";            // your network SSID (name)
char pass[] = "asafnoa15";        // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status
String apiKey = "P7GPWQYR14DXAOWU";
char server[] = "api.thingspeak.com";

char timeServer[] = "asia.pool.ntp.org";  // NTP server - time.nist.gov
unsigned int localPort = 2390;        // local port to listen for UDP packets

const int NTP_PACKET_SIZE = 48;  // NTP timestamp is in the first 48 bytes of the message
const int UDP_TIMEOUT = 5000;    // timeout in miliseconds to wait for an UDP packet to arrive

byte packetBuffer[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing packets



// A UDP instance to let us send and receive packets over UDP
WiFiEspUDP Udp;
/********************************************************************/
WiFiEspClient client;

/*valve configuraiton:*/
//int8_t valve_open_pin = 10; //in1 in the relay
//int8_t valve_close_pin = 11; //in2 in the relay
//int8_t is_closed_pin = 12; //red
//int8_t is_open_pin = 9; //green
#define valve_open_pin  (10UL) //in1 in the relay, YELLOW
#define valve_close_pin  (11UL) //in2 in the relay, BLUE
#define is_closed_pin  (12UL) //red
#define is_open_pin  (9UL) //green
/*black to GND*/
#define close_time (18UL)
#define open_time (7UL)
/*******************/

/*datetime configuration:*/
unsigned  long update_timestamp = 0;
unsigned  long new_time = 0;
int years = 0;
int8_t month = 0;
int8_t day = 0;
int8_t hours = 0;
int8_t minutes = 0   ;
int8_t seconds = 0;
// macros from DateTime.h


/*function declartion*/
//bool led_flag = false;
void rotateValve(bool state);
void    writeTime();
void   updateValveIndicator ();
int checkValveState();
void calculateValveState ();
void time(long val);
void sendNTPpacket(char *ntpSrv);
void print_temp ();
unsigned long update_time();
void send_temp ();
void send_data (String data);
/********************/


void setup() {
  // put your setup code here, to run once:

  client.flush();
  Serial.begin(9600); // Start up the dallas library
  sensors.begin(); // initialize serial for ESP module
  Serial1.begin(9600); // initialize ESP module
  WiFi.init(&Serial1);
  if (WiFi.status() == WL_NO_SHIELD) {//Serial.println("WiFi shield not present");
  }

  // attempt to connect to WiFi network
  while ( status != WL_CONNECTED) {
    //Serial.print("connect to WPA SSID: ");
    //Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);
  }

  // you're connected now, so print out the data
  //Serial.println("You're connected to the network");
  //setup pins states
  pinMode(valve_open_pin, OUTPUT);
  pinMode(valve_close_pin, OUTPUT);
  digitalWrite(valve_open_pin, HIGH); //LOW
  digitalWrite(valve_close_pin, HIGH); //LOW
  pinMode(is_closed_pin, INPUT_PULLUP);
  pinMode(is_open_pin, INPUT_PULLUP);
  pinMode(LED_BUILTIN, OUTPUT);
  /***************************/

}

void loop()
{
  Udp.begin(localPort);
  Serial.println("loop...");
  Udp.flush();
  
  unsigned  long ntptime = update_time ();
  Serial.print("ntptime:");
  Serial.println(ntptime);

  if (ntptime > 0)
  { update_timestamp = millis();
    new_time = ntptime;
    time(new_time) ;
  }
  else {
    time(new_time + (millis() - update_timestamp) / 1000  ) ;
  }
  delay (5000);

  Udp.stop();

  calculateValveState();

  String data ="field6=";
  data += checkValveState();
  send_data (data);
  
delay(15000);
  //writeTime();
  send_temp ();
  //print_temp ();
  delay(10000);
}


void rotateValve(bool state)
{
  long start_at = millis();
  if (state == 1)
  { digitalWrite (valve_close_pin, HIGH); //LOW
    while (checkValveState() != 1) { //valve is not fully open
      digitalWrite (valve_open_pin, LOW); //HIGH
      if (start_at < millis() - 6000) break;
    }
    
    digitalWrite (valve_open_pin, HIGH); //LOW
  }
  else if (state == 0)
  {
    { digitalWrite (valve_open_pin, HIGH); //LOW

      while (checkValveState() != 2) { //valve is not fully closed
        digitalWrite (valve_close_pin, LOW); //HIGH
        if (start_at < millis() - 6000) break;
      }
 
      digitalWrite (valve_close_pin, HIGH); //LOW
    }
  }

}


/*void  updateValveIndicator ()
{
  if ( checkValveState() == 1 && (seconds % 2) == 0 ) ////valve is fully opened
  {
    digitalWrite (LED_BUILTIN, HIGH);
  }
  else if (checkValveState() == 2 && (seconds % 4) == 0 ) //valve is closed
  {
    digitalWrite (LED_BUILTIN, HIGH);
  }
  else {
    digitalWrite (LED_BUILTIN, LOW); //valve is half opened
  }
}*/

int checkValveState()
{

  int is_open = digitalRead(is_open_pin) ;
  int is_closed = digitalRead(is_closed_pin) ;

  if (is_open == LOW && is_closed == HIGH) ////valve is fully opened
  { //Serial.println("valve is fully opened");
    return 1;
  }
  else if (is_open == HIGH && is_closed == LOW) //valve is closed
  { //Serial.println("valve is fully closed");
    return 2;
  }
  else {
    //Serial.println("valve is in the middle");
    return 0; //valve is half opened
  }

}


void calculateValveState ()
{ Serial.println("calculateValveState");
  writeTime();
  Serial.print("valve state:");
  Serial.println(checkValveState());

print_temp ();
if (years < 2018 || sensors.getTempCByIndex(0) == - 127.00 || sensors.getTempCByIndex(0) == 85.00 || sensors.getTempCByIndex(1) == - 127.00 || sensors.getTempCByIndex(1) == 85.00 || sensors.getTempCByIndex(2) == - 127.00 || sensors.getTempCByIndex(2) == 85.00) //clock or temp is misscalcultaed
{ Serial.println ("misscalculatoin"); rotateValve(1);} //open valve

  else
  {
  if (checkValveState() != 1 && ((sensors.getTempCByIndex(0) > sensors.getTempCByIndex(1) -5 ) && (hours < close_time && hours > open_time )))
  { Serial.print(" valve is openging...");
    rotateValve(1); //open valve
  }
  else if (checkValveState() != 2  && ((sensors.getTempCByIndex(1) > sensors.getTempCByIndex(0)+5) || (hours > close_time|| hours < open_time)))
  { Serial.print(" valve is closing...");
    rotateValve(0);//close valve
  }
}

  
}


void time(unsigned long val) {
  //Serial.print ("the val in time:");
  //Serial.println (val);
  hours = (val  % 86400L) / 3600 + 3; //the +3 for IL time
  minutes = (val % 3600) / 60;
  seconds  = val % 60;
  years = (val / 31536000UL) +1970 ;
  //month = val % 31536000UL / (60*60*24);
  
}

void writeTime()
{

  Serial.print("arduino time:");
  Serial.print(hours);
  Serial.write(":");
  Serial.print(minutes);
  Serial.write(":");
  Serial.print(seconds);
  Serial.write(",");
  Serial.print(years);
  Serial.write(",");  
  Serial.print(month);
  Serial.write(",");  
    Serial.print(day);
  Serial.write(",");  
  Serial.print(checkValveState());
  Serial.write(",");
}

// send an NTP request to the time server at the given address
void sendNTPpacket(char *ntpSrv)
{
  // set all bytes in the buffer to 0
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)

  packetBuffer[0] = 0b11100011;   // LI, Version, Mode
  packetBuffer[1] = 0;     // Stratum, or type of clock
  packetBuffer[2] = 6;     // Polling Interval
  packetBuffer[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp:
  Udp.beginPacket(ntpSrv, 123); //NTP requests are to port 123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();

}

unsigned long update_time()
{
  //calculate time
  //Serial.println("updateingTime");
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  // wait for a reply for UDP_TIMEOUT miliseconds
  unsigned long startMs = millis();
  while (!Udp.available() && (millis() - startMs) < UDP_TIMEOUT) {}
  //Serial.println(Udp.parsePacket());
  if (Udp.parsePacket()) {
    //Serial.println("update_time.packet received");
    // We've received a packet, read the data from it into the buffer
    Udp.read(packetBuffer, NTP_PACKET_SIZE);

    // the timestamp starts at byte 40 of the received packet and is four bytes,
    // or two words, long. First, esxtract the two words:

    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
    // combine the four bytes (two words) into a long integer
    // this is NTP time (seconds since Jan 1 1900):
    unsigned long secsSince1900 = highWord << 16 | lowWord;
    //Serial.print("Seconds since Jan 1 1900 = ");
    //Serial.println(secsSince1900);

    // now convert NTP time into everyday time:
    Serial.print("Unix time = ");
    // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
    const unsigned long seventyYears = 2208988800UL;
    // subtract seventy years:
    unsigned long epoch = secsSince1900 - seventyYears;
    // print Unix time:
    //Serial.println(epoch);

    return epoch;
  }

  return 0;
}

void print_temp () {
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  Serial.print("Request temp.");
  sensors.requestTemperatures(); // Send the command to get temperature readings
  //Serial.println("DONE");
  Serial.print("Tempe0: ");
  Serial.println(sensors.getTempCByIndex(0)); //intake
  Serial.print("Tempe1: ");
  Serial.println(sensors.getTempCByIndex(1)); //outtake
  Serial.print("Tempe2: ");
  Serial.println(sensors.getTempCByIndex(2)); //tank
  /********************************************************************/
}

void send_temp () {
    String data = "";
    for (int i = 0; i < 3; i++) {
      data += "field";
      data += i + 1;
      data += "=";
      data += sensors.getTempCByIndex(i);
      if (i < 2) {
        data += "&";
      }
    }
    data += "&field4=";
    data += hours;
    data += "&field5=";
    data += minutes;
    Serial.println (data);
    send_data (data);
  }


void send_data (String data) {
  //Serial.println("Starting connection to thingspeak...");
      //Serial.print("\ndata in send_data:");
    //Serial.println(data);
  // if you get a connection, report back via serial
  if (client.connect(server, 80)) {
    //Serial.println("Connection to thingspeak succeed");
    String postStr = apiKey;
    postStr += "&";
    postStr += data;
      //Serial.print("/npostStr in send_data:");
    //Serial.println(postStr);
    client.print("POST /update HTTP/1.1\nHost: api.thingspeak.com\nConnection: close\nX-THINGSPEAKAPIKEY: " + apiKey + "\nContent-Type: application/x-www-form-urlencoded\nContent-Length: ");
    client.print(postStr.length());
    client.print("\n\n");
    client.print(postStr);

  }
  //Serial.println("printing response--------------------");
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }
  //Serial.println("end of printing response--------------------");

  delay (3000);
  client.flush();
  client.stop();

  //Serial.println("client stopped");

}

Credits

asafa52

asafa52

1 project • 4 followers

Comments