Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- # Editor : Daniel .P Mårtensson
- # Ver : 1.5
- # Umeå Universitet, Maskinteknik/Mechanical Engineering, TFE
- # Email: Daniel.martensson100@outlook.com
- # CPU: ATmega328P-PU
- # IDE: Arduino 1.0.6
- # Date: 2014-12-17
- # Written in C++, not C
- */
- #include <OneWire.h>
- #include <DallasTemperature.h>
- #include <Wire.h>
- #include <LiquidCrystal_I2C.h>
- #include <SoftwareServo.h>
- #define BAUDRATE 9600 // Speed 9600 bps - do not change
- #define ONE_WIRE_BUS 10 // Digital pin 2 - do not change
- #define pHpin 0 // Analog pin 0 - do not change
- #define LARM_PUMP_SET 60 // This is a larm set for Pump
- #define servoPin 11 // Set servo pin to 8
- SoftwareServo myservo; // create servo object to control a servo
- LiquidCrystal_I2C lcd(0x20,16,2); // Set the LCD address to 0x20 for a 16 chars and 2 line display. Do not change.
- OneWire oneWire(ONE_WIRE_BUS); // do not change
- DallasTemperature sensors(&oneWire); // do not change
- /* global variables*/
- int E; // E is a analog value from the pH-meter
- float Eo; // Eo is a constant value from the PC
- float k; // k is a constant value from the PC
- byte state; // Case for switch
- double PHbor; // PH set point
- long K; // konstant P-regulator
- int PORT; // if PORT = 1 then PH stat is starting. Else not.
- int LARM_PUMP = 0; // Begning value of larm pump
- long sum_PH_AD; // Sum of PH analog value
- long antal_PH_AD; // Antal of PH analog value
- float sum_PH; // Sum of PH value
- int antal_PH; // Antal of PH value
- int larmState = 0; // Larm stat
- int SetAlarm = 0;
- double e_before; // The PHar but before
- double Ti;
- double Td;
- double MAX;
- class call
- {
- public:
- // Start of hardware setup
- static void serial_begin()
- {
- Serial.begin(BAUDRATE); // baudrate
- }
- static void setupLCD()
- {
- lcd.init(); // Initialize the lcd
- lcd.backlight(); // Backlight lcd ON
- }
- static void startTempSensor()
- {
- sensors.begin(); // Activate temp sensor
- }
- static void setupPins()
- {
- pinMode(9, OUTPUT); // for the pump
- pinMode(13, OUTPUT); // for the green LED
- pinMode(7, OUTPUT);
- myservo.attach(servoPin); // attaches the servo on pin
- }
- // End of hardware setup
- // convert a string from PC to a float
- static float string_to_float(String data)
- {
- char carray[data.length() + 1]; //get lenght of variable data
- data.toCharArray(carray, sizeof(carray)); //put readStringinto an array
- return atof(carray); //convert the array into an Integer
- }
- // call temperature from the DS18B20 temperature sensor
- static float callTemp()
- {
- sensors.requestTemperatures(); // Send the command to get temperatures
- return sensors.getTempCByIndex(0); // getTempCByIndex(0) is the first sensor. We can plug in more sensors on the same one-wire if we want.
- }
- // Call the pHmeter with analog value
- static float callPHmeter_AD()
- {
- E = analogRead(pHpin);
- return E;
- }
- // Call the pHmeter with calculated pH value
- static float callPHmeter_PH()
- {
- E = analogRead(pHpin);
- return (E-Eo)/k;
- }
- static void shout()
- {
- // Send SMS
- if (SetAlarm == 0)
- {
- digitalWrite(7, 1); // Relay ON
- delay(400); // Delay 400 ms
- digitalWrite(7, 0); // Relay OFF
- SetAlarm = 1; // Only ONE SMS can be send!
- }
- // Open larmState to ON
- larmState = 1;
- }
- // Show values of temp and ph on the 16x2 LCD. If i = 0 -> show analog values, else show pH value.
- static void show_values_display(float temp, float pH, int i)
- {
- lcd.home();
- if (i == 0)
- {
- lcd.print("AD value:"); //... "pH" on the display
- }
- else
- {
- lcd.print("pH value:");
- }
- lcd.setCursor(10, 0);
- lcd.print(pH);
- lcd.setCursor(0, 1);
- lcd.print("Temp value:");
- lcd.setCursor(11, 1);
- lcd.print(temp);
- }
- // Send just one AD value after 60 seconds
- static int send_AD_value()
- {
- while (antal_PH_AD < 2080)
- {
- sum_PH_AD += callPHmeter_AD(); // Add to the sum
- antal_PH_AD++; // Count one
- }
- // Send the total average of pH AD
- Serial.println(sum_PH_AD/antal_PH_AD);
- // Send the AD value and one temp value to the display
- show_values_display(callTemp(), sum_PH_AD/antal_PH_AD, 0);
- // Return statement
- int AD = sum_PH_AD/antal_PH_AD;
- // Reset
- sum_PH_AD = 0;
- antal_PH_AD = 0;
- return AD;
- }
- // Send ONE pH value after 60 seconds
- static float send_PH_value(int i)
- {
- while (antal_PH < 2080)
- {
- sum_PH += callPHmeter_PH(); // Add to the sum
- antal_PH++; // Count one
- }
- if (i == 1)
- {
- // Send the total average of real pH
- Serial.println(sum_PH/antal_PH); // average
- }
- // Send the PH value and one temp value to the display
- show_values_display(callTemp(), sum_PH/antal_PH, 1);
- // Return statement
- float PH = sum_PH/antal_PH;
- // Reset
- sum_PH = 0;
- antal_PH = 0;
- return PH;
- }
- // A function who we call from the switch statement.
- static void get_pH_values()
- {
- int a = 0;
- String text;
- while (a == 0)
- {
- if(Serial.available() > 0)
- {
- text = Serial.readString();
- int firstcolon = text.indexOf(';');
- int secondcolon = text.indexOf(';', firstcolon+1);
- Eo = string_to_float(text.substring(0, firstcolon));
- k = string_to_float(text.substring(firstcolon+1, secondcolon));
- PORT = 2;
- a = 1; // Breake loop
- }
- }
- }
- // A function who we call from the switch statement.
- static void pump_flow_start()
- {
- analogWrite(9, 255); // send out 1 voltage
- }
- // A function who we call from the switch statement.
- static void pump_flow_stop()
- {
- analogWrite(9, 0); // send out 0 voltage
- }
- // Get values from flik 5 at LabView
- static void get_values_from_flik_5()
- {
- int a = 0;
- String text;
- while (a == 0)
- {
- if(Serial.available() > 0)
- {
- text = Serial.readString();
- int firstcolon = text.indexOf(';');
- int secondcolon = text.indexOf(';', firstcolon+1);
- int thirdcolon = text.indexOf(';', secondcolon+1);
- int fourthcolon = text.indexOf(';', thirdcolon+1);
- int firthcolon = text.indexOf(';', fourthcolon+1);
- PHbor = string_to_float(text.substring(0, firstcolon));
- K = string_to_float(text.substring(firstcolon+1, secondcolon));
- Td = string_to_float(text.substring(secondcolon+1, thirdcolon));
- Ti = string_to_float(text.substring(thirdcolon+1, fourthcolon));
- MAX = string_to_float(text.substring(fourthcolon+1, firthcolon));
- Serial.flush();
- Serial.print(PHbor);
- Serial.print(";");
- Serial.print(K);
- Serial.print(";");
- Serial.print(Td);
- Serial.print(";");
- Serial.print(Ti);
- Serial.print(";");
- Serial.print(MAX);
- Serial.print("#");
- Serial.flush();
- a = 1; // Breake loop
- }
- }
- }
- static void startPH()
- {
- PORT = 1; // START!
- }
- static void stopPH()
- {
- PORT = 2; // Just STOP but display PH values on LCD!
- pump_flow_stop(); // stop pump
- larmState = 0; // Stop the laud.
- LARM_PUMP = 0; // reset
- }
- static double average_before(double e)
- {
- // average of e_before
- static int i;
- static int a;
- static double e0, e1, e2;
- if (i == 0)
- {
- e0 = e;
- i++;
- if (a == 0)
- {
- // only runs ONE time
- return e0;
- a++;
- }
- }
- else if (i == 1)
- {
- e1 = e;
- i++;
- if (a == 1)
- {
- // only runs ONE time
- return (e0 + e1)/2;
- a++;
- }
- }
- else if (i == 2)
- {
- e2 = e;
- i = 0;
- }
- return (e0 + e1 + e2)/3;
- }
- static int U_pump(double PHar)
- {
- // The wrong values
- double e = pow(10, -PHar) - pow(10, -PHbor);
- // Derivate
- double D = Td*(e-e_before);
- // Integral - This can increase and decrease
- static double I;
- I += (1/Ti)*e;
- // The roof of the integral
- if (I >= MAX)
- {
- I = MAX;
- }
- if (PHar >= PHbor)
- {
- I = 0; // reset integral.
- }
- double PH_voltage = K*(e + D + I); // Lovely PID-regulator
- e_before = average_before(e); // save e as e_before for next loop
- int Bit_int;
- if (PH_voltage >= 1)
- {
- Bit_int = 255; // The pump will run at max.
- }
- else if (PH_voltage <= 0)
- {
- Bit_int = 0; // The pump will stop.
- }
- else
- {
- Bit_int = 255*PH_voltage;
- }
- analogWrite(9, Bit_int);
- return Bit_int; // Return a integer value between 0 and 255 for logging.
- }
- static void alarmPUMP(int U_bit)
- {
- if(U_bit > 255*0.9) // if U_bit is bigger that 90% of U_bit max = 255*0.9
- {
- LARM_PUMP++; // just add one+
- }
- else
- {
- LARM_PUMP = 0; // if not...reset.
- larmState = 0; // Open larmState to OFF
- SetAlarm = 0; // Set Alarm to begin!
- }
- if (LARM_PUMP > LARM_PUMP_SET)
- {
- shout(); // Alarm..something is brokend!
- }
- }
- static void vavle(int servo_state)
- {
- int C = 0;
- while (C < 130)
- {
- myservo.write(servo_state); // Stop test_valve - Turn back 0 degrades
- delay(15);
- SoftwareServo::refresh();
- C++;
- }
- }
- };
- void setup()
- {
- // Hardware setup
- call::serial_begin(); // Open for serial port
- call::setupLCD(); // Start the display
- call::startTempSensor(); // Start the temperature sensor
- call::setupPins(); // declare the pins
- call::vavle(0); // close valve
- }
- void loop()
- {
- if(Serial.available() > 0)
- {
- // what state is comming from PC?
- state = Serial.readString().toInt();
- switch(state)
- {
- case 0:
- call::send_AD_value(); // Send just ONE analog pH value
- break;
- case 1:
- call::pump_flow_start(); // Pump start at max flow.
- break;
- case 2:
- call::pump_flow_stop(); // Pump stop.
- break;
- case 3:
- call::send_PH_value(1); // Send just ONE pH value
- break;
- case 4:
- call::get_values_from_flik_5(); // gett values from flik 5
- break;
- case 5:
- call::startPH(); // Start logging PH
- break;
- case 6:
- call::stopPH(); // Stopp logging PH
- break;
- case 7:
- call::vavle(100); // Open vavle
- break;
- case 8:
- call::vavle(0); // Close vavle
- break;
- case 9:
- call::get_pH_values(); // Get Eo and k values for calucalate the real pH value
- break;
- default :
- Serial.println(state);
- break;
- }
- }
- if (PORT == 1)
- {
- /* This state is when we logging */
- // clock time T1
- long T1 = millis();
- // Read PH
- float PHar = call::send_PH_value(0);
- // Send U to pump
- int U_bit = call::U_pump(PHar);
- // check if U_bit has stay for long
- call::alarmPUMP(U_bit);
- // Read Temp
- float temp = call::callTemp();
- // Send to display
- call::show_values_display(temp, PHar, 1);
- // if the larm is awaken
- if (larmState == 1)
- {
- tone(8, 400, 1000); // Make a noice with 400 freq and durb 1000 ms.
- }
- // clock time T2
- long T2 = millis();
- // send to PC
- Serial.print(PHar);
- Serial.print(";");
- Serial.print(temp);
- Serial.print(";");
- Serial.print(T2-T1); // send millisecond
- Serial.print(";");
- Serial.print(U_bit);
- Serial.print("#");
- }
- else if(PORT == 2)
- {
- /* This state is when we have send Eo och k values and want to see the real PH */
- //Read real pH
- float PHar = call::callPHmeter_PH();
- // Read Temp
- float temp = call::callTemp();
- // Send to display with analog pH insted
- call::show_values_display(temp, PHar, 1);
- }
- else
- {
- /* This state is when we have not send Eo och k values yet and want to see the analog PH */
- //Read analog pH
- float PHar = call::callPHmeter_AD();
- // Read Temp
- float temp = call::callTemp();
- // Send to display with analog pH insted
- call::show_values_display(temp, PHar, 0);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement