Appendix A. Microcontroller Source Code (ATmega328)
/****************************************************************************************************
CSP_MCDI ATmega328 source code
Title: Design and implementation of an electrical characterization system for membrane capacitive deionization units for water treatment.
Authors: Federico Leon, Alejandro Ramos-Martin and David Santana-Quintana.
****************************************************************************************************/
// V2-2021/07/07
#include <TimerOne.h>
#include <Wire.h>
#include <Adafruit_ADS1115.h>
#include <Adafruit_MCP4725.h>
// Configuracion nombres del sistema ADS y DAC
Adafruit_ADS1115 ads;
//Adafruit_MCP4725 dac;
Adafruit_MCP4725 dac1;
// Configuración de los reles para conseguir sistemas aislados
const int Rele1 = 2;//Rele de control 1.
const int Rele2 = 3;//Rele de control 2.
int16_t a;
int16_t b;
int c = 0; // Consigna para los ensayos
/************************************************************************************
* Inicialización de variables
************************************************************************************/
unsigned long inicio=0;//Variable de entrada que fuerza la puesta en marcha y parada del ensayo.
// 0 -> En espera o parado.
// 1 -> Cargar con consigna de tension maxima.
// 2 -> Cargar con consigna de carga electrica.
// 3 -> forzar descarga con resistencia externa.
// 4 -> carga y descarga.
// 5 -> conductimetro.
unsigned long tiempo_1=0;//Tiempo de precarga.
unsigned long tiempo_2=0;//Tiempo de carga, cuando se establezca la referencia de carga eléctrica (inicio=2).
unsigned long tiempo_3=0;//Tiempo de estado de auto-descarga o tiempo de mantenimiento de la tensión
unsigned long tiempo_4=0;//Tiempo de estado de descarga.
unsigned long tiempo_5=0;//Tiempo de estado de auto-descarga.
uint16_t Vcmax=0;//Consigna de tensión máxima de carga, siempre se aplicará por seguridad.
int estado=1;//Variable de salida que indica en que modo de operación se encuentra la celda de CDI
// 0 -> En espera o stop, pero enviando datos.
// 1 -> En estado de precarga, durante tiempo_1.
// 2 -> En estado de carga, hasta que se complete el tiempo_2 o se alcance la tensión Vcmax para evitar la
// electrolisis
// 3 -> En estado de auto-descarga.
// 4 -> Finalizado el ensayo.
unsigned long control_tiempos=0;//Variable de control de tiempos en cada estado.
/* RESOLUCIONES del MCP4725
* Tensiones del Arduino:
* 0 V > 2.5 V ------>> Tensiones positivas 0–2048 bit para MCP4725
* 2.5 V > 5 V ------>> Tensiones negativas 2048–4095 bit para MCP4725
*/
//Expresión de cálculo; NOTA: Vx4=Gain*(Vx2-Vard)+Voffset; Gain=1;Voffset=0;
/*
* Vx4=(Vx2-Vard)
*/
/*********************************************************************
* Ventrada<>[−2.5;2.5]V // Valores de entrada al OPA548
********************************************************************/
uint16_t Vcuenta1=0;//Vopa ---->[X4=2.5 V]
uint16_t Vcuenta2=2048;//Vopa ---->[X4=0 V]
uint16_t Icons=2048;//Consigna establecida de corriente de carga-descarga.
// Iconns es un valor inicial que luego se refresca
int16_t results;
int16_t results1;
/************************************************************************************
* Configuración del puerto serial y del timerone
************************************************************************************/
void setup()
{
Serial.begin(9600);
pinMode(Rele1, OUTPUT);
pinMode(Rele2, OUTPUT);
digitalWrite(Rele1, HIGH);//HIGH--> NC en el relé 1
digitalWrite(Rele2, HIGH);//HIGH--> CDI descargada (NC en el relé 2)
Timer1.initialize(100000);// Configuración del timerONE
Timer1.attachInterrupt(intu);// Asignación de la subrutina a la interrupción del timerONE
dac1.begin(0 × 62); //Control de la corriente. Direccionamiento del conversor ADC
//dac.begin(0 × 63); //Control de la tensión. Direccionamiento del conversor ADC
ads.begin(); //Inicia el ADS1115.
ads.setGain(GAIN_ONE); // 1× gain +/− 4.096 V 1 bit = 2 mV 0.125 mV
// Establecimiento de la ganancia del ADC
/*
* Ventrada<>[2,5;−2,5] --> Rcerámica=18 ohm
* I_carga_max=2.5/18=138,9 mA
* Icarga maxima=138.9 mA --> {Icons=0}
* Icarga mínima=−138.9 mA -> {Icons=4095}
*/
/************************************************************************************
* Configuración de los DAC y los relés
************************************************************************************/
dac1.setVoltage(2048, false);//Inicializado a 0A.
digitalWrite(Rele1, HIGH);//Rele NC
digitalWrite(Rele2, HIGH);//Rele NC
/*
* El OPA esta como un seguidor de tensión y la CDI está a tierra
*/
}
//interructión a los 1 micros
void intu()
{
Serial.print(a);
Serial.print(“,”);
Serial.print(b);
Serial.print(“,”);
Serial.print(Icons);
Serial.print(“,”);
Serial.print(Vcmax);
Serial.print(“,”);
Serial.println(estado);
// Serial.print(“,”);
// Serial.println(inicio);
control_tiempos=control_tiempos+1;
}
/***********************************************************************************************
* Se realizan los ensayos
***********************************************************************************************/
void loop(void)
{
Timer1.detachInterrupt();//Se deshabilita la interrupcion de envio de datos
switch (inicio){
//Tiempo a 0 sg
case 0: //Estado de espera o parada.
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
control_tiempos=0;
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
/*****************************************************************************************
* RESOLUCIONES del MCP4725
* Vard= 5 V − 2.5 V ------>> Tensiones positivas 4095–2048 bit para MCP4725
* Vard= 2.5 V − 0 V ------>> Tensiones negativas 2048–0 bit para MCP4725
******************************************************************************************/
case 1: //Carga con consigna de tensión máxima.
switch (estado){
case 1: //Forzar estado de precarga.
digitalWrite(Rele1, HIGH);//Rele abierto (NC)
digitalWrite(Rele2, HIGH);//Rele cabierto (NC)
//Tensión
//dac.setVoltage(4095, false);//Tensión en el OPA, X4= −2.5 V.
//Corriente
// Se le asigna un ‘0’ al OPA
dac1.setVoltage(2048, false);//Corriente en el OPA, X4= 0 A.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if(control_tiempos>=tiempo_1){
estado=2;
control_tiempos=0;
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 2: //Forzar estado de carga sólo con límite de tensión.
// Estado de carga, hasta que se complete el tiempo_2 o se alcance la
// tensión máxima
digitalWrite(Rele1, LOW);//Relé abierto (NA).
digitalWrite(Rele2, LOW);//Relé abierto (NA).
//<<<[Corriente]>>>
dac1.setVoltage(Icons, false);//Falta asignar la corriente.
//<<<[Tensión]>>>
//dac.setVoltage(Vcuenta1, false);//Falta asignar la tensión.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
// Valor máximo de tensión 1,2 V o 1 V para evitar la electrolisis de la CDI
if (a > Vcmax) {
estado=3;//Estado de auto-descarga
control_tiempos=0;
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
// Corriente
dac1.setVoltage(2048, false);//corriente en el OPA, X4= OA. Se le
// asigna un ‘0’ al OPA
// Tensión
//dac.setVoltage(4095, false);//Tensión en el OPA, X4= −2,5 V.
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 3://Forzar estado de auto-descarga.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if(control_tiempos>=tiempo_3){
//Tiempo_3--> Tiempo de estado de auto-descarga
estado=4;//Ensayo finalizado
inicio=0;
control_tiempos=0;
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
}
//Fin del switch (estado)
break;
case 2://Carga con consigna de carga eléctrica.
switch (estado){
case 1: //Forzar estado de precarga.
digitalWrite(Rele1, HIGH);//Rele NC.
digitalWrite(Rele2, HIGH);//Rele NC.
//<<<[Tensión]>>>
//dac.setVoltage(4095, false);//Aproximadamente en el OPA, X4= −2.5 V.
//<<<[Voltaje]>>>
dac1.setVoltage(2048, false);//Aproximadamente en el OPA, X4= 0 A.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if(control_tiempos>=tiempo_1){
estado=2;
control_tiempos=0;
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 2://Forzar estado de carga con limite de tiempo 2.
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
//<<<[Corriente]>>>
dac1.setVoltage(Icons, false);//dac.setVoltage(3000, false);//Falta asignar la corriente.
//<<<[Tensión]>>>
//dac.setVoltage(Vcuenta1, false);//dac.setVoltage(3000, false);//Falta asignar la tension.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if (a > Vcmax) {
estado=3;// Estado de auto-descarga
control_tiempos=0;
digitalWrite(Rele1, LOW);//Relé NA.
digitalWrite(Rele2, LOW);//Relé NA.
//<<<[Corriente]>>>
dac1.setVoltage(2048, false);//Aproximadamente en el OPA, X4=OA.
//<<<[Tensión]>>>
//dac.setVoltage(4095, false);//Aproximadamente en el OPA, X4=−2.5 V.
}
if(control_tiempos>=tiempo_2){
estado=3;// Estado de auto-descarga
control_tiempos=0;
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
//<<<[Corriente]>>>
dac1.setVoltage(2048, false);//Aproximadamente en el OPA, X4=OA.
//<<[Tensión]>>>
//dac.setVoltage(4095, false);//Aproximadamente en el OPA, X4=−2.5 V.
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 3:// Forzar estado de auto-descarga.
// En este estado la posibilidad de emplear un interruptor para realizar dos tipos
// de ensayos.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if(control_tiempos>=tiempo_3){
estado=4;// Ensayo terminado
inicio=0;
control_tiempos=0;
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
}//Fin switch (estado)
break;
case 3:// Se fuerza la descarga indefinida con resistencia de descarga.
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
//<<<[Corriente]>>>
dac1.setVoltage(2048, false);//Aproximadamente en el OPA, X4= OA.
//<<<[Tensión]>>>
//dac.setVoltage(4095, false);//Aproximadamente en el OPA, X4= −2.5 V.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
control_tiempos=0;
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 4:// Carga y descarga de la CDI
switch (estado){
case 1: //Forzar estado de precarga.
digitalWrite(Rele1, HIGH);//Rele abierto (NC)
digitalWrite(Rele2, HIGH);//Rele cabierto (NC)
//Tensión
//dac.setVoltage(4095, false);//Tensión en el OPA, X4= −2.5 V.
//Corriente
// Se le asigna un ‘0’ al OPA
dac1.setVoltage(2048, false);//Corriente en el OPA, X4= 0 A.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if(control_tiempos>=tiempo_1){
estado=2;
control_tiempos=0;
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 2: //Forzar estado de carga sólo con límite de tensión.
// Estado de carga, hasta que se complete el tiempo_2 o se alcance la
// tensión máxima
digitalWrite(Rele1, LOW);//Relé abierto (NA).
digitalWrite(Rele2, LOW);//Relé abierto (NA).
//<<<[Corriente]>>>
dac1.setVoltage(Icons, false);//Falta asignar la corriente.
//<<<[Tensión]>>>
//dac.setVoltage(Vcuenta1, false);//Falta asignar la tensión.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
// Valor máximo de tensión 1,2 V o 1 V para evitar la electrolisis de la CDI
if (a > Vcmax) {
estado=3;//Estado de auto-descarga
control_tiempos=0;
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
// Corriente
dac1.setVoltage(2048, false);//corriente en el OPA, X4= OA. Se le
// asigna un ‘0’ al OPA
// Tensión
//dac.setVoltage(4095, false);//Tensión en el OPA, X4= −2.5 V.
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
case 3:
//<<<[Corriente]>>>
dac1.setVoltage(Icons, false);//Falta asignar la corriente.
//<<<[Tensión]>>>
//dac.setVoltage(Vcuenta1, false);//Falta asignar la tensión.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if (){
}
break
case 4:
//<<<[Corriente]>>>
dac1.setVoltage(Icons, false);//Falta asignar la corriente.
//<<<[Tensión]>>>
//dac.setVoltage(Vcuenta1, false);//Falta asignar la tensión.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
// Valor máximo de tensión 1,2 V o 1 V para evitar la electrolisis de la CDI
if (a > Vcmax) {
estado=3;//Estado de auto-descarga
control_tiempos=0;
digitalWrite(Rele1, HIGH);//Relé NC.
digitalWrite(Rele2, HIGH);//Relé NC.
// Corriente
dac1.setVoltage(2048, false);//corriente en el OPA, X4= OA. Se le
// asigna un ‘0’ al OPA
// Tensión
//dac.setVoltage(4095, false);//Tensión en el OPA, X4= −2.5 V.
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break
case 5://Forzar estado de auto-descarga.
results1 = ads.readADC_Differential_0_1();
results = ads.readADC_Differential_2_3();
a = results1;
b = results;
if(control_tiempos>=tiempo_3){
//Tiempo_3--> Tiempo de estado de auto-descarga
estado=4;//Ensayo finalizado
inicio=0;
control_tiempos=0;
}
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
break;
}
case 5:// conductimetro
// Aquí hay que implementar el código del conductimetro
//*************** Prueba *****************************
//#include <AD9833.h>
//
//const int fsync_pin= 6;
//const int sdata_pin = 7;
//const int sclk_pin = 8;
//
//static AD9833 DDS (sdata_pin, sclk_pin, fsync_pin);
//float F=1000;
//int PH=0, ch=0, s=0;
//void setup() {
//
//// pick a mode
//DDS.set_mode (s, ch); // values for s: 0=sine, 1=triangle, 2=square, ch = channel 0 or 1
//// To change settings:
//
//DDS.set_freq (F, ch); // F = output frequency in hertz, ch = channel 0 or 1
//DDS.set_phase (PH, ch); // PH = phase 0 degrees to 359.999, c = channel 0 or 1
//
//}
//
//void loop() {
// // put your main code here, to run repeatedly:
//
//}
break;//Se rompe el case
}//fin switch(inicio)
}//fin void loop()
/***********************************************************************************************
* Etapa del serial Event
***********************************************************************************************/
/*
* C ---> La consigna del ensayo{CASO -}
* Por ejemplo:
* Inicio --> 2
* Tiempo_1-> 50
* Tiempo_2-> 200
* Tiempo_3-> 50
** Tiempo_4-> 100
** Tiempo_5-> 100
* Icons --> 1500
* Vcmax --> 1000
*/
void serialEvent(){
////**1**//c 2,50,200,50,1500,1000 c 1,50,200,50,1500,1000 c 3,50,200,50,1500,1000
///***2***//c 2,50,200,50,100,100,1500,1000
Serial.println(“holaaaaa estoy aquiii David”);// Línea de prueba del SerialEvent
if (Serial.peek() == ‘c’) { //Verifica el caracter significativo para que pueda ser comandado
Timer1.detachInterrupt();//Se deshabilita la interrupción de envio de datos
Serial.read(); //Lee el puerto serial
inicio = Serial.parseInt();
tiempo_1 = Serial.parseInt();
tiempo_2 = Serial.parseInt();
tiempo_3 = Serial.parseInt();
tiempo_4 = Serial.parseInt();
tiempo_5 = Serial.parseInt();
Icons = Serial.parseInt();
Vcmax = Serial.parseInt();
estado=1;//Inicia el primer estado del ensayo.
control_tiempos=0;
Timer1.attachInterrupt(intu); //Se habilita la interrupción de envio de datos.
}
while (Serial.available() > 0){
Serial.read();
}
}
Appendix B. Processing Source Code (ATmega328)
/****************************************************************************************************
CSP_MCDI GUI
Title: Design and implementation of an electrical characterization system for
membrane capacitive deionization units for water treatment.
Authors: Federico Leon, Alejandro Ramos-Martin and David Santana-Quintana.
****************************************************************************************************/
// V2-2021/07/07
import processing.serial.*;
import controlP5.*;
String nom_archivo=“name.txt”,para_nom_archivo=“name.txt”,estado_CDI=“Stop”;
String hora_inicio=“Begin: “+hour()+”:”+minute()+”:”+second();
String tiempo_1=“0”,tiempo_2=“0”,tiempo_3=“0”, tiempo_4=“0”, tiempo_5=“0”, tipo_CDI=“ONE”;
String I_c=“0,1”,V_c=“1,2”;
String tipo_ensayo=“0”;
PrintWriter archivo;//Archivo de datos ensayo.
PrintWriter fichero;//Parametros del ensayo.
ControlP5 cp5;
Serial myPort;
boolean serialInited;
int muestras_segundo=10;
int finalizado=0;
int xPos = 1;
int esquina_x=600;
int esquina_y=100;
int ancho=1200;
int alto=600;
int pocision_alto=0;
int guardar_datos=−1,inicio=0;
String dato_1=“____”,dato_2=“____”,dato_3=“____”,dato_4=“____”,dato_5=“____”,dato_6=“____”;
PShape bot;
// Configuración de los botones
int ancho_ventana=3020,alto_ventana=1500;
int x_r1=500,y_r1=90,dx_r1=450,dy_r1=345;
int mx_r1=10,my_r1=30,dy_t=30;
int x_r2=40,y_r2=90,dx_r2=385,dy_r2=130;
int mx_r2=10,my_r2=30;
int ancho_campo_texto=210;
int x_resto=40,y_resto=250,dy_resto=25;
int x_r3=40,y_r3=300,dx_r3=210,dy_r3=35;
int mx_r3=10,my_r3=30;
int ancho_boton=110,alto_boton=20,ancho_mitad_boton=55;
int x_r4=250,y_r4=450,dx_r4=700,dy_r4=285;
int mx_r4=10,my_r4=30;
int ancho_campo_texto_4=150;
int x_r5=45,y_r5=450,dx_r5=170,dy_r5=270;
int mx_r5=10,my_r5=30;
int x_r6=120,y_r6=280,dx_r6=210,dy_r6=85;
int mx_r6=10,my_r6=30;
int lf = 10;
int BAUD_RATE=9600;
String inString=null;
void setup () {
cp5 = new ControlP5(this);
cp5.addButton(“cargar_parametros_archivo”)
.setValue(0)
.setPosition(x_r4+40*mx_r4,y_r4+4*my_r4)
.setSize(ancho_boton+ancho_mitad_boton,alto_boton)
;
cp5.addTextfield(“nom_archivo”)
.setPosition(x_r2+2*mx_r2+ancho_campo_texto, y_r2+my_r2/3)
.setSize(150,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“para_nom_archivo”)
.setPosition(x_r4+25*mx_r4+ancho_campo_texto, y_r4+4*my_r4/3)
.setSize(150,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“tiempo_1”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“tiempo_2”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+4*dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“tiempo_3”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+7*dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“tiempo_4”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+10*dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“tiempo_5”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+13*dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“I_c”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+16*dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“V_c”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+19*dy_t/3)
.setSize(100,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addTextfield(“tipo_CDI”)
.setPosition(x_r4+mx_r4+ancho_campo_texto_4, y_r4+my_r4+22*dy_t/3)
.setSize(200,25)
.setCaptionLabel(““)
.setColorBackground(color(84,153,199))
.setColorActive(color(100,0,0))
.setColorForeground(color(100,0,0))
.setFont(createFont(“times new roman”,20))
;
cp5.addToggle(“tension_max”)
.setPosition(x_r5+10*mx_r5,y_r5+3*my_r5/2)
.setSize(50,20)
.setCaptionLabel(“on off”)
.setColorLabel(color(21,67,96))
.setColorBackground(color(235,245,251))
.setColorActive(color(26,82,118))
.setValue(false)
.setMode(ControlP5.SWITCH)
;
cp5.addToggle(“carga_culombios”)
.setPosition(x_r5+10*mx_r5,y_r5+6*my_r5/2)
.setSize(50,20)
.setCaptionLabel(“on off”)
.setColorLabel(color(21,67,96))
.setColorBackground(color(235,245,251))
.setColorActive(color(26,82,118))
.setValue(false)
.setMode(ControlP5.SWITCH)
;
cp5.addToggle(“descarga_resistencia”)
.setPosition(x_r5+10*mx_r5,y_r5+9*my_r5/2)
.setSize(50,20)
.setCaptionLabel(“on off”)
.setColorLabel(color(21,67,96))
.setColorBackground(color(235,245,251))
.setColorActive(color(26,82,118))
.setValue(false)
.setMode(ControlP5.SWITCH)
;
cp5.addToggle(“carga_descarga”)
.setPosition(x_r5+10*mx_r5,y_r5+12*my_r5/2)
.setSize(50,20)
.setCaptionLabel(“on off”)
.setColorLabel(color(21,67,96))
.setColorBackground(color(235,245,251))
.setColorActive(color(26,82,118))
.setValue(false)
.setMode(ControlP5.SWITCH)
;
cp5.addToggle(“conductimetro”)
.setPosition(x_r5+10*mx_r5,y_r5+15*my_r5/2)
.setSize(50,20)
.setCaptionLabel(“on off”)
.setColorLabel(color(21,67,96))
.setColorBackground(color(235,245,251))
.setColorActive(color(26,82,118))
.setValue(false)
.setMode(ControlP5.SWITCH)
;
/***************************************************************************
Configuration window GUI
***************************************************************************/
size(1040,740);
stroke(227,10,10);
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
myPort.clear();
myPort.buffer(80);
// Throw out the first reading, in case we started reading
// in the middle of a string from the sender.
inString = myPort.readStringUntil(lf);
inString = null;
background(513,123,20);
bot = loadShape(“ULPGC.svg”);
shape(bot, 22, 22, 72, 52);
shape(bot, −100,−100);
color(26,82,118);
String s_1=“ULPGC-University of Las Palmas de Gran Canaria”;
String s_2=“Interface for MCDI and MCI characterization”;
textSize(22);
fill(248, 249, 249);
text(s_1, 100, 45);
text(s_2, 100, 70);
}
/*********************************************************************************
Test configuration
**********************************************************************************/
void tension_max(boolean theFlag) {
if(theFlag==true) {
fichero = createWriter(“Ensayo.”+nom_archivo);
fichero.print(“Test 1: “);
fichero.println(“Charge Vcmax y self-discharge”);
fichero.print(“CDI type: “);
fichero.println(tipo_CDI);
fichero.print(“Time 1: “);
fichero.println(tiempo_1);
fichero.print(“Time 2: “);
fichero.println(tiempo_2);
fichero.print(“Time 3: “);
fichero.println(tiempo_3);
fichero.print(“Ic: “);
fichero.println(I_c);
fichero.print(“Vcmax: “);
fichero.println(V_c);
fichero.flush();
fichero.close();
// Ensayo 1: con consigna Vcmax y auto-descarga
inicio = 1;
String Vc_arduino=str(convierte_Vcmax_cuentas(V_c));
String Ic_arduino=str(convierte_Icons_cuentas(I_c));
String tiempo_3_arduino=str(convierte_tiempo_horas(tiempo_3));
String tiempo_1_arduino=str(convierte_tiempo_minutos(tiempo_1));
String tiempo_2_arduino=str(convierte_tiempo_segundos(tiempo_2));
String i=““;
String t1=““;
String t2=““;
String t3=““;
String ic=““;
String vcmax=““;
i=str(inicio);
t1=tiempo_1_arduino;
t2=tiempo_2_arduino;
t3=tiempo_3_arduino;
ic=Ic_arduino;
vcmax=Vc_arduino;
tipo_ensayo=“1”; // Ensayo a tensión máxima Vcmax
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
hora_inicio=“Comienzo: “+hour()+”:”+minute()+”:”+second();
if(archivo==null){
}else{
archivo.flush();
archivo.close();
}
archivo = createWriter(nom_archivo);// Se crea un TXT
nom_archivo=“I-”+nom_archivo;
}else{
//STOP de CDI
String i=““+0;
String t1=““+0;
String t2=““+0;
String t3=““+0;
String ic=““+4095;
String vcmax=““+1000;
tipo_ensayo=“0”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
if(archivo==null){
} else {
archivo.flush();
archivo.close();
}
}
}
void carga_culombios(boolean theFlag) {
if(theFlag==true) {
fichero = createWriter(“parameters.”+nom_archivo);
fichero.print(“Test 2: “);
fichero.println(“Current density”);
fichero.print(“CDI type”);
fichero.println(tipo_CDI);
fichero.print(“Time 1: “);
fichero.println(tiempo_1);
fichero.print(“Time 2: “);
fichero.println(tiempo_2);
fichero.print(“Time 3: “);
fichero.println(tiempo_3);
fichero.print(“Ic: “);
fichero.println(I_c);
fichero.print(“Vcmax: “);
fichero.println(V_c);
fichero.flush();
fichero.close();
//Ensayo 2: Carga eléctrica Q
/*
I=Culombios/tiempo ---> Con t2 es otro ensayo para carga y descarga
*/
inicio = 2;
String Vc_arduino=str(convierte_Vcmax_cuentas(V_c));
String Ic_arduino=str(convierte_Icons_cuentas(I_c));
String tiempo_3_arduino=str(convierte_tiempo_horas(tiempo_3));
String tiempo_1_arduino=str(convierte_tiempo_minutos(tiempo_1));
String tiempo_2_arduino=str(convierte_tiempo_segundos(tiempo_2));
String i=““+inicio;
String t1=““+tiempo_1_arduino;
String t2=““+tiempo_2_arduino;
String t3=““+tiempo_3_arduino;
String ic=““+Ic_arduino;
String vcmax=““+Vc_arduino;
tipo_ensayo=“2”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
hora_inicio=“Begin: “+hour()+”:”+minute()+”:”+second();
if(archivo==null){
} else {
archivo.flush();
archivo.close();
}
archivo = createWriter(nom_archivo);
nom_archivo=“I-”+nom_archivo;
} else {
String i=““+0;
String t1=““+0;
String t2=““+0;
String t3=““+0;
String ic=““+4095;
String vcmax=““+1000;
tipo_ensayo=“0”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
if(archivo==null){
} else {
archivo.flush();
archivo.close();
}
}
}
void descarga_resistencia(boolean theFlag) {
if(theFlag==true) {
inicio = 3;
String i=““+inicio;
String t1=““+tiempo_1;
String t2=““+tiempo_2;
String t3=““+tiempo_3;
String ic=““+I_c;
String vcmax=““+V_c;
tipo_ensayo=“3”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
if(archivo==null){
} else {
archivo.flush();
archivo.close();
}
} else {
String i=““+0;
String t1=““+0;
String t2=““+0;
String t3=““+0;
String ic=““+4095;
String vcmax=““+1000;
tipo_ensayo=“0”;//CDI Stop
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
if(archivo==null){}
else{
archivo.flush();
archivo.close();
}
}
}
void carga_descarga (boolean theFlag) {
if(theFlag==true) {
fichero = createWriter(“test_4.”+nom_archivo);
fichero.print(“Test 4: “);
fichero.println(“Charge and discharge of the CDI”);
fichero.print(“CDI type: “);
fichero.println(tipo_CDI);
fichero.print(“Time 1: “);
fichero.println(tiempo_1);
fichero.print(“Time 2: “);
fichero.println(tiempo_2);
fichero.print(“Time 3: “);
fichero.println(tiempo_3);
fichero.print(“Time 4: “);
fichero.println(tiempo_4);
fichero.print(“Time 5: “);
fichero.println(tiempo_5);
fichero.print(“Ic: “);
fichero.println(I_c);
fichero.print(“Vcmax: “);
fichero.println(V_c);
fichero.flush();
fichero.close();
inicio = 4;
String Vc_arduino=str(convierte_Vcmax_cuentas(V_c));
String Ic_arduino=str(convierte_Icons_cuentas(I_c));
String tiempo_3_arduino=str(convierte_tiempo_horas(tiempo_3));
String tiempo_1_arduino=str(convierte_tiempo_minutos(tiempo_1));
String tiempo_2_arduino=str(convierte_tiempo_segundos(tiempo_2));
String tiempo_4_arduino=str(convierte_tiempo_segundos(tiempo_4));
String tiempo_5_arduino=str(convierte_tiempo_horas(tiempo_5));
String i=““;
String t1=““;
String t2=““;
String t3=““;
String t4=““;
String t5=““;
String ic=““;
String vcmax=““;
i=str(inicio);
t1=tiempo_1_arduino;
t2=tiempo_2_arduino;
t3=tiempo_3_arduino;
t4=tiempo_4_arduino;
t5=tiempo_5_arduino;
ic=Ic_arduino;
vcmax=Vc_arduino;
tipo_ensayo=“4”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(t4);
myPort.write(“,”);
myPort.write(t5);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
hora_inicio=“Comienzo: “+hour()+”:”+minute()+”:”+second();
if(archivo==null){
}else{
archivo.flush();
archivo.close();
}
archivo = createWriter(nom_archivo);
nom_archivo=“I-”+nom_archivo;
}else{
//STOP CDI
String i=““+0;
String t1=““+0;
String t2=““+0;
String t3=““+0;
String t4=““+0;
String t5=““+0;
String ic=““+4095;
String vcmax=““+1000;
tipo_ensayo=“0”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(t4);
myPort.write(“,”);
myPort.write(t5);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
if(archivo==null){
} else {
archivo.flush();
archivo.close();
}
}
}
void conductimetro(boolean theFlag) {
if(theFlag==true) {
fichero = createWriter(“Test.”+nom_archivo);
fichero.print(“Test 5: “);
fichero.println(“conductimeter CDI”);
fichero.print(“CDI type: “);
fichero.println(tipo_CDI);
fichero.print(“Time 1: “);
fichero.println(tiempo_1);
fichero.print(“Time 2: “);
fichero.println(tiempo_2);
fichero.print(“Time 3: “);
fichero.println(tiempo_3);
fichero.print(“Ic: “);
fichero.println(I_c);
fichero.print(“Vcmax: “);
fichero.println(V_c);
fichero.flush();
fichero.close();
inicio = 5;
String Vc_arduino=str(convierte_Vcmax_cuentas(V_c));
String Ic_arduino=str(convierte_Icons_cuentas(I_c));
String tiempo_3_arduino=str(convierte_tiempo_horas(tiempo_3));
String tiempo_1_arduino=str(convierte_tiempo_minutos(tiempo_1));
String tiempo_2_arduino=str(convierte_tiempo_segundos(tiempo_2));
String i=““;
String t1=““;
String t2=““;
String t3=““;
String ic=““;
String vcmax=““;
i=str(inicio);
t1=tiempo_1_arduino;
t2=tiempo_2_arduino;
t3=tiempo_3_arduino;
ic=Ic_arduino;
vcmax=Vc_arduino;
tipo_ensayo=“5”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
hora_inicio=“Begin: “+hour()+”:”+minute()+”:”+second();
if(archivo==null){
}else{
archivo.flush();
archivo.close();
}
archivo = createWriter(nom_archivo);// Se crea un TXT
nom_archivo=“I-”+nom_archivo;
}else{
//STOP de CDI
String i=““+0;
String t1=““+0;
String t2=““+0;
String t3=““+0;
String ic=““+4095;
String vcmax=““+1000;
tipo_ensayo=“0”;
myPort.write(“c”);
myPort.write(i);
myPort.write(“,”);
myPort.write(t1);
myPort.write(“,”);
myPort.write(t2);
myPort.write(“,”);
myPort.write(t3);
myPort.write(“,”);
myPort.write(ic);
myPort.write(“,”);
myPort.write(vcmax);
if(archivo==null){
} else {
archivo.flush();
archivo.close();
}
}
}
/*********************************************************************************
Interface configuration
**********************************************************************************/
void draw () {
// Comand DRAW
fill(255, 243, 224);
rect(x_r1,y_r1,dx_r1,dy_r1);
color(250,0,0,205);
fill(0, 102, 153);
text(“ ### Measured data ###”, x_r1+mx_r1, y_r1+my_r1);
text(“> vc_measu= “+dato_1, x_r1+mx_r1, y_r1+my_r1+dy_t);
text(“> ic_measu= “+dato_2, x_r1+mx_r1, y_r1+my_r1+2*dy_t);
text(“> Time 1= “+tiempo_1+” minutes”, x_r1+mx_r1, y_r1+my_r1+3*dy_t);
text(“> Time 2= “+tiempo_2+” seconds”, x_r1+mx_r1, y_r1+my_r1+4*dy_t);
text(“> Time 3= “+tiempo_3+” hours”, x_r1+mx_r1, y_r1+my_r1+5*dy_t);
text(“> Time 4= “+tiempo_4+” secons”, x_r1+mx_r1, y_r1+my_r1+6*dy_t);
text(“> Time 5= “+tiempo_5+” hours”, x_r1+mx_r1, y_r1+my_r1+7*dy_t);
text(“> Icons_c = “+I_c+” A”, x_r1+mx_r1, y_r1+my_r1+8*dy_t);
text(“> Vcmax = “+V_c+” V”, x_r1+mx_r1, y_r1+my_r1+9*dy_t);
text(“> CDI_type= “+tipo_CDI+” prototype”, x_r1+mx_r1, y_r1+my_r1+10*dy_t);
fill(255, 243, 224);
rect(x_r2,y_r2,dx_r2,dy_r2);
color(250,0,0,205);
fill(0, 102, 153);
text(“File name:”,x_r2+mx_r2, y_r2+my_r2);
text(nom_archivo,x_r2+mx_r2, y_r2+my_r2+dy_t);
text(hora_inicio,x_r2+mx_r2, y_r2+my_r2+2*dy_t);
text(“Saving: “+hour()+”:”+minute()+”:”+second(),x_r2+mx_r2, y_r2+my_r2+3*dy_t);
fill(255, 255, 255);
strokeWeight(1);
color(250,0,0,255);
strokeWeight(2);
// Configuración de la interfaz del panel de parámetros de entradas
fill(255, 355, 205);
rect(x_r4,y_r4,dx_r4,dy_r4);
color(250,0,0,205);
fill(0, 102, 153);
text(“ **** Input parameters **** “, x_r4+mx_r4, y_r4+my_r4);
text(“Timer_1(min): “, x_r4+mx_r4, y_r4+my_r4+dy_t);
text(“Timer_2(seg): “, x_r4+mx_r4, y_r4+my_r4+2*dy_t);
text(“Timer_3(h): “, x_r4+mx_r4, y_r4+my_r4+3*dy_t);
text(“Timer_4(seg): “, x_r4+mx_r4, y_r4+my_r4+4*dy_t);
text(“Timer_5(h): “, x_r4+mx_r4, y_r4+my_r4+5*dy_t);
text(“Icons_c(A): “, x_r4+mx_r4, y_r4+my_r4+6*dy_t);
text(“Vcmax(V): “, x_r4+mx_r4, y_r4+my_r4+7*dy_t);
text(“CDI type: “, x_r4+mx_r4, y_r4+my_r4+8*dy_t);
text(“Name.file:”,x_r4+29*mx_r4, y_r4+2*my_r4);
text(“Test.”+para_nom_archivo,x_r4+29*mx_r4, y_r4+2*my_r4+dy_t);
fill(255, 355, 205);
rect(x_r5,y_r5,dx_r5,dy_r5);
color(250,0,0,205);
fill(0, 102, 153);
text(“Panel”, x_r5+6*mx_r5, y_r5+my_r5);
text(“Vcmax “, x_r5+2*mx_r5, y_r5+my_r5+1*dy_t);
text(“Q”, x_r5+4*mx_r5, y_r5+my_r5+5*dy_t/2);
text(“Rdesc”, x_r5+mx_r5, y_r5+my_r5+8*dy_t/2);
text(“Ch-dis”, x_r5+mx_r5, y_r5+my_r5+11*dy_t/2);
text(“σ”, x_r5+4*mx_r5, y_r5+my_r5+14*dy_t/2);
fill(255, 243, 224);
rect(x_r6,y_r6,dx_r6,dy_r6);
color(255,255,0,0);
fill(255, 0, 0);
ellipse(x_r6+2*mx_r4, y_r6+3.5*my_r6/2, 20, 20);
text(estado_CDI,x_r6+4*mx_r6,y_r6+2.5*my_r6/1.25);
text(“Estado CDI”, x_r6+5*mx_r6, y_r6+0.85*my_r6);
}
void serialEvent (Serial myPort) {
try{
inString = myPort.readStringUntil(‘\n’);
inString = trim(inString);
if (inString != null) {
String[[] lista = split(inString,”,”);
dato_1=lista[0];
dato_2=lista[1];
dato_3=lista[4];
estado_CDI=“ “;
switch(int(dato_3)) {
case 1:
estado_CDI=“Precarga”;
break;
case 2:
estado_CDI=“Cargando”;
break;
case 3:
estado_CDI=“Auto-descarga”;
break;
case 4:
estado_CDI=“Finalizado”;
break;
case 0:
estado_CDI=“Stop”;
break;
}
/*********************************************************************************
Save data to file txt
**********************************************************************************/
guardar_datos=int(dato_3);
if(guardar_datos>3){
guardar_datos=0;
archivo.close();
}
if(tipo_ensayo==“0”){
guardar_datos=0;
}
if(guardar_datos>0){
archivo.print(year( )+” “); // Year
archivo.print(month( )+” “); // Month
archivo.print(day( )+” “); // Day
archivo.print(hour( )+” “); // Hours
archivo.print(minute( )+” “); // minutes
archivo.print(second( )+” “); // Seconds
archivo.print(tipo_ensayo+” “);
archivo.print(dato_3+” “);
archivo.print(dato_1+” “);
archivo.println(dato_2+” “);
archivo.flush();
}
}
}
catch(RuntimeException e) {
println(e);
}
}
/*********************************************************************************
**********************************************************************************/
public void cargar_parametros_archivo(int theValue) {
println(“Botón del Evento: “+theValue);
String lines[] = loadStrings(“Ensayo.”+para_nom_archivo);
String list[] = split(lines[1], ‘:’);
tipo_CDI=list[1];
list = split(lines[2], ‘:’);
tiempo_1 =list[1];
list = split(lines[3], ‘:’);
tiempo_2 =list[1];
list = split(lines[4], ‘:’);
tiempo_3 =list[1];
list = split(lines[5], ‘:’);
I_c =list[1];
list = split(lines[6], ‘:’);
V_c =list[1];
para_nom_archivo=“nombre.txt”;
}
/*********************************************************************************
Subrutines
**********************************************************************************/
int convierte_tiempo_horas(String t_string) {
float tiempo_float=0;
int tiempo_int_cuentas=0;
tiempo_float=float(t_string);
tiempo_int_cuentas=round(3600*tiempo_float*muestras_segundo);
return tiempo_int_cuentas;
}
int convierte_tiempo_minutos(String t_string) {
float tiempo_float=0;
int tiempo_int_cuentas=0;
tiempo_float=float(t_string);
tiempo_int_cuentas=round(60*tiempo_float*muestras_segundo);
return tiempo_int_cuentas;
}
int convierte_tiempo_segundos(String t_string) {
float tiempo_float=0;
int tiempo_int_cuentas=0;
tiempo_float=float(t_string);
tiempo_int_cuentas=round(tiempo_float*muestras_segundo);
return tiempo_int_cuentas;
}
int convierte_Icons_cuentas(String Icons_string) {
float Ic_float=0;
int Icons_int_cuentas=2048;
Ic_float=float(Icons_string);
Ic_float=Ic_float-.0;
Ic_float=−14741.88*Ic_float+2047.5;
Icons_int_cuentas=round(Ic_float);
return Icons_int_cuentas;
}
int convierte_Vcmax_cuentas(String Vcmax_string) {
float Vcmax_float=1.2;
int Vcmax_int_cuentas=0;
float sensibilidad=0.125;
float Voffset=0.7;
Vcmax_float=float(Vcmax_string);
Vcmax_float=(Vcmax_float+Voffset)*1000/sensibilidad;
Vcmax_int_cuentas=round(Vcmax_float);
return Vcmax_int_cuentas;
}