// This arduino code is used to run the conductivity sensor module
// Communication is based od https://forum.arduino.cc/t/serial-input-basics-updated/382007


// Pin definitions
#define L293D_ENA1_pin 5 //Enable pin of the motor driver
#define L293D_IN1_pin 7 //Direction pin of the motor driver
#define L293D_IN2_pin 8 //Direction pin of the motor driver
#define L293D_out1_pin 6 //Pin connected to output 1 of the motor driver
#define L293D_out2_pin 7 //Pin connected to output 2 of the motor driver
#define Middle_potential_pin 5 //Pin connected to the connection between resistor and sensor
#define NTC_pin 4 //Pin connected to the NTC

// Global variables
int last_time = 0; //last time measurement data was sent by the arduino in s
int time = 0; //actual time in s
int timeinterval = 1; //time interval in which measurements should be made and their data sent in s
const byte numChars = 32;     // number of characters in the message received from the PC. Can be much bigger, because the buffer is cleared before it is full
char receivedChars[numChars]; // Array for received characters
char tempChars[numChars];     // temporary array for use when parsing to not change the original data receivedChars
float L293D_out1_potential1;  //measured potential in V
float L293D_out1_potential2;  //measured potential in V
float L293D_out2_potential1;  //measured potential in V
float L293D_out2_potential2;  //measured potential in V
float Middle_potential1;      //measured potential in V
float Middle_potential2;      //measured potential in V
float U_resistor1;  //voltage drop over the reference resistor at one polarity in V
float U_resistor2;  //voltage drop over the reference resistor at the other polarity in V
float U_sensor1;    //voltage drop over the conductivity sensor at one polarity in V
float U_sensor2;    //voltage drop over the conductivity sensor at the other polarity in V
float Reference_resistance = 1000; //Ohms
float Resistance1;  //measured resistance of the conductivity sensor at one polarity in Ohms
float Resistance2;  //measured resistance of the conductivity sensor at the other polarity in Ohms
float Resistance_average; //average of the resistance between both polarities in ohms
float conductivity; //calculated conductivity in mS/cm
int U_NTC_10K; //NTC voltage in V
double Temperature; //Calculated NTC temperature
unsigned long Starttime; //starttime of conductivity measurement in us
unsigned long Enddtime;  //endtime of conductivity measurement in us

// variables to hold the parsed data
// The received data has the format "<Arduino,Actor,Actorvalue>" with the name of the arduino and the actor, whichs value should be changed to the actorvalue
char Arduino[numChars] = {0};   // Variable for the name of the arduino, whichs actors should act
char Actor[numChars] = {0};   // Variable for the name of the actor, whichs value should be changed
int Actorvalue = 0;           // Variable for the value the actor should be changed to
boolean NewInstructions = false; // Indicates if message is completely received



// Setup of pin's and communication
void setup() {
  pinMode(L293D_ENA1_pin, OUTPUT);
  pinMode(L293D_IN1_pin, OUTPUT);
  pinMode(L293D_IN2_pin, OUTPUT);
  pinMode(L293D_out1_pin,INPUT);
  pinMode(L293D_out2_pin,INPUT);
  pinMode(Middle_potential_pin, INPUT);
  Serial.begin(9600);
}



// Main loop running continuously
void loop() {

    // This arduino continuosly measures and sends data, therefore the functions for receiving and executing instructions are not used in this code
    //ReceiveInstructions(); // the ReceiveInstructions function is defined below and receives the instructions from the PC to the arduino using serial communication

    //if (NewInstructions == true) { //if new instructions have been received
    //    ExecuteInstructions(); // execute the instructions by setting the values of the actors. The ExecuteInstructions function is defined below
    //    NewInstructions = false; //set the variable to show, that the instructions have been executed
    //}

    measurements(); //this function performs the measurements and is defined below

    time = millis()/1000; // calculate actual time in s
    if((time-last_time)>=timeinterval){ // check if it is time to send new measurement data
      SendData(); // send the data using the SendData function defined below
      last_time = time; // remember the last time data has been sent
    }
}



void ReceiveInstructions() { //receives the instructions from the PC to the arduino using serial communication
    static boolean recvInProgress = false; //indicates if startMarker has been received and message is collected
    static byte ndx = 0; //index for the char array
    char startMarker = '<'; //startMarker for the array
    char endMarker = '>'; //endMarker for the array "New Line" in arduino IDE serial monitor puts a '\n' at the end of each message as endMarker
    char rc; // single received character which is put into the receivedChars array

    while (Serial.available() > 0 && NewInstructions == false) { //if new data is available and the message is not completed 
        rc = Serial.read(); //read single character from buffer

        if (recvInProgress == true) { //if the start marker has been received and the message is now collected
            if (rc != endMarker) { //if the received character is not the endMarker
                receivedChars[ndx] = rc; //attach the character to the array
                ndx++; //increase index of the received character array
                if (ndx >= numChars) { //check that not too many characters have been received
                    ndx = numChars - 1;
                }
            }
            else { //if the received character is the endMarker
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false; //set the indicator that the message is completely received
                ndx = 0; //reset the array index
                NewInstructions = true; //set the indicator that the data can be displayed
            }
        }

        else if (rc == startMarker) { //if the received character is the startMarker
            recvInProgress = true; //set the indicator that the characters should be collected to the message
        }
    }
}



void ExecuteInstructions() {  //process the received data and execute the instructions

    // Parse the received Data into it's components
    char * strtokIndx; // char * is a pointer (the memory adress for char data) this is used by strtok() as an index
    strcpy(tempChars, receivedChars); //copies the string in receivedChars into tempChars
    // this temporary copy is necessary to protect the original data
    // because strtok() used in parseData() replaces the commas with \0
    strtokIndx = strtok(tempChars,",");      // strtok splits a string (tempChars) into pieces (tokens) using a delimiter (,). it replaces the delimiter with \0 (NULL) and returns the pointer to the next token each time it is called
    strcpy(Arduino, strtokIndx); // copy it to messageFromPC
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    strcpy(Actor, strtokIndx); // copy it to messageFromPC
    strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
    Actorvalue = atoi(strtokIndx);     // convert this part to an integer
  
  // Execute the received instructions
  if (strcmp(Arduino,"Arduino2")==0){
    if (strcmp(Actor,"red")==0){
      if (Actorvalue == 0){}
      if (Actorvalue == 1){}
    }
    if (strcmp(Actor,"yellow")==0){
      if (Actorvalue == 0){}
      if (Actorvalue == 1){}
    }
  }
}

void measurements(){ //in this function the conductivity and the temperature are determined
  
  // Measurement of potentials for determination of conductivity
  Starttime=micros();
  // Conductivity in one direction (first polarity)
  // Start current in one direction (with one polarity) usinge the motor driver
  analogWrite(L293D_ENA1_pin,255);
  digitalWrite(L293D_IN1_pin,HIGH);
  digitalWrite(L293D_IN2_pin,LOW);
  delayMicroseconds(50);
  // Measurement of the potential for current flow in one direction
  L293D_out1_potential1=analogRead(L293D_out1_pin);
  L293D_out2_potential1=analogRead(L293D_out2_pin);
  Middle_potential1=analogRead(Middle_potential_pin);
  delayMicroseconds(50);
  // Start current in the other direction (with other polarity) usinge the motor driver
  digitalWrite(L293D_IN1_pin,LOW);
  digitalWrite(L293D_IN2_pin,HIGH);
  delayMicroseconds(50);
  // Measurement of the potential for current flow in the other direction
  L293D_out1_potential2=analogRead(L293D_out1_pin);
  L293D_out2_potential2=analogRead(L293D_out2_pin);
  Middle_potential2=analogRead(Middle_potential_pin);
  delayMicroseconds(50);
  // Stopping the current using the motor driver
  analogWrite(L293D_ENA1_pin,0);
  digitalWrite(L293D_IN1_pin,LOW);
  digitalWrite(L293D_IN2_pin,LOW);
  Enddtime=micros();
  // Calculation of resistance and conductivity
  U_resistor1=(Middle_potential1-L293D_out2_potential1)/204.6; //voltage across the resistor for one polarity in V (1023/5V=204.6/V)
  U_resistor2=(Middle_potential2-L293D_out2_potential2)/204.6; //voltage across the resistor for the other polarity in V (1023/5V=204.6/V)
  U_sensor1=(L293D_out1_potential1-Middle_potential1)/204.6; //voltage across the conductivity sensor for one polarity in V (1023/5V=204.6/V)
  U_sensor2=(L293D_out1_potential2-Middle_potential2)/204.6; //voltage across the conductivity sensor for the other polarity in V (1023/5V=204.6/V)
  Resistance1=U_sensor1/U_resistor1*Reference_resistance; // resistance between the electrodes of the conductivity sensor for one polarity in ohm
  Resistance2=U_sensor2/U_resistor2*Reference_resistance; // resistance between the electrodes of the conductivity sensor for one polarity in ohm
  Resistance_average=(Resistance1+Resistance2)/2; // average resistance of the conductivity sensor
  conductivity=2.167*pow(10,4)*pow(Resistance_average,-1.509); // this equation was obtained using calibration measurements
  if (isnan(conductivity)){
    conductivity = 0.00;
  }
  
  // Determination of Temperature
  U_NTC_10K=analogRead(NTC_pin);
  Temperature=log(10000.0 * ((1024.0 / U_NTC_10K - 1)));
  Temperature= 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temperature * Temperature ))* Temperature )-273.15;
}


void SendData() { //sent the acutal timestamp and the measurement values from the arduino to the pc
  Serial.print("time,");
  Serial.print(time);
  Serial.print(",Conductivity,");
  Serial.print(conductivity);
  Serial.print(",T3,");
  Serial.println(Temperature);
}