Започнах тест на нова версия контролер с Ардуино.
С кода по-долу се тества в момента.
Код: Избери всички
#define codeVersion "codeVersion: 1575600701 31.10.2016 "
#define compilationDate __DATE__
#define compilationTime __TIME__
#define lowTemperatureLimit 34 // Condenser temperature setpoint for start
#define highTemperatureLimit 44 // Condenser temperature setpoint for stop
#define defrostStartTemperature 10 // Defrost limit for T61-T62
#define defrostEndtTemperature 15 // Defrost limit for T62
#define minRunTime 1200000 // 1200 s
#define checkDefrostTime 1800000 // 2400 s
#define minDefrostTime 60000 // 60 s
#define maxDefrostTime 300000 // 300 s
#define hotDefrostTime 3000000 // 50 min
#define modeDelay 60000 // 60 s
#define afterOverheatTimeH 3000000 // 50 min
#define afterOverheatTimeL 1800000 // 30 min
#define pinT61 26 //Ambient air temperature pin
#define pinT62 30 //Evaporator temperature pin
#define pinT63 34 //Condensator temperature pin
#define pinCompressor 48
#define pinFan 46
#define pinPump 44
#define pinHeater 42
#define pinSwitch 40
#define feedTime 30000 //Time interval for sending data to Xively, ms
#define sensorsTime 10000 //Time interval for reading sensors, ms
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <OneWire.h>
#include <HttpClient.h>
#include <Xively.h>
#include <EEPROM.h>
#include "EEPROMAnything.h"
#include <MsTimer2.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x42, 0x3B };
byte ip[] = { 192,168,0, 3 };
byte gateway[] = {192,168,0,1};
byte subnet[] = { 255, 255, 255, 0 };
//Berlin, Germany: Technische Universitaet Berlin
//130.149.17.21: ntps1-0.cs.tu-berlin.de
//130.149.17.8: ntps1-1.cs.tu-berlin.de
//132, 163, 4, 101 time-a.timefreq.bldrdoc.gov
IPAddress timeServer(130,149,17,21);
const int timeZone = 2; // East European Time
EthernetUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
// Your Xively key to let you upload data
char xivelyKey[] = "update key";
// Define the strings for our datastream IDs
XivelyDatastream datastreams[] =
{
XivelyDatastream("0", 1, DATASTREAM_FLOAT), //Ambient air temperature
XivelyDatastream("1", 1, DATASTREAM_FLOAT), //Evaporator temperature
XivelyDatastream("2", 1, DATASTREAM_FLOAT), //Condenser temperature
XivelyDatastream("3", 1, DATASTREAM_FLOAT), //
XivelyDatastream("4", 1, DATASTREAM_FLOAT), //
XivelyDatastream("5", 1, DATASTREAM_FLOAT), //
XivelyDatastream("6", 1, DATASTREAM_FLOAT), //
XivelyDatastream("7", 1, DATASTREAM_FLOAT), //
XivelyDatastream("8", 1, DATASTREAM_FLOAT), //
XivelyDatastream("9", 1, DATASTREAM_FLOAT)
};
#define datastreamsNumber 10
// Finally, wrap the datastreams into a feed
XivelyFeed feed(1575600701, datastreams, datastreamsNumber);
float T61,T62,T63,T64,T65,T66,F,P,P1, PulsePeriod,Q61,Q61f=0,Q62,Q62f=0,temp_f, Tfl[10];
long loopTime, readSensors_time, sendTime, eepromTime,sendTimeInterval, recirculationTime;
int ret,i,imp1,imp2;
byte data[12];
float datastreamTemp[datastreamsNumber], datastreamNew[datastreamsNumber], datastreamUpdated[datastreamsNumber];
bool newData, switchOn;
volatile long lastFlowPulseTime;
int mode=0;
long FlowPulseTime, SensorsReadTime, Q62Time, modeTime, TflTime;
EthernetClient client;
XivelyClient xivelyclient(client);
// initialize the library instance:
EthernetServer webserver(80);
void setup()
{
Serial.begin(9600);
Serial.println(codeVersion);
Serial.print("Compilation date: ");
Serial.println(compilationDate);
Serial.print("Compilation time: ");
Serial.println(compilationTime);
Serial.print("IP:");
Serial.print(ip[0]);
Serial.print(".");
Serial.print(ip[1]);
Serial.print(".");
Serial.print(ip[2]);
Serial.print(".");
Serial.println(ip[3]);
Ethernet.begin(mac, ip);
delay(1000);
startConversion(pinT61); //Ambient air temperature
startConversion(pinT62); //Evaporator temperature
startConversion(pinT63); //Condenser temperature
// attachInterrupt(2, Pulse1, FALLING); // Pulse on pin21 for MEGA2560, xively ID 4,
// attachInterrupt(3, Pulse2, FALLING); // Pulse on pin22 for MEGA2560, xively ID 7,
//pinMode(21, INPUT);
//digitalWrite(21, HIGH);
//pinMode(22, INPUT);
//digitalWrite(22, HIGH);
delay(1000);
Udp.begin(localPort);
Serial.println("getNtpTime");
setSyncProvider(getNtpTime);
webserver.begin();
digitalClockDisplay();
imp1=0;
imp2=0;
MsTimer2::set(9982, every_10_seconds);
MsTimer2::start();
digitalWrite(pinCompressor, 1);
pinMode(pinCompressor, OUTPUT);
digitalWrite(pinFan, 1);
pinMode(pinFan, OUTPUT);
digitalWrite(pinPump, HIGH);
pinMode(pinPump, OUTPUT);
digitalWrite(pinHeater, HIGH);
pinMode(pinHeater, OUTPUT);
Serial.print("T61: ");
Serial.println(readSensor(pinT61));
Serial.print("T62: ");
Serial.println(readSensor(pinT62));
Serial.print("T63: ");
Serial.println(readSensor(pinT63));
}
void Pulse1()
{
imp1++;
}
void Pulse2()
{
imp2++;
}
void every_10_seconds()
{
P1=analogRead(2)/200.0;
temp_f=Q61f;
Q61f=temp_f+P1/360;
sensorsRead();
if (loopTime-TflTime>60000)
{
TflTime=loopTime;
for ( i=0 ; i<9 ; i++ ) Tfl[i]=Tfl[i+1];
Tfl[9]=T65;
}
}
void loop()
{
loopTime=millis();
sensorsRead();
flowCalculation();
controlOutput();
sendData();
webServer();
}
void controlOutput()
{
if (!switchOn && mode!=0 && mode<70) mode=70;
if (P1>4.5) // Compressor overload
{
compressorOff(); // Stop compressor
modeTime=loopTime;
mode=40;
}
switch ( mode )
{
case 0 : //Standby
if (switchOn && loopTime-modeTime>modeDelay)
{
pumpOn(); // Start circulation pump
modeTime=loopTime;
mode=1;
}
break;
case 1 : //Circulation on && temperature high
if (T63<lowTemperatureLimit && loopTime-modeTime>modeDelay)
{
compressorOn(); // Start compressor
fanOn(); // Start fan & 4-way valve
modeTime=loopTime;
mode=9;
}
break;
case 9 : //Heating minimum time
if (loopTime-modeTime>minRunTime && loopTime-modeTime>modeDelay)
{
modeTime=loopTime;
mode=10;
}
break;
case 10 : //Heating
if (T63>highTemperatureLimit) // Stop heating
{
compressorOff(); // Stop compressor
modeTime=loopTime;
if (T61<7) mode=40; else mode=50;
}
if (loopTime-modeTime>checkDefrostTime) mode=11;
break;
case 11 : //Heating and check for defrost
if (T63>highTemperatureLimit) // Stop heating
{
compressorOff(); // Stop compressor
modeTime=loopTime;
if (T61<7) mode=40; else mode=50;
}
if (T61-T62>defrostStartTemperature) // Stop for defrosting
{
compressorOff(); // Stop compressor
modeTime=loopTime;
if(T61>2) mode=20; //Hot defrost
else mode=30; //Cold defrost
}
break;
case 20: //Hot defrosting
if (T62>1 && loopTime-modeTime>hotDefrostTime) //Hot defrost time
{
modeTime=loopTime;
mode=99;
}
break;
case 30 : //Afterheating time for fan and 4-way valve before defrosting
if (loopTime-modeTime>modeDelay)
{
fanOff(); // Stop fan & 4-way valve
modeTime=loopTime;
mode=31;
}
break;
case 31 : //Compressor start delay
if (loopTime-modeTime>120000)
{
compressorOn(); // Start compressor
modeTime=loopTime;
mode=32;
}
break;
case 32 : //Defrosting stage 1
if (loopTime-modeTime>minDefrostTime) //Min defrosting time elapsed
{
mode=33;
}
break;
case 33 : //Defrosting stage 2
if (loopTime-modeTime>maxDefrostTime || T62>defrostEndtTemperature) //Stop defrosting
{
compressorOff(); // Stop compressor
modeTime=loopTime;
mode=34;
}
break;
case 34: //Defrosting stage 3
if (loopTime-modeTime>modeDelay)
{
fanOn();
modeTime=loopTime;
mode=99;
}
break;
case 40: //Overheat or setpoint reached
if (loopTime-modeTime>afterOverheatTimeL)
{
modeTime=loopTime;
mode=99;
}
break;
case 50: //Overheat or setpoint reached
if (loopTime-modeTime>modeDelay)
{
fanOff(); // Stop fan & 4-way valve
modeTime=loopTime;
mode=51;
}
break;
case 51: //Pause after overheat
if (loopTime-modeTime>afterOverheatTimeH)
{
modeTime=loopTime;
mode=99;
}
break;
case 70 : //Stop delay
if (loopTime-modeTime>modeDelay)
{
compressorOff();
modeTime=loopTime;
mode=71;
}
break;
case 71 : //Circulation pump time after switch Off
if (loopTime-modeTime>modeDelay)
{
pumpOff(); // Stop pump
fanOff(); // Stop fan & 4-way valve
modeTime=loopTime;
mode=0;
}
break;
case 80 : //Circulation fault
compressorOff();
modeTime=loopTime;
mode=81;
break;
case 81 : //Time after compressor stop
if (loopTime-modeTime>modeDelay)
{
pumpOff(); // Stop pump
fanOff(); // Stop fan & 4-way valve
modeTime=loopTime;
mode=0;
}
break;
case 99 : //Fan after time
if (loopTime-modeTime>modeDelay)
{
fanOff(); // Stop fan & 4-way valve
modeTime=loopTime;
mode=1;
}
break;
default: mode=0;
}
}
void compressorOn()
{
digitalWrite(pinCompressor, 0); // Start compressor
}
void compressorOff()
{
digitalWrite(pinCompressor, 1); // Stop compressor
}
void fanOn()
{
digitalWrite(pinFan, 0); // Start fan & 4-way valve
}
void fanOff()
{
digitalWrite(pinFan, 1); // Stop fan & 4-way valve
}
void pumpOn()
{
digitalWrite(pinPump, 0); // Start water circulation pump
}
void pumpOff()
{
digitalWrite(pinPump, 1); // Stop water circulation pump
}
void heaterOn()
{
digitalWrite(pinHeater, 0); // Start defrost heater
}
void heaterOff()
{
digitalWrite(pinHeater, 1); // Stop defrost heater
}
void flowCalculation()
{
if (lastFlowPulseTime==FlowPulseTime)
{
if (loopTime-lastFlowPulseTime>9999) F=0;
}
else
{
PulsePeriod=lastFlowPulseTime-FlowPulseTime;
F=3600000/PulsePeriod;
if (F>2000 || F<0) F=0;
temp_f=Q62f;
Q62f=(T62-T63)*0.00115+temp_f;
FlowPulseTime=lastFlowPulseTime;
}
}
void FlowPulseSet()
{
lastFlowPulseTime=millis();
}
void sensorsRead()
{
if (loopTime-SensorsReadTime>sensorsTime)
{
SensorsReadTime=loopTime;
//Ambient air temperature
datastreamTemp[0]=readSensor(pinT61);
if (datastreamTemp[0]>-90 && datastreamTemp[0]<85) datastreamNew[0]=datastreamTemp[0];
startConversion(pinT61);
T61=datastreamNew[0];
//Evaporator temperature
datastreamTemp[1]=readSensor(pinT62);
if (datastreamTemp[1]>-90 && datastreamTemp[1]<85) datastreamNew[1]=datastreamTemp[1];
startConversion(pinT62);
T62=datastreamNew[1];
//Condenser temperature
datastreamTemp[2]=readSensor(pinT63);
if (datastreamTemp[2]>-90 && datastreamTemp[2]<85) datastreamNew[2]=datastreamTemp[2];
startConversion(pinT63);
T63=datastreamNew[2];
//Manual On switch
if (digitalRead(pinSwitch)) switchOn=0;
else switchOn=1;
datastreamNew[3]=mode;
datastreamNew[4]=digitalRead(pinSwitch);
datastreamNew[5]=digitalRead(pinCompressor);
datastreamNew[6]=digitalRead(pinFan);
datastreamNew[7]=digitalRead(pinPump);
datastreamNew[8]=digitalRead(pinHeater);
Serial.print("switchOn=");
Serial.print(switchOn);
Serial.print("T61: ");
Serial.print(T61);
Serial.print(" degC; T62: ");
Serial.print(T62);
Serial.print(" degC; T63: ");
Serial.println(T63);
}
}
void sendData()
{
if (loopTime-sendTime>feedTime)
{
sendTime=loopTime ;
for ( i = 0; i < datastreamsNumber; i++) datastreams[i].setFloat(datastreamNew[i]);
// Serial.println("Uploading it to Xively");
ret = xivelyclient.put(feed, xivelyKey);
// Serial.print("xivelyclient.put returned ");
// Serial.println(ret);
if (ret==200) for ( i = 0; i < datastreamsNumber; i++) datastreamUpdated[i]=datastreamNew[i];
digitalClockDisplay();
}
}
void startConversion(byte pin) // Start temperature conversion
{
// Serial.print("Start temperature conversion 1-wire sensor on pin");
// Serial.println(int (pin));
OneWire ds(pin);
ds.reset();
ds.write(0xCC); // Skip ROM command.
ds.write(0x44,1); // start conversion, with parasite power on at the end
}
float readSensor(byte pin) // Read 13 bit resolution temperature sensor DS18B20
{
// Serial.print("Read temperature 1-wire sensor on pin");
// Serial.println(int (pin));
OneWire ds(pin);
int16_t raw;
float raw_f;
ds.reset();
ds.write(0xCC); // Skip ROM command.
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++)
{ // we need 9 bytes
data[i] = ds.read();
// Serial.print(data[i], HEX);
// Serial.print(" ");
}
// Serial.print(" CRC=");
// Serial.print( OneWire::crc8( data, 8), HEX);
// Serial.println();
// Serial.print(" CRC from device=");
// Serial.print( data[8], HEX);
// Serial.println();
if (OneWire::crc8( data, 8)==data[8])
{
raw = (((int16_t) data[1]) << 8) | data[0];
raw_f=(float)raw/16;
}
if (OneWire::crc8( data, 8)!=data[8]) // CRC error
{
raw_f=-98;
}
if (data[8]==0) // Short circuit between data wire and ground
{
raw_f=-99;
}
if (data[8]==255) // Wire break
{
raw_f=-97;
}
// Serial.println(raw_f);
return raw_f;
}
void webServer()
{
// listen for incoming clients
EthernetClient webclient = webserver.available();
// Client webclient = webserver.available();
if (webclient)
{
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (webclient.connected())
{
if (webclient.available())
{
char c = webclient.read();
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank)
{
// send a standard http response header
webclient.println("HTTP/1.1 200 OK");
webclient.println("Content-Type: text/html");
webclient.println();
webclient.print("loop time: ");
webclient.print(loopTime/1000);
webclient.print(" <br>");
webclient.print("sendTime: ");
webclient.print(sendTime/1000);
webclient.print(" <br>");
webclient.print("eepromTime: ");
webclient.print(eepromTime/1000);
webclient.print(" <br>");
webclient.print("imp1: ");
webclient.print(imp1);
webclient.print(" <br>");
webclient.print("imp2: ");
webclient.print(imp2);
webclient.print(" <br>");
webclient.print("Ambient air temperature: ");
webclient.print(datastreams[0]);
webclient.print("temp: ");
webclient.print(datastreamTemp[0]);
webclient.print(" <sup>o</sup>C<br>");
webclient.print("Evaporator temperature: ");
webclient.print(datastreams[1]);
webclient.print("temp: ");
webclient.print(datastreamTemp[1]);
webclient.print(" <sup>o</sup>C<br>");
webclient.print("Condenser temperature: ");
webclient.print(datastreams[2]);
webclient.print("temp: ");
webclient.print(datastreamTemp[2]);
webclient.print(" <sup>o</sup>C<br>");
webclient.print("Mode: ");
webclient.print(mode);
webclient.print("<br>");
webclient.print("Switch: ");
webclient.print(switchOn);
webclient.print("<br>");
webclient.print(codeVersion);
webclient.print("<br>xivelyclient.put returned ");
webclient.print(ret);
// digital clock display of the time
webclient.print("<br>");
webclient.print(hour());
webclient.print(":");
if(minute() < 10) webclient.print("0");
webclient.print(minute());
webclient.print(":");
if(second() < 10) webclient.print("0");
webclient.print(second());
webclient.print(" ");
webclient.print(day());
webclient.print(".");
webclient.print(month());
webclient.print(".");
webclient.print(year());
break;
}
if (c == '\n')
{
// you're starting a new line
currentLineIsBlank = true;
}
else if (c != '\r')
{
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
webclient.stop();
}
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(".");
Serial.print(month());
Serial.print(".");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
sendNTPpacket(timeServer);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
// 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(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}