With the communication system working, one of the final major tasks left was constructing the AUV. Our initial designs for the AUV were pretty simplistic, as we did not realize the enormity of the many mechanical challenges involved in getting a vehicle to move fluidly through the water at different depths while never springing a leak that would damage the electronics inside. On top of these challenges, the vehicle could not be sealed completely shut with a sealant or epoxy, as we had to be able to access our electronics for reprogramming/debugging tasks and also had to be able to disconnect and reconnect the sensors so that the vehicle could be modular and accept multiple types of sensors other than simply the ones we picked here. So eventually the design became quite sophisticated, and something we're really proud of now. The design ended up looking much like a traditional underwater glider, and was actually based greatly off of the OSUG: Open-Source Underwater Glider hackaday project (which can be found here https://hackaday.io/project/20458-osug-open-source-underwater-glider). So thanks so much to that project for the inspiration!
The first major design choice we made was to build the major structural components of the AUV our of PVC piping and PVC fittings. PVC is relatively cheap compared to other potential options like acrylic, and PVC fittings are by design meant to prevent water leaks. So we put our trust in the plumbers of America, and tested how far we could push the waterproofing of conventional PVC pipe connections.
Before discussing the ins and outs of how we built what, its worth having a small discussion about sealants/epoxys. No matter what, this application required some form of sealant or epoxy for fusing joints of separately constructed components. As we did not have very advanced machinery available to us (or much knowledge on how to design precisely for waterproofing applications for that manner, as we are all electrical and computer engineers), sealants became very important for filling in any designed or accidental gaps in our assembly. For the AUV, we used four different types of sealants: conventional PVC cement, Loctite Marine Epoxy, Flexible Loctite Marine Sealant, and 100% silicone caulk. The PVC cement was used for fusing all PVC-to-PVC connections, and worked perfectly for us as it never sprung a leak. The Loctite Marine Epoxy (which can be found here https://www.bluerobotics.com/store/cables-connectors/tools/loctite-marine-epoxy/) was a two-part epoxy that formed a hard, durable surface when cured. We loved this epoxy and found it to be extremely effective. It only took two hours to set and was cured enough for testing (basically a full cure after 24 hours), which helped a lot as we wanted to test the AUV really quickly after building different stages of it. This therefore became our go-to epoxy, and was used for attaching sensors to their housings, filling in gaps around the clamps holding on the AUV nose, and for filling the edge of the water intake hole. As it was a two-part sealant, we had to mix it on a surface before applying it. We typically mixed it on a removable surface such as duct tape, and then inserted the mixed solution into a cheap syringe from CVS for application.
The Flexible Loctite Marine Sealant (which can be found here https://www.homedepot.com/p/Loctite-PL-Marine-3-fl-oz-Fast-Cure-Adhesive-Sealant-2020627/206156433) was also a great choice for us, as it provided a seal that was almost as reliable as the hard Loctite sealant while still being flexible in its form. Thus, it was great for portions of the AUV that would be under more stress and needed the "give" of a flexible material. In fact, some areas that we used the hard Loctite sealant on ended up forming cracks in the sealant when the vehicle was put under stress. We filled these cracks with the flexible sealant to prevent any future cracks, and never had any problems with it. This was the last sealant we found, so it honestly didn't get as much use as it should have. In hindsight we would have used this more for some of our more stressed connections. The final sealant we used was regular silicone caulk. We had read online that 100% silicone caulk was a cheap way to seal edges for below waterline applications. However, this caulk definitely gave us more problems than it was worth. We thought it would be good for repairs as it was flexible and boasted a 30 minute setting time. In reality, when enough caulk is used (which was necessary for some of our larger gaps), setting took longer than 24 hours. A full cure took a few days. We definitely wouldn't recommend this for future use, as the flexible Loctite sealant is just as cheap and works way better. So if you're planning on replicating this design or doing something similar, we advise staying away from the caulking options.
With that longer than intended sealant discussion out of the way, let's move onto the cooler parts of this design. One of our first steps of ingenuity was using threaded PVC caps to make our sensors modular. For most of our sensor sizes, regular old 3/4'' male threaded PVC plugs (https://www.homedepot.com/p/Charlotte-Pipe-3-4-in-PVC-Sch-40-Plug-PVC-02113-0800HD/203850342) worked perfectly. We simply drilled a hole in the wall of the plug that just allowed the particular sensor at hand to slip through it, and then we sealed the edge between the plug and the sensor with the hard Loctite epoxy. Done. By then using a 3/4'' female fitting attached to the AUV, the sensors could be screwed onto and off of the AUV for an easy waterproof seal. The male plugs were also covered with standard plumber's tape to ensure a waterproof seal. There were a few exceptions to this design as well, though. For one, the ROV tether used to attach the AUV to the ASV did not need any PVC fittings, as being a Blue Robotics product we simply bought the appropriate cable penetrator (https://www.bluerobotics.com/store/cables-connectors/penetrators/penetrator-10-25-a-8mm-r2/) to go with it and connected the cable penetrator directly to the AUV's back. The second tether we used also used a similar penetrator. Our pH sensor also didn't need a plug fitting, as it was already male-threaded on its handle and could screw directly into a female PVC fitting on the AUV. Our turbidity sensor was also too big and oddly shaped for the PVC plugs we found, so we ended up using a trap adapter to build this attachment instead (https://www.homedepot.com/p/NIBCO-1-1-2-in-PVC-DWV-Trap-Adapter-C480127HD112/100347086?MERCH=REC-_-PIPHorizontal2_rr-_-100345781-_-100347086-_-N). Finally, our depth/temperature sensor was also threaded and could be inserted directly into the AUV while still being modular. As the surface area of the AUV's back (a 4'' diameter circle resulting from the main body being a 4'' diameter PVC pipe) to attach each sensor directly to the back's surface, we created a breakout attachment for two sensors using some 3/4'' PVC pipe, a 90 degree PVC fitting, and a tee PVC fitting. Some images of these modular sensor housings are shown below.
Sensor fittings with pH sensor adapter (rightmost hole) visible
Overview of sensor fittings, with blue ROV tether, yellow ROV tether, depth/temperature sensor (red), turbidity sensor (back), conductivity sensor (top left), and dissolved oxygen sensor (top right)
Turbidity sensor being fitted to trap adapter housing
As seen in these images, the sensors all attached to a 4'' PVC cap placed on the end of the main 4'' pipe body of the AUV. Holes were drilled into this cap to attach the fittings. The cap was PVC sealed to the pipe, and the female attachments were also PVC and hard Loctite sealed to the cap. The back of the vehicle was thus not removable, and all inserting and removal of the inner electronics would occur through the front of the AUV. Therefore, the front of the AUV had to be designed to be both waterproof and removable. The conventional means of doing so would be by creating an O-ring attachment for the AUV nose. However, given our lack of experience in O-ring design, lack of machinery for creating the specific grooves needed by the O-rings, and lack of time, designing a custom O-ring attachment was not an option. Our solution, therefore, came from stumbling upon what's called a PVC test plug (found here https://www.homedepot.com/p/Oatey-4-in-Gripper-Mechanical-Plastic-Test-Plug-33403D/100204964). The plug was designed for 4'' PVC piping and is meant to seal off a pipe when repairs are being performed on it. The plug features an expandable O-ring that forms a watertight seal when screwed onto the end of the pipe. Therefore, we simply had to screw this plug into the PVC nose and we were set to have a watertight, removable front seal.
The next task was figuring out how to configure the water intake for the buoyancy system in such a way that it could be easily detached and reattached when the inner electronics/buoyancy system had to be inserted and removed. We opted to have a tube on the inner buoyancy system attach in a removable manner to an intake hole with a prong on the end. To make sure that the prong did not stick up too far and block the inner housing from being inserted, it was attached in the gap of a male-to-male 4'' PVC fitting. This fitting can be seen on the end of the AUV right before the nose. This also allowed the nose (a 4'' PVC cap) to sit flush on another surface, allowing us to install clamps on the nose and put a secondary O-ring in the groove between nose and male-to-male fitting for additional waterproofing. A guide was also installed on the nose cap for guiding the ROV tethers from the back of the AUV to its front and for securing the tethers firmly to the AUV. Thus, the front of the AUV was assembled in the order of main PVC body --> male-to-male fitting --> small 4'' PVC pipe piece --> 4'' test plug --> clamped on nose cap. An image of the almost finished AUV externals can be seen below.
The final step in finishing the AUV externals was to build and attach the wings. The wings were meant to stabilize the vehicle and prevent it from any excessive rolling as it moved through the water. The wings themselves were made of two thin aluminum sheets purchased from Home Depot. Aluminum bars of 1/4'' thickness were screwed into the wing sheets to give them additional support. The wings were mounted to the AUV using two 3D printed wing mounts, based on the design from the open source underwater glider mentioned previously. The final AUV externals can be seen in the following images.
10. Building the AUV - Internal
The internals of the AUV performed the heavy work of actually taking water quality measurements and controlling the submersible's buoyancy. Evidently, it also required a sophisticated mechanical design to fit the necessary components into the confined 4'' pipe main housing while still maximizing the vehicle's performance. We again used the OSUG: Open-Source Underwater Glider hackaday project (which can be found here https://hackaday.io/project/20458-osug-open-source-underwater-glider) to assist us in building this design, so thanks again to that project!
The first design parameter that had to be decided upon was picking out the syringes that would be used in the submersible for buoyancy control. We wanted to maximize the volume of water that we could pull into the syringes to correspondingly maximize the control over the AUV's buoyancy that we had. However, at the same time we wanted to minimize the space taken up by these syringes so that we could fit the entire internal system in a pipe of 2 feet in length. Obviously, these two goals conflicted with each other, so we had to settle on the perfect middle ground between the two.
After performing some calculations with the 4'' x 2' main PVC pipe housing dimensions and the dimensions of the different syringe options we found online, we decided on using three 150 mL syringes for buoyancy control (which can be found here https://www.amazon.com/gp/product/B07BJ9P8FP/ref=ppx_od_dt_b_asin_title_s00?ie=UTF8&psc=1). These three syringes were just barely capable of fitting side by side into a custom mount that could fit inside the 4'' pipe. Additionally, the total volume of water capable of being captured by these syringes (450 mL) was greater than the volume produced by any other combination of syringes of other sizes that could still fit in the 4'' pipe. Thus, this syringe combination effectively maximized our potential for intaking water for buoyancy control out of all of the syringe options we saw in our search. Assuming a water density of 1000 kg/m^3 (1 g/mL) for simplicity, this volume of 450 mL would allow us to change the effective buoyancy of the AUV by 450 g, or about 0.992 lbs. In this manner, by calibrating the weight of the AUV to be approximately neutrally buoyant with no water in the syringes, the hope was that by intaking water and changing the effective weight of displaced water (water displaced by the AUV) by about a pound, the AUV would begin to sink at a steady rate even with the forward motion force of the ASV. We performed some empirical testing with the system, and found that we could calibrate the AUV's weight to be close enough to neutrally buoyant (while erring on the positively buoyant side so that the AUV would naturally float with no water in the syringes) that intaking just 115 mL of water into the syringe system would cause the AUV to begin to sink. Intaking the full 450 mL of course made the AUV sink faster. Thus, we proved empirically that our buoyancy system could feasibly allow the AUV to alternate between being positively buoyant and negatively buoyant. When the syringe plungers were fully extended, the syringes measured about 16 inches in length. This would leave about 8 inches of room in the 2' length pipe to fit the component mounts, the stepper motor, the two Arduino Unos, and the sensor interface boards. While this wasn't much space, we developed a design that feasibly squeezed everything in.
The system for controlling the positioning of the syringe plungers (controlling the intake/expelling of water into/from the syringes) functioned as follows. Two 3D printed mounts would attach to the fronts and backs of the syringe bodies to hold them firmly in place. An additional 3D printed mount would attach firmly to the backs of the syringe plungers. Thus, holding the first 3D mounted prints in place and pulling on the second 3D mounted print would allow the syringe plungers to be pulled out. This syringe body and syringe plunger 3D printed mount system is showed in the image below.
The syringe plunger 3D printed mount contained a standard nut (1/4 in.-20) secured in its center and constrained so that it could not move independently of the mount. A 1/4 in.-20 threaded rod was then threaded through this nut and all the way through holes in both ends of the syringe body mount. Two lock nuts were threaded onto the rod on both faces of the end syringe body mount piece. This restricted the rod from having any linear motion. Thus, when the rod was turned, the nut in the syringe plunger mount would thread up or down the rod, thus moving the syringe plungers in or out. In this manner, a motor could be used to spin the 1/4 in.-20 threaded rod and control the positioning of the syringe plungers to intake or expel water. Three thinner #8-32 threaded through rods were used to secure the non-moving mounts together.
A stepper motor was chosen to control the motion of the 1/4 in.-20 center threaded rod as this type of motor would be easiest to interface with while providing great power and range of motion. To attach the stepper motor shaft to the center threaded rod, a 1/4 in.-20 coupling nut was used (https://www.truevalue.com/shop/hardware/fasteners/bolts-nuts/nuts/steel-coupling-nut-coarse-thread-1-4-in-20). Two holes were drilled into the coupling nut for set screws, and the end of the center threaded rod was filed to create a flat face. From here, the coupling nut could be threaded onto the end of the center threaded rod, slipped onto the stepper motor shaft (which was also 1/4 in.), and secured by having two set screws screwed into it (such that the set screws then sat on the flat faces of the threaded rod and the motor shaft). With the coupling nut secured, any motion made by the motor shaft was directly transferred to the center threaded rod with no slipping and very little wasted friction.
The stepper motor we chose for the AUV was a Nema 23 stepper motor (which can be found here https://www.amazon.com/gp/product/B00PNEPF5I/ref=ppx_od_dt_b_asin_title_s00?ie=UTF8&psc=1). The stepper motor had a current limit of 2.8A and a maximum torque output of 178.5oz.in/1.26Nm. We chose this motor based on its size, price, and some back of the envelope torque calculations that a mechanical engineering friend of ours made for us. We predicted that this motor would have plenty of torque to move the plungers effectively, even with the increased pressure force on the intake hole at larger water depths (we wanted the AUV to be capable of reaching a maximum depth of about 30 feet). In reality, some empirical torque experiments we performed with the system proved that it would only be capable of overcoming the water pressure (pushing water out despite the inward pressure force of the water depth) at pressures up to about 6 psi, which occurs at a water depth of about 14 feet. However, as we did not have time to redesign the system after conducting these empirical experiments, we continued forward with this stepper motor and just limited our testing depth more. In the future, we would figure out how to use this motor's torque output more effectively or use a different motor to make the AUV able to travel deeper.
A 3D printed mount was developed to hold the stepper motor in place. Additionally, an interesting 3D mount was developed to hold the two Arudinos, the motor driver, and the four sensor interface boards. This mount took the form of a triangular prism with a hollow center and rounded edges (to sit flush on the round pipe surface). Two of the prism faces were used for mounting the two Arduinos, while the other face was used for mounting three of the sensor interface boards (the conductivity, dissolved oxygen, and pH sensor boards). The motor driver and the last sensor interface board (the turbidity board) were mounted on one of the inside faces. This mount allowed us to place a large number of components efficiently in a very small space (the mount was only 4 inches in length), and can be seen below...
Latex tubing was used at the front of the syringe system to connect the three syringe tips to one central tube that could be connected to the intake hole in the main PVC pipe housing. Additionally, two push buttons were installed to serve as end stops for the syringe plunger mount. One push button was installed on the stepper motor housing facing the plunger mount, and the other was installing in the plunger mount itself facing the syringe body mount. These end stops would be used in emergency situations if the stepper motor accidentally tried to pull/push the plungers past their defined range of motion in either direction. If an end stop button was pushed, the Arduino controlling the stepper motor would stop whatever motion was occurring and understand where the plungers were based on which push button was pressed. The end stops could also be used to calibrate the plunger positioning on startup. By moving the plungers all the way forward until the front push button was pressed on startup, the buoyancy control Arduino would be able to know where the plungers were always on startup and then calculate further plunger positions based on the known movements from this point.
With these designs implemented, the AUV internals were complete. Attached below are some additional images of the internal AUV system.
One of our initial prototypes of the AUV internal system
11. Connecting the AUV to the ASV
To connect the AUV to the topside ASV, two tethers were used. One was an ROV tether developed by Blue Robotics (which can be found here https://www.bluerobotics.com/store/cables-connectors/cables/fathom-tether-nb-4p-26awg-r2/) and the second was a tether from an unknown developer that was found in our capstone lab. The Blue Robotics tether is very high quality and contains four unshielded twisted pairs of 26 AWG wire. Its pretty expensive normally, but you can save a bunch of money if you're able to get one from their "Dings & Dents" page. Blue Robotics uses this page to post some of their used or non-standard items for sale, and they often have their ROV tether posted here to sell some of their already cut but unused cable. The catch here is that you don't get to select your cable size; its randomly picked from their inventory. Blue Robotics has a set of cut cables from previous orders that are of random lengths that are too short to sell as a normal item. They do give you a range of what the size of your cable will be, though. For example, we paid $20 for a cable that would be between 10 and 16 meters in length, and received a cable that was 14 meters long. So if you're looking for a good deal on an otherwise expensive cable and can live with a cable of relatively random length, this is a really good option.
While this Blue Robotics tether contained enough wires for all of the connections we needed between the topside and the AUV, we had a problem with the cable gauge. One of the connections we needed to send down was power for the stepper motor. This power would be a 24 V signal capable of drawing up to 3 A, potentially. However, based on our experience and on some online research, the 26 AWG wire in the Blue Robotics tether could carry a maximum current of 1 A safely. Therefore, as Blue Robotics didn't have any tethers with a larger gauge of wire, we needed a second tether for sending power down. Thankfully, a tether we happened to find from a previous project in our lab worked well, as it seemed to be a power cable for an underwater pool cleaning robot with 20 AWG wire (capable of carrying up to 5 A safely).
So we ended up attaching the two tethers together using zip ties and used them both. The blue tether in all of the images was the power tether used for powering the stepper motor. The yellow tether (the Blue Robotics tether) however was used for powering the two Arduinos (which had a current draw limit of about 800 mA) and for making a serial communication connection between the Raspberry Pi on the ASV and the sensor control Arduino on the AUV. A 12 V rechargeable power supply was connected to a bus on the ASV used to distribute 12 V of power over the yellow tether to the two Arduinos (using two twisted painnected to this 12 V bus to step the voltage up to 24 V to be sent over the blue tether to the stepper motor power input. 12. Programming and Calibrating the Sensors With the AUV completely built, it was time to program and calibrate the sensors. To reiterate, 5 sensors were used to measure water quality parameters in this project: a depth/temperature sensor, a conductivity sensor, a dissolved oxygen sensor, a pH sensor, and a turbidity sensor. The depth/temperature sensor used was the Bar30 High-Resolution 300m sensor produced by Blue Robotics (found here https://www.bluerobotics.com/store/sensors-sonars-cameras/sensors/bar30-sensor-r1/), while the other 4 sensors were all produced by DFRobot. These sensors can be found with the following links.
All of the sensors used featured open source code samples and libraries for calibrating the sensors and working with the measurements taken by the sensors. As such, we were able to leverage these code samples and libraries greatly when calibrating the sensors and writing the Arduino ino file for interfacing with them.
The ino file written for our sensor interfacing Arduino basically just runs through the steps shown in the code samples for taking measurements from each sensor, and then compiles these measurements into a single string message. This single string message is then sent over the serial connection to the Raspberry Pi for decoding, being saved locally on the Pi, packaging into the custom message, and being sent over the radio connection to the GCS.
Of the five sensors used, only one sensor (the depth/temperature sensor) was configured such that it did not need to be calibrated. The remaining sensors all featured some form of a calibration process. The depth/temperature sensor was also the only digital interfacing sensor, as it communicated over I2C. The remaining sensors were all analog sensors that had to be sampled directly by the Arduino.
For the dissolved oxygen sensor, a two-point calibration process was also conducted using the procedure and code explained here https://wiki.dfrobot.com/Gravity__Analog_Dissolved_Oxygen_Sensor_SKU_SEN0237. For this calibration, dipping the probe in water and then exposing it directly to air served as the 100% dissolved oxygen calibration point. The 0% dissolved oxygen calibration point was created by saturating a beaker of distilled water with sodium sulfite (Na2SO3), which would react with the water to consume all of the oxygen in the water. Additionally, it was important to make a solution of 0.5 mol/L NaOH to place in the probe of the dissolved oxygen sensor, as the probe needed this solution to take the measurements properly and the solution was not included with the sensor. We created this solution ourselves by obtaining some NaOH tablets from our chemistry department and then mixing the appropriate weight of NaOH with the appropriate volume of distilled water. The NaOH tablets can also be purchased online. Make sure you do this step correctly, as it is imperative for the correct functioning of the sensor!
For the pH sensor, a two-point calibration process was conducted using a 7.0 pH calibration solution, a 4.0 pH calibration solution, and the code and process explained here https://wiki.dfrobot.com/PH_meter_SKU__SEN0161_. We obtained these calibration solutions from our chemistry department, but they can also be purchased online.
For the turbidity sensor, no formal calibration process was conducted. Most turbidity standards are very expensive to purchase, and our chemistry department and internal contacts did not have any standards on hand. Additionally, the sensor we were using was not incredibly accurate (it is a cheap sensor typically used to measure water cloudiness in dishwashers), so having accurate turbidity standards was not even necessary. We intended on using a Secchi tube to measure the turbidity of some common, cheaper solutions (water, oil, soda, etc.) empirically and then calibrate the sensor based on these solutions, but we did not have enough time to perform these tests. So instead, we simply used the voltage to turbidity in NTU equation provided for the sensor by DFRobot here https://wiki.dfrobot.com/Turbidity_sensor_SKU__SEN0189. This produced reasonable enough results in our testing.
By leveraging the open source code available to us, these sensors were all pretty easy to set up and almost worked right out of the box. The biggest challenges we faced with them were tracking down the appropriate calibration solutions and compiling the various code sources and interfacing methods into a single, cohesive ino file. Performing the wiring to the Arduino was also challenging, as we had to create power and ground busses with very little space and had to neatly assign the sensors to convenient input pins on the Arduino so that a single header could be used to connect all of the analog input signals. With these challenges sorted out, the sensors were all set up and ready to begin taking important water quality measurements. 13. Programming the Stepper Motor Functions and Tuning the Buoyancy Control PID Controller While the sensor Arduino was being programmed, the buoyancy control Arduino also had to be programmed to control the stepper motor and communicate with the sensor Arduino. Thus, the buoyancy control Arduino was programmed to take a depth measurement, take a temperature measurement, send these measurements to the sensor Arduino once per second (the buoyancy control Arduino sampled depth and temperature measurements faster than 1 Hz to achieve a finer PID controller, but the sensor Arduino only sampled measurements at 1 Hz and thus only needed depth/temperature measurements once per second), check to see if the sensor Arduino had a new depth value for the buoyancy system to maintain, and then run the next iteration of the PID loop to update the stepper motor position based on the current depth measurement.
As mentioned previously, the depth/temperature sensor communicated over I2C, and thus had to be connected to the I2C pins on the Arduino. While the depth/temperature sensor we used did not require any calibration, we still utilized a Blue Robotics open source library for interfacing with it. This library can be found here https://github.com/bluerobotics/BlueRobotics_MS5837_Library. Additionally, this sensor ran on 3.3V logic, rather than the 5V logic present on the Arduino. As such, a level shifter had to be connected between the Arduino and the sensor to properly step the Arduino->sensor voltage down to 3.3V and the sensor->Arduino voltage up to 5V (we used this level shifter https://www.amazon.com/gp/product/B07F7W91LC/ref=ppx_od_dt_b_asin_title_s03?ie=UTF8&psc=1). Don't forget to use this level shifter!! This expensive sensor is very delicate, and you do not want to risk frying it.
To control the stepper motor, we leveraged the open source Arduino library for the AMIS-30543 stepper motor driver, which can be found here https://github.com/pololu/amis-30543-arduino/. This library made it relatively painless to send messages to the stepper motor to have it move a given number of rotations at a given speed.
Unfortunately, we were never able to perform the final and biggest step of setting up the buoyancy control system: tuning the PID controller. With the looming due date for the project, we simply did not have enough time to perform the experiments needed for tuning the PID parameters properly. Because of this, we actually did not use the PID controller in our final system tests for generating notable results. We simply performed tests at two "buoyancy levels": one where the AUV floated (the syringes had no water in them) and one where the AUV sunk as far as possible (the syringes were pulled all the way in). In the future, having more time to perform this step would allow us to tune the PID controller to have fine grain control over the AUV's depth. The PID controller would also allow us to update this depth dynamically, as we would be able to send a new "desired depth" from the GCS, to the Pixhawk, to the Pi, to the sensor Arduino, and finally to the buoyancy control Arduino so that it could update the depth attempting to be achieved by the controller. Each of the necessary components (the full communication chain, the code for running the PID controller, the code for controlling the stepper motor, etc.) all worked independently, so in the future we would simply have to tune the PID controller and debug any issues associated with these experiments to achieve the goals just mentioned. Thankfully, we produced impressive results even without the PID controller.
14. Adding a Data Visualization Tab to Mission Planner
At this point, the whole system was created and working as designed. Therefore, the final step we completed before conducting our final system tests was adding a data visualization tab to the Mission Planner GCS application. The purpose of this data visualization tab was to allow the user to visualize the water quality data being captured by the AUV in real-time in a useful manner. Thus, we wanted this visualization tab to include useful visualizations such as temporal plots of quantities, scatter plots of one quantity versus another quantity, heat maps of a given quantity over the geography traversed by the AUV, and common statistics for a given quantity (mean, maximum value, and minimum value).
Again, as Mission Planner is a C# open source application, we modified it by using a Visual Studio C# development environment. To facilitate the creation of a new tab (as we had very little C# experience in our group), we simply took over the currently existing "Help" tab in Mission Planner and modified it to meet our needs. Standard C# GUI graphing tools in Visual Studio were used to generate the temporal plots and the plots of one quantity versus another quantity. Standard display boxes were used to display the common quantity statistics. The method explained here http://dylanvester.com/2015/10/creating-heat-maps-with-net-20-c-sharp/ was used to generate the heat map plot.
To make the plot generation real-time while not wasting resources, Mission Planner was modified to use the following method for handing the incoming water quality data. When the Data Visualization tab was not opened, all of the incoming water quality data would be saved to local RAM in the application. Then, when the Data Visualization tab was opened, the water quality data in RAM would be written to a designated CSV file on the ground control station's hard drive. The RAM would then be cleared, and the CSV file would be read to generate the plots. Thus, every time the Data Visualization tab was opened, the CSV file would be updated with the latest data and the new CSV file version would be used to generate the plots. In this manner, the Data Visualization tab maintained a real-time feel of operation, while not wasting too many resources within the application. This algorithm worked under the assumption that the user would open the Data Visualization tab a fair number of times throughout the mission being conducted, which we felt was a decent assumption to make.
A sample image of the Data Visualization tab we created (with real data from our final testing shown) is given below.