Indicador de Nivel de Gas
Este dispositivo electrónico consiste en un lector remoto de nivel de liquido en tanques estacionarios
Lo que hace es obtener la medición del nivel de liquido en tanques estacionarios por ejemplo de agua o de Gas Licuado, enviar esta información inalambricamente vía Bluetooth a un celular o tablet android con su respectiva App en la que se puede conocer este valor y general una gráfica del historial de cambio de nivel.
La importancia de este dispositivo radica en las ventajas que ofrece al usuario final al permitirle conocer el nivel de liquido de sus depósitos al mismo tiempo que genera una gráfica historial del consumo del mismo recurso dándole la facilidad de administrarlo de una mejor manera.
a continuación se ven varias fotos de la App en funcionamiento con sus respectivas mediciones de un tanque de Gas Licuado:
2
3
4
5
6
7
8
9
0
// MAIN.C file
#include <stm8l15x.h>
#include "stm8l15x_clk.h"
#include "stm8l15x_pwr.h"
#include "stm8l15x_usart.h"
#include "stm8l15x_adc.h"
#include "stm8l15x_i2c.h"
#include "math.h"
#define Mag 0x3C
/*12-bit ADC=4096
8-bit read address 0x3D
8-bit write address 0x3C
*/
#define TIMEOUT_MAX 0x3000
//uint8_t GetData=100;
uint16_t RBuffer[2] = {0x00, 0x00};
uint16_t TimeOut;
int16_t Mx=0,My=0,Mz=0;
float Angx,Angy,Angz;
void delay(unsigned long i)
{
unsigned int j;
for(j=0;j<(i*10);j++){;}
}
void Init_Usart(void)
{
/*_____________________Clock Conf______________________*/
CLK_DeInit();
CLK_HSICmd(ENABLE); //highSpeedInternal
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
CLK_HaltConfig(CLK_Halt_BEEPRunning, DISABLE);
CLK_HaltConfig(CLK_Halt_FastWakeup, DISABLE);
CLK_HaltConfig(CLK_Halt_SlowWakeup, ENABLE);
PWR_UltraLowPowerCmd(ENABLE);
/*_____________________Uart Conf________________________*/
USART_DeInit(USART1);
GPIO_ExternalPullUpConfig(GPIOC,GPIO_Pin_2,ENABLE ); //Set the USART RX and USART TX at high level
GPIO_ExternalPullUpConfig(GPIOC,GPIO_Pin_3,ENABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_USART1, ENABLE);// Enable USART clock
USART_Init(USART1,
9600,
USART_WordLength_8b,
USART_StopBits_1,
USART_Parity_No,
USART_Mode_Rx|USART_Mode_Tx);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_Cmd(USART1, ENABLE);
//enableInterrupts();
}
void Init_Adc(void)
{
CLK_PeripheralClockConfig(CLK_Peripheral_ADC1,ENABLE);
GPIO_Init(GPIOA,GPIO_Pin_6,GPIO_Mode_In_FL_No_IT);
ADC_DeInit(ADC1);
ADC_Init(ADC1,ADC_ConversionMode_Continuous,ADC_Resolution_8Bit,ADC_Prescaler_2);
ADC_SamplingTimeConfig(ADC1,ADC_Group_SlowChannels,ADC_SamplingTime_4Cycles);
ADC_VrefintCmd(ENABLE);
ADC_Cmd(ADC1,ENABLE);
ADC_ChannelCmd(ADC1,ADC_Channel_0,ENABLE);
ADC_SoftwareStartConv(ADC1);
}
uint8_t I2C_WriteDR(uint32_t Addr,uint32_t Register,uint8_t Data)
{
// Enable the I2C peripheral
I2C_GenerateSTART(I2C1, ENABLE);
// Test on EV5 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB))
{
if (TimeOut-- == 0){return 0;}
}
// Disable Acknowledgement
I2C_AcknowledgeConfig(I2C1, DISABLE);
// Transmit the slave address and enable writing operation
I2C_Send7bitAddress(I2C1, Addr, I2C_Direction_Transmitter);
// Test on EV6 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR))
{
if (TimeOut-- == 0){return 0;}
}
// Read status register 2 to clear ADDR flag
I2C1->SR2;
// Test on EV8 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE))
{
if (TimeOut-- == 0){return 0;}
}
// Transmit the Register for w operations
I2C_SendData(I2C1, Register);
// Test on EV8 and clear it
TimeOut = TIMEOUT_MAX;
while ((!I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF)))
{
if (TimeOut-- == 0){return 0;}
}
// Transmit the Data for w operations
I2C_SendData(I2C1, Data);
// Test on EV8 and clear it
TimeOut = TIMEOUT_MAX;
while ((!I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF)))
{
if (TimeOut-- == 0){return 0;}
}
// End the configuration sequence
I2C_GenerateSTOP(I2C1, ENABLE);
// Return the read value
return 0;
}
uint8_t I2C_ReadDR(uint32_t Addr,uint32_t Register)
{
uint8_t tmp = 0;
// Enable the I2C peripheral
I2C_GenerateSTART(I2C1, ENABLE);
// Test on EV5 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB))
{
if (TimeOut-- == 0){return 0;}
}
// Disable Acknowledgement
I2C_AcknowledgeConfig(I2C1, DISABLE);
// Transmit the slave address and enable writing operation
I2C_Send7bitAddress(I2C1, Addr, I2C_Direction_Transmitter);
// Test on EV6 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR))
{
if (TimeOut-- == 0){return 0;}
}
// Read status register 2 to clear ADDR flag
I2C1->SR2;
// Test on EV8 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE))
{
if (TimeOut-- == 0){return 0;}
}
// Transmit the first address for r/w operations
I2C_SendData(I2C1, Register);
// Test on EV8 and clear it
TimeOut = TIMEOUT_MAX;
while ((!I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE)) || (!I2C_GetFlagStatus(I2C1, I2C_FLAG_BTF)))
{
if (TimeOut-- == 0){return 0;}
}
// Regenerate a start condition
I2C_GenerateSTART(I2C1, ENABLE);
// Test on EV5 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_SB))
{
if (TimeOut-- == 0){return 0;}
}
// Transmit the slave address and enable writing operation
I2C_Send7bitAddress(I2C1, Addr, I2C_Direction_Receiver);
// Test on EV6 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_ADDR))
{
if (TimeOut-- == 0){return 0;}
}
// Read status register 2 to clear ADDR flag
I2C1->SR2;
// Test on EV7 and clear it
TimeOut = TIMEOUT_MAX;
while (!I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE))
{
if (TimeOut-- == 0){return 0;}
}
// End the configuration sequence
I2C_GenerateSTOP(I2C1, ENABLE);
// Load the register value
tmp = I2C_ReceiveData(I2C1);
// Enable Acknowledgement
I2C_AcknowledgeConfig(I2C1, ENABLE);
// Return the read value
return tmp;
}
void Init_Mag(void)
{
GPIO_Init(GPIOC, GPIO_Pin_1, GPIO_Mode_Out_OD_HiZ_Fast);
GPIO_Init(GPIOC, GPIO_Pin_0, GPIO_Mode_Out_OD_HiZ_Fast);
CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, ENABLE);
I2C_DeInit(I2C1);
I2C_Init(I2C1, 1000, 0, I2C_Mode_I2C, I2C_DutyCycle_2, I2C_Ack_Enable,I2C_AcknowledgedAddress_7bit);
I2C_Cmd(I2C1, ENABLE);
I2C_WriteDR(Mag,0x00,0x78);//=75Hz, or 0x70 = 15 (Default)
I2C_WriteDR(Mag,0x01,0x00);
I2C_WriteDR(Mag,0x02,0x00);
}
uint16_t ArcTang(uint16_t y,uint16_t x)
{
uint16_t z=y/x;
uint16_t at=0;
at=z-((z^3)/3)+((z^5)/5)-((z^7)/7)+((z^9)/9)-((z^1)/1)+((z^13)/13)-((z^15)/15)+((z^17)/17)-((z^19)/19)+((z^21)/21);
return 57.3*at;//180/pi=57.3
}
uint8_t Lectura(void)
{
uint8_t Ang=0;
return 190;
RBuffer[0]=I2C_ReadDR(Mag,0x03);
RBuffer[1]=I2C_ReadDR(Mag,0x04);
Mx=((RBuffer[1]&0x00ff) | ((RBuffer[0]<<8)&0xff00));
RBuffer[0]=I2C_ReadDR(Mag,0x07);
RBuffer[1]=I2C_ReadDR(Mag,0x08);
My=((RBuffer[1]&0x00ff) | ((RBuffer[0]<<8)&0xff00));
/*RBuffer[0]=I2C_ReadDR(Mag,0x05);
RBuffer[1]=I2C_ReadDR(Mag,0x06);
Mz=((RBuffer[1]&0x00ff) | ((RBuffer[0]<<8)&0xff00));*/
Ang=ArcTang(100,100);
}
//arc tan (x) = x - x^3/3 + x^5/5 - x^7/7 + ...
/*int16_t _atan2(float y, float x)
{
#define fp_is_neg(val) ((((uint8_t*)&val)[3] & 0x80) != 0)
float z = y / x;
int16_t zi = abs(int16_t(z * 100));
int8_t y_neg = fp_is_neg(y);
if ( zi < 100 )
{
if (zi > 10) z = z / (1.0f + 0.28f * z * z);
if (fp_is_neg(x))
{
if (y_neg) z -= PI;
else z += PI;
}
}
else
{
z = (PI / 2.0f) - z / (z * z + 0.28f);
if (y_neg) z -= PI;
}
z *= (180.0f / PI * 10);
return z;
}*/
int Conex(void)
{
int i=0,n=0,p=0;//T/2=delay(1000);
for(i=0;i<5;i++)
{
if(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_0)){p++;}
if(!GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_0)){n++;}
delay(500);
}
if( ((p-n)>2)|((n-p)>2) ){return 1;}
else{return 0;}
}
int main()
{
GPIO_Init (GPIOD,GPIO_Pin_0,GPIO_Mode_In_FL_IT);
GPIO_Init (GPIOB,GPIO_Pin_7,GPIO_Mode_Out_PP_Low_Fast);
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
GPIO_Init (GPIOB,GPIO_Pin_4,GPIO_Mode_Out_PP_Low_Fast);
GPIO_ResetBits(GPIOB,GPIO_Pin_4);
PWR_PVDLevelConfig(PWR_PVDLevel_3V05);
PWR_PVDITConfig(ENABLE);
PWR_PVDCmd(ENABLE);
Init_Usart();
//Init_Adc();
Init_Mag();
//enableInterrupts(); problemas!
while(1)
{
if(PWR_GetFlagStatus(PWR_FLAG_PVDOF)==RESET)
{
delay(1000);
while(PWR_GetFlagStatus(PWR_FLAG_PVDOF)==RESET)
{
GPIO_SetBits(GPIOB,GPIO_Pin_7);
if(Conex())
{
while(GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_0))
{
GPIO_SetBits(GPIOB,GPIO_Pin_4);
if(USART_GetITStatus(USART1,USART_IT_RXNE)==SET)
{
if(USART_ReceiveData8(USART1)=='0')
{
/*if(ADC_GetConversionValue(ADC1)<=250)
{USART_SendData8(USART1,ADC_GetConversionValue(ADC1));}
else{USART_SendData8(USART1,250);}*/
USART_SendData8(USART1,Lectura());
}
USART_ClearITPendingBit(USART1,USART_IT_RXNE);
}
}
GPIO_ResetBits(GPIOB,GPIO_Pin_4);
}
}
}
else
{
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
GPIO_ResetBits(GPIOB,GPIO_Pin_4);
}
}
return 1;
}
/*
INTERRUPT_HANDLER(EXTIE_F_PVD_IRQHandler,5)
{
// In order to detect unexpected events during development,
// it is recommended to set a breakpoint on the following instruction.
if (PWR_PVDGetITStatus() != RESET)
{
if (PWR_GetFlagStatus(PWR_FLAG_PVDOF) != RESET)
{// Falling Direction Detected
GPIO_ResetBits(GPIOB,GPIO_Pin_7);
}
else
{// Rising Direction Detected
GPIO_SetBits(GPIOB,GPIO_Pin_7);
}
}
PWR_PVDClearITPendingBit();
}*/
Comments