Al código de wikipedia yo le agregaria esto en el setup y por enda habria que modificar la conversión a ph.
AnalogReference(INTERNAL);
Solo válido para MEGA/DUE
Ya que la lectura máxima será de 414.12 mV y con esa referencia interna de 1100mV logras mejorar la calidad de la lectura vs una lectura contra una referencia de 5000 mV como siempre se hace.
En el setup agregas esto
void setup(void)
{
pinMode(LED,OUTPUT);
Serial.begin(9600);
Serial.println("pH meter experiment!"); //Test the serial monitor
analogReference(INTERNAL);
}
y si asi lo usaras en el loop modificas esto
voltage = avergearray(pHArray, ArrayLenth)*5.0/1024;
por esto
voltage = avergearray(pHArray, ArrayLenth)*1.1/1023;
Ya utilice el sketch de dfrobot pero con fallos, no conseguía una lectura estable de la sonda, mas tarde me di cuenta que no respondia a los tampones pH de 7 y 4, es decir no presentaba variación alguna en el voltaje.
la figura o imagen que viene en Enlace Ph Sensor Module V1.1 no se corresponde con el modelo que tengo yo parece ser el modelo de la version 1.0, no se si esto afectaria al codigo o es que los cambios son minimos ya que la arquitectura es la misma y llevan los mismos componentes.
mañana subire el sketch y los datos enviados al monitor serie con y sin cambios.
Pues hoy he estado haciendo pruebas con la sonda con este código que he cambiado según me comentaste.
#define SensorPin A2 //pH meter Analog output to Arduino Analog Input 2
#define Offset 0.00 //deviation compensate
#define LED 13
#define samplingInterval 20
#define printInterval 800
#define ArrayLenth 40 //times of collection
int pHArray[ArrayLenth]; //Store the average value of the sensor feedback
int pHArrayIndex=0;
void setup(void)
{
pinMode(LED,OUTPUT);
Serial.begin(9600);
Serial.println("pH meter experiment!"); //Test the serial monitor
analogReference(INTERNAL1V1);
}
void loop(void)
{
static unsigned long samplingTime = millis();
static unsigned long printTime = millis();
static float pHValue,voltage;
if(millis()-samplingTime > samplingInterval)
{
pHArray[pHArrayIndex++]=analogRead(SensorPin);
if(pHArrayIndex==ArrayLenth)pHArrayIndex=0;
voltage = avergearray(pHArray, ArrayLenth)*1.1/1023;
pHValue = 3.5*voltage+Offset;
samplingTime=millis();
}
if(millis() - printTime > printInterval) //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
{
Serial.print("Voltage:");
Serial.print(voltage,2);
Serial.print(" pH value: ");
Serial.println(pHValue,2);
digitalWrite(LED,digitalRead(LED)^1);
printTime=millis();
}
}
double avergearray(int* arr, int number){
int i;
int max,min;
double avg;
long amount=0;
if(number<=0){
Serial.println("Error number for the array to avraging!/n");
return 0;
}
if(number<5){ //less than 5, calculated directly statistics
for(i=0;i<number;i++){
amount+=arr[i];
Y esto es lo que me dio como resultado la sonda cuando estaba sumergida en el buffer de pH 7.0
Queria comprobar que las conexiones estan hechas de manera correcta ya que los pines de salida tenian una nomenclatura algo rara:
"To" "Do" "Po" "G" "G" "V+"
To = esto creo que es la señal de temperatura para la correccion del pH
Do = no estoy seguro si puede ser una salida digital (Digital Output)
G = Neutros
V+= Voltaje
La señal será mas o menos estable de acuerdo al circuito que uses.
Normalmente todos tomamos varias muestras y las promediamos y asi quitamos esa molesta fluctuación.
Algunos usamos el promedio móvil que arranca lento pero luego es sencillamente extraordinario.
Para tu caso sería muy bueno porque no esperas cambios bruscos de ph sino graduales. En estos casos el promedio móvil funciona muy bien.
Buscalo en wikipedia o en google como Arduino movil average o Arduino promedio movil.
Estuve hablando con los que me proporcionaron la sonda y me pasaron sus códigos, se solucionan algunos fallos pero surgen nuevos problemas.
La sonda para pH4 me da valores altos de pH calibrando analogicamente abarco un rango de pH de 9.30 a 13.00 y creo que la correspondencia lineal entre mV y pH esta invertida.
/*
# This sample codes is for testing the pH meter V1.0.
# Editor : YouYou
# Date : 2013.10.21
# Ver : 0.1
# Product: pH meter
# SKU : SEN0161
*/
#define SensorPin 0 //pH meter Analog output to Arduino Analog Input 0
#define Offset -3.00 //deviation compensate
unsigned long int avgValue; //Store the average value of the sensor feedback
void setup()
{
pinMode(13,OUTPUT);
Serial.begin(9600);
Serial.println("Ready"); //Test the serial monitor
}
void loop()
{
int buf[10]; //buffer for read analog
for(int i=0;i<10;i++) //Get 10 sample value from the sensor for smooth the value
{
buf[i]=analogRead(SensorPin);
delay(10);
}
for(int i=0;i<9;i++) //sort the analog from small to large
{
for(int j=i+1;j<10;j++)
{
if(buf[i]>buf[j])
{
int temp=buf[i];
buf[i]=buf[j];
buf[j]=temp;
}
}
}
avgValue=0;
for(int i=2;i<8;i++) //take the average value of 6 center sample
avgValue+=buf[i];
float phValue=(float)avgValue*5.0/1024/6; //convert the analog into millivolt
phValue=3.5*phValue+Offset; //convert the millivolt into pH value
Serial.print(" pH:");
Serial.print(phValue,2);
Serial.println(" ");
digitalWrite(13, HIGH);
delay(800);
digitalWrite(13, LOW);
}
Rantamplan, parece que tienes poca idea de como es la estructura de un programa en Arduino o te malentiendo y quieres ayudar con ese código pero no sirve para este microcontrolador.
Basicamente un programa de arduino tiene un área de definiciones y librerías
una de setup
y finalmente el loop que se ejecuta indefinidamente.
#include <Librerias.h>
// variables globales.
void setup() {
// cosas que se inicializan 1 sola vez
}
void loop() {
// Programa que se ejecuta indefinidamente
}
El código que has puesto es para otro microcontrolador que nada tiene que ver con Arduino mas que la programación en C. Una un compilador muy reconocido que se llama Keil que nada tiene que ver con Arduino.
Entonces cuando busques información pones en Google: arduino ph shield 1.1 y ahi tienes tus códigos.
Gracias, lo de la estructura lo tengo claro, creia que keil era la libreria, es lo que tiene la falta de estudios y la ignorancia.
He cargado el codigo,
/*
# This sample code is used to test the pH meter V1.1.
# Editor : YouYou
# Date : 2014.06.23
# Ver : 1.1
# Product: analog pH meter V1.1
# SKU : SEN0161
*/
#define SensorPin A2 //pH meter Analog output to Arduino Analog Input 2
#define Offset 0.00 //deviation compensate
#define LED 13
#define samplingInterval 20
#define printInterval 800
#define ArrayLenth 40 //times of collection
int pHArray[ArrayLenth]; //Store the average value of the sensor feedback
int pHArrayIndex=0;
void setup(void)
{
pinMode(LED,OUTPUT);
Serial.begin(9600);
Serial.println("pH meter experiment!"); //Test the serial monitor
}
void loop(void)
{
static unsigned long samplingTime = millis();
static unsigned long printTime = millis();
static float pHValue,voltage;
if(millis()-samplingTime > samplingInterval)
{
pHArray[pHArrayIndex++]=analogRead(SensorPin);
if(pHArrayIndex==ArrayLenth)pHArrayIndex=0;
voltage = avergearray(pHArray, ArrayLenth)*5.0/1024;
pHValue = 3.5*voltage+Offset;
samplingTime=millis();
}
if(millis() - printTime > printInterval) //Every 800 milliseconds, print a numerical, convert the state of the LED indicator
{
Serial.print("Voltage:");
Serial.print(voltage,2);
Serial.print(" pH value: ");
Serial.println(pHValue,2);
digitalWrite(LED,digitalRead(LED)^1);
printTime=millis();
}
}
double avergearray(int* arr, int number){
int i;
int max,min;
double avg;
long amount=0;
if(number<=0){
Serial.println("Error number for the array to avraging!/n");
return 0;
}
if(number<5){ //less than 5, calculated directly statistics
for(i=0;i<number;i++){
amount+=arr[i];
}
avg = amount/number;
return avg;
}else{
if(arr[0]<arr[1]){
min = arr[0];max=arr[1];
}
else{
min=arr[1];max=arr[0];
}
for(i=2;i<number;i++){
if(arr[i]<min){
amount+=min; //arr<min
min=arr[i];
}else {
if(arr[i]>max){
amount+=max; //arr>max
max=arr[i];
}else{
amount+=arr[i]; //min<=arr<=max
}
}//if
}//for
avg = (double)amount/(number-2);
}//if
return avg;
}
la lectura sale invertida, los acidos por encima de 8 y alcalinos no por debajo, como se modifica esto?
Podes comprobar que la salida de la sonda sensora de PH es similar a la tabla?
La sonda para pH4 me da valores altos de pH calibrando analogicamente abarco un rango de pH de 9.30 a 13.00 y creo que la correspondencia lineal entre mV y pH esta invertida.
Bueno parece que hablamos de sondas diferentes de modo que habrá que considerar ajustar las cosas de otro modo.
Hay que hacer una calibración y modificar la recta para obtener offset y pendiente de la recta que SI represente a esa sonda.
Son dos o mas puntos pero supongamos dos.
y2 = m*x2 + b
y1 = mx1 + b
donde
b = ordenada al origen u offset
m = pendiente de la recta que será negativa por estar invertida
y2,x2 par de puntos en calibración 2
y1,x1 par de puntos en calibración 1.
Y es ph
X es lectura que toma el arduino via ADC.
Despejan b y m y obtienen la respuesta.
Si restan 1 de 2 eliminan b m = (y2- y1)/(x2-x1)
reemplazan en una ecuación y tienen b
b = y1-mx1= y1 - (y2- y1)/(x2-x1)x1
__b = (y1x2-y2*x1)/((x2-x1))__
Tu ecuación será: y (en ph) = m*X(en mV del ADC) + b
con m y b obtenidos previamente.
Asi que debes hacer un programa que permita calibrar y otro que permita usar los valores de m y b para obtener la lectura que buscas.
Buffer solution Con ph 7.0 voltage: 2.84 mV y pH value : 9.94
Con ph 4.0 voltage: 3.37 mV y pH value : 11.78
directamente midiendo con el multimetro con ph 7 da 2.819mv
ph 4 da 3.342mv
Son dos o mas puntos pero supongamos dos.
y2 = mx2 + b 7.0 = m2.84 + b
y1 = mx1 + b 4.0 = m3.37 + b
donde
b = ordenada al origen u offset
m = pendiente de la recta que será negativa por estar invertida
y2,x2 par de puntos en calibración 2
y1,x1 par de puntos en calibración 1.
Y es ph
X es lectura que toma el arduino via ADC.
Despejan b y m y obtienen la respuesta.
Si restan 1 de 2 eliminan b
m = (y2- y1)/(x2-x1) m = (7.0- 4.0)/(2.84-3.37)= -5.6603773585
reemplazan en una ecuación y tienen b
b = y1-mx1= y1 - (y2- y1)/(x2-x1)x1
b = (y1x2-y2x1)/((x2-x1)) b = (4.02.84-7.03.37)/((2.84-3.37))= 23.0754716981
Tu ecuación será: y (en ph) = m*X(en mV del ADC) + b
con m y b obtenidos previamente.
float PH_Sensor(int pin_PH){
int ADC;
float Tension,nivel;
ADC=analogRead(pin_PH);//Leemos en el canal pin
Tension=ADC_to_Volt(ADC);//Conversion a Voltios
nivel=-5.6603773585*(Tension)+23.0754716981; // ecuación de surbyte
return nivel;
}
float ADC_to_Volt(int ADC_value){
float Volt=0;
Volt=(ADC*5.0)/1023;
return Volt;
}
se ajusta a ph 4 y a ph 7 en cuanto tenga un calibrador dijital o liquido "buffer" con otro Ph para contrastar la lectura comentare... con mas puntos de referencia se puede aplicar el comando pow por si en vez de recta resulta que es curva
Gracias one more time.
Gracias por el interés surbyte y Rantamplan, si a mi también me quedan las clases algo lejos jeje, las usaba un montón con el espectrofotometro para las rectas de calibración en determinación de metales pesados en las aguas y es una pena que todo lo que no usamos cotidianamente se vaya perdiendo...
Le echare un ojo hoy a la sonda y trasteare un rato a ver si consigo algo.
Gracias de nuevo a todos, hoy he "reaprendido" mucho.
Yes okyanusumhakan than the moment I only calibrate with two points, try to charge the last two codes and compile it, Po pin to analog input, vcc to 5v and grnd--grng, later with the pot on shield accurate it... my English not is so good but... report results
Haciendo un intento de mejorar el codigo, en el monitor sale a izquierda la lectura pasando por el "estabilizador", a la derecha la lectura que viene directa de la ecuación sobre adc-volt.
No consigo hacer una media con decimales, alguna idea? Después veo que al alimentar otros dispositivos (una pcb con relé y dos leds) incluso creo que el led tx del usb al parpadear hace que varie la lectura del ADC/Volt/PH, creo que con AREF se soluciona, algun aporte? Se puede disponer el codigo mas ordenadamente ?
const int numReadings = 10;
int readings[numReadings]; // la lectura de la entrada analógica
int index = 0; // el índice de la lectura actual
float average = 0; // la media
int total = 0;
void setup(){
Serial.begin(9600); //Abrir comunicacion con el monitor
// inicializa todos los elementos del arreglo con 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
pinMode (2, OUTPUT);
}
void loop(){
float medida;
medida=PH_Sensor(2);
// resta la última lectura
total= total - readings[index];
// lectura del sensor
readings[index] = (medida);
// suma la lectura actual y el total
total= total + readings[index];
// avanza al siguiente elemento del arreglo
index = index + 1;
// si se llego al final de arreglo (al último elemento)
if (index >= numReadings)
// se vuelve al primer elemento (índice 0)
index = 0;
// calcula la media
average = total / numReadings;
// envía el resultado a la PC
delay(1); // retraso entre lectura y lectura para la estabilidad
//imprime en monitor
Serial.print(" Lectura Sonda: ");Serial.print(medida);Serial.println(" pH");
Serial.print(" estabilizada: ");Serial.print(average);
delay(500);
}
float PH_Sensor(int pin_PH){ //nombre variable
int ADC;// crea nombre para almacenar variables
float Tension,nivel; //nombre variables
ADC=analogRead(pin_PH);//Leemos en el canal pin
Tension=ADC_to_Volt(ADC);//Conversion a Voltios
// conversion a rango ph nivel = pendiente de la
//recta por voltaje ADC mas ordenada al origen
nivel=-5.6603773585*(Tension)+23.0754716981;
return nivel; // devuelve nivel a ph sensor
}
//conversion a lectura 0-5v
float ADC_to_Volt(int ADC_value){
float Volt=0;
Volt=(ADC*5.0)/1023;
return Volt;
}