// Visual Micro is in vMicro>General>Tutorial Mode // /* Name: HMGVacuum.ino Created: 5/15/2019 7:39:18 PM Author: ABBOTT-LAP\Abbott */ #include #include #include #include #define LINE_COUNT 8 #define LINE_CHECK_DELAY 1000; #define TEMP_IS_FREEZING 32; #define TEMP_IS_WARM 42; #define LINE_CHECK_DELAY 1000; #define PIN_TEMP_BUS 2 // ONE_WIRE_BUS #define PIN_LED1 3 #define PIN_LED2 4 #define PIN_LED3 5 #define PIN_LED4 6 // Digial Pin usage // 6 - 13 Sap Valve Lines 1 - 8 int SapPins[] = {0,0,1,2,4,8,16,32,64 }; // first entry allows us to use line # relative to 1 // Temperature Bus - Pin 2; // Vacuum Analog Pin 5 int vacuumPin = A5; class IOShield { static const byte mcp_address = 0x20; // I2C Address of MCP23017 Chip static const byte GPIOA = 0x12; // Register Address of Port A static const byte GPIOB = 0x13; // Register Address of Port B static const byte IODIRA = 0x00; // IODIRA register static const byte IODIRB = 0x01; // IODIRB register static const byte GPIOALL = 0x255; public: static bool Init() { //Send settings to MCP device Wire.begin(); // join i2c bus (address optional for master) Wire.beginTransmission(mcp_address); Wire.write((byte)IODIRA); // IODIRA register Wire.write((byte)0x03); // set GPIOA-0/GPIOA-1 to inputs Wire.endTransmission(); //Wire.begin(); // wake up I2C bus // // set I/O pins to outputs //Wire.beginTransmission(0x20); //Wire.write(0x00); // IODIRA register //Wire.write(0x00); // set all of port A to outputs //Wire.endTransmission(); } static void TestMeIPButtons() { Wire.beginTransmission(mcp_address); Wire.write((byte)GPIOA); // set MCP23017 memory pointer to GPIOB address Wire.endTransmission(); Wire.requestFrom(0x20, 1); // request one byte of data from MCP20317 int inputs = Wire.read(); // store the incoming byte into "inputs" if ((inputs & 0x01) == 0) { Wire.beginTransmission(mcp_address); Wire.write(GPIOA); // address bank A Wire.write((byte)0x04); // value to send GPIOA-2 HIGH Wire.endTransmission(); } if ((inputs & 0x02) == 0) { Wire.beginTransmission(mcp_address); Wire.write(GPIOA); // address bank A Wire.write((byte)0x08); // value to send GPIOA-3 HIGH Wire.endTransmission(); } else { Wire.beginTransmission(mcp_address); Wire.write(GPIOA); // address bank A Wire.write((byte)0x00); // value to send GPIOA LOW Wire.endTransmission(); } } static void TestMeOutputLeds() { Wire.beginTransmission(0x20); Wire.write(0x12); // address bank A Wire.write((byte)0xAA); // value to send - all HIGH Wire.endTransmission(); delay(500); Wire.beginTransmission(0x20); Wire.write(0x12); // address bank A Wire.write((byte)0x55); // value to send - all HIGH Wire.endTransmission(); delay(500); } }; class ValveRelays { public: static bool CloseValve(int lineNumber) { int digitalPin = SapPins[lineNumber]; digitalWrite(digitalPin, HIGH); return true; } static bool OpenValve(int lineNumber) { int digitalPin = SapPins[lineNumber]; digitalWrite(digitalPin, LOW); return true; } // http://www.martyncurrey.com/controlling-a-solenoid-valve-from-an-arduino-updated/ // https://bestengineeringprojects.com/arduino-mosfet-led-driver-circuit/ }; // // LiquidCrystal_I2C Pinouts // //SDA->Analog 4 //SCL->Analog5 //VCC-> 5vdc //GND->GND // // // Red->5vdc // Yellow->Signal To Pin x // Black->GND // 4.7k ohm resistor between Vdd and Signal class VacuumGuage { static double SensorValue; //Save Sensor input Voltage static float ResultkPa; // Save Result in kPa static float ResultBar; // Save Result in Bar static float ResultPsi; // Save Result in Psi public: static float GetPsiVacuum() { static const float BarToPsi = 14.503773800722; SensorValue = analogRead(vacuumPin); ResultkPa = (SensorValue * (.00488) / (.022) + 20); ResultBar = (ResultkPa * 0.01) - 1.0172; //multiply (1 kPa x 0.01 bar) and deduct atmospheric pressure ResultPsi = ResultBar * BarToPsi; Serial.println(ResultBar); return ResultPsi; } }; /* * SAPLINE CLASS DEFINITION */ class SapLine { private: byte pinLED; int lineNumber = 0; boolean lcdState = LOW; unsigned long timeLedOn; unsigned long timeLedOff; unsigned long timeLineOn = 0; unsigned long timeLineOff = 0; unsigned long timeLineFailed = 0; bool IsBreached = false; bool IsStopped = true; unsigned long nextChangeTime = 0; public: void Init(int lineNumber) { this->lineNumber = lineNumber; pinLED = SapPins[lineNumber]; pinMode(pinLED, OUTPUT); } // Might have to include delay for open int ShutMeOff() { IsStopped = true; timeLineOff = millis(); ValveRelays::CloseValve(lineNumber - 1); return lineNumber - 1; } int TurnMeOn() { IsStopped = false; timeLineOn = millis(); ValveRelays::OpenValve(lineNumber - 1); return lineNumber - 1; } }; class SapLines { private: int lineCount = 0; int LinesUp = 0; long timeStarted = 0; long timeLastChecked = 0; SapLine* sapLineList; public: SapLines(int lineCount) { this->lineCount = lineCount; sapLineList = new SapLine[lineCount]; for (int i = 0; i < lineCount; i++) { sapLineList[i].Init(lineCount + 1); sapLineList[i].TurnMeOn(); } } int CheckAllLines() { int onCount = 0; //With all lines open for (int i = 0; i < lineCount; i++) { sapLineList[lineCount + 1].TurnMeOn(); } long openVacuum = VacuumGuage::GetPsiVacuum(); for (int i = 0; i < lineCount; i++) { sapLineList[lineCount + 1].ShutMeOff(); } long closedVacuum = VacuumGuage::GetPsiVacuum(); return onCount; } int TurnOffAllLines() { int offCount = 0; for (int i = 0; i < lineCount; i++) { sapLineList[i].ShutMeOff(); offCount++; } return offCount; } }; static const uint8_t _lcd_addr = 0x27; static const uint8_t _lcd_cols = 16; static const uint8_t _lcd_rows = 2; static char const* PRMPT_TEMP = "Temp F:"; static char const* PRMPT_STATE = "State:"; static char const* PRMPT_LINES = "Valves:"; static char const* START_MSG = "Vacuum Start"; static char const* START_CLOSE__MSG = "-Lines"; static LiquidCrystal_I2C* lcd; static SapLines * sapLines; static unsigned long nextLineTestTime = millis(); static bool InFreezingState = true; /********************************************************************/ // Setup Dallas Temperature Sensor /********************************************************************/ // Setup a oneWire instance to communicate with any OneWire devices // (not just Maxim/Dallas temperature ICs) OneWire oneWire(PIN_TEMP_BUS); /********************************************************************/ // Pass our oneWire reference to Dallas Temperature. DallasTemperature sensors(&oneWire); /********************************************************************/ void setup() { Start_Lcd(); sapLines = new SapLines(LINE_COUNT); Serial.begin(9600);// start serial port Serial.println("Dallas Temperature IC Control Library Demo"); // Start up the library sensors.begin(); } void loop() { if (IsOkToRun()){ } } bool IsOkToRun() { bool okToRun = false; if (nextLineTestTime < millis()) { nextLineTestTime = millis() + LINE_CHECK_DELAY; okToRun = true; } // ToDo Check Temperature return okToRun; } void Start_Lcd() { lcd = new LiquidCrystal_I2C(_lcd_addr, _lcd_cols, _lcd_rows); lcd->begin(); // Turn on the blacklight and print a message. lcd->backlight(); lcd->print(START_MSG); lcd->print(LINE_COUNT); lcd->println(START_CLOSE__MSG); } bool IsTemperatureOK() { bool temperatureOK = false; Serial.print(" Requesting temperatures..."); sensors.requestTemperatures(); // Send the command to get temperatures Serial.println("DONE"); Serial.print("Temperature is: "); Serial.print(sensors.getTempFByIndex(0)); // Index 0 = we only have 1 temp sensor return temperatureOK; }