Advertisement
Guest User

Untitled

a guest
Dec 19th, 2014
169
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.27 KB | None | 0 0
  1. /*
  2.  # Editor : Daniel .P Mårtensson
  3.  # Ver    : 1.5
  4.  # Umeå Universitet, Maskinteknik/Mechanical Engineering, TFE
  5.  # Email: Daniel.martensson100@outlook.com
  6.  # CPU: ATmega328P-PU
  7.  # IDE: Arduino 1.0.6
  8.  # Date: 2014-12-17
  9.  # Written in C++, not C
  10. */
  11.  
  12. #include <OneWire.h>
  13. #include <DallasTemperature.h>
  14. #include <Wire.h>
  15. #include <LiquidCrystal_I2C.h>
  16. #include <SoftwareServo.h>
  17.  
  18. #define BAUDRATE 9600                                    // Speed 9600 bps - do not change
  19. #define ONE_WIRE_BUS 10                                  // Digital pin 2 - do not change
  20. #define pHpin 0                                          // Analog pin 0 - do not change
  21. #define LARM_PUMP_SET 60                                 // This is a larm set for Pump
  22. #define servoPin 11                                      // Set servo pin to 8
  23.  
  24. SoftwareServo myservo;                                   // create servo object to control a servo
  25. LiquidCrystal_I2C lcd(0x20,16,2);                        // Set the LCD address to 0x20 for a 16 chars and 2 line display. Do not change.
  26. OneWire oneWire(ONE_WIRE_BUS);                           // do not change
  27. DallasTemperature sensors(&oneWire);                     // do not change
  28.  
  29.  
  30. /* global variables*/
  31. int E;                                                       // E is a analog value from the pH-meter                                              
  32. float Eo;                                                    // Eo is a constant value from the PC        
  33. float k;                                                     // k is a constant value from the PC
  34.  
  35. byte state;                                                  // Case for switch
  36.  
  37. double PHbor;                                                 // PH set point
  38. long K;                                                      // konstant P-regulator
  39.  
  40. int PORT;                                                    // if PORT  = 1 then PH stat is starting. Else not.
  41. int LARM_PUMP = 0;                                           // Begning value of larm pump
  42.  
  43. long sum_PH_AD;                                              // Sum of PH analog value
  44. long antal_PH_AD;                                            // Antal of PH analog value
  45.  
  46. float sum_PH;                                                // Sum of PH value
  47. int antal_PH;                                                // Antal of PH value  
  48.  
  49. int larmState = 0;                                           // Larm stat
  50. int SetAlarm = 0;
  51. double e_before;                                             // The PHar but before
  52.  
  53. double Ti;
  54. double Td;
  55. double MAX;
  56.  
  57.                                        
  58. class call
  59. {
  60.   public:
  61.       // Start of hardware setup
  62.       static void serial_begin()
  63.       {
  64.         Serial.begin(BAUDRATE);                                              // baudrate
  65.       }
  66.  
  67.       static void setupLCD()                          
  68.       {
  69.         lcd.init();                                                        // Initialize the lcd
  70.         lcd.backlight();                                                   // Backlight lcd ON
  71.       }
  72.  
  73.       static void startTempSensor()                  
  74.       {
  75.         sensors.begin();                                                   // Activate temp sensor
  76.       }
  77.  
  78.       static void setupPins()
  79.       {
  80.         pinMode(9, OUTPUT);                                                // for the pump
  81.         pinMode(13, OUTPUT);           // for the green LED
  82.         pinMode(7, OUTPUT);
  83.         myservo.attach(servoPin);                                          // attaches the servo on pin
  84.       }
  85.       // End of hardware setup
  86.  
  87.       // convert a string from PC to a float
  88.       static float string_to_float(String data)
  89.       {
  90.         char carray[data.length() + 1];                                    //get lenght of variable data
  91.         data.toCharArray(carray, sizeof(carray));                          //put readStringinto an array
  92.         return atof(carray);                                               //convert the array into an Integer
  93.       }
  94.      
  95.       // call temperature from the DS18B20 temperature sensor
  96.       static float callTemp()
  97.       {
  98.         sensors.requestTemperatures();                                    // Send the command to get temperatures
  99.         return sensors.getTempCByIndex(0);                                // getTempCByIndex(0) is the first sensor. We can plug in more sensors on the same one-wire if we want.
  100.       }
  101.      
  102.       // Call the pHmeter with analog value
  103.       static float callPHmeter_AD()
  104.       {
  105.           E = analogRead(pHpin);
  106.           return E;
  107.       }
  108.      
  109.       // Call the pHmeter with calculated pH value
  110.       static float callPHmeter_PH()
  111.       {
  112.          E = analogRead(pHpin);
  113.          return (E-Eo)/k;
  114.       }
  115.      
  116.       static void shout()
  117.       {
  118.         // Send SMS
  119.         if (SetAlarm == 0)
  120.         {
  121.           digitalWrite(7, 1);                                                         // Relay ON
  122.           delay(400);                                                                 // Delay 400 ms
  123.           digitalWrite(7, 0);                                                         // Relay OFF
  124.           SetAlarm = 1; // Only ONE SMS can be send!
  125.         }
  126.          
  127.         // Open larmState to ON
  128.         larmState = 1;
  129.       }
  130.      
  131.       // Show values of temp and ph on the 16x2 LCD. If i = 0 -> show analog values, else show pH value.
  132.       static void show_values_display(float temp, float pH, int i)
  133.       {
  134.         lcd.home();
  135.         if (i == 0)
  136.         {
  137.           lcd.print("AD value:");                                           //... "pH" on the display
  138.         }
  139.         else
  140.         {
  141.           lcd.print("pH value:");  
  142.         }
  143.         lcd.setCursor(10, 0);
  144.         lcd.print(pH);
  145.  
  146.         lcd.setCursor(0, 1);
  147.         lcd.print("Temp value:");
  148.         lcd.setCursor(11, 1);
  149.         lcd.print(temp);
  150.       }
  151.      
  152.       // Send just one AD value after 60 seconds
  153.       static int send_AD_value()
  154.       {
  155.  
  156.         while (antal_PH_AD < 2080)                        
  157.         {
  158.            sum_PH_AD += callPHmeter_AD();                                  // Add to the sum
  159.            antal_PH_AD++;                                                  // Count one
  160.         }
  161.        
  162.         // Send the total average of pH AD
  163.         Serial.println(sum_PH_AD/antal_PH_AD);                            
  164.        
  165.         // Send the AD value and one temp value to the display
  166.         show_values_display(callTemp(), sum_PH_AD/antal_PH_AD, 0);      
  167.        
  168.         // Return statement
  169.         int AD = sum_PH_AD/antal_PH_AD;
  170.        
  171.         // Reset
  172.         sum_PH_AD = 0;                                                        
  173.         antal_PH_AD = 0;
  174.        
  175.         return AD;                                                
  176.       }
  177.      
  178.       // Send ONE pH value after 60 seconds
  179.       static float send_PH_value(int i)
  180.       {  
  181.        
  182.         while (antal_PH < 2080)                      
  183.         {
  184.            sum_PH += callPHmeter_PH();                                     // Add to the sum
  185.            antal_PH++;                                                     // Count one
  186.         }
  187.        
  188.         if (i == 1)
  189.         {
  190.           // Send the total average of real pH
  191.           Serial.println(sum_PH/antal_PH);                                   // average
  192.         }
  193.          
  194.         // Send the PH value and one temp value to the display
  195.         show_values_display(callTemp(), sum_PH/antal_PH, 1);
  196.        
  197.         // Return statement
  198.         float PH = sum_PH/antal_PH;
  199.        
  200.         // Reset
  201.         sum_PH = 0;                                                        
  202.         antal_PH = 0;
  203.        
  204.         return PH;    
  205.       }
  206.      
  207.       // A function who we call from the switch statement.
  208.       static void get_pH_values()
  209.       {
  210.         int a = 0;
  211.         String text;
  212.         while (a == 0)
  213.         {
  214.           if(Serial.available() > 0)
  215.           {
  216.             text = Serial.readString();
  217.             int firstcolon = text.indexOf(';');
  218.             int secondcolon = text.indexOf(';', firstcolon+1);
  219.             Eo = string_to_float(text.substring(0, firstcolon));
  220.             k = string_to_float(text.substring(firstcolon+1, secondcolon));
  221.             PORT = 2;
  222.             a = 1;                                                                 // Breake loop
  223.           }
  224.         }
  225.       }
  226.      
  227.       // A function who we call from the switch statement.
  228.       static void pump_flow_start()
  229.       {
  230.         analogWrite(9, 255);                                     // send out 1 voltage
  231.       }
  232.      
  233.       // A function who we call from the switch statement.
  234.       static void pump_flow_stop()
  235.       {
  236.         analogWrite(9, 0);                                       // send out 0 voltage
  237.       }
  238.      
  239.       // Get values from flik 5 at LabView
  240.       static void get_values_from_flik_5()
  241.       {
  242.         int a = 0;
  243.         String text;
  244.         while (a == 0)
  245.         {
  246.           if(Serial.available() > 0)
  247.           {
  248.             text = Serial.readString();
  249.             int firstcolon = text.indexOf(';');
  250.             int secondcolon = text.indexOf(';', firstcolon+1);
  251.             int thirdcolon = text.indexOf(';', secondcolon+1);
  252.             int fourthcolon = text.indexOf(';', thirdcolon+1);
  253.             int firthcolon = text.indexOf(';', fourthcolon+1);
  254.             PHbor = string_to_float(text.substring(0, firstcolon));
  255.             K = string_to_float(text.substring(firstcolon+1, secondcolon));
  256.             Td = string_to_float(text.substring(secondcolon+1, thirdcolon));
  257.             Ti = string_to_float(text.substring(thirdcolon+1, fourthcolon));
  258.             MAX = string_to_float(text.substring(fourthcolon+1, firthcolon));
  259.             Serial.flush();
  260.             Serial.print(PHbor);
  261.             Serial.print(";");
  262.             Serial.print(K);
  263.             Serial.print(";");
  264.             Serial.print(Td);
  265.             Serial.print(";");
  266.             Serial.print(Ti);
  267.             Serial.print(";");
  268.             Serial.print(MAX);
  269.             Serial.print("#");
  270.             Serial.flush();            
  271.             a = 1;                                                                 // Breake loop
  272.           }
  273.         }
  274.       }
  275.      
  276.       static void startPH()
  277.       {
  278.         PORT = 1;                                                            // START!
  279.       }
  280.       static void stopPH()
  281.       {
  282.         PORT = 2;          // Just STOP but display PH values on LCD!
  283.         pump_flow_stop();  // stop pump
  284.         larmState = 0;     // Stop the laud.
  285.         LARM_PUMP = 0;     // reset
  286.        
  287.       }
  288.      
  289.       static double average_before(double e)
  290.       {
  291.         // average of e_before
  292.         static int i;
  293.         static int a;
  294.         static double e0, e1, e2;
  295.        
  296.         if (i == 0)
  297.         {
  298.           e0 = e;
  299.           i++;
  300.           if (a == 0)
  301.           {
  302.             // only runs ONE time
  303.             return e0;
  304.             a++;
  305.           }
  306.         }
  307.         else if (i == 1)
  308.         {
  309.           e1 = e;
  310.           i++;
  311.           if (a == 1)
  312.           {
  313.             // only runs ONE time
  314.             return (e0 + e1)/2;
  315.             a++;
  316.           }
  317.         }
  318.         else if (i == 2)
  319.         {
  320.           e2 = e;
  321.           i = 0;
  322.         }
  323.        
  324.         return (e0 + e1 + e2)/3;
  325.        
  326.       }
  327.      
  328.       static int U_pump(double PHar)
  329.       {
  330.         // The wrong values
  331.         double e = pow(10, -PHar) - pow(10, -PHbor);                        
  332.        
  333.         // Derivate
  334.         double D = Td*(e-e_before);
  335.        
  336.         // Integral - This can increase and decrease
  337.         static double I;  
  338.         I += (1/Ti)*e;
  339.        
  340.         // The roof of the integral
  341.         if (I >= MAX)
  342.         {
  343.           I = MAX;
  344.         }
  345.        
  346.         if (PHar >= PHbor)
  347.         {
  348.           I = 0; // reset integral.
  349.         }
  350.        
  351.         double PH_voltage = K*(e + D + I);                                       // Lovely PID-regulator
  352.        
  353.         e_before = average_before(e);                                            // save e as e_before for next loop
  354.  
  355.         int Bit_int;
  356.         if (PH_voltage >= 1)
  357.         {
  358.           Bit_int = 255;                                                         // The pump will run at max.
  359.         }
  360.         else if (PH_voltage <= 0)
  361.         {
  362.           Bit_int = 0;                                                            // The pump will stop.
  363.         }
  364.         else
  365.         {
  366.           Bit_int = 255*PH_voltage;
  367.         }
  368.         analogWrite(9, Bit_int);
  369.         return Bit_int;                                                           // Return a integer value between 0 and 255 for logging.
  370.       }
  371.      
  372.       static void alarmPUMP(int U_bit)
  373.       {
  374.         if(U_bit > 255*0.9)                                        // if U_bit is bigger that 90% of U_bit max = 255*0.9
  375.         {
  376.           LARM_PUMP++;                                                    // just add one+
  377.         }
  378.         else
  379.         {
  380.           LARM_PUMP = 0;     // if not...reset.  
  381.           larmState = 0;    // Open larmState to OFF
  382.           SetAlarm = 0;     // Set Alarm to begin!
  383.         }
  384.        
  385.         if (LARM_PUMP > LARM_PUMP_SET)
  386.         {
  387.           shout();                                                        // Alarm..something is brokend!
  388.         }
  389.       }
  390.      
  391.       static void vavle(int servo_state)
  392.       {
  393.         int C = 0;
  394.         while (C < 130)
  395.         {
  396.           myservo.write(servo_state);                                  // Stop test_valve - Turn back 0 degrades
  397.           delay(15);
  398.           SoftwareServo::refresh();
  399.           C++;
  400.         }
  401.      }
  402. };
  403.  
  404. void setup()
  405. {
  406.   // Hardware setup
  407.   call::serial_begin();                                 // Open for serial port
  408.   call::setupLCD();                                     // Start the display
  409.   call::startTempSensor();                              // Start the temperature sensor
  410.   call::setupPins();                                    // declare the pins  
  411.   call::vavle(0);                                       //  close valve
  412. }
  413.  
  414. void loop()
  415. {
  416.   if(Serial.available() > 0)
  417.   {
  418.    // what state is comming from PC?
  419.    state = Serial.readString().toInt();
  420.    switch(state)
  421.    {
  422.    case 0:                                              
  423.       call::send_AD_value();                           // Send just ONE analog pH value
  424.       break;
  425.    case 1:
  426.       call::pump_flow_start();                         // Pump start at max flow.
  427.       break;
  428.    case 2:    
  429.       call::pump_flow_stop();                          // Pump stop.
  430.       break;  
  431.    case 3:
  432.        call::send_PH_value(1);                          // Send just ONE pH value
  433.        break;  
  434.    case 4:
  435.        call::get_values_from_flik_5();                 // gett values from flik 5
  436.        break;  
  437.    case 5:
  438.        call::startPH();                                // Start logging PH
  439.        break;  
  440.    case 6:
  441.        call::stopPH();                                 // Stopp logging PH
  442.        break;  
  443.    case 7:
  444.        call::vavle(100);                               // Open vavle
  445.        break;  
  446.    case 8:
  447.        call::vavle(0);                                 // Close vavle
  448.        break;
  449.    case 9:
  450.        call::get_pH_values();                           // Get Eo and k values for calucalate the real pH value
  451.        break;    
  452.    default :
  453.       Serial.println(state);
  454.       break;
  455.    }  
  456.  }
  457.    
  458.  if (PORT == 1)
  459.  {
  460.    /* This state is when we logging */
  461.    
  462.    // clock time T1
  463.    long T1 = millis();
  464.    
  465.    // Read PH
  466.    float PHar = call::send_PH_value(0);
  467.    
  468.    // Send U to pump
  469.    int U_bit = call::U_pump(PHar);
  470.    
  471.    // check if U_bit has stay for long
  472.    call::alarmPUMP(U_bit);
  473.      
  474.    // Read Temp
  475.    float temp = call::callTemp();
  476.  
  477.    // Send to display
  478.    call::show_values_display(temp, PHar, 1);
  479.    
  480.    // if the larm is awaken
  481.    if (larmState == 1)
  482.    {
  483.      tone(8, 400, 1000);                                                          // Make a noice with 400 freq and durb 1000 ms.  
  484.    }  
  485.    
  486.    // clock time T2
  487.    long T2 = millis();
  488.    // send to PC  
  489.    Serial.print(PHar);
  490.    Serial.print(";");
  491.    Serial.print(temp);
  492.    Serial.print(";");
  493.    Serial.print(T2-T1);                                                           // send millisecond
  494.    Serial.print(";");
  495.    Serial.print(U_bit);
  496.    Serial.print("#");  
  497.    }
  498.    
  499.    else if(PORT == 2)
  500.    {
  501.      /* This state is when we have send Eo och k values and want to see the real PH */
  502.      
  503.      //Read real pH
  504.      float PHar = call::callPHmeter_PH();
  505.      
  506.      // Read Temp
  507.      float temp = call::callTemp();
  508.      
  509.      // Send to display with analog pH insted
  510.      call::show_values_display(temp, PHar, 1);
  511.      
  512.    }
  513.    else
  514.    {
  515.      /* This state is when we have not send Eo och k values yet and want to see the analog PH */
  516.      
  517.      //Read analog pH
  518.      float PHar = call::callPHmeter_AD();
  519.      
  520.      // Read Temp
  521.      float temp = call::callTemp();
  522.      
  523.      // Send to display with analog pH insted
  524.      call::show_values_display(temp, PHar, 0);
  525.    }
  526. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement