miércoles, 9 de marzo de 2016

Aforador.

  • Me llega una pregunta a través de mi blog AhoraMeDedicoAlCacharreo, alguien esta intentando construir un aforador con un Arduino y me pide ayuda con las formulas. 
  • El aforador mide el nivel de ocupación de un depósito de agua cilíndrico tumbado. De alguna manera se mide la altura o nivel de agua con respecto al suelo.
  • Para emular el sensor de nivel utilizo un potenciometro o divisor de tensión en A0.
  • El espacio vacío, visto desde el alzado, deja un segmento circular sin ocupar. El área del segmento circular es el área del sector circular (quesito) menos el área del triangulo definido por los radios y la cuerda del segmento  vacío (ver gráfica).
Me entra la curiosidad y me pongo a ello. Recupero algunos conceptos ya casi olvidados.
  • Sector circular. "Quesito" que contiene el segmento circular.
  • Segmento circular. Intento encontrar las fórmulas en internet , no me entero de nada, y decido desarrollarlas por mi mismo. A veces es necesario este tipo de decisiones para refrescar conocimientos.
  • Coseno del ángulo suplementario:\cos \alpha = -\cos (180^\circ - \alpha) 
  • Teorema de Pitágoras.
Empiezo el desarrollo de las fórmulas que me permitan calcular los volúmenes correspondientes. Creo que no me he equivocado, creo que las fórmulas son correctas, pero pudiera suceder que no. Ahí va mi borrador.


  • No me entiendo a mi mismo. No se por que calculo de una manera tan rara el tercer lado del triángulo (1/2 de b), si con aplicar directamente  Pitágoras  vale. Conozca la hipotenusa y uno de los catetos, luego R²=h²+b²=>b²=R²-h²=>b=raiz(R²-h²). Podría justificarme diciendo que así utilizamos, y refrescamos, trigonometría.
  • Preparo una batería de medidas para comprobar un posible error al calcular las fórmulas.
  • H, altura del nivel del líquido, H=2*R (2*Radio). Esto equivale a barril lleno. Esta prueba la cumplen.
  • H, altura del nivel del líquido, H=R (Radio). Esto equivale a barril medio lleno. Esta prueba la cumplen.
  • Dos medidas con H=2R-x y H=x. El espacio libre en la primera medida debe ser igual al espacio lleno de la segunda medida y viceversa. Esta prueba también la cumplen para cualquier probado de x.

  • Si menos de la mitad del barril está lleno el segmento  circular menor es el espacio ocupado, no el espacio vacío.


  • Cuando barril tiene un nivel menor a la mitad la altura del  barril, las formulas calculadas siguen valiendo. La altura del triangulo y el coseno del ángulo pasan a ser negativos. Para cosenos negativos la función ACOS de excel y la función  ATAN2 de arduino devuelven el ángulo suplementario, aquel que sumado al ángulo da 180º, lo que al repartir el área del circulo proporcionalmente nos da el área ocupada por el resto del circulo. Como el área del triángulo da negativo, recordemos que h es negativo, al restarla, añadimos al resto del circulo ese valor,  sumando todo ello la parte no ocupada del barril.


Llevo las fórmulas a excel. Utilizo variables con nombre.
  • A=H-R
  • Area_Sector=R^2*ACOS(A/R)
  • Area_Segmento=Area_Sector-Area_Triangulo
  • Area_Triangulo=A*RAIZ(R^2-A^2)
  • H=$Aforador.$E$2
  • L=$Aforador.$B$2
  • R=$Aforador.$A$2
  • Radio=$Aforador.$A$2
  • V=$Aforador.$D$2
  • Volumen_ocupado=V-Volumen_Segmento
  • Volumen_Segmento=Area_Segmento*L
  • Traduzco el desarrollo en excel a código Arduino.

Código Arduino:



#include <math.h>



double Pi=3.1415926536;

double Radio=50,Longitud=100;

double V=pow(Radio,2)*Pi*Longitud, h,AT,HAnt,ASec,ASeg,VSeg,VOcu,PorCen;



unsigned long H;



void setup()

{

Serial.begin(9600);

Serial.println(V);

Calculos();

}



void loop()

{

    H=analogRead(A0)*2*Radio/1023;

  if(H!=HAnt)

  {Calculos();

  //  Serial.println(H);

    HAnt=H;

  }

 

}



void Calculos()

{



  h=H-Radio;

  // Area del triangulo h*RAIZ(R^2-h^2)

  AT=h*sqrt(pow(Radio,2)-h*h);

 // area del sector R^2*ACOS(A/R)

 ASec=pow(Radio,2)*MiACos(h/Radio);

 //Area_Sector-Area_Triangulo

 ASeg=ASec-AT;

 //Volumen segmento Area_Segmento*Longitud

 VSeg=ASeg*Longitud;

 VOcu=V-VSeg;

 PorCen=VOcu*100/V;

 Serial.println("****************************************");

 Serial.println(Radio);

 Serial.println(Longitud);

 Serial.println(V);

 Serial.println(AT);

 Serial.println(ASec);

 Serial.println(ASeg);

 Serial.println(VSeg);

 Serial.println(VOcu,2);

 Serial.println(PorCen,2);

 Serial.println("****************************************");

}



unsigned long Fact(long N)

{unsigned long I;

 unsigned long R=1;

 for(I=1;I<=N;I=I+1)

 {

  R=R*I;



 }

return R;

}



float Grados(float Rd)

{

  float G=(Rd*360)/(2*Pi);

return G;



}



float Radianes(float G)

{

  float Rd=(G*Pi)/180;



return Rd;



}











float Pi4()



{

float signo=1,i;

float p=0,x4=1/2+1/3,x1,x2,x3 ;//1/2+1/3:



for(i=1;i<40;i=i+2)

{

  x1=signo/i;



  x2=1/pow(2.0,i);

  x3=1/pow(3.0,i);



/*

if(i>15)

 {

  x2=1/pow(2.0,15);

  x2=x2/pow(2.0,i-15);

  x3=1/pow(3.0,15);

  x3=x3/pow(3.0,i-15);



 }*/

//p=p+signo/(i*pow(2.0,i))+ signo/(i*pow(3.0,i));

p=p+x1*x2+x1*x3;

signo=signo*(-1) ;

/*Serial.print(i,0);

Serial.print(" ");

Serial.print(x2,20);

Serial.print(" ");

Serial.println(x3,20);*/

}



return p;

}







float MiACos(float R)

{

float S, C, T;

C = R;

S = sqrt(1 - pow(R , 2));









return atan2(S,C);



}





float MiASen(float R)

{

float S, C;

S = R;

C = sqrt(1 - pow(R , 2));







return atan2(S,C);



}