// This aruino code is used to run the heater module // Communication is based on https://forum.arduino.cc/t/serial-input-basics-updated/382007 //Libraries #include // this library is used to send commands to the remote controled power socket in which the heating element is plugged // Pin definitions #define NTC_pin_bath 7 // GND-reference resistor-NTC_pin_bath-NTC in bath-5V #define NTC_pin_plate 6 // GND-reference resistor-NTC_pin_plate-NTC on hotplate-5V // Objects RCSwitch mySwitch = RCSwitch(); // Object used to sending commands to a remotely controllable switch // Global variables int last_save_time = 0; //last time measurement data was sent by the arduino in s int last_heat_time = 0; //last time the temperature was controled in s int time = 0; //actual time int save_timeinterval = 1; //time interval in which measurements should be made and their data sent int heat_timeinterval = 1; //time interval in which the temperature should be controlled 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 // variables to hold the parsed data // The received data has the format "" 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 float U_NTC_10K_bath; // voltage of the NTC for bath temperature in V float U_NTC_10K_plate; // voltage of the NTC for heating plate temperature in V float Temperature_bath; // temperature of the bath NTC in °C float Temperature_plate; // temperature of the heating plate NTC in °C float start_Temperature; // temperature at the beginning of the temperature ramp float target_Temperature = 25.0; // target temperature in °C float set_Temperature; // actual set temperature of the temperature ramp for the temperature controler in °C float Temperature_rise_rate = 2.0/60.0*1.1; // rise rate of the temperature ramp in °C/ 1.1 s unsigned long start_time; //start time of the temperature ramp in ms unsigned long current_time; //current time of the temperature ramp in ms int heater_status; // 1 if heater is on 0 if it is off // Setup of pin's and communication void setup() { Serial.begin(9600); // serial communication with the computer // Setup the Transmitter for sending instructions to the remote controlled switch mySwitch.enableTransmit(10); // Transmitter is connected to Arduino Pin #10 mySwitch.setProtocol(1); // Optional set protocol (default is 1, will work for most outlets) mySwitch.setPulseLength(424); // Optional set pulse length. // mySwitch.setRepeatTransmit(15); // Optional set number of transmission repetitions. // Setup the pins pinMode(NTC_pin_bath,INPUT); pinMode(NTC_pin_plate,INPUT); // Calculations of initial values U_NTC_10K_bath=analogRead(NTC_pin_bath); Temperature_bath=log(10000.0 * ((1024.0 / U_NTC_10K_bath - 1))); //correlation between temperature an measured voltage U_NTC_10K_plate=analogRead(NTC_pin_plate); Temperature_plate=log(10000.0 * ((1024.0 / U_NTC_10K_plate - 1))); //correlation between temperature an measured voltage start_Temperature= 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temperature_plate * Temperature_plate ))* Temperature_plate )-273.15; //correlation between temperature an measured voltage set_Temperature = start_Temperature; start_time = millis(); heater_status = 0; } // Main loop running continuously void loop() { 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 DecodeInstructions(); // decode the instructions NewInstructions = false; //set the variable to show, that the instructions have been executed } time = millis()/1000; // calculate actual time in s if ((time-last_heat_time)>=heat_timeinterval){ // this loop is for temperature control of the heater TemperatureControl(); // the TemperatureControl function is defined below last_heat_time = time; // remember the last time the temperature has been controlled / the heater status has been changed } if((time-last_save_time)>=save_timeinterval){ // check if it is time to send new measurement data SendData(); // send the data using the SendData function defined below last_save_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 DecodeInstructions() { //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 } void TemperatureControl() { // Determine current variables current_time=millis()-start_time; U_NTC_10K_bath=analogRead(NTC_pin_bath); Temperature_bath=log(10000.0 * ((1024.0 / U_NTC_10K_bath - 1))); Temperature_bath= 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temperature_bath * Temperature_bath ))* Temperature_bath )-273.15; U_NTC_10K_plate=analogRead(NTC_pin_plate); Temperature_plate=log(10000.0 * ((1024.0 / U_NTC_10K_plate - 1))); Temperature_plate= 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temperature_plate * Temperature_plate ))* Temperature_plate )-273.15; if (strcmp(Arduino,"Ard_Heat")==0){ // if the received instructions are actually for the arduino called Ard_Heat if (strcmp(Actor,"Heater")==0){ // if the instructions are vor the Heater actor target_Temperature = Actorvalue; // set the received actor value to the new target temperature if(target_Temperature > 100){ // prevent unrealistic target temperatures target_Temperature = 100; } else if (target_Temperature < 0){ target_Temperature = 0; } if((Temperature_plate<=(set_Temperature-2.5)) && (Temperature_plate > (-100))){ // if the actual plate temperature is valid and below the set temperature - 2.5 mySwitch.send("000101010001010101010101"); // send a command to the rc switch to switch it on. This command was determined by listening to the command of the original remote of the switch using a receiver delay(100); // wait 100 ms mySwitch.send("000101010001010101010101"); // send the command again in case it was not received at the first time heater_status = 1; // set the indicator for the heater status to 1 } } } if((Temperature_plate > (set_Temperature-2)) || (Temperature_plate < (-100))){ // if the actual plate temperature is not valid or higher than the set temperature - 2 mySwitch.send("000101010001010101010100"); // send a command to the rc switch to switch it off. This command was determined by listening to the command of the original remote of the switch using a receiver delay(100); // wait 100 ms mySwitch.send("000101010001010101010100"); // send the command again in case it was not received at the first time heater_status = 0; // set the indicator for the heater status to 0 } if(set_Temperature < -100){ // if the set temperature is not valid set_Temperature = Temperature_plate; // set it to the actual plate temperature } set_Temperature = set_Temperature + Temperature_rise_rate; // increase the set temperature until if(set_Temperature > target_Temperature){ // it is higher than the target_Temperature set_Temperature = target_Temperature; } } void SendData() { //sent the acutal timestamp and the measurement values from the arduino to the pc Serial.print("time_Ard_Heat,"); Serial.print(current_time/1000); Serial.print(",T1,"); Serial.print(Temperature_plate); Serial.print(",T2,"); Serial.print(Temperature_bath); Serial.print(",T1_set,"); Serial.print(set_Temperature); Serial.print(",heater_status,"); Serial.println(heater_status); }