Components and supplies
Arduino UNO
Alphanumeric LCD, 20 x 4
Solar Panel, 2.5 W
Relay (generic)
Infrared Module (Generic)
DS3231M - ±5ppm, I2C Real-Time Clock
Project description
Code
Solar switch
arduino
Switches relais on if solar energy is sufficient. Switches also on by the end of the daylight, if water heating duration was yet insufficient.
1// This sketch is for Arduino Uno, with a clock, an LCD screen, a mini sloar panel, an infrared sensor and a relais 2// Solar energy is measured by a mini solar panel attached to a window, If solar energy level exceeds a threshold voltage then a relais switches on an electric water heater. 3// If by the end of the daylight the duration of the water heating is insufficient,(heating < 2 hours) then the water is further heated with main grid energy 4// The IR sensor switches on the light of the LCD display 5// Design by Kees Vink 6// This software is open source. 7//Components: 8// Mini solar panel: positive on Analogue in A0 9// clock: SCL op Analog in A5, SDA op Analog in A4, VCC op +5V 10// LCD display: like clock (parallel to clock, both feeding and I2C) 11// Relais: S on pin 10 12// 13//DS3231-AT24C32-IIC-High-Precision-Real-Time-Clock-Module-p-81066.html?akmClientCountry=NL&utm_design=41&utm_source=emarsys&utm_medium=Neworder171109&utm_campaign=trigger-emarsys&utm_content=winna&sc_src=email_2675773&sc_eh=5e919a3f442cad831&sc_llid=6449160&sc_lid=105229698&sc_uid=CdRKDGHiw9&cur_warehouse=CN 14//IIC-I2C-2004-204-20-x-4-Character-LCD-Display-Module-Blue-p-908616.html?utm_design=41&utm_source=emarsys&utm_medium=Neworder171109&utm_campaign=trigger-emarsys&utm_content=winna&sc_src=email_2675773&sc_eh=5e919a3f442cad831&sc_llid=6449160&sc_lid=105229698&sc_uid=CdRKDGHiw9&cur_warehouse=UK 15//UNO-R3-ATmega328P-Development-Board-For-No-Cable-p-964163.html?akmClientCountry=NL&utm_design=41&utm_source=emarsys&utm_medium=Neworder171109&utm_campaign=trigger-emarsys&utm_content=winna&sc_src=email_2675773&sc_eh=5e919a3f442cad831&sc_llid=6449160&sc_lid=105229698&sc_uid=CdRKDGHiw9&cur_warehouse=UK 16//5V-PIR-Motion-Sensor-Adjustable-Time-Delay-Sensitive-Module-p-1244536.html?akmClientCountry=NL&utm_design=41&utm_source=emarsys&utm_medium=Neworder171109&utm_campaign=trigger-emarsys&utm_content=winna&sc_src=email_2675773&sc_eh=5e919a3f442cad831&sc_llid=15735979&sc_lid=105229698&sc_uid=CdRKDGHiw9&cur_warehouse=CN 17//Portable-Mini-5V-60mA-0_3W-Solar-Epoxy-Panel-p-1144421.html?gmcCountry=NL¤cy=EUR&createTmp=1&utm_source=googleshopping&utm_medium=cpc_bgcs&utm_content=frank&utm_campaign=pla-nlg-rm-all-purchase-pc&gclid=Cj0KCQiAr8bwBRD4ARIsAHa4YyK8nkgjRuT2EZHUMS5KNWzDH5LIH1HWJv7SQh2aNpPYdD7o40G5GuQaAgu1EALw_wcB&cur_warehouse=CN 18 19#include <Wire.h> 20#include <LiquidCrystal_I2C.h> 21#define DS3231_I2C_ADDRESS 0x68 22#include <SPI.h> 23#include <DS3231.h> 24DS3231 Clock; 25RTClib RTC; 26byte Year; 27byte Month; 28byte Day; 29byte DoW; 30byte Hour; 31byte Minute; 32byte Second; 33 34bool Century=false; 35bool h12; 36bool PM; 37byte ADay, AHour, AMinute, ASecond, ABits; 38bool ADy, A12h, Apm; 39bool Daltarief,Boiler_on,grid_time_window; 40int minontime = 300; // minimal time (s) boiler_on before it will be turned off because of too low solar light to avoid too many swaps (pendelen) 41long lastswitchtime,lastIRtime; 42float V_threshold=2.35; 43long starttime,sumtime,diftime,ontime,onLighttime; 44int pinOut = 10; 45int nswitchtimes = 0; 46int solarpin = 0; // pin number of solar 47// IR sensor: 48int sensor = 2; // the pin that the sensor is atteched to 49int state = LOW; // by default, no motion detected 50int val = 0; // variable to store the sensor status (value) 51 52#define BACKLIGHT_PIN 13 53LiquidCrystal_I2C lcd(0x27, 2,1,0,4,5,6,7,3, POSITIVE); // Set the LCD I2C address 54 55const uint8_t charBitmap[][8] = { 56 { 0xc, 0x12, 0x12, 0xc, 0, 0, 0, 0 }, 57 { 0x6, 0x9, 0x9, 0x6, 0, 0, 0, 0 }, 58 { 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0, 0x0 }, 59 { 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0, 0x0 }, 60 { 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0, 0x0 }, 61 { 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0, 0x0 }, 62 { 0x0, 0x0, 0x0, 0x6, 0x9, 0x9, 0x6, 0x0 }, 63 { 0x0, 0x0, 0x0, 0xc, 0x12, 0x12, 0xc, 0x0 } 64 65}; 66// Convert normal decimal numbers to binary coded decimal 67byte decToBcd(byte val){ 68 return( (val/10*16) + (val%10) ); 69} 70// Convert binary coded decimal to normal decimal numbers--------------------------------------------------------------------------------- 71byte bcdToDec(byte val){ 72 return( (val/16*10) + (val%16) ); 73} 74//----------------------------------------------------------------------------------------------------------------------------------- 75void readDS3231time(byte *second, 76byte *minute, 77byte *hour, 78byte *dayOfWeek, 79byte *dayOfMonth, 80byte *month, 81byte *year){ 82 Wire.beginTransmission(DS3231_I2C_ADDRESS); 83 Wire.write(0); // set DS3231 register pointer to 00h 84 Wire.endTransmission(); 85 Wire.requestFrom(DS3231_I2C_ADDRESS, 7); 86 // request seven bytes of data from DS3231 starting from register 00h 87 *second = bcdToDec(Wire.read() & 0x7f); 88 *minute = bcdToDec(Wire.read()); 89 *hour = bcdToDec(Wire.read() & 0x3f); 90 *dayOfWeek = bcdToDec(Wire.read()); 91 *dayOfMonth = bcdToDec(Wire.read()); 92 *month = bcdToDec(Wire.read()); 93 *year = bcdToDec(Wire.read()); 94} 95//----------------------------------------------------------------------------------------------------------------------------------- 96void displayTime(){ 97 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; 98 // retrieve data from DS3231 99 readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, 100 &year); 101 // send it to the serial monitor 102 lcd.setCursor (0 ,0 ); 103 lcd.print(dayOfMonth, DEC); 104 lcd.print("/"); 105 lcd.print(month, DEC); 106 lcd.print("/"); 107 lcd.print(year, DEC); 108 lcd.print(" "); 109 lcd.print(hour, DEC); 110 if (hour == 0){ 111 sumtime = 0.; 112 nswitchtimes = 0; } 113 // convert the byte variable to a decimal number when displayed 114 lcd.print(":"); 115 if (minute<10){ 116 lcd.print("0"); 117 } 118 lcd.print(minute, DEC); 119 lcd.print(":"); 120 if (second<10){ 121 lcd.print("0"); 122 } 123 lcd.print(second, DEC); 124 lcd.setCursor (0 ,1 ); 125// lcd.print(" Day of week: "); 126 127 if ((hour>17) and (hour<20)) { //opwarmen op netstroom supplementair 128 grid_time_window=true;} 129 else{ 130 grid_time_window=false;} 131 Daltarief=false; 132 if (hour>22){ 133 Daltarief=true;} 134 if (hour<7){ 135 Daltarief=true;} 136 //lcd.print("hour:"); 137 //lcd.print(hour,DEC); 138 switch(dayOfWeek){ 139 case 1: 140 lcd.print("Sunday"); 141 Daltarief=true; 142 break; 143 case 2: 144 lcd.print("Monday"); 145 break; 146 case 3: 147 lcd.print("Tuesday"); 148 break; 149 case 4: 150 lcd.print("Wednesday"); 151 break; 152 case 5: 153 lcd.print("Thursday"); 154 break; 155 case 6: 156 lcd.print("Friday"); 157 break; 158 case 7: 159 lcd.print("Saturday"); 160 Daltarief=true; 161 break; 162 163 } 164} 165//----------------------------------------------------------------------------------------------------------------------------------- 166void setup() 167{ 168 Wire.begin(); 169 Serial.begin(9600); 170 pinMode(10, OUTPUT); 171 int charBitmapSize = (sizeof(charBitmap ) / sizeof (charBitmap[0])); 172 173 // Switch on the backlight 174 pinMode ( BACKLIGHT_PIN, OUTPUT ); 175 digitalWrite ( BACKLIGHT_PIN, HIGH ); 176 177 lcd.begin(19,4); // initialize the lcd 178 //pinMode(led, OUTPUT); // initalize LED as an output 179 pinMode(sensor, INPUT); // initialize IR sensor as an input 180 181 delay ( 1000 ); 182 183} 184//----------------------------------------------------------------------------------------------------------------------------------- 185void loop() 186{ 187 val = digitalRead(sensor); // read sensor value 188 if (val == HIGH) { // check if the sensor is HIGH 189 delay(100); // delay 100 milliseconds 190 if (state == LOW) { 191 DateTime now = RTC.now(); 192 lastIRtime = now.unixtime(); 193 lcd.backlight(); // set lcd light on 194 state = HIGH; // update variable state to HIGH 195 } 196 } 197 else { 198 delay(200); // delay 200 milliseconds 199 200 if (state == HIGH){ 201 state = LOW; // update variable state to LOW 202 } 203 } 204 205 int solarvalue = analogRead(solarpin); 206 float solarvoltage = solarvalue*5.0/1024.0; //between 0 and 5 volts into integer values between 0 and 1023. 207 208 lcd.home (); // go home 209 lcd.clear (); 210 displayTime(); // display the real-time clock data on the Serial Monitor // set dal/piek en timewindow grid charge 211 lcd.setCursor ( 0, 2 ); 212 if (grid_time_window) 213 { lcd.print("Tijdraam Grid");} 214 else 215 {lcd.print("Tijdraam Solar"); } 216 217 lcd.setCursor ( 0, 3 ); // go to the next line lcd.setCursor(col, row) 218 if (Daltarief){ 219 lcd.print("Low tariff");} 220 else{ 221 lcd.print("Normal tariff"); } 222 223 delay(5000); // every second 224 lcd.home (); // go home 225 lcd.clear (); 226 lcd.setCursor ( 0, 0 ); // go to the next line lcd.setCursor(col, row) 227 if (solarvoltage>V_threshold) 228 lcd.print ("Sunlight sufficient"); 229 else 230 lcd.print ("Sunlight insufficient"); 231 DateTime now = RTC.now(); 232 diftime = (now.unixtime()-starttime); 233 ontime = now.unixtime()-lastswitchtime; 234 onLighttime = now.unixtime()-lastIRtime; 235 if(float(onLighttime/60)>1.) // after 1 minute light out 236 lcd.noBacklight(); 237 if ((grid_time_window) and (!Boiler_on) and ((float(sumtime/3600.)<2.))){ 238 digitalWrite(pinOut, HIGH); // switch the heater on 239 Boiler_on = true; 240 DateTime now = RTC.now(); 241 starttime=now.unixtime(); 242 lastswitchtime=starttime; 243 nswitchtimes=nswitchtimes+1; 244 } 245 246 if (!grid_time_window){ 247 if((ontime>minontime) and (Boiler_on) and (solarvoltage<V_threshold)){ // Boiler is on and will be turned off provided it has been on for longer than minontime (to avoid oscillation/pendelen in time of 5 min.) 248 digitalWrite(pinOut, LOW); 249 Boiler_on = false; 250 sumtime=sumtime+diftime; 251 nswitchtimes=nswitchtimes+1;} 252 else 253 if(Boiler_on){ 254 sumtime=sumtime+diftime; 255 starttime=now.unixtime(); 256 } 257 if((!Boiler_on)and(solarvoltage>=V_threshold)){ // Boiler was off and is now set on 258 digitalWrite(pinOut, HIGH); 259 Boiler_on = true; 260 DateTime now = RTC.now(); 261 starttime=now.unixtime(); 262 lastswitchtime=starttime; 263 nswitchtimes=nswitchtimes+1; 264 }} 265 lcd.setCursor (0 ,1 ); // go to the next line 266 if(Boiler_on) 267 lcd.print ("Boiler aan"); 268 else 269 lcd.print ("Boiler uit"); 270 lcd.print (" Nsw: "); 271 lcd.print (nswitchtimes); 272 lcd.setCursor (0 ,2 ); // go to the next line 273 lcd.print ("Laadduur dag: "); 274 lcd.print (float(sumtime/3600.)); 275 //lcd.print (sumtime); 276 lcd.print (" u"); 277 lcd.setCursor (0 ,3 ); // go to the next line 278 lcd.print ("V: "); 279 lcd.print (solarvoltage); 280 lcd.print (" Vt: "); 281 lcd.print (V_threshold); 282 delay ( 5000 ); 283 284}
Comments
Only logged in users can leave comments
KeesVink
0 Followers
•1 Projects
1
0