Introduction: Assistive Aquaponics Fish Tank

About: Hey! I'm Teddy Warner✌️, a maker, and a student at the University of Southern California's Iovine and Young Academy. My passion lies in rapid prototyping & digital fabrication - check out my website, to see so…

A monitored aquaponics ecosystem, expanding the accessibility of successful & thriving aquaponics ecosystems.

Hey, I'm Teddy Warner, a junior in high school enrolled at Charlotte Latin School in Charlotte, North Carolina. I have a great interest in modern fabrication technologies such as 3d printing & CNC machines. I love using these interests to benefit my community through volunteering.

The Assistive Aquaponics Fish Tank is my magnum opus example of mixed media digital fabrication, utilizing a plethora of tools and workflows including ...

  • 3D Printing
  • CNC Milling
  • Laser Cutting/Engraving
  • PCB Design & Milling
  • SMD Soldering
  • And Lots & Lots of CAD Design

This project served as my final project masterpiece concluding my cycle in the Fab Academy . "The Fab Academy is a fast-paced, hands-on learning experience where students learn rapid-prototyping by planning and executing a new project each week, resulting in a personal portfolio of technical accomplishments" (fabacademy.org). The program is a globally distributed offshoot of MIT's How to Make (Almost) Anything course and takes a deep 20-week dive into digital fabrication. Be sure to check out the Assistive Aquaponics Fish Tank's documentation on my fab academy site!

Final Project Concept

I've always had an interest in having my own home garden capable of growing plants and herbs, as I enjoy the access to fresh foods, however, my past attempts at gardening always seemed to be relatively fruitless. Due to my structured high school student schedule, I am usually not around to look after and take care of a garden, and thus, this want for fresh foods hasn't become a reality. My interest in my Fab Academy final project came from this interest in having a home garden that could morph into my tight high school schedule. I started brainstorming this concept and found many projects and articles that were helpful or influential to my idea, some of them being Gardening + Arduino, Garduino, DIY Home Assistant Garden Automation System, Raspberry Pi Powered IOT Garden, and the Advanced Irrigation System. Although looking at projects like these gave me some inspiration, I have many personal design factors that have also helped me form my idea. I started the Fab Academy course with the idea of an Automated Windowsill Garden for my final project, talked about on my Orginal Project Concept page, however as I began work through the class, I expanded on the idea. After talking with Professor Neil Gershenfeld about my Final Project concept in the Computer-Aided Design week lecture, I began to alter my idea from this windowsill box garden, into a garden in a different form factor. While discussing my windowsill box concept, Neil suggested some research into the world of 'ponics', the techniques of growing plant life without soil, where plant roots are placed in a water-mineral solution and fed with liquid fertilizers. After some research, I found the practice of Aquaponics especially appealing to me. "Aquaponics is a system of producing food that combines aquaculture (raising fish, snails, or prawns) and hydroponics (growing plants in water). It can be an elegant closed system whereby the fish produce waste which, in turn, circulates to feed the plants which, in turn, purify the water for the next school of aquatic generations" (The Evolution of “Ponics” in Organic). The second thought that also led me to this change was the form factor of the projects themselves. I attend Fab Academy classes on my Highschool campus after I finished my school day, and carrying in a windowsill box like a coffin to and from our lab every day would be impractical. With this form factor issue comes my third motivation for this change, my family may be moving houses in the upcoming months, and I would not want to build a windowsill box to fit a windowsill on a house that I may not even live in by the end of this course. With all of these thoughts in mind, I was still committed to the idea of a Garden in general, and settled on an aquaponic garden in a fish tank-like form factor, with the plants growing on top of the tank itself. This not only solves my transportation problem, but a fish tank-style aquaponic garden could be placed inside, and then be moved from house to house.

Research, Planning & Sketches

Before starting work on designing, manufacturing, and running an aquaponics system, I set off to learn about the practice of aquaponics more in-depth. As stated previously, "Aquaponics is a system of producing food that combines aquaculture (raising fish, snails, or prawns) and hydroponics (growing plants in water). It can be an elegant closed system whereby the fish produce waste which, in turn, circulates to feed the plants which, in turn, purify the water for the next school of aquatic generations" (The Evolution of “Ponics” in Organic). An Aquaponics system is thus an ecosystem shaped like a closed circle, where each step leads to the next until returned to where the system started. I jotted down this "Circle" concept in the diagram shown below, listing out each step taken in the system to return to the starting place.

Reference the Aquaponics System Diagram visuals above.

When in balance, six steps create a successful aquaponics ecosystem, where all parts of the system rely on the others, a process known as recirculation. The aquatic life of the tank contributes poop and waste food into the ecosystem, creating ammonia, a toxin for the fish, in the water in the process. This generated ammonia is then converted into helpful Nitrites, and eventually, Nitrates by bacteria in the system through a natural process called The Nitrification Cycle, after which, the system's plants absorb these Nitades as plant food, filtering the water in the process, and therefore the eliminating any harmful ammonia in the system's water, returning the system to its starting place. The six major players in the system, Fish, Plants, Bacteria, Ammonia, Nitrites, and Nitrates, rotate around this six-step ecosystem repeatedly, and when kept intolerance with each other, create the thriving aquaponics ecosystem I'm looking for in creating my aquaponics fish tank. In The Effectiveness of Aquaponic Compared to Modified Conventional Aquaculture for Improved of Ammonia, Nitrite, and Nitrate, an academy journal article written by Deswati, Amelliza Deviona, Ella Intan Sari, Yulizar Yusuf, and Hilfi Pardi for the Rasayan Journal of Chemistry, elements of the aquaponic system are analyzed, and some ideal thresholds are given for a balanced system between Fish, Plants, Bacteria, Ammonia, Nitrites, and Nitrates, all with included real-life large scale aquaponics systems. I found this journal super helpful in providing applications to aquaponics and also expanding my understanding of the ecosystem components through the journal's experiments.

Deswati, et al. “The Effectiveness of Aquaponic Compared to Modified Conventional Aquaculture for Improved of Ammonia, Nitrite, and Nitrate.” Rasayan Journal of Chemistry, vol. 13, no. 1, Jan. 2020, p. 1. EBSCOhost, search.ebscohost.com/login.aspx?direct=true&db=edb&AN=142699175&site=eds-live.

With the workings of this system in mind, I began to sketch out a design for my aquaponics tank, where a garden box is located above a fish tank, to allow for optimal water paths. I planned on making this structure from plywood and then adding additional internal sections for both the fish and plants, connecting these two to the plywood structure, which will also house electronics. Attached above are some of these concept sketches, showing the brainstorming of the tank's plywood structure.

Project License

This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.

Supplies

--- Total Cost: $323.60 ---

Software & Tools

  • Autodesk Fusion 360
  • Autodesk Eagle
  • Inkscape
  • An IDE of some sorts - I like VSC with Platform IO, although the Arduino IDE also works great
  • Vectric Aspire
  • Soldering Iron
  • Wire Cutters
  • Tweasers
  • PCB Milling Machine (Or access to order fabricated PCBs)
  • CNC Milling Machine (Or access to order milled parts)
  • Laser Cutter (Or access to order laser cut parts)
  • 3D Printer (Or access to order 3D printed parts)
  • An In-Circuit Programmer- this can be bought or fabricated, be sure to check out my UPDI Serial Programmer
  • Basic Woodworking tools ( Drill, Saw, Chisle, etc.)
  • An M3 Allen Key
  • Gloves & Paper Towel
  • Painter's Tape
  • Corner Clamps
  • Hot Glue Gun

Downloads

Click Here to access and download all files, including CAD, Code, and Schematics, for this project. These files can be used and altered with attribution, as stated and enforced by my project license. In addition to the files included in this downloads folder, please note that Fusion 360 source files can be accessed with the Open in Fusion 360 button in the bottom right-hand corner of each of the embedded designs on this page.

Step 1: Tank Render

Like most makers, I love seeing a project come together. Though my passion lies in all of digital fabrication, the aspect of digital fabrication that is most appealing to me is simply the ability to glimpse a final product even before its fabrication begins. The workflow of digital fabrication, going from bits on a computer to atoms off of your machine ensures one's ability to "prove" an idea. Autodesk's Fusion 360 served as my whiteboard for this project, where I was not only able to produce my final designs for this project but also able to proof ideas during this project's research phase. Below is the final iteration of the Assistive Aquaponics Fish Tank in Fusion 360, version 71.

Step 2: Main Board Prototyping and Design

I started this final project board design process following the same steps I used while making any other board in the previous weeks of this class, beginning the process by creating a schematic of my board. Throughout the schematic creating process, I referenced a prior Fab Academy final project, the Sashakit "an Arduino compatible, fabbable board, and also an improved version of Fabkit." (Quote from the Sashakit, as well as one of my professors, Dr. Adam Harris, In-Circuit programmer board I made in my week 4 class. I found that looking at the labeled schematics and board designs for these boards give me the information I needed to dive deeper into the workings of a microcontroller. Before starting any work in Autodesk EAGLE, I took some time to write out my needs on a final project board and was able to use all of this pre-work to start creating my final project board schematic. I worked through this schematic system by system, adding components as I went until I had a finished schematic. I found this approach to be more assistive in my understanding of how the components interact with each other and also allowed me to do some additional research on the different needed sections while working on them. I finished all major sections of my schematic following this approach, and the only editing that I had to go in to add later were 0-ohm jumper resistors, a component I used to connect traces at intersections while designing my final project board.

Reference Image 1 Above

With this schematic done, I moved on to generating my final board file, however, I wasn't entirely happy with the default generation for my final project board, as I wanted it to have a little more flair, so I set off to add a custom board shape, and some icons to my board design before routing any traces on the board. After doing some research on this process, I found this good article on Importing Custom Images into Eagle, a process easier said than done. Although this process of importing images and shapes into EAGLE is entirely possible, the software cannot handle the importing of any closed polygons or shapes with complex curves of any kind, and therefore any images/icons you want to be imported require a good bit of prep work. I completed this prep work in Inkscape on my desired board shape, a fishbowl, as well as on a little fish icon, and a TW logo for some more personalization. The prep work process for all these images was the same in Inkscape, starting with tracing the bitmaps into SVGs of these images after opening them in Inkscape. This step was to dive by right-clicking on the imported bitmap and selecting the Trace from Bitmap tool. This process generated a scalable vector graphic of the imported bitmap, that I could then start to alter so it could be imported into EAGLE. My workflow of altering this graphic started by resizing the Inkscape page by going to

File > Document Properties

and selecting the Resize page to drawing or selection button under the Custom Size window. After this, I converted the graphic into a path by selecting Object to Path under the Path tab and at the top of the Inkscape GUI, and ungrouped all parts of this path by selecting everything in the design, right-clicking, and then selecting Ungroup. Nextly, I navigated to

Extensions > Modify Path

Where I used the Add Nodes tool to add excess nodes to my design. Under this same menu, I removed any complex curves that EAGLE would not be able to handle by using the Flatten Beziers tool with a flatness value of 8. Finally, to address EAGLE's inability to import closed polygons, I used the Division tool under the Path menu to cut any closed polygons in half and then separated all of these nodes by using the Break Apart tool under the same menu. This process adds some unwanted dividing lines, that can be removed once imported into EAGLE, but these lines allow for the successful importing of these shapes in the first place, so are required.

Reference Images 2,3 & 4 Above

Once all this pre-work in Inkscape was complete, I saved each of these altered files as a .dxf file to my computer from Inkscape. To import these .dxf files into EAGLE, I found making use of the import-dxf plugin for EAGLE worked the best. After installing this ULP into EAGLE following the instructions provided by the import-dxf Github, I opened my final project generated board file in EAGLE and ran the command

run import-dxf

This line opens the import-dxf interface, where the desired .dxf file can be selected, and then imported into a specific layer of a board design. I imported my fishbowl .dxf into layer 20 of my design, the Dimensions layer, to replace the generic rectangle board profile, and then ran the same command to import both the fish icon, and the TW logo, but to the Top layer over the Dimensions. Because these shapes are on the Top layer of my board design, they will both be milled as traces instead of being included with the outline shape of the board. With all of this importing work done, I had a template to start routing the traces of my board around. I opted for the hand routing process for my final project board, as after attempting to autoroute a couple of times, I just wasn't happy with the results. This also gave me the ability to utilize parts like 0-ohm resistors as jumpers over weird interceptions of the board, a technique I took advantage of while routing the traces on this board. This hand routing process was relatively tedious and pretty time-consuming, but I think the results look great and work much better than the autorouter-generated traces with the weird constraints put in place by the odd board shape.

Reference Image 5 Above

Unfortunately, this first iteration of my final project board didn't work on the first attempt, and I seemed to have an excess of noize across it, probably due to the large quantity of 0-ohm resistors in line with the traces.

I kept iterating on this board, working towards the removal of the excess 0 ohms with better trace routing, an aspect of my board design that only improved over the iterations. On the sixth iteration of this board, shown in the schematic and board file images below, I had reduced the number of 0 ohms's on my board by a good bit, but also worked on the smoothing capacitors routing.

Reference Images 6 & 7 Above

Just like its prior iterations though, this sixth iteration was still unsuccessful, and so far I had been unable to get a version working. I began to make some larger strides on this board during my week 13 class and started another iteration of this board by working back through all systems in the board's schematic, familiarizing myself with the purpose of each system/component. From here, I started work on adding in a 12v to 5v voltage regulator on the fishbowl board, as my fish tank will be run on a 12v DC supply, and this regulator will allow for this 12v system. I took advantage of a 12v to 5v voltage regulator in this regulator system, as opposed to a variable voltage regulator, as the components on my fishbowl board will always be 5v, and thus the voltage can be set by the regulator itself. Along with this regulator, I included two 10uf capacitors between GND and VCC on the voltage regulators' input and output, reducing portion noise on my board.

Reference Image 8 Above

With the addition of these new voltage regulator systems, a rewiring of the fishbowl board was needed, and during this time around, I took some extra time to reduce the needed components on the board, and allow for easier soldering. After messing around in the board file for a bit, I found I could use one of my "Fish Bowl" shape decorative traces as a GND line that surrounded the entirety of my board. This line implemented a universal ground way more accessible from everywhere on the board and offered another solution to a problem I had previously addressed by using 0-ohm jumpers resistors to solve, routing GND lines over other traces with these "jumpers". This surrounding ground line reduced the crazy amount of 0-ohm resistors on my board and made the board's soldering/stuffing process simpler and less time-consuming.

Reference Image 9 Above

I milled this board following the same steps I used while milling boards previously in week 4, and other electronics production assignments in my previous weeks, starting with the board traces operation with a PCB engraving bit. While iterating on this board since week 6, I've milled a handful of tests, some yielding successes in some systems, but always including another issue/broken system to flatten out. I next moved on to milling the board's holes and outline, using a 1/32" bit for these two operations, before moving onto board soldering.

The part reduction steps I had taken earlier while encluding the wrap-around GND trace on my board paid off here, and the board's soldering and stuffing time had been greatly reduced. One thing that I've picked up on while soldering prior test fishbowl boards is a "drag" technique while soldering the ATMega to the board. I used this technique on these boards as well, first aligning the chip to its corresponding pins (ensuring correct orientation), before tacking down one of the pins of the chip to the board, and then dragging the tinned iron across one of the rows of pads, allowing solder to flow and connect between each of the chips pins and the board's pads, and leaving me with a clean set of joints. With the chip soldered, I wrapped up the board by soldering all of the other components, finishing with the three largest components, the crystal, voltage regulator, and reset button, leaving me with the boards shown in Image 10 above.

As the first test for this new fishbowl board, after soldering, I hooked up the board to a 12v DC power supply, and then probed the new voltage regulator output to test the output voltage. To my luck, the regulator yielded a 5v output and remained at a constant voltage throughout my probing. I next moved on to attempting to burn a bootloader to the fishbowl board. This process is similar to the one taken while burning the bootloader on my Sashakit made in our Student Bootcamp class. The bootloader is burned to my board through an Arduino acting as an ISP programmer, so the first step while attempting to burn the bootloader was to set up the Arduino. I uploaded the Arduino example skets, Arduino as ISP, to an Arduino board, and referencing the Arduino as ISP sketch, and my fishbowl board eagle file, I attached the two with some jumpers using the pins called on by the Arduino as ISP sketch. From here, I opened the Arduino IDE, selected the port my Arduino acting as a programmer was connected to, and then used the IDE's Burn Bootloader tool, and ... it failed. Unfortunately, even after triple-checking my wiring, switching my Arduino board, reuploading the Arduino as an ISP sketch, and ensuring my fishbowl board was receiving enough power from my power supply, I still received an error message upon any attempt to burn a bootloader. I tried this process a couple of times and received two different error codes, one of which is shown in image 11 above.

A bit of research into the codes I was receiving helped me break down the problem a little bit, but not a ton. I found that there were three major potential flaws, however, a board short / VCC error, a "bricked" chip, or a non-oscillating clock, and decided to look into these three more. Being the easiest resolved I began looking into the VCC error a little more, starting by probing each of my board's traces for continuity between places that should not be connected, and also probed the voltages of the GND and VCC line of the board when supplied power, however, all of these results looked normal. After a little more research of the matter online, as well as into the ATMega 328p, I noticed that it is recommended to include a smoothing 100nf capacitor in between the chips AREF line and its nearest GND pin, so back in the board's eagle file, I added this smoothing capacitor along with the previously existing 100nf smoothing capacitor running between two GND and VCC pins on my chip.

Reference Image 12 Above

From here, I also explored the other two potential causes of my bootloader burning issue, however, I found no easy fix to a "bricked" chip, and therefore moved on to researching a non-oscillating clock a little more. I found that similar to the "bricked" chip, a non-oscillating clock is not easily fixed, but can be avoided, as the clock will not turn to its non-oscillating state unless the fuses of the ISP programmer are incorrectly set. Confirming in my ISP programmer, I had the correct fuses set, and eliminated this as being one of my potential issues.

As a workaround to my inability to "Un-Brick" a chip, I followed the advice of one of my instructors, Dr. Adam Harris, to test the working of my chip before using it aboard. To do this, I soldered up a Sashakit board, just like I had in my Student Bootcamp class, however, I left the chip unsoldered to this board. I was then able to connect this Sashakit board to an ArduinoISP programmer, and then use it to try out the bootloader on multiple chips. I aligned a chip with its corresponding pads of the sashakit, heald it down in the center with a pair of tweezers, and used the Arduino IDE to burn a bootloader to my board. All this worked! and the Arduino let me burn a bootloader to a couple of different chips, however, I did find some other faulty "Bricked" chips along the way. Despite that, I was left with a couple of chips with bootloaders burned, that I could be sure were working, and was able to eliminate another potential issue on my board.

Reference Image 13 Above

With all this troubleshooting into my issues at a stopping point, I was ready to manufacture another board iteration, going first milling the PCB, then soldering and stuffing, leaving me with the board shown in Images 14 & 15 above.

Due to my previous failures with this board, I was pretty nervous to test this iteration and started my first just powering up the board through a power supply. Unfortunately, this simple startup produced a cloud of smoke from the top of my board, and the board's voltage regulator exploded. This error sucked, and ended up stemming from the misplacement of a strip of 5v to 3.3v regulators in a bin meant for 12v to 5v (the ones needed by my board), and the false component use ended up frying one of my boot loaded chips. I unsoldered the remains of the busted voltage regulator, as well as the fired chip, and replaced them with working correct components. I tested the board with power again, this time fortunately without explosion, and was ready to attempt to program the board again. I wired the board to an Arduino with the Arduino as ISP sketch flashed to it, and tried to upload a blink code ... no luck. Upon this uploading attempt, the uploading process began, and then returned error 0x0000000, a GND or Reset error.

Here I went back to my schematic, and went through the system by system, and referenced the datasheets for major components. I wanted to make sure to include all recommended/required components for components on each of their pins. In addition to what I already had, this included adding a larger smoothing capacitor between GND and VCC, another capacitor between AREF and its closest GND pin, as well as an additional RST pin, without the 100nf inline capacitor. After a board works though with Dr. Adam Harris, I also moved these additional smoothing capacitors closer to my board's ATMega 328 to reduce any resistance built upon the traces. All of these changes left me with yet another board iteration, shown in Image 16 above.

Again, I worked through the manufacturing process for this board, first milling, and the soldering and stuffing of the board. All of these board iterations have sped up their production time, as I now have the component layout of the board memorized, and have increased my soldering speed with each iteration.

Reference Image 17 Above

Working Iteration of the ATMega 328 Fish Bowl Board

Just like the prior iterations, I wired up this board to an Arduino with the Arduino as ISP example sketch flashed to it, and attempted a bootloader burn, this time, yielding successful results!!

Step 3: Main Board Testing

After all of the troubleshooting that went into my fishbowl board, it was super nice to finally have to worry about code. I began this fishbowl board programming process with a simple blink sketch, and uploaded the Arduino IDE Blink example sketch to my fishbowl board via an Arduino as ISP programmer, yielding a successful upload shown in image 2 above.

This simple sketch proved the working of my board and flashed my onboard pin 13 LED on my fishbowl board.

Reference Image 2 Above

Step 4: PH Sensor

A quick beginning note - the pH scale I referenced during the pH work of my tank is attached as Image 4 above. Goldfish, the fish that will be used in my ecosystem, thrive at a neutral pH, something between 7 & 8.

I settled on using an Atlas Scientific Gravity pH Probe in my tank. This sensor, in addition to coming from a reputable company, allows the probe to be underwater up to its connector indefinitely, an important aspect of any tank probe, as well as for a connection between the probe and its interfacing board constantly, without a need for the probe to be detached when not in use. Before beginning the work on my board to interface with this pH probe and board, I did a bit of research into the operating principle of the sensor, a subject well covered in the Probe's Datasheet, with some highlights covered below.

"A pH (potential of Hydrogen) probe measures the hydrogen ion activity in a liquid. At the tip of a pH probe is a glass membrane. This glass membrane permits hydrogen ions from the liquid being measured to defuse into the outer layer of the glass, while larger ions remain in the solution. The difference in the concentration of hydrogen ions (outside the probe vs. inside the probe) creates a VERY small current. This current is proportional to the concentration of hydrogen ions in the liquid being measured." (Probe Datasheet)

Reference Image 5 Above

"A pH electrode is a passive device that detects a current generated from hydrogen ion activity. This current (which can be positive or negative) is very weak and cannot be detected with a multimeter, or an analog to digital converter. This weak electrical signal can easily be disrupted and care should be taken to only use proper connectors and cables ... The current that is generated from the hydrogen ion activity is the reciprocal of that activity and can be predicted using [the equation pictured below]" (Probe Datasheet)

E=E^0 + RT/F * ln( a_{H+}) = E^0 - 2.302RT/F * pH

  • Where R is the ideal gas constant
  • T is the temperature in Kelvin
  • F is the Faraday constant

Reference Image 6 Above

To calibrate the pH probe to work against these voltage reading thresholds, a calibration is required. Included along with the Atlas Scientific pH probe I ordered were three packs of pH calibration liquids, a 4, 7, and 10 level liquid. The concept of the calibration reflects measurements of the probe at each of these points, and the probe can be calibrated by being placed in each one of these liquids and then set to the liquid's corresponding pH value, leaving a scale like that shown below.

Reference Image 7 Above

To achieve probe calibration and eventual readings from the probe, I created a simple analog sensor interfacing board with an ATTiny 1614 microcontroller. This board includes data pins to connect to the pH probe board array, along with transmitting and receiving pins that will be used for the eventual calibration of the probe.

Reference Images 2 & 3 Above

This board is designed to reflect the exact board footprint of the pH sensing board, as well as its electrical isolation board used between the connection. Speaking of which, this electrical isolation board is a pH probe board accessory from Atlas Scientific that connects between the Atlas Scientific pH board and my analog interfacing board, allowing for complete isolation of analog signal from the pH sensor board, and its conversion into a PWM signal. This isolation board removes the issue of false readings that could occur from excess current in the water released by my tank's pump and leaves me with accurate pH readings. After the completion of my analog interfacing board, I milled and stuffed the board with its four components, leaving me with the board shown below.

Reference Image 8 Above

With this board manufactured and ready to program, I again referenced the pH Probe's Datasheet, to find the Atlas Scientific Gravity pH Library & Sample Code. This library adds a ton of helpful calibration and probe reading functions to Arduino. I ended up modifying the pH calibration example sketch included in this library for my final pH reading sketch, due to the inclusion of the entire calibration via serial feature as well as integration with my electrical isolation board. After this calibration function, the pH itself is read, and then written to a string and printed to serial. In front of this pH value, the line 3pH = is printed, to interface with my tank's LCD parsing statements, a function of code discussed later on this page, leaving me with the pH reading and printing loop function below ...

void loop() {
  if (Serial.available() > 0) {                                                      
    user_bytes_received = Serial.readBytesUntil(13, user_data, sizeof(user_data));   
  }

  if (user_bytes_received) {                                                      
    parse_cmd(user_data);                                                          
    user_bytes_received = 0;                                                        
    memset(user_data, 0, sizeof(user_data));                                         
  }

  Serial.println("3pH = " + String(pH.read_ph(), 2));                                                      
  delay(20000);
}

This loop with my pH reading string was then incorporated back into the other functions of my pH code, and I was left with the final code below.

#define USE_GRAV_ISOLATOR
#ifdef USE_GRAV_ISOLATOR#include "ph_iso_grav.h"       
  Gravity_pH_Isolated pH = Gravity_pH_Isolated(10);         
#else#include "ph_grav.h"             
  Gravity_pH pH = Gravity_pH(10);   
#endif

uint8_t user_bytes_received = 0;                
const uint8_t bufferlen = 32;                   
char user_data[bufferlen];                     

void parse_cmd(char* string) {                   
  strupr(string);                                
  if (strcmp(string, "CAL,7") == 0) {       
    pH.cal_mid();                                
    Serial.println("MID CALIBRATED");
  }
  else if (strcmp(string, "CAL,4") == 0) {            
    pH.cal_low();                                
    Serial.println("LOW CALIBRATED");
  }
  else if (strcmp(string, "CAL,10") == 0) {      
    pH.cal_high();                               
    Serial.println("HIGH CALIBRATED");
  }
  else if (strcmp(string, "CAL,CLEAR") == 0) { 
    pH.cal_clear();                              
    Serial.println("CALIBRATION CLEARED");
  }
}

void setup() {
  Serial.begin(9600);                            
  delay(200);
  Serial.println(F("Use commands \"CAL,7\", \"CAL,4\", and \"CAL,10\" to calibrate the circuit to those respective values"));
  Serial.println(F("Use command \"CAL,CLEAR\" to clear the calibration"));
  if (pH.begin()) {                                     
    Serial.println("Loaded EEPROM");
  }
}

void loop() {
  if (Serial.available() > 0) {                                                      
    user_bytes_received = Serial.readBytesUntil(13, user_data, sizeof(user_data));   
  }

  if (user_bytes_received) {                                                      
    parse_cmd(user_data);                                                          
    user_bytes_received = 0;                                                        
    memset(user_data, 0, sizeof(user_data));                                         
  }

  Serial.println("3pH = " + String(pH.read_ph(), 2));                                                      
  delay(20000);
}

I uploaded this code to my analog pH interfacing board, and connected the board's communication and power headers to their corresponding pins on an FTDI chip, and then via USB to my laptop.

Reference Image 1 Above

Following the calibration steps discussed a bit above, I completed the pH probe's first calibration starting with the 7 mid-calibration liquid. I placed the end of the probe in the liquid and set the command CAL,7 via serial to my analog pH interfacing board. After this, I repeated this step with the 4 low calibration liquid with the line CAL,4, and for a final time with the 10 high calibration liquid, and the line CAL,10.

Step 5: Temperature & Humidity Sensor

Following my system's PH sensor, the next sensor in my system is a DHT11 Temperature and Humidity sensor I manufactured in my week 11 inputs class. For space reasons, this page just covers the highlights of the working temperature/humidity monitoring board, and the troubleshooting behind it can be read about on my week 11 inputs class page.

I began this temperature monitoring board manufacturing process by reading up on the DHT11 temp and humidity sensor, finding this link on its set up with an Arduino helpful, giving me some useful wiring diagrams. I planned on using this DHT11 Temperature and Humidity sensor on my temp and humidity monitoring board, reading the sensor through an onboard ATtiny 412, and writing the read values to another microcontroller through RX and TX pins. I started in EAGLE, creating a small ATtiny 412 circuit, incorporating a DHT11 Temperature and Humidity sensor, as well as some headers for programming and communication. First, I started a new schematic for the board, keeping in mind the required components while adding them to the schematic. The DHT11 sensor is a four-pin sensor with a VCC, GND, and two data pins. In my case, I communicated with the sensor via one data pin, keeping in mind this pin not only needed to be connected to my ATtiny 412 but also ran to VCC with a 10k ohms resistor. Along with its connection to this sensor, my board's ATtiny 412 also runs to two separate headers, one for programming via the board's UPDI pin, and another supplying the board's power, and RX and TX pins, for future communication between boards. A final little touch to this schematic was a power indicating LED, and this left me with the schematic shown in image 1 above.

The next step in this board design process was the conversion of my schematic into my temperature and humidity reading board. Keeping with the aquarium theme, I decided to shape this board like a fish, following the same steps I used to create a custom board shape in eagle during week 6. For this board outline, I used the same fish icon I had created in that week's assignment, importing the shape into the dimensions layer of my sensor board file to create the shape. From here I began the process of laying out the board's components, in eagle, starting with the mounting position of the DHT11 sensor and ATtiny 412, and positioning around those two components. One thing I had to keep in mind during this layout is the size of the DHT11, as its connection to my board uses a 4-pin header, but the body of the sensor itself was much larger than this. I began by positioning the header where I thought the rest of the sensor would fit, and checked this positioning by drawing a square from the corner of the header, so its dimensions were the size of the DHT11. From here I laid out all other components on my board and routed the board's traces. Due to the small size of this board, the trace routing was a relatively simple task and left me with a nice-looking temperature and humidity monitoring fish board.

Reference images 2, 3 & 4 above

Similarly to before starting my board's schematic, before programming the board, I read up on the DHT11 sensor, referencing the same site as before, found here.

"The DHT11 detects water vapor by measuring the electrical resistance between two electrodes. The humidity sensing component is a moisture-holding substrate with electrodes applied to the surface. When water vapor is absorbed by the substrate, ions are released by the substrate which increases the conductivity between the electrodes. The change in resistance between the two electrodes is proportional to the relative humidity. Higher relative humidity decreases the resistance between the electrodes, while lower relative humidity increases the resistance between the electrodes. The DHT11 measures temperature with a surface mounted NTC temperature sensor (thermistor) built into the unit." (Circuit Basics)

The sensor relies on the DHTLib Arduino library and can read the sensor's data pin into a readable humidity and temperature output. The libraries follow the equation below to derive the relative humidity from the sensor.

RH = (P_{w}/P_{s}) * 100%

  • Where RH is the Relative Humidity
  • P_{w is the density of water vapor
  • P_{s} is the density of water vapor at saturation

With knowledge of the DHT11's workings, I began programming the code to read temp and humidity through the DHT11 and print the found values through TX to a serial monitor. I used the sensors reference code found on the Circuit Basics code as a reference and began the coding process. The code starts by including the needed DHTLib library and setting up the DHT11's connections to my boards ATtiny 412. Next, the code begins serial and then prints the found values to it, with the prefixes "Temp" & "Humidity" in front of their corresponding values. This left me with the sensor reading code below.

#include <Arduino.h>
#include <dht.h>

dht DHT;

#define DHT11_PIN 4

void setup(){
  Serial.begin(9600);
}

void loop(){
  int chk = DHT.read11(DHT11_PIN);
  Serial.print("Temp = ");
  Serial.println(DHT.temperature);
  Serial.print("Humidity = ");
  Serial.println(DHT.humidity);
  delay(5000);
}

At the end of this sensor reading loop, I included a 5-second delay, as the DHT11 can only be read every 2 seconds, so this gives the sensor plenty of wiggle room.

With this code flattened out, I wired my fish sensor board to my in-circuit programer, made in week 4's electronic production class, connecting my boards GND and VCC to the programmer's corresponding pins, and my sensor boards UPDI to the UPDI pin of my in-circuit programmer. I followed the same programing steps I've used for all of my other ATtiny 412 containing boards, like that in week 4, uploading my sensor reading code through my in-circuit programmer using the Arduino IDE's Upload Using Programmer tool. This code was uploaded successfully to my board, and I was ready to move on to testing and reading my sensor.

I attached this fish board to an FDTI chip, RX to TX, TX to RX, and GND to GND, and then attempted to read the sensors values again, and this time, it worked! Every five seconds the serial monitor is updated with reading temperature and humidity values from my DHT11 and outputs the values in a serial monitor through serial, as shown in image 5 above.

The final step in this sensor board code was a little bit of alteration to the serial prints I did in my week 14 class. These alterations allow for the communication required to print the transmitted values to a specific line on my system's LCD, a feature discussed later on this page. Beginning this process, I had to figure out how to print a specific line of incoming serial to a controlled position on an LCD. After a bit of research online, It seemed like the best way about doing this would be to include an indicator between different lines being sent over serial, and then read that indicator to determine the position of the text in the interface. With this idea in mind, I altered my input board's code to include a 1 before the transmitted temperature line, and a 2 before the transmitted humidity.

//(c) Teddy Warner 28 May 2021

//This work may be reproduced, modified, distributed, performed, and displayed 
//for any purpose, but must acknowledge the Assistive Aquaponics Fish Tank. 
//Copyright is retained and must be preserved. The work is provided as is; 
//no warranty is provided, and users accept all liability.

#include <Arduino.h>
#include <dht.h>

dht DHT;

#define DHT11_PIN 4

void setup(){
  Serial.begin(9600);
}

void loop(){
  int chk = DHT.read11(DHT11_PIN);
  Serial.print("1Temp = ");
  Serial.println(DHT.temperature);
  delay(5000);
  Serial.print("2Humidity = ");
  Serial.println(DHT.humidity);
  delay(5000);
 }
}

Step 6: LCD

I spent the better half of an afternoon during my week 13 output class searching for the perfect LCD for my tank, as the space requirements of the mounting area, along with the need for a 20 x 4 LCD minimum to display all necessary info in a readable format made this search more difficult. Eventually, I stumbled on the C204C-FTW-LW65 from Focus LCDs, a vertical compact 20 x 4 LCD, that works great for my use case. I originally began work on my systems LCD during my week 13 output class, as mentioned above, and just like the previous temperature and humidity monitoring board, this page will just touch on the working highlights of this feature, and my week 13 page goes into more depth on the troubleshooting behind it.

This LCD met all of my space and screen size requirements, and I began in Eagle creating a breakout board to the screen. This board will mount to the LCD, and break out the screen pins to the headers that will need to connect to a microcontroller. The premise of the breakout board was pretty simple, and I referenced the C204C-FTW-LW65's datasheet and attached the needed data lines from the LCD, DB4-DB7, to a set of breakout pins on the board. I next hooked up the LCD's VCC and GND, as well as its backlight VCC and GND, to their corresponding power headers on the board. A 330 ohms resistor is included on the LCD backlight's VCC line, to dim the light so the screen's content is readable. I found the 330 resistance value worked better than the standard 220 for my C204C-FTW-LW65 greyscale style screen and allowed for better readability. The final portion of this board was a contrast adjusting 10k ohms potentiometer. This potentiometer provides a voltage to the LCD's contrast adjusting pin, allowing the LCD character brightness to be altered, leaving me with the final schematic shown in image 4 above.

With this schematic flatted out, I moved on to converting this schematic into my LCD breakout board. Here I began again by referencing the datasheet, positioning the LCD mounting headers to the correct dimensions on my board to line up with the C204C-FTW-LW65 LCD. From here, I positioned the contrast adjusting potentiometer to mount on the backside of the board, allowing the LCD to mount directly over the breakout board, in the most space-efficient manner. From here, I also positioned the board's resistor and jumper resistors, and then positioned the breakout headers towards the bottom of the board, before running all of the board's traces. Due to the mounting position of this breaker board, the shape had to fit in as compact of a space behind the LCD as possible, so I dragged the boards outline down to fit around the boards content, and used Eagles miter tool to round over the board's corners, leaving me with the boards shown in image 5 above.

Due to its single 330 ohms resistor component and three-pin potentiometer, the milling and stuffing of this LCD breakout board weren't super time-consuming, and I worked through it with relative ease. I first attached the breakout board to the backside of the LCD board, soldering the pins of the LCD to their propper pads on the breakout board. From here I tracked down the 330 ohms resistor, and also soldered the potentiometer in place. Finally, I attached the breakout board headers, that would allow for connections between the LCD and the board, leaving me with the LCD and breakout system shown in images 6 & 7 above.

After the completion of my LCD breakout, I began the interface coding process in the second half of my week 13, and then later expanded on the interface in my week 14 networking and communication assignment. The LCD interface code utilizes the Liquid Crystal Library included by default in the Arduino library for LCD control. Breaking down the code, there are two sections of my LCD interface, a boot screen, and a status display screen that will in the future, provide information read from my Aquaponics fish tank's sensors. I started the interface work on my tank's boot screen. The boot screen code is a simple display of characters spanning the width of the LCD, with the top and bottom lines being filled with -, and the middle lines displaying the text Aquaponics Fish Tank and ... In Development. The inclusion of this boot screen in the Void Setup function of my code shows this boot screen upon bootup of the system, and the function includes a short delay while displaying the screen, allowing all of the input sensors to get started up and begin future communications with the mainboard.

Reference images 1 & 2 above

From this boot screen, the interface next moves into its status screen display. It was here where I planned on taking full advantage of the 20 x 4 display size of my LCD, and decided to create some custom characters to include a fish icon on my status screen, as well as include an Aquaponics Fish Tank title. I began this status screen creation with some research on the creation of custom characters, where I found this Hackster.io article to give a good description of the topic. The article is linked to an online LCD Character Creator, where a GUI is provided that converts a drawn character into the hex codes that can be written to an LCD in code. I used this generator online to create a 2 x 3 character fish and was able to copy the generated characters generated into my LCD code.

Reference image 8 above

I began the status screen code in the Void Loop function of my code, where I started by including an Aquaponics Fish Tank title printed at the top of the display. Following this, I called upon each of my 6 custom characters established earlier in the code, positioning each of them to create a 2 x 3 fish icon on the left side of the screen. The final touch to this first iteration of the status screen would be indicators for Temp, Humidity, and PH, each receiving their line in the interface. In this instance of the status screen, these indicators are just text displayed on a set line of the interface, to the right of the fish icon. All of this left me with the first iteration of the status screen, shown in image 9 above.

I began working from this interface in my week 14 class to include the sensor readings on my interface's status screen, altering the loop to read transmitting nodes via the software serial library, and print them to their proper interface positions, removing the setup Temp =, Humidity =, and PH = place holders in the process.

The bulk of this communication setup work is discussed on my week 14 page, but I'll touch on the highlights on this function here. As mentioned above, this LCD networking feature in my system uses the software serial library. This library allows serial communications on any of a microcontroller's digital pins, and allows me to configure two receiving and transmitting pins on my mainboard node, and communicate with bus addresses to my two input nodes. My first step while implementing this library was to set up two communication ports in my mainboard code, one for communication with my systems temperature and humidity input node, and another for the PH input node. Through this setup, I'm able to communicate across all three nodes, passing through these two set communication ports, and will be able to call on specific nodes with their defined addresses, portDHT and portPH.

Reference image 10 above

I call upon each of these different nodes throughout my mainboard interface code. Each port is started with the line ...

 portDHT.listen();

as in the software serial library can only listen to one transmitting node through one port at a time, and then this data is saved to an incoming string. From here, the data is run through two of my code's parsing If statements, to determine whether the board is receiving temperature or humidity data, and the base of this, just as before, will print the read values to my LCD.

Reference image 11 above

This same process is repeated in the Void Loop function, after the listing of portDHT, with portPH. This, just like the previous port, saves read data to a string, and then prints the read data to the proper line of the LCD interface, this time without any If statement due to the singular reading that will be coming in over this address.

Reference image 12 above

All of these interface features and functions together left me with an LCD interface code capable of reading from transmitting sensor nodes and printing to the LCD, also including a startup routine with an included interface boot screen, as well as the main status screen with a custom fish icon. This final interface code, with all of these features implemented, is included below.

//(c) Teddy Warner 28 May 2021

//This work may be reproduced, modified, distributed, performed, and displayed 
//for any purpose, but must acknowledge the Assistive Aquaponics Fish Tank. 
//Copyright is retained and must be preserved. The work is provided as is; 
//no warranty is provided, and users accept all liability.

#include <LiquidCrystal.h>
#include <SoftwareSerial.h>    

SoftwareSerial portDHT(2, 3);
SoftwareSerial portPH(4, 5);

const int rs = 12, en = 11, d4 = 10, d5 = 9, d6 = 8, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

String Temp;
String Humidity;
String pH;

byte fishbl[] = {
  B00011,
  B00111,
  B01111,
  B01111,
  B00110,
  B00000,
  B00000,
  B00000
};

byte fishbr[] = {
  B11000,
  B11100,
  B11110,
  B11110,
  B01100,
  B00000,
  B00000,
  B00000
};

byte fishml[] = {
  B11111,
  B11111,
  B11111,
  B01111,
  B01111,
  B00111,
  B00111,
  B00011
};

byte fishmr[] = {
  B11111,
  B11111,
  B11111,
  B11110,
  B11110,
  B11100,
  B11100,
  B11000

};

byte fishtl[] = {
  B00000,
  B00000,
  B00000,
  B00011,
  B00111,
  B01111,
  B01111,
  B11111
};

byte fishtr[] = {
  B00000,
  B00000,
  B00000,
  B11000,
  B11100,
  B11110,
  B11110,
  B11111
};

void setup() {

  Serial.begin(9600);
  portDHT.begin(9600);
  portPH.begin(9600);

  lcd.begin(20, 4);

  lcd.setCursor(0,0);
    lcd.print("--------------------");
  lcd.setCursor(0,1);
    lcd.print("Aquaponics Fish Tank");
  lcd.setCursor(0,2);
    lcd.print("... In Development");
  lcd.setCursor(0,3);
    lcd.print("--------------------");

  delay(5000);
  lcd.clear();

}

void loop() {

 lcd.createChar(1,fishtl);
 lcd.createChar(2,fishtr);
 lcd.createChar(3,fishml);
 lcd.createChar(4,fishmr);
 lcd.createChar(5,fishbl);
 lcd.createChar(6,fishbr);

 lcd.setCursor(0,0); 
 lcd.print("Aquaponics Fish Tank");

  lcd.setCursor(0,1);  
  lcd.write(1);
  lcd.setCursor(1,1);
  lcd.write(2);
  lcd.setCursor(0,2);
  lcd.write(3);
  lcd.setCursor(1,2);
  lcd.write(4);
  lcd.setCursor(0,3);
  lcd.write(5);
  lcd.setCursor(1,3);
  lcd.write(6);

 String IN;
 String readString;

 portDHT.listen();
 portDHT.print(F("AT\r\n"));     

 delay(100);

while(portDHT.available()) {
  delay(100);
  if (portDHT.available() > 0) { 
    char c = portDHT.read();
    readString += c;
  }
 }

 IN = readString;

 if(IN.substring(0,1)=="1"){
  Temp = IN.substring(1);
  lcd.setCursor(3,1);
  lcd.print(Temp);
 }

  lcd.setCursor(15,1);
  lcd.print(" ");
  lcd.setCursor(16,1);
  lcd.print(" ");

 if(IN.substring(0,1)=="2"){
  Humidity = IN.substring(1);
  lcd.setCursor(3,2);
  lcd.print(Humidity);
 }

  lcd.setCursor(19,2);
  lcd.print(" ");

 portPH.listen();
 portPH.print(F("AT\r\n"));     

 delay(100);

while(portPH.available()) {
  delay(100);
  if (portPH.available() > 0) { 
    char b = portPH.read();
  readString += b;
  }
 }

 IN = readString;

 if(IN.substring(0,1)=="3"){
  pH = IN.substring(1);
  lcd.setCursor(3,3);
  lcd.print(pH);
 }

  lcd.setCursor(13,3);
  lcd.print(" ");
  lcd.setCursor(14,3);
  lcd.print(" ");

}

I updated my Fish Bowl mainboard with this final code, and tested the system with my Temp/Humidity sensor board, (shown in image 3 above), and ... It Worked!

Step 7: Power Supply & Breakout

To power, all of these parts of my electronics system & the tank as a whole, I'll be using a 12v DC power supply with a connection to an AC mains adapter to take wall power. Before doing any powering from this supply, I dialed the output voltage to exactly 12v DC, as shown in image 1 above.

Water Pump, Tank & Plant Lights

All three outputs from this DC power supply run to a power breakout board allowing the four power drawing components to receive power, the Fish Bowl Main Board, Tank Lights, Grow Lights, and Water Pump. This power breakout board directs two of the three 12v DC inputs to its tank lights and mainboard output terminals and steps down the third input to a 5v current to be used in an ATTiny 412 timing circuit. This third line powers the tank's pump at 5v, as well as the timing circuit, which toggles a MOSFET on and off every 12 hours to allow 12v DC to reach the tank's plant lights.

Reference images 2 & 3 above

I manufactured this board following the same steps as all PCBs previously made for my project and then was ready to begin the programming process.

After a bit of research online, indoor plants grown under grow lights thrive under 10 to 14 hours of grow lights, and I took the middle of this for my timer and toggled every 12 hours. The time sketch is super simple, just writing a MOSFET on pin 4 to high for 12 hours, and then low for another 12. The final grow light timer code is included below.

//(c) Teddy Warner 28 May 2021

//This work may be reproduced, modified, distributed, performed, and displayed 
//for any purpose, but must acknowledge the Assistive Aquaponics Fish Tank. 
//Copyright is retained and must be preserved. The work is provided as is; 
//no warranty is provided, and users accept all liability.

int Mosfet = 4;

void setup(){
pinMode(Mosfet,OUTPUT);
}
void loop(){
  digitalWrite(Mosfet,HIGH);
  delay(43200000);                  // 12hr
  digitalWrite(Mosfet,LOW);
  delay(43200000);                  // 12hr
}

To test this sketch and board, however, I didn't want to wait the 12-hour alternating period, so I shortened the time frame of my sketch to only 5 seconds by dropping the delay from 12 hours ...

delay(43200000);                  // 12hr

... to 5 seconds...

delay(5000);                  // 5sec

I uploaded this test code to my power breakout board, connected it to a voltage input, and probed the output terminal block ports with a multimeter, yielding the 5 seconds on 5 seconds off results shown below.

After this successful test, I uploaded the final 12-hour iteration of the code and was then ready to test the breakout in my system, the step where everything when wrong. Although the timing circuit of my power breakout board worked great, the board itself did not. Unfortunately during the design process, I forgot to consider my usage of an inductive load, my water pump. Upon the first bootup of my system with this power breakout board, the circuit worked great, however, after cutting power to the system, my inductive water pump sent a current back into my breakout, destroying the timing circuit of the board. This board design left me facing the problem of always off grow lights after powering the water pump since when power is cut to a motor, like my water pump, the motion doesn't stop, and the excess current generated needs to go somewhere, in my case, my timing circuit. The fix for this use of an inductive load revolves around the use of a flyback diode, a feature I'm familiar with from use on 3D Printers.

With this solution in mind, I began the process of setting up a diode flyback protection circuit around my water pump terminals, starting with some research yielding these two articles, Simple Over-Voltage Protection Circuit using Zener Diodes & How To Prevent an Inductive Load from Damaging Your Power Supply. Based off of the information in the first Simple Over-Voltage Protection Circuit using Zener Diodes article, I began work on modifying my power breakout schematic to include a Zener diode in parallel with the water pumps two terminals, orientated to direct any returning current into ground, and creating a new part of least resistance for the returning current. Due to the spec of the SMD Zener diode that was accessible to me, however, another component was needed, a current liming resistor. This resistor keeps the Zener diode from exploding on my board and reduces the current down to one the diode could handle, in my case I used a 100 ohms resistor. Unfortunately, this implementation only leads to more troubleshooting, as the current draw of the pump during its startup couldn't be matched with this Zener diode & limiting resistor setup, so after a couple more iterations, I decided to take another approach, based more off of the information in the second article, How To Prevent an Inductive Load from Damaging Your Power Supply. This lead to the implementation of a second flyback diode setup, one where a Schottky diode is run in parallel with the water pumps terminal headers, along with a second in line with the input VCC to the system. In addition to this diode setup, I also completely isolated the voltage regulation setup for my pump, eliminating any connection to the timing circuit, and allowing for complete isolation of my inductive water pump load. In this instance, like the prior, the two diodes prevent a returning current from the water pump from reaching my voltage regulation circuitry, by creating a new path of least resistance to a GND line. This update left me with the board schematic and board file shown in images 4 & 5 above. Again, I fabricated this power breakout board (shown In image 6 above), and uploaded my timing sketch to it.

I then implemented the power board in my tank's electronics system and booted up the PSU, yielding the results in the video below. All aspects of the electronics system are powered from the breakout, and bootup after multiple power cuts.

Step 8: Aspire Work & CNC Structure Milling

The wooden tank structure was my first large physical step toward my final project that I completed in my week 7 computer-controlled machining assignment. The structure is documented in-depth on my week 7 page, and again, for space concerns, this page will just tough on the important bits and highlights.

Although I created a model of this wooden structure in Fusion 360 while planning the project, I began the structure creation process by starting to put some thought into the manufacturing processes I would need to take to produce this structure in real life. I settled on milling 6 different pieces to assemble the structure, one back wall, two sides, and 3 stacked pieces to make the base of the structure. I planned on creating these parts based on their corresponding components in my Fusion 360 design. For each of these pieces, I created a new sketch on the face of the profile and used Fusion 360's Project tool found under the Sketch menu to project all desired lines for each part into one single sketch in the Fusion 360 browser. With all of these lines in one single sketch for each of the 6 different components, I could export each sketch from the Fusion 360 browser onto my computer as a .dxf file by right-clicking on the sketch and then selecting export as .dxf.

Reference image 1 above

To generate the toolpaths I would later run on a CNC machine from my altered .svg files, I used Vectric CNC's Aspire CAM software. I firstly created a new file in Aspire, where I was prompted to set a workplane size. The workplane of the ShopBot PRSalpha, the CNC I would be milling on, was 96" x 48", and my material height was 0.776", so I entered these values in the prompt accordingly. I then imported each of my .svg files into Aspire, nesting the files as I imported to reduce waste stock material. I spent a little more time with all of my files imported messing with the part orientation to ensure that there would be little stock material waste between my parts. In the assembly of my design, I planned to use milled tabs to align the back piece to the structure's two sidewalls and created this feature in my design. I then switched over to Aspires 3D View by clicking on the tab labeled 3D View at the top of the interface's workspace. Here I could start working on generating the different toolpaths for my parts. Throughout this process, I referenced my original Fusion 360 design to determine which sections of each of my files would require different toolpath operations. The first toolpath operation I generated was a Boreing operation that would boreholes for alignment dowels in the base of my structure. This operation was especially needed in my operation as I was not planning on switching to a drill bit anytime throughout the milling process, and this boreing operation allows me to mill these holes with an endmill instead. Nextly I generated Profile toolpaths for all of my parts, outlining each of my files, and cutting them out. I selected all intended profile cuts for each of my files and set the depth of each of these profile cuts to 0.776", the thickness of my stock material. This cut depth would ensure all of my profile cuts would go all the way through the material. Nextly I selected a .25 Endmill bit for both my profile and boreing operations, as this was the endmill I was planning on using. To prevent the movement of each of these parts after the profile cut completes, I added tabs to the toolpath under the Edit Tabs section of the toolpaths settings. These "Tabs" leave a small bit of stock material connecting the profile to the rest of the stock and holding their position. I found adding 3 to 4 tabs per profile, depending on size and shape, worked best to hold my parts in place. The final tool paths I generated were pocket cuts. These toolpaths remove material to add depth to some of my parts. These pockets were relatively straightforward, as they didn't require any added tabs because they cont cut through the material, however, I used a different, larger, bit size for these pockets to speed up milling time, so I was required to change that. Finally, before exporting any of these toolpaths, I went back through and turned on "Ramping" for each operation. This setting diagonally moves the Endmill bit, as opposed to vertical plunges and then horizontal movement, allowing the side of the endmill to cut material as intended. I saved all of these toolpaths from Aspire through the Save Toolpath menu. Each of these toolpaths was saved under the Shopbot format, .sbp, and grouped based on the bit used. This left me with 3 different .sbp files for each a 1/8", 1/4", and 1/2" bit.

Reference image 4 above

I began by prepping my machine with the proper bit and mounted my stock to the machine's bed. My classmate Graham Smith and I did all of our millings this week together as the operation of a machine on this scale can be unsafe if the right precautions are not taken, or if operated alone. I loaded my first tool path, my 1/2" pocket operation, into the Shopbot Command Console through the Load File menu under the File tab. I selected my .sbp toolpath, and under the pop-up menu, selected 3D Offset as the operations offset, and then proceeded to click enter to start the cut. This "3D Offset" allows for me to complete an "Air Cut" of my file, where the tool doesn't engage with my stock material but just runs above it. I ran this Air Cut to ensure my part placement fit with the side of the machine's workspace limits, and also didn't run into any screws. This test of cutting air was successful, so I was ready to move on to the real milling operation. I loaded the file into Shopbot Command Console following the same steps taken previously, but this time I left the offset dropdown set to the default No Offset as opposed to 3D offset, so the machine would run another air cut. Before running this operation, I ensured the dust collection was turned on, and then clicked the enter key to start the operation.

The assembly and post-processing work on this wooden tank structure is well documented on my week 7 computer-controlled machining class page, and that work will not be documented in-depth again on this page for space reasons, however, the final assembled and post-processed beauty shots are shown as image 2 & 3 above.

After the completion of my tanks structure in my week 7 class, a couple of additions had to be made to allow for the mounting of a mains AC input, my front panel electronics, as well as a mount for my tank's grow lights. Beginning with the mount for my mains AC adapter, I used a paddle bit on my drill to take out some material in the shape of the adapter on the back of the tank, before finishing up the rectangle with a chisel, using the adapter as a reference until reaching a press-fit install. I also drilled two M4 mounting holes with this adapter as a reference, allowing for a secure attachment of the adapter to the frame.

Reference image 5 above

The cables from this adapter are routed through this pocket on the back of my tank, and into the underside electronics enclosure before the adapter is mounted to the frame with M4 bolts, as shown in the images below. Note these M4 screws were just a place holder and were replaced with some nice matching matte black M4 bolts, allowing for a cleaner adapter look.

Reference images 6 & 7 above

The next addition to my plywood tank structure is the grow light mounting bard, which ran across between the two highest points of my structure. This bar is made out of some scrap plywood from my tank's CNC job, and I ripped it down to size on a table saw, before tweaking the height to match that of its mounts on a bandsaw. I used the same tactics sued to assemble the tank structure to mount this light bar, with something dowels for alignment, with wood glue to hold. Underneath this bar, on the side that will be facing the eventual plant box, I mounted three rows of Grow Light Strips, a strip of special neo pixels with light frequencies meant to help plant growth. In my particular case, I used 4 red : 1 blue strip, and alternated the mounting of the three rows to offset this pattern.

Reference image 8 above

The final modification needed on my plywood tank structure was a pocket allowing for the mounting of my front panel's electronics, a switch, and my tank's LCD. I spent a while pinpointing the location and sizing of this box, so as to not interfere with the lip holding the acrylic panel over my electronics enclosure, a feature discussed later on this page. I used a speed square and a Metric/Imperial ruler to draw out a pocket large enough to fit the two needed components, with some additional space for wiring, considering the restrictions of the area throughout.

Reference image 9 above

I then followed the same approach taken to remove material for my mains AC adapter mount, starting by removing material with paddle bits and my drill, before cleaning up with a chisel. This hole will eventually be completely covered with the front panel of my tank, so I wasn't too concerned with the appearance of this one. After all the material was removed, I was left with the clearance hole, shown below.

Reference image 10 above

Step 9: Laser Cut Tank Front Plate

To cover up this newly carved electronics clearance hole, and also complete the side symmetry of my plywood structure, my next step was to laser cut my tank structure's front plate. I began this plate in Fusion 360, as even in 2d design, I find myself most conferrable when using Fusion 360's constraints and sketch interface. I mocked this plate up to hold my system's LCD and a light power switch over the physical cut clearance hole and then added some icons to the plate, including a TW logo, as well as a light on and light off icon.

I saved this Fusion 360 sketch as a .dxf and imported the file into CorelDRAW, where I could then, following the same process I took in week 3, could run this file on our lab's Fusion Pro 48 laser cutter. I ran this plate on a sheet of 1/4" plywood, a sheet with matching veneer to that of my plywood structure, allowing the front plate to blend in with the rest of the structure. I wanted to reduce as much laser residue and char on this piece as possible, so I weighted this piece down to the bed of the laser before focusing on the laser, and starting the job. Getting a minimal amount of char took a couple of different attempts, but eventually, I was left with the product shown in image 1 above ...

... and after a bit of touching up, fit perfectly to the front of my tank, aligning with the electronics clearance hole, and when mounted with some brass furniture screws, left me with the tank front shown in image 2 above.

Step 10: Laser Cut Electronics Compartment Cover

To finish up the fish tank structure that will be the bones of my final project, I laser cut a press-fit acrylic bottom panel for the base of the tank that will cover the electronic housing cutout located on the bottom of the tank structure. I followed the same steps taken earlier this week to export the bottom panel as a .dxf file from Fusion, but instead of worrying about toolpaths for this file, I imported the .dxf into Inkscape, where I added in some air holes over the PSU mounting position, as well as a mount for a 40x40 fan for cooling. As a final touch, I included a QR code that links to this project page you're reading currently, along with the project name and copyright.

Reference image 1 above

Next, following the same process I took in week 3, I laser cut this file from 1/4" acrylic on our lab's Fusion Pro 48 laser cutter.

Reference image 2 above

Step 11: Laser Cut Acrylic Fish Tank

Being the real centerpiece of my Aquaponics Fish Tank project, the fish tank itself was a special piece to work on, that I spent a good bit of time planning out before its creation. The tank, in its simplest form, is 5 acrylic panels cut on a laser cutter and bonded together to form the tank itself with WeldOn 16. However, just a plain acrylic box like this is a little too basic, and taking inspiration from an assignment completed by 7th-grade engineering classes in our lab, I decided to etch something on the back wall of my tank. This assignment I took inspiration from is a pretty simple project completed by our lab's seventh graders as an intro to the laser cutter. The gist of the assignment involves laser-cutting and etching an acrylic sign, and then shining a neopixel strip down on the acrylic, lighting up the etched portion of the assignment. My fish tank will include white neopixel light strips on the inside of the tank as accent lighting, and an etched back wall of my fishtank would complement well with these lights, just like the seventh-grade sign project. Although I didn't know for sure what I would be etched into this back panel yet, I knew I wanted this design to align with the four cutouts on the back wall of my wooden tank structure, so I began this tank design work referencing my physical wooden tank structure. I used Inkscape to create the tank's basic 5 rectangles, so four outer walls would all sit on a larger tank baseplate. From here, referencing the wooden structure again, I projected the cutouts of my structure's back wall to the back panel, giving me a workspace to include my future design. During all this Inkscape work, I remembered a conversation between one of my instructors, Mr. Tom Ducick, and our Fab group, where Mr. Dubick brought up the inclusion of our Eagle designs outside of circuit boards. For the back panel of my fish tank, I decided on embedding an SVG exported from my first mainboard attempt made all the back in week 6. I used Inkscape's Intercect tool to crop this SVG down into the back walls of four design slots. My final bit of work on this tank design fell on this back panel design again, as after meeting with another one of my instructors Dr. Terence Fagan, the point was brought up that as sweet as the etched original circuit board would look on the back panel of the tank, my final project is a fish tank, something that is more organic and doesn't make you think of something as modern looking as the sharpe traces of a circuit board. To combat this, I increased the nodes of this back panel design in Inkscape, and then also increased the designs beziers, until left with something still legible as my original circuit board, but less sharp and with more organic curves, leaving me with the finished fish tank design in Inkscape, shown in image 2 above.

I exported this Inkscape design as an SVG file, and then opened the file into CorelDRAW, and following the workflow for laser cutting I used in my week 3 class, I ran this tank file on a sheet of 1/4" clear acrylic on our lab's Fusion Pro 48 laser cutter.

This job left me with the 5 panels of my tank, ready to assemble.

Reference image 4 above

As mentioned earlier, for the panel assembly of my tank, I'm using WeldOn 16 to bond all of my acrylic panels together. This bonding process was super time-consuming, as each run with Weldon 16 required a 24-hour set time to completely bond. Despite this long total set time, the work time of WeldOn 16 is only a little over a minute, so all of my applications had to be clean and quick. I used a set of two 90 degrees angle clamps to hold my tank's panels in place while using WeldOn 16 and left the clamps on through the 24 hours set time for each individual corner to allow for a square tank.

Reference image 5 above

The longes part of the tank assembly was all 4 of the sidewalls of the tank, and after this 4-day process was complete, I followed the same application process for the bottom of the tank, this time holding the pieces in place with some painters tape along all edges, as well as across both pieces, shown in image 6 above.

After this final bit of bonding was entirely set, I went to test out by tank, setting the tank up on a sheet of cardboard to see if any water leaked out, and unfortunately, it did ... a lot.

Reference image 7 above

I found that although WeldOn 16 worked great for the structure of my tank, and allowed for a secure bond between all of the tank's panels, it didn't leave a watertight seal. This problem was simply fixed, however, with the application of silicon to the interior edges of my tank. During this step finding an Aquarium-Safe Silicone is super important, so as to not kill any future fish. I found this article on Aquarium-Safe Silicones to be a super helpful reference while picking one of these, and with the article as a reference, was able to pick a tank safe silicone out from my local hardware store.

The application process for this silicone was worlds easier than the previous WeldOn 16 work, due to the large working window with the product, and the ability to do all of my tank's edges at once. I worked through starting with the four bottom edges of my tank, before tackling the four vertices, and then taking out any high spots on these lines with a popsicle stick.

Reference image 8 above

The set time for this silicone was only 15 hours, but 24 was recommended on my brand's datasheet before exposure to water, so after this time, another watertight test of my tank was in order. I set up my silicone sealed tank with some sheets of dry computer paper, to reveal any leaks right away. I stress tested the sealed tank, filling it up to the brim with water, and then allowing the tank to sit for 3 hours, checking back on it around every 30 minutes. This test yielded successful results, with no water on the computer paper, and dry external semes on the tank, leaving with finally, a fish-ready tank!

Reference images 1 & 3 above

Step 12: 3D Printed Plant Box

Following the acrylic fish tank, the aqua part of the aquaponics system, it was time to move onto my tank's plant box, covering the system ponics side. The fabrication of this plant box is one of the additive processes used on my tank, allowing me to incorporate otherwise impossible features, such as embedded water pipes, and nice cable management. Around the time of designing this plant box a nice article from Prusa Research came out on How to Make Prints Waterproof, and its contents gave this additive plant box manufacturing some more light. With the contents of that article, as well as this article on Waterproof Printing from All3D as a reference, I settled on some basic goals for this plant box manufacturing, The box itself will be printed from white PETG. PETG is not only one of my favorite filaments to print in, but is also considered a watertight material, and when not colored and left white, is also fish tank safe.

With the manufacturing process in mind, I began work on the plant box's CAD in Fusion 360. The CAD for this part is pretty complex, including not just water routing from a connection port on the bottom of the part, but also a water directing reflow system, and cable management with board mounts incorporated in the design. The part is split into four separate sections, to allow for optimal print orientation on my printer's bed. These four pieces align with three mounting alignment holes for embedded M3 nuts and bolts, and these same alignment screws are used to secure the four sections together.

After the completion of all design work for my tank's plant box, the tedious process of manufacturing was ready to begin. In total, all four parts of the plant box took just over 72 hours to print. Each of the printed parts went through a couple of extra steps in the slicing process, where the plant box's water tightness would be ensured. The basic premise of a watertight component relates very closely to the density of that component. With this in mind, each of the four plant box parts is sliced with four perimeters, and with a 10% gyroid infill, an infill type with super high strength along with a low weight (less filament usage). Each of these parts runs at a 0.20mm layer height, allowing for a relatively high part density while keeping a lower number of layer lines, places where water could seep into the print. After all of this, I used Prusa SLicer's ( my slicer of choice) Paint on Supports tool, to add supports to the aspects of my print where they were needed. This step, as opposed to auto-generating the supports allowed me to keep the internal water pipes of my part intact and usable without supports clogging them, as shown in image 1 above.

This slicing setup process was used across all four parts of my tank plant box, and after a ton of print time, I was left with the task of assembly. As mentioned above, my CAD design for this part includes alignment pins for all four of the plant box's sections. After cleaning up the supports from each of these sections, I inserted the embedded M3 nuts used in this alignment setup and dry-fit the four parts together with the alignment M3 bolts. After this, I repeated the same assembly process, this time using the same silicone used to seal my tank on all of the inside surfaces on my plant box sections, leaving me with the assembled part shown in image 2 above.

Step 13: 3D Printed Electronics Mounting & Cable Management

Following the plant box system of my assistive aquaponics fish tank, a plethora of other small bits and pieces helping with the system integration of my part were also made with the 3d printing workflow. Due to a large number of these small bits, and their relative simpleness, instead of taking a deep dive into the concept behind each design and the manufacturing of the part, I'll just hit some design concept highlights in this paragraph, and include the CAD and manufacture a part for each piece below. All of these parts are mounts of one kind or another, either press fit for boards, or bolt down for cables/sensors. A lot of these pieces serve as a visual benefit just as much as their purpose of mounting and cable management. With this in mind, many of the pieces are designed with a framing drafted banding around the edge. Inspiration for this angled framing came from my time in my 8th-grade art class, where I was taught the practice of directing a viewer's vision. The angled frame of a lot of these mounts serves to direct your vision inward, away from the frame itself. In addition to the angled nature of these mounts, any part I'm wishing to achieve this effect with is printed from a black PETG, assisting in the directing of vision away from them, as they don't 'pop'. A good example of this effect is seen in the Fish Bowl Board Mount part included below. This mount, for my fishbowl mainboard, uses the framing draft angle technique, along with the black filament color to direct one's eyes toward the center of the board, where the microchip is located, upon first glance.

Fish Bowl Board Mount

Reference images 1 & 2 above

Jumper Cable Mounts

Reference image 3 above

PSU Mounting Brackets

Reference images 4 & 5 above

Wire Grommet

Reference images 6 & 7 above

PSU Terminal Cover

Reference images 8 & 9 above

Power Breakout Board Mount

Reference images 10 & 11 above

pH Boards Mounts

Reference image 12 above

pH Probe Mount

Reference image 13 above

Cable Bundle Mounting Clips

Reference image 14 above

Step 14: System Assembly & Testing

Due to the countless design hours spent planning the assembly of my entire tank, this process had plenty of digital references, making the most time-consuming process of the assembly the one, not digitally planned aspect, cable management. I began the assembly process on this task, beginning with the connection of my power supply to mains via the inlaid AC adapter in my tank structure. Due to the dangerously high voltages in these terminals, I followed best practices for the connecting of these wires, using crimp-on connectors for each wire connected to these terminals, as well as grounding the whole system, and including an AC adapter with a 250v fuze.

Reference image 4 above

As included above, these PSU terminals have a 3d printed terminal cover plate, to provide a little extra protection from any accidental bumps into the terminals. After completing the terminal wiring of the PSU, I installed this terminal cover plate, screwing it down to the wooden plate with M3 screws. I then, with the installed PSU as a reference, found the center of the remaining chunk of the electronics compartment and installed my printed fishbowl main board mount.

Reference image 5 above

Taking a break from cable management for a bit, It was time to begin the incorporation of my tank's subsystems into my plywood tank structure, beginning with my acrylic fish tank. The tank was designed to be an exact fit in this plywood structure, and after real-world fabrication, fit in the structure tight enough to stay put without adhesives of fasteners, even when upsidedown. For the installation of the acrylic tank into the plywood structure, I used four wood clamps long enough to span the width/length of both pieces, and then used the clamps to slowly and evenly press the tank into the structure so it sat flush on all four connecting walls. Following this, I then reattached the structure's laser-cut front panel with some brass furniture screws.

Refernece image 2 above

Next, I began preparing the next subsystem of my tank, the plant box. Due to the predesigned cable management features, the process of including the necessary components here was pretty straightforward. I first routed the tank light strips along their channel, using the zip tie cable mount and cable passthrough to route the cables out the back grommet hole of the plant box. From here I routed a wire that would later be connected to the tank's water pump and finally moved onto the inlaying of the fishbowl board. Behind this board's inlay is a little channel meant for the jumpers to run through while attached to the backside of the board. I connected these jumpers to their pins on my fish board, super glued them in place, and took a picture for reference later, as the wires will next be completely hidden. Then, I pressed the board into its corresponding slot, followed by its press-fit laser cut acrylic cover, and sealed around any gaps with silicon. This left me, as shown below, with a mounted sensor board with only the sensor itself exposed.

Reference image 6 above

I was then ready to press this plant box into place, with all of its mounted electronics. The plant box follows the same tight press fit mounting principle as the previous acrylic tank, however instead of using clamps, I slowly worked the assembled plant box back into position, until aligned with the acrylic fish tank and plywood structure, shown in image 7 above.

While pressing the plant box into position, I was sure to route and keep the structures grow light wires in their cable passthrough on the side of the plant box, yielding some nice clean cable routing across the components of the whole system.

Reference images 8 & 9 above

After the installation of all this, a test of the newly installed lights was in order, and I hooked up both my tank's grow & tank lights to a power supply set to 12v and turned them on.

Reference image 3 above

With the bulk of the structure assembly done, I next began the mounting and integration process, starting with the internal tank components like the pH probe. I attached both printed probe clamps to my pH probe and then used some silicone to stick it in the back left corner of my tank, where the probe cable routed up through the plant box, hidden away.

Reference image 10 above

Following the pH probe, next up in the tank itself was the water pump. I first connected the pump to the plant box via both a bit of silicone tubing cut to length and then hose clamped and siliconed in place, as well as with connection between the pump's cable and the router pump wires installed previously. I then used the pump's two included mounts to stick the pump down to the tank floor with silicone.

Reference image 11 above

Once all contents of the tank/plant box systems were embedded, I could move on routing their cables down to my structure's main electronics compartment. I used the 3D-printed cable clips printed earlier to route these cables down the back of my tank, between the two included wire grommets. I wrapped all of these cables with some cable wrap I had laying around from and Ender 3 mod I had done.

Reference image 12 above

These routed cables run through the cable passthrough grommet on the backside of the tank and then slot through their cable route in the PSU terminal cover plate, until out the other side. From here the bulk of cable management began, starting with the power breakout system. I mounted the power breakout board on its 3D printed mount right below the fishbowl mainboard, and then connected the correct incoming and outgoing wires to their connected headers while referencing my eagle power breakout board file. Each of these cables was screwed into their terminal headers before the board was mounted down to the wooden base. From here I began the mounting of the 3 remaining pH boards, two of which sit to the left of my mainboard, and one just off-centered above. These three boards mount via press-fit mounts & their mounting holes, two boards with 3mm holes, and one with 4mm. I then connected the incoming pH probe cable to its terminal, and wired the three pH boards together, before moving onto the main data wiring. Using all of my testing media as a reference, I made the jumper connections for all of the lines in my electronics enclosure, coming from the pH board, temp/humidity sensor, LCD, and light switch, and with that had an integrated system.

Reference image 13 above

Although I had wired all of my connections with mounted boards in my electronics enclosure, I finished the system integration process with some additional cable management via jumper cable mounts.

Reference image 1 above

... and, with all this assembly & integration work done, it was time for final testing. Below is a successful demonstration of my tank's electronics system. Just a note, in this video, my tank's pump is disconnected, because it's never good to run a water pump outside of water. Instead of leaving this pump connected during the testing of the electronics system, I tested the voltage and current from the pump cables run under the plant box.

Finally, came the water test. Despite the number of water tests I had done with the subsystems before, and the proof of their watertight features, this test was damn stressful leading up to it, due to the inclusion of all my electronics in my system on this test. I prepared a spot outside where I could test my tank, and then began preparing the tank, first by filling the plant box with my LECA grow medium ...

Reference image 14 above

... and next, by filling the tank itself. I did this with the help of a couple of my fab groupmates and was able to use a spare water pump and some excess silicone tubing to pump water into my fish tank, without concern of spilling around the base of the tank, where its electronics are located.

Unsurprisingly, but to my relief, the filling of the tank went smoothly, and there was absolutely no spillage/leaks anywhere in the whole system, leaving me with the last remaining tank ... turning it on.

it worked!, upon bootup, water begins flowing through the system, and draining out through the plant boxes draining feature, at the same time as the electronics system is taking measurements from the system and displaying it all of the tanks embedded front LCD.

Step 15: Final Project Presentation

Check out my presentation of the Assistive Aquaponics Fish Tank to the Fab Academy class of 2021! My presentation begins at 1:10:33 and runs till 1:13:45 on the official broadcast, and can be streamed by itself below.

Thanks for checking my project out! Be sure to follow my Instagram @teddymakesstuff, to keep up with my latest work!!

Digital Fabrication Student Design Challenge

First Prize in the
Digital Fabrication Student Design Challenge