Table of Contents
- Project Introduction
- Getting Started
- Calibrating the MPX2050DP Pressure Sensor
- Calculations and Noise Reduction
- Using Vivado and Testing the System
- Project Report Updated
**********************************************************************************************************************
Using Vivado
Here I have used the same project from the third blog, that is: "Cmod S7-25 XADC Demo"
I have used and modified the "Cmod S7-25 XADC Demo" example. So the main.c looks as shown below:
/* * This is the demo main file for the Cmod S7-25 XADC demo. * * Changelog: * 06/07/2018 (ArtVVB): Created * * */ #include "xparameters.h" #include "xsysmon.h" #include "xil_printf.h" #include "xil_cache.h" #include "sleep.h" #define XADC_DEVICE_ID (XPAR_XADC_WIZ_0_DEVICE_ID) // TODO: create an "xadc/" subdirectory of project src. make as portable to other boards/xadc configs as possible typedef struct XadcInfo { int NumChannels; int Channels[2]; int ChannelIsDiff[2]; char *ChannelNames[2]; } XadcInfo; typedef struct Xadc_ChannelInfo { int SequencerIndex; int IsDiff; char *Name; } Xadc_ChannelInfo; void Xadc_Init(XSysMon *InstancePtr, const Xadc_ChannelInfo DeviceInfo[], const int NumChannels, const u32 DeviceId); void Xadc_ReadData(XSysMon *InstancePtr, const Xadc_ChannelInfo DeviceInfo[], const int NumChannels, u16 RawData[]); void EnableCaches(); void DisableCaches(); // Initialize the XADC Wizard IP void Xadc_Init(XSysMon *InstancePtr, const Xadc_ChannelInfo DeviceInfo[], const int NumChannels, const u32 DeviceId) { u32 ChannelsMask; u32 InputModeMask; int i; XSysMon_Config *xadc_cfg_ptr; xadc_cfg_ptr = XSysMon_LookupConfig(DeviceId); XSysMon_CfgInitialize(InstancePtr, xadc_cfg_ptr, xadc_cfg_ptr->BaseAddress); ChannelsMask = 0; InputModeMask = 0; for (i = 0; i < NumChannels; i++) { ChannelsMask |= 1 << DeviceInfo[i].SequencerIndex; if (DeviceInfo[i].IsDiff) InputModeMask |= 1 << DeviceInfo[i].SequencerIndex; } // Disable the Channel Sequencer before configuring the Sequence registers. XSysMon_SetSequencerMode(InstancePtr, XSM_SEQ_MODE_SAFE); // Leave alarm enables default // Leave channel averaging default // Set single-ended input mode for all channels XSysMon_SetSeqInputMode(InstancePtr, InputModeMask); // Leave acquisition time default XSysMon_SetSeqAcqTime(InstancePtr, ChannelsMask); // Enable all channels XSysMon_SetSeqChEnables(InstancePtr, ChannelsMask); // Leave the ADCCLK frequency default // Leave calibration default // Enable the Channel Sequencer in continuous sequencer cycling mode XSysMon_SetSequencerMode(InstancePtr, XSM_SEQ_MODE_CONTINPASS); } // Captures Data from each XADC Channel void Xadc_ReadData(XSysMon *InstancePtr, const Xadc_ChannelInfo DeviceInfo[], const int NumChannels, u16 RawData[]) { //TODO: implement timeout on status check int i; // Clear the Status XSysMon_GetStatus(InstancePtr); // Wait until the End of Sequence occurs while ((XSysMon_GetStatus(InstancePtr) & XSM_SR_EOS_MASK) != XSM_SR_EOS_MASK); //Capture data from each channel, return via RawData for (i = 0; i < NumChannels; i++) { RawData[i] = XSysMon_GetAdcData(InstancePtr, DeviceInfo[i].SequencerIndex); } return; } int main() { const int NumChannels = 2; const Xadc_ChannelInfo CmodS7_XadcInfo[2] = { {21, 0, "AIN_32"}, // VAUX_5 {28, 0, "AIN_33"} // VAUX_12 }; const int Xadc_VoltageScaler_SingleEnded = (0xFFFF) / (1000 * 3.3); // FROM 0 TO 3300 mv XSysMon Xadc_Ctrl; u16 Xadc_RawData[2]; int Xadc_Voltage; // x100 from actual value. Two decimal point precision. int Xadc_VoltageRemainder; //float X_test; int i; EnableCaches(); xil_printf("Initializing Cmod S7-25 XADC Demo...\n\r"); Xadc_Init(&Xadc_Ctrl, CmodS7_XadcInfo, NumChannels, XADC_DEVICE_ID); xil_printf("Demo Initialized\n\r"); while (1) { Xadc_ReadData(&Xadc_Ctrl, CmodS7_XadcInfo, NumChannels, Xadc_RawData); for (i = 0; i < NumChannels; i++) { // Convert raw data in this channel to an int in the range 0 to 330, representing // the voltage on that input channel multiplied by 100 Xadc_Voltage = ((int)Xadc_RawData[i] / Xadc_VoltageScaler_SingleEnded); if ((Xadc_Voltage == 1890)) { xil_printf("%s h->00cm "); } if ((Xadc_Voltage >= 1891 && Xadc_Voltage <= 1894)) { xil_printf("%s h->01a05cm "); } if ((Xadc_Voltage >= 1895 && Xadc_Voltage <= 1898)) { xil_printf("%s h->06a10cm "); } if ((Xadc_Voltage >= 1899 && Xadc_Voltage <= 1902)) { xil_printf("%s h->11a15cm "); } if ((Xadc_Voltage >= 1903 && Xadc_Voltage <= 1906)) { xil_printf("%s h->16a20cm "); } if ((Xadc_Voltage >= 1907)) { xil_printf("%s h->21cm "); } Xadc_VoltageRemainder = Xadc_Voltage % 1000; Xadc_Voltage = (Xadc_Voltage/1000) % 100; // Print the name of the channel, followed by the voltage xil_printf("%s: %01d.%03dV ", CmodS7_XadcInfo[i].Name, Xadc_Voltage, Xadc_VoltageRemainder ); } xil_printf("\n\r"); usleep(500000); // wait 500ms } DisableCaches(); return 0; } void EnableCaches() { #ifdef __MICROBLAZE__ #ifdef XPAR_MICROBLAZE_USE_DCACHE Xil_DCacheEnable(); #endif #ifdef XPAR_MICROBLAZE_USE_ICACHE Xil_ICacheEnable(); #endif #endif } void DisableCaches() { #ifdef __MICROBLAZE__ #ifdef XPAR_MICROBLAZE_USE_DCACHE Xil_DCacheDisable(); #endif #ifdef XPAR_MICROBLAZE_USE_ICACHE Xil_ICacheDisable(); #endif #endif }
Main modifications:
- Voltage range from 0 to 3300 millivolts
const int Xadc_VoltageScaler_SingleEnded = (0xFFFF) / (1000 * 3.3); // FROM 0 TO 3300 mv
- Height readings range was 5 centimeters
if ((Xadc_Voltage == 1890)) { xil_printf("%s h->00cm "); } if ((Xadc_Voltage >= 1891 && Xadc_Voltage <= 1894)) { xil_printf("%s h->01a05cm "); } if ((Xadc_Voltage >= 1895 && Xadc_Voltage <= 1898)) { xil_printf("%s h->06a10cm "); } if ((Xadc_Voltage >= 1899 && Xadc_Voltage <= 1902)) { xil_printf("%s h->11a15cm "); } if ((Xadc_Voltage >= 1903 && Xadc_Voltage <= 1906)) { xil_printf("%s h->16a20cm "); } if ((Xadc_Voltage >= 1907)) { xil_printf("%s h->21cm "); }
- Print readings with thousandths of voltage
Xadc_VoltageRemainder = Xadc_Voltage % 1000; Xadc_Voltage = (Xadc_Voltage/1000) % 100;
- Take readings every 500 milliseconds
usleep(500000); // wait 500ms
Testing the System
First, it is necessary to glue the hose with silicone on the water container. Below you see a simple tour of this project before putting it to the test.
The tests performed are shown below.
Conclusion
- At the end of this project I can say that it is possible to use a pressure sensor to measure the water level in a container.
- In my case the MPX2050DP pressure sensor handles small voltages from 0 to 50 millivolts. Even with the op amp I only managed to increase it a gain of 200 millivolts.
- In my experiment, I was able to measure distances of 5 centimeters, equivalent to 1 liter of water in the used container. This would be very useful to measure the water level of a tank in which you could measure from 0 to 200 liters.
- If I want to improve the resolution, for example to measure centimeter distances, then it is necessary to use a smaller and more sensitive sensor, for example the MPX5010, which has an output of 0 to 5 volts and without using an operational amplifier.