404
+Page Not Found
+The page you're looking for doesn't exist or has been moved.
+ + + Return Home + +diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/404.html b/404.html new file mode 100644 index 00000000..7e657bb3 --- /dev/null +++ b/404.html @@ -0,0 +1,515 @@ + + + +
+ + + + + + + + + + + + + + + + + + +The page you're looking for doesn't exist or has been moved.
+ + + Return Home + ++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+I’ve used microcontrollers in most of my past projects. IC data sheets are super helpful in board design with their pinouts, but I’ve noticed much of the contents have been pretty foreign to me. Every once in a while, the youtube algorithm recommended one of Ben Eater’s computer concept videos to me, which provide a great explanation of the simplistic logic and proofs in computers. I ended up watching his entire 8-bit Breadboard Computer series (embedded below) over the fall of 2021, to try to get a bit of a better idea of the workings of a microcontroller. The computer is an “as simple as possible”1 take on an 8-bit computer, using only simple logic to create an 8-bit computer on breadboards. The computer is built-in sectioned modules and then interfaced together, making each section a bit easier to swallow.
+Documentation Style
+This page is a bit different than my other project pages, as it is a build log for my take on this 8-bit Breadboard Computer. Instead of outlining project development (as Mr. Eaters’ videos do an amazing job with that), this page will be a collection of media behind each of my computer modules, as well as some final programs ran on the computer.
+Qty. | +Description | ++ | Cost | +URL | +
---|---|---|---|---|
14 | +Breadboard | ++ | $112 | +link | +
10 | +1kΩ resistor | ++ | + | + |
9 | +10kΩ resistor | ++ | + | + |
1 | +100kΩ resistor | ++ | + | + |
24 | +470Ω resistor | ++ | + | + |
1 | +1MΩ resistor | ++ | $16.99 | +link | +
1 | +1MΩ potentiometer | ++ | $1.39 | +link | +
6 | +0.01µF capacitor | ++ | $1.20 | +link | +
16 | +0.1µF capacitor | ++ | $3.00 | +link | +
1 | +1µF capacitor | ++ | $0.15 | +link | +
4 | +555 timer IC | ++ | $0.63 | +link | +
2 | +74LS00 (Quad NAND gate) | ++ | $0.76 | +link | +
1 | +74LS02 (Quad NOR gate) | ++ | $0.76 | +link | +
5 | +74LS04 (Hex inverter) | ++ | $0.87 | +link | +
3 | +74LS08 (Quad AND gate) | ++ | $0.72 | +link | +
1 | +74LS32 (Quad OR gate) | ++ | $0.89 | +link | +
1 | +74LS107 (Dual JK flip-flop) Note: The videos use the 74LS76 which is extremely difficult to find. The 74LS107 is functionally equivalent but be careful: it has a different pinout. |
++ | $1.58 | +link | +
2 | +74LS86 (Quad XOR gate) | ++ | $1.11 | +link | +
1 | +74LS138 (3-to-8 line decoder) | ++ | $0.80 | +link | +
1 | +74LS139 (Dual 2-line to 4-line decoder) | ++ | $1.55 | +link | +
4 | +74LS157 (Quad 2-to-1 line data selector) | ++ | $1.58 | +link | +
2 | +74LS161 (4-bit synchronous binary counter) | ++ | $1.95 | +link | +
8 | +74LS173 (4-bit D-type register) | ++ | $1.45 | +link | +
2 | +74189 (64-bit random access memory) | ++ | $9.90 | +link | +
6 | +74LS245 (Octal bus transceiver) | ++ | $1.26 | +link | +
1 | +74LS273 (Octal D flip-flop) | ++ | $1.99 | +link | +
2 | +74LS283 (4-bit binary full adder) | ++ | $1.38 | +link | +
3 | +28C16 EEPROM | ++ | $11.85 | +link | +
3 | +Double-throw toggle switch | ++ | $2.97 | +link | +
3 | +Momentary 6mm tact switch | ++ | $1.05 | +link | +
1 | +8-position DIP switch | ++ | $0.79 | +link | +
1 | +4-position DIP switch | ++ | $0.79 | +link | +
44 | +Red LED | ++ | + | + |
8 | +Yellow LED | ++ | + | + |
12 | +Green LED | ++ | + | + |
21 | +Blue LED | ++ | $12.99 | +link | +
4 | +Common cathode 7-segment display | ++ | $4.36 | +link | +
1 | +22 AWG Solid Tinned-Copper Hook-Up Wire | ++ | $29.95 | +link | +
— Total Cost - $228.66 — +
+
+
First 12 Numberes in the Fibonacci Sequence
+n | +Fibonacci Number | +
---|---|
0 | +0 | +
1 | +1 | +
2 | +1 | +
3 | +2 | +
4 | +3 | +
5 | +5 | +
6 | +8 | +
7 | +13 | +
8 | +21 | +
9 | +34 | +
10 | +55 | +
11 | +89 | +
https://eater.net/8bit ↩
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+A Theoretical Confrontation to Contemporary Farming Challenges.
+Paralleling the growth of the global human population, the increased strain is placed on ever-expanding food production. Following current population growth trends, the United Nation’s Food and Agricultural Organization (FAO) predicts a required 70% growth in food production by 2050 to adequately match global needs.1 As of 2020, 9.9% of the present human population faced undernourishment with an estimated 720 and 811 million humans going hungry. Continued reliance on current insufficient North American Agriculture practices will bolster inadequate access to nutrition. Seedstock.com divides problems with contemporary agricultural practices into categories including …
+Addressing the developing demand for food requires a direct confrontation with each of these four challenges and opens the door for sustainable alternatives to classic agricultural practices - massive potential for entrepreneurial pursuit. Aquaponics offers the potential to address the problems of contemporary agricultural practices whilst demonstrating scientific principles and modeling biological cycles for the education of a local community. “Aquaponics is a form of agriculture that combines raising fish in tanks (recirculating aquaculture) with soilless plant culture (hydroponics). In aquaponics, the nutrient-rich water from raising fish provides a natural fertilizer for the plants and the plants help to purify the water for the fish”, and this is a sustainable method to both raise fish and grow crops.2
+
+
+
+
Adaptable Aquaponics serves as a theoretical successor to my Assistive Aquaponics Fish Tank, a small-scale, self-sustaining ecosystem, with the hopes ofexpanding the accessibility of successful & thriving aquaponics ecosystems to individuals. While the Assistive Aquaponics Fish Tank is equipped to enable access to aquaponics at an individual level, economic optimization of the project came second to maintaining a sleek design hoping to catalyze in-house acceptance of the product. Adaptable Aquaponics offers some contrasting design choices with the goal of addressing all four categories of contemporary agricultural challenges and addressing the current bottlenecks of global nutrition.
+Both the Fusion 360 model and the prototyping mesh & SVG files for this project can be accessed via the button below. 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. The renders of my Adaptable Aquaponics model utilize the Ulmer Muenster HDRI from polyhaven.com in their environment. Additionally, this model’s Solar Panels, Water Pump & Casters are altered files from CAD libraries.
+Make it Modular
+ +Adaptive Aquaponics is the scaled successor to my Assistive Aquaponics Fish Tank & my winning entry into Autodesk Instructable’s Make It Modular student design challenge receiving the Autodesk Construction Solutions Scholarship Award. Be sure to check Adaptable Aquaponics out on instructables!
+Being the theoretical successor to my Assistive Aquaponics Fish Tank, the CAD for Adaptable Aquaponics utilizes the same “skeleton” of a closed-loop water circulation system, incorporating a remixed version of my Assistive Aquaponics Fish Tank’s plant box. Each “Aquaponics Cell” in Adaptable Aquaponics (I’ll touch on the distinction of these mentioned modules later in this section) contains eight individual plant boxes, each with a volume over two times as great as the smaller plant box of my Assistive Aquaponics Fish Tank. These up-scaled cells have been altered to ensure proper water flow at a larger scale, and are linked in series via several pipes to a Biofilter housed on the “Aquaponics Rack”. Unlike in a small-scale ecosystem such as my Assistive Aquaponics Fish Tank, a biofilter is an essential component of a large-scale aquaponics setup. The filter expands the surface area of your system, providing ample space for the nitrogen cycle to occur.
+Following the Assistive Aquaponics Fish Tank once more, Adaptable Aquaponics is a cross between a Nutrient Film & Media Bed aquaponics system. As water is pumped into each plant box from the biofilter, it continuously flows along the sloping profile of the plant box’s bed, passing through the plant roots, before exiting the plant box through a waterfall-esk exit slit & draining into the fish tank below. Plant beds & fish tanks are placed in an eight-to-one ratio in each “Aquaponics Cell”, a stack in contrast to the small tank and one-to-one ratio of the Assistive Aquaponics Fish Tank. Opting for a larger fish tank increases the output efficiency of an aquaponics farm. Instead of being restrained to small-scale aquaculture (such as goldfish in my Assistive Aquaponics Fish Tank), hardier fish such as Tilapia & Catfish can be farmed - making the food output of the farms even more efficient. Water is pumped out through a drain pipe at the bottom of each tank, flowing through a sediment tank located on the “Aquaponics Rack” before into the water pump & then back into the biofilter. Parraling the system’s inclusion of a larger tank for larger fish, a sediment tank is a must to free the system of excessive fish waste, allowing for maintained water clarity. Heavy waste carried in by the stream of water in the system will sink to the bottom of the sediment tank under conditions of low flow.
+The principle behind my design work on Adaptable Aquaponics parallels the “circles of progress” model, where you begin by achieving the core minimum viable product, and expanding the diameter of your “circle”, inflating your project with more layers of progress. Though this isn’t my suggested approach to CAD, I found using the “circles of progress” mindset useful while thinking of the modularity scales in my file.
+Adaptable Aquaponics is constructed with layered modularity, a distinction highlighted by the component layering in my Fusion browser.
+Eight Individual plant boxes make up a single aquaponics cell, two aquaponics cells make up a single aquaponics rack, and two aquaponics racks are housed inside of a single shipping container. The scaling of modularity allows for application scaling to be applied to Adaptable Aquaponics. A single plant box could be used in the form factor of my Assistive Aquaponics Fish Tank, or multiple Adaptable Aquaponic Shipping Containers could be housed in parallel to allow for large-scale farming. Modularity in the case of Adaptable Aquaponics not only enables future iteration & reconfiguration but also the scaling of the ecosystem itself - meeting the needs of any potential consumers - ranging from individual to community.
+Shifting to an analysis of the CAD work behind Adaptable Aquaponics, I was super stoked to get to experiment with Fusion 360’s new Automated Modeling tool! I used automated modeling to generate an optimized vertical support structure for my systems aquaponics rack, as well as for the angled mounts for adaptable aquaponics solar panels. The tool can be found under the Automate menu in the toolbar.
+Automated modeling is about as intuitive as you can get, requiring only three inputs to generate a body - Faces to Connect, Bodies to Avoid & Operation type. I began the computational design work of my aquaponics rack outside of the automated modeling tool itself, but instead by creating both the top and bottom plates of my Aquaponics rack & attaching 6 mounting points to each sheet. Then, working around the prepositioned Aquaponics Cells, biofilter & sediment tank, I created shelves to hold the content of the racks, unattached to support. I then opened the automated modeling tool and selected the previously created mounting points on both the top and bottom plates as well as each shelf with the Faces to Connect selection tool. Note, that there are three individual vertical supports on each Aquaponics rack, so I selected a corresponding set of 1/3 of the total created faces for each automated operation. I moved on to the Bodies to Avoid selection tool, highlighting the components of each Aquaponics Cell, the biofilter & the sediment tank closest to the selected points of connection. I was careful here to only select crucial bodies to avoid, not all in the model - the fewer input selections, the faster computation time. With these selected inputs, I generated a design with a New Body operation.
+
+
+
After ~10 Mins, the Automated Modeling menu presented me with 6 generated bodies under the Alternatives menu. You can click through these generated bodies to see them in the workspace, before finalizing your selection with the Ok button. I repeated this generation for the two other vertical supports on the Aquaponics Rack, choosing a visually similar generation between all three to keep consistency to the rack. Computationally designed bodies can also be seen in the solar panel mounts located on the roof of Adaptable Aquaponics. These bodies followed a similar workflow, where I connected the back face of each solar panel to pre-created mounting points.
+The complex spatial routing of Adaptable Aquaponics plumbing required the use of Fusion 360’s ability to sketch non-planar line sand splines. To enable this feature, click on your user icon in the top right of the window & navigate to …
+ +… and toggle this option on. Be sure to click Apply in the bottom right-hand corner of the Preferences menu before exiting.
+Fusion 360’s non-planar sketching allows spline points to be removed from their initial sketch plane and routed to other planes. Once a point is placed on a 3D spline, Fusion allows for the alteration of direction in three dimensions before you place the next point.
+Beginning from the intake valve of each plant box, I routed a spline to a t-connector before using the Pipe tool with each routed spline as a reference - leaving me with all of the plant boxes in a given Aquaponics Cell routed in series. Additionally, 3D splines were used to route the plumbing from each fish tank to the sediment tank, from the sediment tank to the water pump, from the water pump to the biofilter, and from the biofilter back to the plant boxes.
+Once Adaptable Aquaponics was finalized - the 95th iteration … phew - I continued to Fusion 360’s rendering workspace.
+I began by setting up the renders scene by navigating to …
+ +… where I chose to upload a custom HDRI backdrop.
++
+As mentioned earlier on this page, I chose the Ulmer Muenster HDRI from polyhaven.com as my backdrop, as the scene offers a compromise of beauty and urban (not that those are mutually exclusive) - preserving the largest of my envisioned use cases for Adaptable Aquaponics, urban farming (stay tuned for the next section!). Once my HDRI backdrop was uploaded, I navigated back to …
+ +… where I took a trial and error approach to tune the renders Environment, Ground & Camera settings until I was left with some nice looking renders! Check them out below!
++ +
+Contemporary agriculture is completely dependent on non-renewable materials. Dependence on fossil fuels is not only not a sustainable practice that is damaging our planet but jeopardizes the future of our agricultural stability. With rigid dependence, how do we expect to handle the extinction of a non-renewable? Adaptable Aquaponics offers a solar-powered solution, completely independent of any non-renewables & costly electric bills that hinder access in communities facing a scarcity of access. Though the elimination of dependencies is crucial to making Adaptable Aquaponics a sustainable solution to contemporary farming challenges, the vertical integration of the system offers a Carnegie-esk entrepreneurial venture, ensuring freedom from the potentially binding agreement for resources.
+Data from the US Geological Society shows rainfall patterns “may become less predictable and dependable”, while the amount of groundwater “drawn for use in irrigation has tripled since the 1950s”.3 Though, unlike fossil fuels, water is a renewable resource, freshwater has its limits. Considering nearly 70% of all freshwater used by humans is used in agriculture, addressing water usage is a warranted concern. When compared to standard agricultural practices, Aquaponics requires 90 to 99% less water.4 Similar to the potential lack of electricity access, Adaptive Aquaponics offers communities with a shortage or imposition in access to water a sustainable agricultural alternative, while also offering entrepreneurs another opportunity to continue to vertically integrate.
+Faulty land management techniques have stripped soil from its nutrients, requiring fertilizers to aid plant growth. The nature of aquaponics replaces any dependency on soil with nutrients from the nitrogen cycle - a naturally occurring ecosystem that can run independently from fertilizers. Adaptive Aquaponics’ cross between a Nutrient Film & Media Bed aquaponics system preserves the dirt-free nature of hydroponics, whilst maintaining a small, modular structure of its plant boxes. The modular nature of adaptive aquaponics allows the system to potentially thrive regardless of scale and location, opening the door for urban farming!
+The UN estimates that 1/3 “of the world’s food goes to waste, either during agricultural production, post-harvest handling, and storage, processing, distribution, or consumption”.3 The modular nature of Adaptive Aquaponics ensures adequate scaling of agriculture in a given population. The compacted form factor and potential for urban or harsh environment farming enable the growth of food locally to a population. Instead of depending on agricultural preservation, processing, storage, and distribution, providing a community with Adaptable Aquaponics enables full control over food production, ensuring neither over nor under production. Interaction with agriculture at a community scale may remove the barrier between farming communities and consumers and hopefully, will catalyze a shift from to favor “conservation over convenience” thus regulating agriculture to ensure adequate food is provided.3
+As has seemingly become a trend across my work, I attempted to use a plethora of digital fabrication in the creation of my scale model. My model is a 2.3% scale prototype of Adaptable Aquaponics, fabricated with both additive and subtractive processes. Shout out to @taimakestuff who was my lab buddy @makerspaceCharlotte while I ground out this project’s post-processing :)
+Computationally designed elements utilize organic surveys to ensure optimal geometry for both strength and efficiency, thus the perfect partner for additive manufacturing. I opted to 3D print all elements of my scale model that utilized Fusion 360’s Automated Modeling, including the shipping container with its solar panel mounts & Aquaponics Rack with its vertical supports. I also printed the contents of each aquaponics rack to achieve the highest accuracy to the draft angles and plumbing locations on the bodies. All parts for this project were printed on my Prusa I3 MK3S+ with a 0.4mm nozzle at a 0.3mm layer height. I chose a white PETG, along with a pretty aggressive layer height to allow for ease of post-processing & painting of the model.
++ + +
+PETG is my go-to generic 3D printing material, however, it really shines when faced with post-processing. PETG takes well to sanding and is overall rather easy to clean up. One of my favorite tricks is taking hot air from a hair-dryer to a PETG printed part. The hot air shrivels any stringing or surface defects into masses that fall off after rubbing your finger over the surface.
+I was lucky enough to stumble across some gloss black acrylic in the scrap bin @makerspaceCharlotte, which I used to create Adaptable Aquaponic’s solar panels. This was my first time using the lasers @makerspaceCharlotte, and the machine that I was on ran a different wattage than the lasers at the Charlotte Latin Fab Lab (my school’s lab & my workplace) so I began with a bit of research into optimal cut settings. After altering the laser focus to achieve the desired (slightly thickened beam) effect, I began batch cutting the model solar panels.
+ + +Note the other test cuts on the stock material above. Though for the sake of focusing on Adaptable Aquaponics and not the prototyping process I’ve chosen to not mention much of the prototyping behind this physical model. I usually include ample prototyping content in my articles, so it felt necessary to call attention to the test cuts here :)
+I cleaned up the final cut parts with some soap and water, before continuing to attach each solar panel to its 3D printed mount & then to the roof of the Adaptable Aquaponics shipping container.
++
+ + + +I followed up my acrylic cutting with the wooden base and top to each Aquaponics Rack. Unfortunately, I didn’t have access to any 1/8” ply, so I had to do some prep work with a piece of 1/4” plywood stock. I planned the surface of my stock material on a drum-sander until down to just below 1/8”. I then focused the laser to this stock & cut all four planks.
+The glue up of these shelves was a bit finicky, as my fingers just seem to be a super glue magnet - but eventually, I got both Aquaponics Racks complete with their plants, vertical support, shelves, Aquaponics Cells, biofilter & sediment tank, and then installed them inside the shipping container.
++ +
+As a finishing touch, I used a Cricut Explore Air 2 to cut the sign attached to the side of Adaptable Aquaponics from vinyl. Though I’ve made dozens upon dozens of stickers with the same workflow, the scale of this logo proved to be a bit of a challenge. I not only had difficulties weeding the cut vinyl at such a small scale, but the machine itself was ripping up parts of the design upon retraction. I ended up altering the cut settings to a custom array as suggested by sofontsy.com, using the Washi Sheet default with a pressure set to More. With these settings, I was able to get a clean enough cut that I could weed the sticker, layer the two colors, and then apply to the side of the Adaptable Aquaponics model.
++ +
+With the design and prototyping completed, I headed out to my local strip mall for a photo op, only getting a couple of strange looks from shoppers wondering what the boy in the old-navy pajama pants was doing taking pictures of a miniature in the middle of the parking lot. But it was worth it! As opposed to settling for a diorama background, or just pictures of my model on my workbench, I highlighted a legitimate potential environment for such a product, and I promise you, when Adaptable Aquaponics hits full scale in a parking lot, the shoppers won’t be blown away by my magnificent fashion choices, but instead by the wonders of Aquaponics!
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+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 to 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 plantlife 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 leads 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.
+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.
+
+
+
+
+
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 with providing application 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. Below are some of these concept sketches, showing the brainstorming of the tank’s plywood structure.
++
+
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.
Qty | +Description | +Price | +Link | +Notes | +
---|---|---|---|---|
1 | +Power Supply | +$26.95 | +Link | +AC to 12v DC - Low Height Profile | +
1 | +AC Power Adapter | +$8.99 | +Link | +Rocker Switch for Power Control - Inline Fuse | +
1 | +Water Pump | +$24.99 | +Link | +12v - 9mm outlet - 130GPH | +
2m / 6.6ft | +9mm Silicon Tubing | +$10.49 | +Link | +N/A | +
5m / 16.4ft | +Grow Light Strips | +$13.99 | +Link | +4 Red : 1 Blue | +
5m / 16.4ft | +White Light Strips | +$11.99 | +Link | +In Lab | +
1 | +pH Sensor | +$66.99 | +Link | +N/A | +
1 | +Electrical Isolation Board | +$16.99 | +Link | +N/A | +
120p | +Female to Female Jumper Cables | +$13.99 | +Link | +In Lab | +
1 Spool | +Speaker Wire | +$9.95 | +Link | +In Lab | +
1 Pack | +18 Gauge Wire | +$15.99 | +Link | +In Lab | +
1.75mm - 1kg | +White PETG | +$23.99 | +Link | +N/A | +
2lb | +Aquaponics Beads | +$11.95 | +Link | +N/A | +
5oz Tube | +WeldOn 16 | +$17.90 | +Link | +N/A | +
10.1oz Caulk Tube | +All Purpose Clear Silicone | +$5.38 | +Link | +N/A | +
6 - 1206 Footprint | +SMD LED | +$3.00 | +Link | +In Lab | +
1 - 1206 Footprint | +100nf Capacitor | +$0.18 | +Link | +In Lab | +
2 - 1206 Footprint | +22pf Capacitor | +$0.10 | +Link | +In Lab | +
7 - 1206 Footprint | +10uf Capacitor | +$1.40 | +Link | +In Lab | +
1 - 1206 Footprint | +1uf Capacitor | +$0.13 | +Link | +In Lab | +
1 | +16Mhz SMD Crystal | +$0.27 | +Link | +In Lab | +
8 - 1206 Footprint | +330 Resistor | +$3.20 | +Link | +In Lab | +
3 - 1206 Footprint | +10k Resistor | +$0.30 | +Link | +In Lab | +
11 - 1206 Footprint | +0 Resistor | +$0.26 | +Link | +In Lab | +
3 | +SMD 12v-5v Fixed Voltage Regulator | +$4.80 | +Link | +In Lab | +
1 | +10k Potentiometer | +$0.87 | +Link | +In Lab | +
3 - 1206 Footprint | +4.9k Resistor | +$1.50 | +Link | +In Lab | +
3 | +SMD Schottky Diode | +$0.36 | +Link | +In Lab | +
1 | +SMD MOSFET | +$0.37 | +Link | +In Lab | +
1 | +ATTiny 1614 | +$0.91 | +Link | +In Lab | +
2 | +ATTiny 412 | +$1.40 | +Link | +In Lab | +
1 | +ATMega 328p | +$2.43 | +Link | +In Lab | +
1 Pack | +Through Hole Male Headers | +$7.49 | +Link | +In Lab | +
5 | +SMD Male Headers | +$4.75 | +Link | +In Lab | +
3 - Single Sided | +Copper PCB Blanks | +$9.35 | +Link | +In Lab | +
Total Cost: $323.60
+Week | +Tool/Practice | +Product | +Link to Compleation | +
---|---|---|---|
6 | +Electronics Design | +Tank Main Board | +✔️ First Board Iteration | +
7 | +CNC Milling | +Aquaponics Tank Plywood Structure | +✔️ Plywood Tank Structure | +
11 | +Inputs | +Temp/Humidity Sensor | +✔️ Temp/Humidity Board | +
13 | +Outputs | +LCD | +✔️ LCD Breakout Board | +
14 | +Networking & Communication | +LCD Interface & Tank System Communication | +✔️ LCD Interface & Communications | +
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 understandings 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.
+ +With this schematic done, I moved onto 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
+ +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 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
+ +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.
++ +
+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
+ +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.
+
+
+
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.
+
+
+
+
+
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, 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.
+
+
+
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.
+
+
+
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 boards 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 show below.
+
+
+
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 onto 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 below.
+
+
+
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 recommended to included 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.
+
+
+
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 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.
+
+
+
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 below.
+ +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 referencing 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 build upon the traces. All of these changes left me with yet another board iteration, shown below.
+ +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 know have the component layout of the board memorized, and have increased my soldering speed with each iteration.
+
+
+
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!!
+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 below.
+ +This simple sketch proved the working of my board and flashed my onboard pin 13 LED on my fishbowl board.
+
+
+
+
+
To interface with my Fish Bowl mainboard, I’m planning on reading a temp/humidity sensor as well as a pH probe placed in my tank. The readings of both temperature and humidity are crucial measurements when calculating the toxicity of ammonia in an aquaponics system. Keeping the nitrogen cycle in check is needed for the success of any aquaponics system, and this is why I’ve chosen these inputs to read.
+A quick beginning note - here’s the pH scale I referenced during the pH work of my tank. Goldfish, the fish that will be using 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)
+“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)
+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.
+ +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.
+
+
+
+
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.
+ +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 tanks 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.
+
+
+
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.
+ + +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 below.
+ +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 creating 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 using 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.
+
+
+
+
+
+
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 sensors data pin into a readable humidity and temperature output. The libraries follow the equation below to derive the relative humidity from the sensor.
+Where: +- \(RH\): Relative Humidity +- \(\rho_w\): Density of water vapor +- \(\rho_s\): 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 programmed, made in week 4’s electronic production class, connecting my boards GND and VCC to the programmers 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 output the values in a serial monitor through serial, shown below.
+ +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);
+ }
+}
+
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 below.
+ +With this schematic flatted out, I moved onto 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 below.
+ +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 below.
+
+
+
+
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.
+
+
+
+
+
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.
+ +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 below.
+
+
+
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.
+I call upon each of these different nodes throughout my mainboard interface code. Each port is started with the line …
+ +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.
+ +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.
+ +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 the image below), and … It Worked!
+
+
+
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, shown in the image below.
+ +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.
+
+
+
+
+
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 …
+ +… to 5 seconds…
+ +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 below.
+
+
+
+
+
Again, I fabricated this power breakout board, and uploaded my timing sketch to it, as done prior.
+
+
+
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.
+ + +The wooden tank structure was my first large physical step towards 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.
+
+
+
To generated 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 value 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.
+ + +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 onto 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 included below.
++
+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 tanks 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.
+
+
+
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.
++
+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 tanks 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.
+ +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, 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.
+
+
+
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.
+ +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 in 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 of 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. To get a minimal amount of char took a couple of different attempts, but eventually, I was left with the product below …
+ +… 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 below.
+ +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 take 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 your reading currently, along with the project name and copyright.
+ +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.
+ +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 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 below.
+ +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
+ +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 application 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. Below is an image of the last bonding run for the tank’s sidewalls.
+ +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 below.
+ +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.
+ +I found that although WeldOn 16 worked great for the structure of my tank, and allowed for a secure bond between all of the tanks 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, 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 ability to do all of my tanks 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.
+ +The set time for this silicone was only 15 hours, but 24 was recommended on my brand’s datasheet before exposer to water, so after this time, another watertight test of my tank was in order. I set up my silicone sealed tank of 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, with a fish ready tank!
+
+
+
+
+
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 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 are 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, shown in the inspected slicing image below.
+ +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 below…
+ +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 from 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 towards the center of the board, where the microchip is located, upon first glance.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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.
+
+
+
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.
+
+
+
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.
+
+
+
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 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.
+
+
+
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 below.
+
+
+
+
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.
+
+
+
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. +
+
+
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.
+
+
+
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.
+
+
+
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.
+
+
+
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.
+
+
+
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.
+
+
+
… 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 …
+ +… 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/leakes 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.
+ + + + + + + + + + + + + + + + + + ++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+This start of the Pandemic project stemmed from my freshman year engineering capstone project. At the start of 8th grade I had an issue, I was a couple of months into learning Fusion360 and I decided to upgrade my setup from an old janky pc to a brand new laptop and some 20-inch monitors to go along with it, which was great and all but gave me a whole tone of issues to sort out. I had this great desk in the corner of my room, that my great grandfather built and that had been passed down to me, however, there was one huge flaw using that desk with my brand new setup and that was cable management. Below are some plans draw out for the desk.
++
+So I set off in Fusion to design a desk that fit all of my needs. My goals were to have a desk measured to fit perfectly in the corner of my room, with plenty of legroom so I would never hit my knees on it, and the best cable management imaginable. And after a couple of different iterations, I came up with this Model.
+ + + + +However shortly after finishing up the CAD aspect of this project, Covid-19 caused our school to resort to online learning, cutting me off from our school’s lab equipment, however, I happen to have a lot of the tools we have in our lab in my little workshop at my house, and I was pretty determined to finish the desk, so just before everything closed down I took a trip to lowes to pick up some lumber and supplies. I settled on a frame and cabinet of 2x4s and some plywood that was painted white pretty quickly, but the top took some more thought. Eventually, I decided to make the top out of cedar planks that were stained with Provincial to match the stain of the floor in my room. Also at lowes, I picked up a Kreg-Jig to drill pocket holes for the desk, as I didn’t like the idea of screws being visible. It was my first time using a Kreg-Jig but it went super well as it’s a relatively simple jig to use.
+A couple of days after getting the wood, I finally started assembling the desk, starting by laying down the frame, making sure the front 2x4 was flat and the back was upright (to give more leg space) and I was pretty excited to get the whole thing together. Maybe a little too excited because even though you can’t tell from the pictures above, I built the whole desk wrong, putting the corner on the wrong side. This was a huge setback to fix as it meant that I would have to take the entire desk apart, use wood filler on all of the newly exposed holes, and build it back up the right way. I was even considering just leave the desk as is, and rearrange my room to match the flaw, however, I wanted my desk to be perfect and that meant fixing it according to my CAD model. So I did the laborious tasks listed above and finished the frame of the desk the right way late that night. The next day I was ready to do some more on of the desk, so I decided to start throwing together the top. I spent that whole day sawing, planning, and sanding the cedar before I put the top together using the Kreg-Jig the next morning. And this time I didn’t make a single mistake, and I’m really happy with the result.
++ +
+I spent the next two days painting the frame with three coats of white paint and staining the cedar with Provincial.
+ + + + +
+
+
As I said earlier the choice of wood for the surface of the desk took some thought, but I’m super glad I went the cedar route. Originally I was planning on using oak, but the cost scared me away to a much better smelling and looking cedar. My only concern with this type of wood was how much it expands and contracts. I was concerned that screwing a cedar top to my frame would just wiggle itself loose over time and cause issues. So I came up with a workaround. Instead of attaching the Cedar top directly to the frame, it’s held by 3d Printed mounts that allow the top to expand and contract a whole lot more without becoming loose. I’m super happy I took the time to figure this one out as it’s going to save me trouble with using cedar in the long run.
+This is a huge part of the project as it’s one of the reasons I decided to even build a new desk in the first place. After attaching the top of the desk to the frame, I threw on this great air spring laptop mount that routs all of the cables from my laptop through a grommet in the top on the table, down to the corner cabinet. The cabinet is designed with a false top that hides all of the cables (except for two going to the subwoofer on a lower shelf) from inside the cabinet. Then the cables are routed through a hole in the back and ran through 3d printed cable clips on the back of the desk. The cable clips are exactly as long as the trim of our floor is, so they don’t push the desk off the wall any more than it needs to be. All of the cables are then ran to where their needed (i.e monitors, speakers, keyboard, google home, etc.). Finally, all of the power cables are ran back into the top of that corner cabinet and plugged into a built-in power strip, which plugs into a wall socket directly to the left of the cabinet, hiding all the cables from view.
+I love how my desk came out, It solves all of my annoying cable issues and fits perfectly in the right corner of my room. Eventually, I’m planning on wall mounting my monitors to give me even more desk space, however, the little corner piece gives me a perfect location to use a pen and some paper and write things out. Putting the desk in its place, I realized that there was way too much space above it and after some browsing, I found some shelves on amazon that use the same stain and match perfectly, so I ordered and installed those over the desk. This project we surprisingly smoothly in the face of the current Pandemic, and even with my building setbacks came out well.
+
+
+
+ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + + +
+Giving agents a temporal understanding through human physiological data.
+ + +There’s a concept in AI research called the World Model, which aims to create neural networks capable of understanding and simulating cause and effect within a temporal and spatial context. Unlike current Large Language Models (LLMs) that primarily predict outputs based on input patterns, world models aspire to simulate both causes and effects based on a deeper understanding of time and space.
+The key to a world model is its ability to grasp cause and effect, which fundamentally requires a temporal understanding. As it turns out, giving a neural network a temporal understanding is quite challenging. While we can instruct an LLM to output current timestamps or locations, it lacks the ability to truly associate actions and experiences within a relative dimension of time and space as humans do.
+Current approaches to building world models include aim to provide AI systems with a sense of time and space, but they may be missing a crucial element of human temporal understanding:
+Imagine a humaniod and a human are sitting together at a table. Suddenly, the human stands up, screams, and hurles a chair across the room. The robot, relying solely on visual input, might respond by moving away. In this case:
+\(x(t)\) is an observation in a given instant and \(a(t)\) is the resulting action in that instant.
+Now, consider the same scenario, but this time two humans sit together at a table. One human stands, screams, and hurles a chair across the room. The other human’s response is more nuanced, responding first physiologically: they exhibit a change in internal state, then physically: they move backward. In this case:
+Thus a contemporary humanoid (one constrained to vision alone) goes from A -> C, while a human goes from A -> B -> C.
+World models cannot truly gain a comprehensive temporal understanding based solely on data collected from robots or purely external observations.
+Temporal understanding cannot be trained from data that goes from A -> C. World models must be trained on data that goes from A -> B -> C.
+The collection of physiological state data may provide insight into man’s temporal understanding, and thus how to train a neural network to understand cause and effect.
+Current efforts in world model development often rely heavily on data collected from robotic systems or external observations that we humans can describe (i.e. see chair thrown -> move backward). These observations forgo the subconscious response integral to a human’s actions (i.e. see chair thrown -> physiological state change -> move backward).
+If we acknowledge that current AI systems lack a subjective understanding of time, why do we primarily use data from these systems to try to instill temporal understanding?
+Data collected from human subjects could provide a window into how humans subjectively experience time, potentially leading to more sophisticated and human-like temporal reasoning in AI systems.
+Yes, physiological states may be able to provide a window into man’s subjective experience of time. But what physiological states?
+It’s important to note that the relationship between physiological states and time perception is complex and influenced by various factors, including attention, emotion, and cognitive load 36 41.
+When my hypothesis first came to me, I believed I had to be naive to some particular reason our pipeline is robot -> simulator -> robot and not human -> simulator -> robot. It was simultaneously a relief and a pain in the ass to not find a specific reason on the first page of Google.
+I’ve got a few thoughts as to why no one has done this yet:
+So what would such a venture look like? Well, there are a few assumptions for us to start from:
+As our context window approaches the total size of the internet, the bottleneck will no longer be compute, but rather data. At the last NeurIPS, Ilya Sutskever notes that data is “the fossil fuel of AI”.
++Yall heard it from the man himself pic.twitter.com/Pie7QLCjA7
— Jason Wei (@_jasonwei) December 13, 2024
+Yall heard it from the man himself pic.twitter.com/Pie7QLCjA7
— Jason Wei (@_jasonwei) December 13, 2024
World models are expanding in prominence amongst academics and top research labs.
++
++
+It is prime time to develop foundational world models, and we currently don’t have enough data, much less granular enough data, to train them. While reviewing the initial draft of this article, Dr. Alexander Titus offered me this thought: “Think of it like filling a mesh. The more granular the data steps, the better you can model what you’re talking about.” If this translates to world models, the A -> B -> C hypothesis will hold.
+Thus I am building a data acquisition venture focused specifically on physiological data acquisition from humans at scale, in hopes of giving agents a better understanding (human-like that is) of time and space.
+Collecting physiological data from humans is hard, but at scale, it is even harder.
+INSERT VIDEO
+Physiological changes should simultaneously govern rewards and be given to the agent as a state. Correlation may then be drawn between an agent’s actions and physiological state changes.
++
+This calls for a few things …
+An “Interoception Model”, that is, a neural netowrk which predicts a physlogical change given an external input.
+A “Temporal Model”, a model to adjust an agent’s “perception of time” (that is with a scalar), in accordance with \(\iota_t\).
+A “Reinforcement Gymnasium”. An agent seeks to maximize rewards. Their actions should be a product of their internal and external states, as well as previous actions/rewards.
+I need to gather some resources before I can get started with physiological state data collection at a large enough scale to train a foundational model, I started by toying around with Vision Transformers and some fMRI datasets I found on the internet.
+The rest of this Interoception Model section is a preprint I wrote while attempting Timeline step one: “Utilize publically available physiological data to asses such data’s ability to provide a window into temporal understanding”.
+This research presents a novel approach to understanding temporal cognition through the application of Vision Transformers to functional Magnetic Resonance Imaging (fMRI) data analysis. While current artificial intelligence approaches to world modeling rely heavily on absolute temporal markers and timestamps, human perception of time operates as a fundamentally subjective experience that adapts with cognitive state and learning progress. We look to demonstrate that neural activation patterns captured during learning through fMRI contain rich temporal information that can inform more nuanced approaches to temporal processing in AI systems.
+By analyzing temporal patterns across multiple learning stages and tasks, we attempt to demonstrate the feasibility of developing AI systems capable of processing time as a relative rather than absolute construct. This work represents an important step toward artificial intelligence systems that can reason about time in ways that more closely mirror human cognitive processes.
+This work implements a Vision Transformer architecture 18 19 optimized for learning stage classification from fMRI data. While fMRI presents known limitations in its reliance on blood-oxygen-level-dependent (BOLD) signals 20, deep learning architectures may be able to extract temporal patterns that traditional analysis methods miss.
+Human learning progresses through distinct stages characterized by shifting patterns of neural activation 15. These transitions are particularly evident in the striatum and medial temporal lobe regions 16. Our architecture’s design mirrors these biological principles through its progressive processing stages and attention mechanisms.
+fMRI captures these learning stages through blood-oxygen-level-dependent (BOLD) signals, providing an indirect but reliable measure of neural activity 20. While this indirect measurement presents certain limitations, research has demonstrated correlations between BOLD signal temporal patterns and learning progression 22. The robust test-retest reliability of fMRI in classification learning tasks 14 provides a stable foundation for extracting temporal patterns relevant to learning stages.
+Recent advances in transformer architectures have revolutionized sequence processing capabilities 18. Our implementation builds on the Vision Transformer architecture 19, but with significant modifications designed specifically for fMRI data processing. These modifications include:
+Our implementation addresses two core challenges: extracting meaningful patterns from complex fMRI data 22 and developing architectures capable of learning from these patterns 14. This section outlines our approach in three parts: data preprocessing implementation, fMRI-specific augmentation strategies, and temporal-aware transformer architecture design 18 19.
+The implementation utilizes four complementary classification learning datasets from OpenFMRI. Each dataset provides specific insights into temporal learning aspects 15. The primary dataset (ds000002) contains data from 17 right-handed subjects performing probabilistic and deterministic classification tasks 16. Task structure includes:
+Data acquisition specifications:
+Three additional datasets complement the primary collection:
+Our implementation uses a three-stage preprocessing approach based on established neuroimaging practices 22 with optimizations for temporal pattern preservation. The pipeline integrates spatial normalization and temporal alignment to maintain both anatomical accuracy and temporal fidelity. The complete preprocessing pipeline follows:
+Where:
+fMRI acquisitions vary in dimensionality 22. Our validation ensures consistent dimensionality while preserving temporal information:
+This validation maintains spatial integrity while ensuring proper temporal dimension handling 20. Single-volume inputs receive an added temporal dimension for consistent processing.
+The implementation standardizes spatial dimensions while maintaining anatomical proportions 22 through trilinear interpolation:
+Target dimensions \((H_t, W_t, D_t) = (64, 64, 30)\) balance spatial resolution and computational efficiency 14. The temporal dimension scaling factor of 1 preserves original temporal resolution.
+Following fMRI preprocessing protocols 22, we implement temporal-aware normalization accounting for BOLD signal dynamics:
+Where:
+This normalization preserves temporal dynamics while standardizing signal intensity across sessions and subjects 20. Independent timepoint normalization maintains relative temporal patterns crucial for learning stage classification.
+Our implementation includes a comprehensive suite of domain-specific augmentation techniques designed to enhance model robustness while respecting the unique characteristics of fMRI data. These techniques are validated through neuroimaging research and carefully adapted for deep learning applications:
+We implement an adaptive temporal dropout mechanism that helps the model learn robust temporal features despite potential signal interruptions or artifacts. The masking strategy:
+The implementation incorporates structured dropout in the spatial domain to handle regional signal variations and encourage learning from distributed patterns. Key features include:
+To account for natural variations in brain structure and registration, we apply anatomically-constrained elastic deformations that:
+Our architecture combines Vision Transformer principles with specific adaptations for fMRI data processing. The implementation consists of three primary components, each optimized for the unique characteristics of neuroimaging data:
+The channel reduction component efficiently processes high-dimensional fMRI input through a dual-stage approach:
+Our temporal processing incorporates hemodynamic response function (HRF) characteristics 20 through causal attention masking:
+This enforces a 6-second BOLD delay constraint, reflecting established HRF parameters 22 while maintaining temporal causality in BOLD response learning.
+We implement a depth-dependent dropout strategy that provides stronger regularization in deeper layers while maintaining high information flow in early layers.
+This strategy:
+We implement dynamic loss scaling for numerical stability:
+This adaptive scaling ensures stable training while maintaining computational efficiency.
+The implementation uses AdamW optimizer with fMRI-validated parameters 19:
+We implement a custom warmup-decay schedule optimized for fMRI data processing:
+Schedule parameters:
+This provides stable initial training followed by gradual learning rate decay for optimal parameter convergence.
+We implement comprehensive regularization following established practices 18:
+Early stopping criteria definition:
+Parameters:
+Our implementation demonstrated patterns in learning stage classification from fMRI data, with performance characteristics varying significantly across learning stages. The complete analysis reveals both potential capabilities and areas requiring further refinement.
+The model achieved an overall accuracy of 35.6% across four learning stages, with a balanced accuracy of 42.8% and a macro F1 score of 0.407.
+While exceeding random chance performance (25% for four classes), these metrics highlight the inherent complexity of learning stage classification from neuroimaging data.
+fMRI data from varaying datasets/test conditions is quite volatile to work with. This research would benefit signficantly from custom/standardized means of physiological state data collection at scale.
+The Cohen’s Kappa score of 0.093 indicates performance above chance but demonstrates the substantial challenge in achieving consistent classification across all learning stages.
+Performance varied substantially across learning stages, revealing distinct patterns in the model’s classification capabilities. The model demonstrated strongest performance in identifying the mastery stage, achieving a precision of 0.600 and recall of 0.750 (F1 = 0.667). The ROC curve for mastery classification shows an impressive AUC of 0.945, suggesting highly distinctive neural activation patterns associated with mastery-level learning.
+The middle learning stage showed moderate classification success (precision = 0.353, recall = 0.429, F1 = 0.387), while early and late stages proved more challenging to classify (F1 scores of 0.258 and 0.316 respectively). The confusion matrix reveals a tendency to misclassify early learning stages as middle stages (47.1% of cases), suggesting a gradual transition in neural activation patterns during learning progression.
+Learning Stage | +Precision | +Recall | +F1 | +Support | +ROC AUC | +Mean Conf. | +Error Rate | +
---|---|---|---|---|---|---|---|
Early | +0.286 | +0.235 | +0.258 | +17 | +0.368 | +0.437 | +0.765 | +
Middle | +0.353 | +0.429 | +0.387 | +14 | +0.556 | +0.412 | +0.571 | +
Late | +0.333 | +0.300 | +0.316 | +10 | +0.740 | +0.389 | +0.700 | +
Mastery | +0.600 | +0.750 | +0.667 | +4 | +0.945 | +0.528 | +0.250 | +
Overall | +0.407 | +0.428 | +0.347 | +45 | +0.652 | +0.437 | +0.644 | +
Analysis of fMRI activation patterns, as exemplified in Figure 2, reveals characteristic spatial distributions associated with different learning stages. The sample brain slice visualization demonstrates the complex nature of the neural activation patterns the model must interpret, with varying intensity values representing normalized BOLD signal strength across different brain regions.
+The model’s reliability metrics provide crucial insight into its decision-making characteristics. The mean confidence of 0.437 with an overconfidence measure of 0.088 indicates relatively calibrated predictions, though the expected calibration error of 0.491 suggests room for improvement in uncertainty estimation. As shown in Figure 1, the confidence distribution shows distinct patterns for each learning stage, with mastery predictions showing a broader, right-skewed distribution compared to the more concentrated distributions of earlier stages.
+The ROC curves reveal a clear progression in classification reliability across learning stages: early (AUC = 0.368), middle (AUC = 0.556), late (AUC = 0.740), and mastery (AUC = 0.945). This progression suggests that distinctive neural patterns become increasingly detectable as learning progresses, with mastery showing particularly clear neural signatures.
+The mean loss of 1.082 (±0.257) suggests stable model training despite the classification challenges, with the relatively small standard deviation indicating consistent performance across validation folds. These results demonstrate both the promise and limitations of our approach, suggesting that while neural activation patterns contain meaningful information about learning stages, additional architectural innovations may be needed to fully capture the complexity of temporal learning progression in fMRI data.
+Github
+All the code and full replication instructions may be found in the Interoception Model repository: https://github.com/Twarner491/learnedSpectrum
*Please note that this repo is in devolopment and may contain faulty code for the time being. Feel free to reach out over email or drop a comment at the bottom of this page and I’d be happy to assemble the last working repo for you.
Clone the repository: +
+Create and activate a virtual environment: +
+Install the package in editable mode with all dependencies: +
+The resulting directory structure will be: +
data/
+├── raw/
+│ ├── ds000002/
+│ ├── ds000011/
+│ ├── ds000017/
+│ └── ds000052/
+├── processed/
+└── cleaned/
+
notebooks/learnedSpectrum.ipynb
visualizations/
models/checkpoints/
Our findings reveal critical implications for AI world model development. The successful extraction of learning stage patterns from fMRI data demonstrates that neural networks can capture subjective temporal experience aspects typically overlooked in current world models 17. This capability suggests that integrating physiological state data into world model training provides essential insights into biological temporal information processing.
+The correlation between neural activation patterns and learning stages demonstrates systematic variation in temporal perception with cognitive state 16. This finding challenges conventional world model time representation, which treats time as an absolute dimension 12. Effective world models require mechanisms for relative temporal processing that adapt to learning contexts and cognitive states.
+Our temporal processing architecture’s success in capturing learning stage transitions suggests three integration pathways for physiological state insights:
+Direct Signal Integration: Train world models directly on physiological state data for nuanced temporal understanding
+Architectural Inspiration: Adapt temporal processing mechanisms based on fMRI characteristics for general world model architectures
+Hybrid Learning Approaches: Combine physiological state data with traditional training signals for comprehensive temporal understanding
+The correlation between learning stage transitions and temporal processing patterns indicates that subjective time perception plays a critical role in biological causal learning 15. Current world model approaches to causal learning, relying on objective temporal sequences, may face fundamental limitations.
+The implementation faces several important constraints:
+Temporal Resolution
+Computational Requirements
+Scaling Challenges
+The exploration of fMRI data for temporal pattern extraction represents a first step toward validating our hypothesis that world models require physiological state-informed training data to develop genuine temporal understanding. Our implementation demonstrates that neural architectures can successfully extract and utilize these biological temporal patterns, suggesting a viable path toward bridging the A → B → C gap in current world model approaches.
+Future work should expand beyond fMRI to incorporate the full spectrum of physiological state signals identified in our introduction (facial EMG, heart rate variability, electrodermal activity). This multi-modal physiological state approach, combined with advanced transformer architectures, could enable world models to develop temporal understanding that more closely mirrors human cognitive processes, particularly in causal reasoning and state transitions. The technical foundation established here provides a framework for this broader integration while addressing the practical challenges of physiological state data collection and processing at scale.
+Github
+All the code and full replication instructions may be found in the Reinforcement Gymnasium repository: https://github.com/Twarner491/Impetus
*Please note that this repo is in devolopment and may contain faulty code for the time being. Feel free to reach out over email or drop a comment at the bottom of this page and I’d be happy to assemble the last working repo for you.
https://runwayml.com/research/introducing-general-world-models ↩
+https://worldmodels.github.io/ ↩
+https://x.com/yugu_nlp/status/1859424088927940831 ↩
+https://x.com/hongyangzh/status/1859288829825515810 ↩
+https://x.com/WayneINR/status/1859448167827186168 ↩
+https://www.forrester.com/blogs/llms-make-room-for-world-models/ ↩
+https://openreview.net/pdf?id=BZ5a1r-kVsf ↩
+https://en.wikipedia.org/wiki/Human_Compatible ↩
+https://en.wikipedia.org/wiki/Model_predictive_control ↩
+https://www.linkedin.com/posts/yannlecun_lots-of-confusion-about-what-a-world-model-activity-7165738293223931904-vdgR/# ↩
+https://techterrain.substack.com/p/world-models-vs-kalman-filter ↩
+https://arxiv.org/abs/2302.10035 ↩
+https://www.1x.tech/discover/1x-world-model ↩
+https://arxiv.org/abs/1803.10122 ↩
+https://openreview.net/pdf?id=BZ5a1r-kVsf ↩
+https://arxiv.org/abs/1704.03924 ↩
+https://arxiv.org/abs/2404.16078 ↩
+https://neilsahota.com/causal-ai-bridging-the-gap-between-correlation-and-causation/ ↩
+https://www.ijcai.org/Proceedings/83-2/Papers/036.pdf ↩
+https://betterworld.mit.edu/spectrum/issues/2024-spring/biometrics-in-the-age-of-artificial-intelligence/ ↩
+https://pubmed.ncbi.nlm.nih.gov/29684246/ ↩
+https://pmc.ncbi.nlm.nih.gov/articles/PMC7875380/ ↩
+https://pmc.ncbi.nlm.nih.gov/articles/PMC1866291/ ↩
+https://www.science.org/doi/10.1126/sciadv.abj0751 ↩
+https://pmc.ncbi.nlm.nih.gov/articles/PMC9320620/ ↩
+https://www.frontiersin.org/journals/psychology/articles/10.3389/fpsyg.2020.01842/full ↩
+https://www.frontiersin.org/journals/neuroscience/articles/10.3389/fnins.2024.1387641/full ↩
+https://cacm.acm.org/research/challenges-and-constraints-to-the-diffusion-of-biometrics-in-information-systems/ ↩
+https://www.nber.org/system/files/working_papers/w29587/w29587.pdf ↩
+https://pmc.ncbi.nlm.nih.gov/articles/PMC9824521/ ↩
+https://www.biorxiv.org/content/10.1101/2022.02.28.482337v2.full ↩
+https://www.pnas.org/doi/10.1073/pnas.1016823108 ↩
+https://pmc.ncbi.nlm.nih.gov/articles/PMC10960227/ ↩
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+Due to uncertainty surrounding lab access during the Covid-19 pandemic, I received an Ender 3 3D-printer at the start of my cycle in Fab Academy. During my second week in the course, I built and began to mod this machine as a little side project to the course work. However as the cycle progressed, I quickly ran out of time to keep working on this machine’s mods and moved the machine to my closet, where it sat up until the Klipper firmware piqued my interest. After modding the printer during Fab Academy1, I was running the machine on Marlin linked to Octoprint2, a setup I use on my other machines. This setup worked great with my machine mods, allowing me to print over a network through Octoprint as I would on any of my other Octoprint enabled machines. In this configuration, a Raspberry Pi running Octorpint hosts a local server that .gcode flies can be uploaded to and ran from. The Pi sends this uploaded .gcode to the machine’s mainboard, where the code is processed, and movements/operations are determined.
+Klipper Opperation Principal
+Klipper on the other hand operates on a different principle. The firmware runs across both the mainboard and the Raspberry Pi, allowing for the same type of hosted server to exist (I used FluiddPi as my servers GUI), but instead of relying on the machines mainboard to compute .gcode, the code parsing is done by the Raspberry Pi - the more powerful computer- leaving the machine mainboard to only worry about stepper movements and operations. This setup uses the given hardware of a setup more optimally, allowing for faster calculations and more precise movements.
+After learning about the benefits of Klipper I knew I had to try it out and thus, the Ender 3 modding project was revied and pulled from the closet.
+Before the installation of Klipper, here are all the hardware mods done to the machine. I upgraded the main bored from the original factory board to a SKR Mini E3 V2, and the original factory screen I switched out to a TFT35 Touchscreen. Following that I added a Bltouch for auto bed leveling, and switched the machine from Bowen to direct drive, with this Thingiverse design. I spent some time adding some customization to the machine as well, giving the direct drive system a little nameplate.
+Finally, I moved all of the electronics of the machine to the rear of the machine using this Thingiverse design. This mod gave the space to add a raspberry pi and a means of power for it in addition to the mainboard, a perfect case for a Klipper-enabled machine.
++
+I used this Thingiverse design to mount a raspberry pi camera to my printer’s x-axis as shown in one of the pictures below. All of these modifications were done with parts printed on my Prusa I3 Mk3S+, and electronics I had laying around, making these printer modifications only take around three days to complete, including the time it took to print the parts.
+As mentioned in the introduction paragraph of this page, I settled on using FluiddPi as the GUI for this Klipper setup. As opposed to a more broadly know GUI like Octoprint, FluiddPi offers some features that work directly with Klipper that make the entire experience pretty seamless. FluiddPi in addition to containing the servers GUI also packages Klipper & Moonraker into the software image, making the install of Klipper super straightforward.
+Beginning the installation of Klipper, the first step is to download and flash the latest FluiddPi image (linked above). This Pi image can be flashed as you would with any other Raspberry Pi project - I use balenaEtcher for flashing, its simple 3-step interface makes the process super straightforward. After a successful flash of this image on your Pi’s SD card configure your WiFi information in the fluiddpi-wpa-supplicant.txt located on the flashed SD card (If you’re using wired internet, you can skip this setup). Then, you can install your flashed SD in your Pi and boot.
+Next, some basic Pi config. Make sure you are on the same WiFi network you set up your Pi on, and then SSH into your booted Pi at the IP fluiddpi.local with the Pi’s default credentials (Username - pi / Password - raspberry). I use Putty as my SSH client as again, it’s pretty straightforward to use. Once connected to your Pi, run the command …
+to open the configuration GUI. Here you can change your Pi’s credentials (highly recommended), set up your local timezone (to allow for accurate machine ETAs), and change your machine’s hostname (thus changing the URL from the default fluiddpi.local to YOURHOSTNAME.local). After all, changes, reboot your Pi and then confirm all software is up to date with the lines
+ +Congrats!
+You have now successfully set up FluiddPi on your Raspberry Pi, and can now connect to its web server with the URL http://fluiddpi.local ( or if you changed your hostname, with the URL http://YOURHOSTNAME.local).
+
+
+
Upon connection, the webserver will throw an error with a lack of a printer.cfg file. This file is your machine config file. Notably different from Marlin, Klipper does not require a machine to be specified before the flash but instead looks to this printer.cfg file for machine configuration. One of the benefits of using FluiddPi for Klipper is the ability to alter this printer.cfg file and reboot the firmware right from the server’s GUI. The machine configuration for my Klipper Enabled Ender 3 is covered later on this page under the Klipper Configuration section, but for any other machines, preconfigured printer.cfg files can be found online.
+Next up, building Klipper to for machines mainboard. SSH back into your Raspberry Pi (making sure to change your IP to match your altered hostname if you changed it) and run the commands …
+ +to open the mainboard configuration GUI. Work through this interface with your mainboards information before running the command …
+to build your set configurations. Now, connect your Pi and machine mainboard via USB and determine the connected serial port with the line
+the report this line will yield provides the serial port that connects your mainboard to your Pi, take note of this.
+Now, to begin the flashing, run the lines…
+making sure to paste in the reported serial port where it says YOUR-SERIAL-PORT-INFORMATION-HERE. This will flash the built Klipper instance to your machine’s mainboard, and then begin communication between the two parallel boards.
+Good Work!
+Klipper is now installed.
+As mentioned prior, unlike the Marlin firmware, Klipper is not compiled for a specific machine. Instead, the firmware looks to a machine configuration file - printer.cfg. This file can be altered without the reflashing of the firmware, just a simple reboot, thus making machine tinkering and hardware swapping significantly simpler. This printer.cfg file can be altered in the FluiddPi web server interface, simplifying the configuration process even more.
+
+
+
As shown above, your printer.cfg file can be accessed in FluiddPi’s configuration menu. Due to Klipper’s ability to experiment with your machine config, my printer’s configuration is always subject to change, but included below is the latest machine config running on my Klipper Enabled Ender 3.
+printer.cfg | |
---|---|
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 |
|
Check out my Klipper Enabled Ender 3 machine profile page, linked below, for information regarding the slicer setup & config, as well as my profile download.
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+A Lithophane is a piece of art made out of a thin translucent material designed to show an image in a “grisaille” color format when held up to light.1 3D printers can be utilized to create some nice-looking lithophanes, a practice made easy with 3dp.rocks lithophane generator, linked below. Due to their easy creation, I find lithophanes to be a nice medium to test slicer changes with, allowing for your time to be spent with the slicer settings, and not the file prep.
+Note
+This page is not documentation on the lithophane making process, but more of a portfolio of some notable lithophanes I’ve printed since taking up this medium.
++
++
++
++
++
++
++
++
++
++
+https://en.wikipedia.org/wiki/Lithophane ↩
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + + + ++ + + + + + +
+Subtractive manufacturing is a process I’ve always found mesmerizing. Although additive processes such as 3D printing allow for the creation of something from seemingly nothing, I believe it’s even cooler to watch the morphing of existing stock into a different object. Despite this interest, I feel as though I’ve barely scratched the surface of CNC - primarily focusing on PCB milling in my subtractive manufacturing projects. I made a first attempt to dive into more subtractive manufacturing work a couple of years ago now when I built V1 Engineering’s original MPCNC.
++
+I absolutely loved building this machine and recommend it to all interested in understanding the workings of CNC, yet I don’t mill on mine all that often, I find more use in using the machine as a GCode dev platform for some of my other projects.
+Since my initial attempted steps with the MPCNC, I’ve become more versed with CNC milling due to exposure during my Fab Academy Week 7: Computer Controlled Machining assignment. For this assignment, I used the CLS Fab Lab’s ShopBot PRSalpha to mill the plywood fish tank housing for my Fab Academy Final Project. I continued my milling work over the summer, running the ShopBot almost daily over July for Young Engineers of Today’s Summer Camps. Last fall, our lab picked up a Bantam Tools Desktop CNC Milling Machine, Bantam’s flagship machine, capable of super-rapid prototyping when partnered with their Milling Machine Software.
+This article attempts to serve as a complete guide for CNC milling, covering machinist jargon, material standards, feeds and speeds, CAM workflows with Autodesk Fusion 360 & Vectric Aspire, and milling workflows for Shopbot & Bantam Tools machines - all through a collection of milling micro-projects ranging from a 1 to 1.9 Million scale mill of Mars’s Gale Crater to brass wax seals .
+Milling Micro-Projects
+This page strays from my normal single-project documentation style, opting to cover different CAM & milling workflows via a collection of micro-projects. In a similar approach to the “Constantly Updating” status of my Lithophane Experiments article, I plan to continually expand the content of this article with any additional milling micro-project I complete. Initally, the page will just host material reference & a feeds and speed calculator. That being said, be sure to stay tuned for future updates!
+Creating a successful subtractive manufacturing toolpath can be a bit more intimidating than slicing for additive manufacturing. Not only can you jeopardize your stock material, but incorrect feeds and speeds can also yield a hazardous environment & potential machine damage. There is no streamlined answer to find the right feeds and speeds, ideal values depend on numerous variables & feeds and speeds may not remain constant from job to job. This section provides a starting place for feeds and speeds, with general values provided as well as a calculator for the required inputs in your toolpath. This is by no means a universal key and necessary precautions & alterations should be made to provide values to mesh with your manufacturing workflow. Often the manufacturer of your tool & your machine will provide generic feeds and speeds for your specific equipment. Operator input is required to achieve successful & safe cuts, often you’ll be able to hear machine strain - a telltale sign of poor cutting. Trial and error adjusting is necessary to achieve the sweet spot for your feeds and speeds.
+Tool Diameter
The diameter of the endmill. When Profile milling or Through Cutting stock, it is best to keep the Tool Diameter ≥ 1/6 Stock Thickness, preserving the integrity of the endmill while allowing for full passes. Larger tool diameters yield shorter cut times when removing a lot of material, while smaller diameters allow for higher detail to be reached. It is typically best to utilize both larger and smaller diameter endmills, using the larger to clear the bulk of stock material, while finishing the mill with a smaller diameter tool to achieve the best detail.
++
+Flute Count
The number of individual flutes an endmill has. Flutes are the upward running cutting edges on an endmill. Lower flute counts allow for better chip & heat clearance from the cutting edge, while higher flute counts provided a smoother finish to a part. Stock materials that require a high surface speed also require higher flute bits, and vice versa with lower surface speed requirements. One to Two flute bits will suffice for prototyping with soft plastics & waxes. Two or more flutes will typically be needed for harder plastics (such as HDPE), woods, and metals.
++
+Surface Speed
The speed at which the tool’s cutting edge travels through the stock. Surface Speed is dependent on both the stock & endmill materials. Maximum surface speeds are typically published by your endmill’s manufacturer and do not need to be derived experimentally. Staring jobs at ≤ 50% of the maximum provided value is the best practice to allow for ample time to ensure the successful operation of your machine.
++
+Chip Load
The thickness of offcut ‘chips’ removed with each flute per revolution of the endmill. Maximum chip load is typically provided by the endmill’s manufacturer, based upon the tool’s characteristics. Finding a balance between chip load extremes is crucial for the safety of you and your machine. While larger chip loads yield shorter machine time, they also put greater forces on your endmill, potentially pushing the bit towards its point of rupture. On the other hand, smaller chip loads increase machine time, while expelling waste and heat from the tool at a slower pace, thus risking overheating and potential fire. Safe chip load values usually fall between 0.001” & 0.010”0.0254mm & 0.254mm.
++
+Spindle Speed
The number of revolutions made by the endmill in a unit of time (RPM is standard). A Lower RPM yields a higher quality surface finish & more cutting power, while a higher RPM decreases machine time. For optimal milling operations, use a higher RPM for roughing passes & a lower for finishing.
++
+Feed Rate
The speed at which the machine moves the tool through the stock. Finding the right feed rate is crucial for the safety of you and your machine. Excessively high feed rates cause excessive load on the cutter, leading to cataclysmic failure of the endmill, spindle, and machine. Feed rates that are too low produce unnecessary vibration on the machine, leading to poor surface finishes & potential cutter failure.
++
+Plunge Rate
The speed at which the endmill is driven down into the stock. The vertically running flutes on an endmill allow the tool to cut horizontally, while vertical plunges are more demanding on the tool. Lower plunge rates prevent tool damage & maintain lower temperatures while boring holes. All plunging cuts should be ramped, as gradual plunging while traveling across the stock will reduce tool stress.
++
+Stepdown
The vertical depth of each pass of the tool into the stock. Best practice is to maintain a step down of ≤ 50% of the tool diameter, however, may be increased while milling softer materials. The step down should always remain less than the tool diameter.
++
+Stepover
The space between passes of the tool into the stock. While pocketing, a maximum stepover of 50% can be used, however lower stepover values will leave a better surface finish.
++
+Feeds and speeds are equally dependent on material properties and the specific of your machine & tool. Below I’ve compiled a table of commonly milled stock materials, ranging from woods to plastics to metals. Each material offers a brief description of the stock, as well as average surface speed & chip loads. Chiploads are tool-dependent just as much as they are material-dependent, so be sure to select an adequate load for your tool’s diameter. More conservative chip loads are given on the left, while aggressive loads are given on the right. Conservative values will extend the life of your tool, while the higher loads will catalyze your job time - select a chipload within the provided range based on your needs. As mentioned above, This is by no means a universal key and necessary precautions & alterations should be made to provide values to mesh with your manufacturing workflow. Often the manufacturer of your tool & your machine will provide generic feeds and speeds for your specific equipment. Operator input is required to achieve successful & safe cuts, often you’ll be able to hear machine strain - a telltale sign of poor cutting.
+Material | +Description | +
Wax | +A easily milled medium, commonly used for casting cores, molds, and CNC program proofs. | +
Soft Wood | +A accessible & stylish medium, not to tricky to mill, often used for large scale parts - Pine, Spruce, Cedar, etc. | +
Hard Wood | +Similar benefits to soft wood, can be a bit more costly - Maple, Walnut, Cherry, Ash, etc. | +
Medium Density Fiberboard MDF |
+ An easily machined & finished material, relatively cheap, commonly used for jigs, fixtures, vacuum molds & engraving. | +
Oriented Strand Board OSB |
+ A strong, light weight, cost-efficient material, a great choice for large scale stiff parts. | +
High-density Polyethylene HDPE |
+ A soft-ish plastic, great for prototyping but a tricky material to mill. | +
Polyetheretherketone PEEK |
+ A high-performance thermoplastic, great for structural applications with resistance to fatigue and stress-cracking. | +
Polyetherimide PEI |
+ A high-performance thermoplastic, with great heat, solvent & flame resistant. Often used in applications with long term steam exposure. | +
Polyvinyl Chloride PVC |
+ An cost efficient & accessible plastic, typically used across industry but offers a cheap & lightweight medium. | +
Polyoxymethylene POM |
+ A general purpose, good all around thermoplastic - also know as Acetal or Delrin. | +
Acrylonitrile Butadiene Styrene ABS |
+ Easily accessed & low cost thermoplastic, commonly used for molding applications. | +
Polycarbonate PC |
+ An incredibly strong and possibly transparent thermoplastic, known for maintained temperature resistance. | +
Nylon | +A cost-effective & long-lasting thermoplastic, used in cases of required mechanical dampening or electrical insulation. | +
Acrylic | +A lightweight insulating thermoplastic, serves as an effective replacement for glass. | +
Carbon Fiber | +A strong & lightweight composite of carbon based fibers, desirable for various industrial applications due to its heat & chemical resistance. | +
Aluminium | +An accessible, easy to mill metal, seen across thermal & electrical conducting components. | +
Brass | +A easy to machine & highly conductive metal, ideal for low friction & intricate parts. | +
Copper | +A malleable metal, typically used for its high electrical & thermal conductivity. | +
Steel | +An iron alloy with high strength & fracture resistance, typically used in situations requiring its high tensile strength, such as tools & machines. | +
Insulation Foam | +A low cost, accessible & easy to mill material, commonly used for large molds & as cores for lightweight parts. | +
Work through the calcuator from top to bottom. First select your coolant prefrence, then input tool diamater and flute count. You may pull reccomended material settings from the table above via the “Material Library” dropdown, or you may under your own. Please note the prior warnings on calcuator dependence: This is by no means a universal key and necessary precautions & alterations should be made to provide values to mesh with your manufacturing workflow. Often the manufacturer of your tool & your machine will provide generic feeds and speeds for your specific equipment. Operator input is required to achieve successful & safe cuts, often you’ll be able to hear machine strain - a telltale sign of poor cutting.
+An addendum - Jan 2025.
+When I set out to write this piece a few years ago, I had the somewhat lofty intention of doccumenting as many different CAD/CAM softwares as I could, providing comprehensive walkthroughs for their usage. By the time I finished assembling and testing the above Material Reference section (believe me when I say this was a lift), I was quite burnt out of this endevour, and so this article just sat, unfinished on this site for a few years.
+In hopes of providing a slightly better “conclusion” to this piece, I’ve appended a gallary of project media below, all of which was machined with settings from the above Feeds & Speeds Calcuator. Enjoy!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
https://www.cnccookbook.com/machining-carbon-fiber-composites-drilling-cnc-tools/ ↩
+https://dragonplate.com/how-to-cut-carbon-fiber ↩
+https://www.gutenberg.org/files/12299/12299-h/12299-h.htm ↩
+https://www.practicalmachinist.com/vb/general-archive/face-milling-pvc-152424/ ↩
+https://www.precisebits.com/tutorials/spindle-rpm ↩
+https://pub.pages.cba.mit.edu/feed_speeds/ ↩
+https://www.protolabs.com/resources/design-tips/cnc-machining-materials/ ↩
+https://www.3erp.com/blog/cnc-milling-materials-choose-application/ ↩
+https://www.hubs.com/knowledge-base/selecting-right-cnc-material/ ↩
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+Octoprint takes 3D printing to new heights, creating a more concise workflow with more accessible machine control. The opensource Octoprint project was created and maintained by Gina Häußge. The software enables a machine with a web interface with full machine controls and a world of community plugins - all of which run on a Raspberry Pi made Server with an octoprint image. I use Octoprint on all of my personal printers, and a special CNC-focused fork of the software for my MPCNC. As mentioned above, web interfacing a machine creates a more concise workflow and thus is great for personal machines. However, an Octoprint setup shines even more in a print farm instance. During the winter months of my sophomore year (2020) I set up secure Octoprint instances on each of my lab’s array of 20 FDM printers. Each of my setup instances can be read seen under the My Octoprint Instances section of this page.
+Octoprint Installation Requirements
+You’ll need a Raspberry Pi (Recommended hardware: Raspberry Pi 3B, 3B+ or 4B), a sufficient power source for the Pi, as well as a micro SD card (4GB or larger) to flash the Octorpint image to.
+First, download and flash the latest Octoprint image (linked above). This Pi image can be flashed as you would with any other Raspberry Pi project - I use balenaEtcher for flashing, its simple 3-step interface makes the process super straightforward. After a successful flash of this image on your Pi’s SD card configure your WiFi information in the octopi-wpa-supplicant.txt located on the flashed SD card (If you’re using wired internet, you can skip this setup). To update the octopi-wpa-supplicant.txt file with your network, open the file in a code editor of your choice.
+Do not use WordPad (Windows) or TextEdit (MacOS X)
+These editors will mess with the file layout, and cause problems with your setup.
+Next, locate the type of network you’ll be connecting to - for this example, I’ll be using the WPA/WPA2 Secured standard,
+ +for any type of connection you choose, you can enable it by uncommenting the sections lines with a single hashtag, leaving you with a block like below.
+ +Next, scroll down to the bottom of the document to the section starting ”# Uncomment the country your Pi is in…”. Here, remove the hashtag in front of your network’s country, and add a hashtag in front of all other (non-selected) countries.
+Then, after saving your file and ejecting your SD, you can install your flashed SD in your Pi and boot.
+Next, some basic Pi config. Make sure you are on the same WiFi network you set up your Pi on, and then SSH into your booted Pi at the IP octopi.local with the Pi’s default credentials (Username - pi / Password - raspberry). I use Putty as my SSH client as again, it’s pretty straightforward to use. Once connected to your Pi, run the command …
+to open the configuration GUI. Here you can change your Pi’s credentials (highly recommended), set up your local timezone (to allow for accurate machine ETAs), and change your machine’s hostname (thus changing the URL from the default octopi.local to YOURHOSTNAME.local). After all, changes, be sure to reboot your Pi.
+Congrats!
+You have now installed Octoprint on your Raspberry Pi, and can now connect to its web server with the URL http://octopi.local ( or if you changed your hostname, with the URL http://YOURHOSTNAME.local).
+With an Octoprint instance up and running, the difficult part of the setup is complete. Access to the web interface allows for easy machine and interface setup, in addition to some more customizations in the form of community plug-ins.
+Beginning with the configuration of the interface itself, basic settings can be found in the web interface by clicking on the wrench icon on the right side of the navigation bar located at the top of the interface. Scrolling through these menus allows for total customization of the interface. A good starting place is under the Octoprint section in the Appearance menu. Here (as shown below) you can customize the interface title - displayed in the interface’s navigation bar, as well as the default interface highlight color.
+To enable Octoprint’s main purpose, a machine must be connected to the hardware running Octoprint via serial. This connection can come in the form of a USB cable in the simplest setup, or GPIO pins can be used for communication as well.
+Personal Setup
+In the case of my Prusa I3 MK3S+, I took advantage of this GPIO communication setup, to allow for the mounting of my Raspberry Pi directly under my printer’s mainboard (via this Raspberry Pi 4 Case) without a bulky USB cable connecting them … +
Your serial connection must be set up software side in the Serial Connection menu found under the Printer section of the interface settings. Octoprint can automatically detect your Serial Port and Baudrate when AUTO is selected in these dropdowns, however, you may also specify specifics for each field.
+Next, a machine profile must be created for your connected machine to ensure safe machine control with regard to hardware limits. A profile can be created in the Printer Profiles menu under the Printer section of the interface’s settings. Create a new profile by clicking the Add Profile… button in the lower right corner of the menu, and fill out the profile with your machine’s information.
+One key feature of Octoprint is its webcam machine stream, allowing for remote supervision of your machine. Anything from USB webcams to Raspberry Pi ribbon cable cameras can be used for this stream & Octoprint will automatically find this attached webcam and will use it to stream your machine (some more exotic cameras or mounting styles may require an additional configuration - discussed below).
+Personal Setup
+On my printer, I’ve mounted a Raspberry Pi camera to the X-Axis stepper of my machine (via this Raspberry Pi camera mount), yielding a pretty nice side view of prints, shown below. +
Due to my printers camera mount, my Raspberry Pi camera is heald in an upsidedown orientation and thus needs to be compensated for on the software side. Luckily, in the Webcam & Timelapse menu under the Features section of the Octorprint interface settings, webcam orientation can be changed. In addition, more advanced webcam options can be found, allowing for the use of almost all cameras connected to the hardware running Octorpint.
+One of the greatest features of Octorpint stems from its open-source nature … its community plugins. Under the Plugin Manager menu in the Octoprint section of the interface’s settings, plugins can be added to the octoprint instance, allowing for entire customization of the instance from the interface to machine interaction. There are tons upon tons of plugins that exist in the Octorprint community, and you may even develop your own, however below is a list of plugins I find to be amazing additions to an instance
+Note
+Some of these shown plugins are machine specific to my Prusa I3 MK3S+
++
+ ++
+Although the Octoprint web interface is rather intuitive, the number of stock features (not to mention plugin-enabled ones) can be a bit overwhelming without a bit of exploring. Below is a short PowerPoint I put together walking through the basics of the interface for students using my lab print farm, allowing for a bit of knowledge before exploration.
+ + +
+
+
+
+
https://plugins.octoprint.org/plugins/thespaghettidetective/ ↩
+https://plugins.octoprint.org/plugins/bedlevelvisualizer/ ↩
+https://plugins.octoprint.org/plugins/custombackground/ ↩
+https://plugins.octoprint.org/plugins/excluderegion/ ↩
+https://plugins.octoprint.org/plugins/floatingnavbar/ ↩
+https://plugins.octoprint.org/plugins/GcodeEditor/ ↩
+https://plugins.octoprint.org/plugins/HeaterTimeout/ ↩
+https://plugins.octoprint.org/plugins/navbartemp/ ↩
+https://plugins.octoprint.org/plugins/display_eta/ ↩
+https://plugins.octoprint.org/plugins/prettygcode/ ↩
+https://plugins.octoprint.org/plugins/themeify/ ↩
+https://plugins.octoprint.org/plugins/ipOnConnect/ ↩
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+Lost a lid or just want a more functional cap? Generate and print your own, compatible with any existing threads!
+ +Be Sure to check out this projects page on PrusaPrinters, and its Instructable!
+ +This model was designed in Fusion 360 and uses 3 required input parameters and standard Metric thread profile equations to generate a cap that will perfectly fit any of your threaded containers. Input Parameters can be found from an existing threaded connector following the documentation below and their values can be written in their corresponding Expression boxes in the Parameters spreadsheet of the attached Parametric Bottle Cap Fusion 360 file (shown below)
+Project Origins
+I originally set out to make this generator due to a need for a lower profile cap for the isopropyl alcohol bottle I keep next to my printer. The thread profile of this bottle is rather abnormal, and thus I found myself finding thread component values with standard Metric thread profile equations, the same used by the generator.
+Following the standard Metric thread profile1 (displayed in the diagram below)…
+The model derives all necessary values from three required input parameters, all of which are fed into Fusion 360’s coil tool, creating entirely parametrically generated threads. The calculations for user parameters derived from the three required input parameters are as followed …
+The implementation of these standard Metric thread profile equations in a Fusion model parametrically was the real kicker of this design. Unfortunately, Fusion’s native thread tool is incompatible with user parameters and thus was unusable in the case of this generator. In its place, I utilized Fusion’s coil tool, manipulating the values found in the generator’s user parameters to create the caps inner threads. The final working coil tool calculations are as followed …
+all of which are included, shown below, to generate the cap’s threads.
+Following the Generation of the caps thread, an inner contour is added defined by the ISO 965-1 standard2 - shown in the diagram below.
+This standard calls for radius value ThreadPitch / 4, and thus the following values are used in the inner contour …
+The contour is created with Fusion’s Fillet tool and the prior mentioned values, shown below.
+All this yields the successful basic generator, embedded below …
+… however, what fun would a custom cap generator be without a little customization. The generator includes four different body styles,
+… allowing for total cap customization. These styles can be changed, along with two other customization factors, discussed in the Cap Generation section below.
+For documentation purposes, I created a new cap for my Nalgene water bottle …
+There are three measurements required to generate your cap, all of which can be taken from the existing threaded connector …
+Connector Diameter - +Measure the diameter (in MM) of your existing connector, from the very farthest point (i.e. the point of the thread) on either side. +
Connector Length - +Measure the height (in MM) of your existing connector, from the top lip to underneath the threads. +
Thread Pitch - +Measure the thread pitch of your existing connector, the distance in MM between the points of two sequential threads. +
To offer a bit more customization to each generated cap, there are a couple of different preferences allowing for different functions.
+Number of Grips - +The number of grips lining the edge of the cap can be changed in the Expression value of the NumofGrips row. I find values between 40 through 55 work best, but if your experimenting, going below 11 will stop the generation of grip chamfered. +
Grip Depth - +The depths of these grips can be altered, determining how grippy your grips are. I’ve found a value around 0.3 or 0.4 offers a good texture around the edge. +
Lid Style - +The lid style of your cap can be toggled between 4 presets in the Fusion Parametric Bottle Cap file by navigating to
+in the Fusion browser. The lid styles can be toggled between via the eye icon to the left of each style. The four styles are included below, with each of the toggles highlighted.
+Congrats!
+You’ve successfully generated your own bottle cap!
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+The behind the scenes of the site you are on right now :)
+This site relies on MKdocs, a static site generator is written in python to create the content of the site, as well as the MKdocs Material Theme for customization. I used this same static site generator to create my Fab Academy Documentation Site, however, that site runs strictly on the MKdocs Material Theme without custom alterations. This site relies on the same structure as the prior Fab Academy Documentation Site but includes experiments with entirely custom components, and an altered MKdocs Material Theme. In addition to all that, it’s also built and hosted through my personal GitHub Pages repo, under my personal domain.
+To start the site I created a new GitHub Pages repo on my GitHub and cloned in some of my site files from my prior Fab Academy Documentation Site (the cloned files were just so site setup files, as well as a bit of content on my Fab Academy final project to be displayed on this site). I then pulled this repo to my local system folder with the command
+REPO-HERE
with your site repo’s Clone with SSH link. This can be found under the Clone button in most Git web interfaces (i.e. Gitlab, Github, etc.).Modern Hosting Platforms such as GitHub or GitLab allow for Repo editing to take place directly in the browser, and thus technically speaking, one does not need to pull their site Repo locally. However, browser editing eliminates the possibility of locally hosting, and thus one cannot view changes before pushing publically. Despite this, If you’d still like to work in a Browser-based editor, you may skip the SSH Setup and Site Publishing sections, and follow an editing and pushing workflow for your specific browser-based editor.
+To clone a Git repository locally, an SSH key must be generated on your computer and then attached to your GitHub account. GitHub has really good documentation on creating a new SSH key and attaching it to your Git Web Interface (Github, Gitlab, etc.).
+The process for generating and attaching a new SSH key to your Git Web Interface is relatively pain-free when following this documentation and using the command written above. My process involved running these commands …
+ssh-keygen -t ed25519 -C "<Your-SSH-Name-Here>" # (1)
+
+Generating public/private ed25519 key pair.
+Enter file in which to save the key (/home/user/.ssh/id_ed25519): # (2)
+
+Enter passphrase (empty for no passphrase): # (3)
+Enter the same passphrase again:
+
+cat ~/.ssh/id_ed25519.pub | clip # (4)
+
This generates a new SSH key on your computer.
+Click enter to confirm location.
+Enter a passphrase for your SSH key, you will need this password whenever you attempt to push your site.
+This copies your new SSH key to clipboard. Replace id_ed25519.pub
with your filename. For example, use id_rsa.pub
for RSA.
Once copied to the clipboard, you can paste the newly generated SSH key in your SSH key settings in your Git Web Interface, to link your computer and your Git Web Interface. Now you can finally clone your site Repository locally as discussed above.
+Requirements
+ +Open your cloned GitHub Pages repo in your code editor of choice, my personal favorite source-code editor is Visual Studio Code, so naturally, I used it. In a new terminal in the clone site folder, run the command
+The MKdocs Material theme is paired with the mkdocs-git-revision-date-localized-plugin by default in your Fab Academy student repo. This plugin enables displaying the date of the last git modification of a page at the bottom of each page. To build your static site, this plugin must be installed in your local site folder with the line below …
+However, one may opt to not use it via the removal of the line
+ +found under the plugins
section of your sites mkdocs.yml file.
Following this setup, I build my static site locally with the command in my site folders terminal
+and followed the link given in my computer’s web browser. You should get an output like this after the mkdocs serve command …
+ +GitHub Actions
+The easiest way for your static site to be built in GitHub pages upon a push is through GitHub Actions allowing for an automated workflow to run to build and pipeline your static site publicly.
+At the root of your repository, create a new GitHub Actions
+workflow, e.g. .github/workflows/ci.yml
, and copy and paste the following
+contents:
You can change the name to your liking.
+At some point, GitHub renamed master
to main
. If your default branch is named master
, you can safely remove main
, vice versa.
This is the place to install further MkDocs plugins or Markdown extensions with pip
to be used during the build.
For my site setup, I added the line …
+… to install the Git Revision date plugin to my site, allowing for the date each page was updated to be displayed under all of the contents of the page.
+The basic setup and customization of your static site are covered wonderfully on the Mkdocs Material Theme Setup Documentation. However, following this basic theme setup, your site can be altered farther by extending the Material Theme - Witch can be read about here. All of my overrides can be found in this site’s GitHub repo.
+When working with other developers in a Git Repo, the Git Pull command is necessary to keep your local branch up to date with others’ work. Running the line …
+will pull in any pushed changes to your repository, allowing you to merge work/changes with work from other branches.
+After working on teddywarner.org for a couple of months, I began to develop a project template page that accumulates different front-end HTML, CSS & Markdown aspects I use on my pages, which can be found via the button below.
+Here I’ve also compiled a bit of a mkdocs markdown cheat sheet with 10 sections for customization, formatting, or additional flair. Again, the Mkdocs Material Theme Setup Documentation covers the theme-specific markdown at length and is a nice resource while setting up specific theme-specific bits. This section compiles theme-specific markdown with overall markdown features & all of the markdowns behind it can be found in the following sections, or on this page source - linked below.
+markdown_extensions:
+ - pymdownx.critic
+ - pymdownx.caret
+ - pymdownx.keys
+ - pymdownx.mark
+ - pymdownx.tilde
+
Bold Text - **bold text**
Italicized Text - *italicized text*
Strikethrough - ~~Strikethrough~~
Subscript - H2O - H~2~O
Superscript - X2 - X^2^
“Unordered lists can be written by prefixing a line with a -
, *
or +
list marker, all of which can be used interchangeably. Furthermore, all flavors of lists can be nested inside each other:” 1
Result -
+“Ordered lists must start with a number immediately followed by a dot. The numbers do not need to be consecutive and can be all set to 1.
, as they will be re-numbered when rendered:” 2
Result -
+Vivamus id mi enim. Integer id turpis sapien. Ut condimentum lobortis + sagittis. Aliquam purus tellus, faucibus eget urna at, iaculis venenatis + nulla. Vivamus a pharetra leo.
+Vivamus venenatis porttitor tortor sit amet rutrum. Pellentesque aliquet + quam enim, eu volutpat urna rutrum a. Nam vehicula nunc mauris, a + ultricies libero efficitur sed.
+Morbi eget dapibus felis. Vivamus venenatis porttitor tortor sit amet + rutrum. Pellentesque aliquet quam enim, eu volutpat urna rutrum a.
+Result -
+Result -
+Lorem ipsum dolor sit amet
Sed sagittis eleifend rutrum. Donec vitae suscipit est. Nullam tempus +tellus non sem sollicitudin, quis rutrum leo facilisis.
+Cras arcu libero
Aliquam metus eros, pretium sed nulla venenatis, faucibus auctor ex. Proin +ut eros sed sapien ullamcorper consequat. Nunc ligula ante.
+Duis mollis est eget nibh volutpat, fermentum aliquet dui mollis. +Nam vulputate tincidunt fringilla. +Nullam dignissim ultrices urna non auctor.
+markdown_extensions:
+ - attr_list
+ - md_in_html
+ - pymdownx.superfences
+ - pymdownx.highlight:
+ anchor_linenums: true
+ - pymdownx.inlinehilite
+ - pymdownx.snippets
+ - pymdownx.superfences
+ - pymdownx.tabbed:
+ alternate_style: true
+
code
, formatted
+ text, assets/images, … basically anything that can be expressed in Markdown.PYTHON EXAMPLE | |
---|---|
Here’s a sentence with a footnote. 3
+Method | +Description | +
---|---|
GET |
+Fetch resource | +
PUT |
+Update resource | +
DELETE |
+Delete resource | +
NOTE EXAMPLE
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+INFO EXAMPLE
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+ABSTRACT EXAMPLE
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla et euismod +nulla. Curabitur feugiat, tortor non consequat finibus, justo purus auctor +massa, nec semper lorem quam in massa.
+markdown_extensions:
+ - pymdownx.emoji:
+ emoji_index: !!python/name:materialx.emoji.twemoji
+ emoji_generator: !!python/name:materialx.emoji.to_svg
+
:fontawesome-regular-laugh-wink:
+ + +Finally, after any changes are made to your site, you can merge your local changes back to your GitHub Pages repo to be built and published with the commands …
+ +Stages all new changes made to your site.
+Gives your push a title that will be visible on GitHub
+Pushes changes to your GitHub - when prompted, enter your SSH password.
+Congrats!
+You now have built your very own static site with MKdocs and its Material Theme.
+Wooo as of 12/01/2021, teddywarner.org is now 100 Commits old!! +
+200 Commits - 05/02/2022! +
+… and 300 Commits! - 06/28/2023! +
+400 Commits - 09/18/2024! +
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + ++ + + + + +
+Many modern small chipsets rely on the Unified Program and Debug Interface (UPDI), a one-wire interface allowing for the changing of fuzes, burning of bootloaders, or uploading of sketches to any AVR Dx-series parts or any modern AVR Microcontrollers. Due to their reliance on the Unified Program and Debug Interface, these parts cannot be programmed with classic ISP style programmers, and thus a UPDI enabled programmer is required. Although UPDI is the only programming option in the case of these parts, the one-wire interface is superior to the four-wire of a classic ISP programmer and allows for quicker programming setup and less cluttered boards due to fewer programming pins. This USB-C UPDI programmer is built with a Ft232rl chip allowing for serial interfacing, and runs alongside the megaTinyCore library witch equips your IDE for serial UPDI programming via a portable python implementation.
+In short, the megaTinyCore library is “An Arduino core for the tinyAVR 0-series, 1-series, and now the 2-series”1. The megaTinyCore project was created and maintained by SpenceKonde. As mentioned above, the library equips your IDE for UPDI programming via a portable python installation and can be used alongside a handful of different programmer types. The USB-C UPDI Serial programmer documented alter on this page is currently the optimal choice out of these options due to its low component requirement and faster speeds than other programmers. In addition to serial programmers, One can use a 328p based board as a programmer (i.e. an Arduino or any of its clones) via megaTinyCore’s jtag2updi sketch, or a designated microchip programming board or and UPDI programming tool that mimicks any listed above. Dr. Adam Harris, a mentor of mine during my cycle of Fab Academy has a Simple Fab-jtag2UPDI Board project where a 328p based board is used alongside the jtag2UPDI sketch and is a great option when creating an In-Circuit programmer though the library. I manufactured this board during my Electronics Production and continued to use it for the next 16 weeks of the course.
+Software Requirement
+Arduino 1.8.13 is recommended for use with the megaTinyCore library
+Recent updates to the megaTinyCore library have simplified the installation process significantly. The library relies upon a board package that can be installed via the board manager witch can be installed with 3 simple steps included below2.
+ +As mentioned prior, jtag2updi is a sketch from the megaTinyCore library, allowing for the use of a 328p-based board (i.e. Arduino or a clone) as an In-Circuit programmer. To begin with, this programming approach, download the latest version of the jtag2udpi sketch via the button below (Code -> Download Zip).
+Extract the contents of this downloaded sketch folder by first unzipping the downloaded folder and next moving the contained sketch folder in the unzipped folder to a separate location. Finally, Rename this sketch folder to jtag2updi, leaving you with a folder similar to the one circled in red in the image below.
+Inside of this jtag2updi folder, navigate to the jtag2UPDI.ino project - circled and highlighted below - and open it in your IDE.
+This will open the jtag2updi project file system, leaving you with a blank jtag2updi sketch followed by multiple file tabs in your IDE (like shown in the picture below).
+You can next upload this sketch to your 328p-based board of choice as you would any other sketch.
+Tip
+As a first test to confirm the successful upload of this sketch to your board, hook up an LED to pin 6 of the board. If the board is successfully programmed, the LED will be dimly lit as shown below. This simple test eliminates a potential error while troubleshooting a project, and confirms the programmer’s working condition. +
Once a board is programmed with the jtag2updi project, it will act as a programmer until the next sketch is uploaded, unless the board’s reset line is cut.
+To make use of a jtag2updi enabled In-Circuit programmer board, prepare a sketch in your IDE to upload to your desired board. For documentation purposes, I’ll be uploading the simple blink sketch included below to a super simple ATtiny 412 based LED board I made in week 4 of my Fab Academy cycle and documenting it for use with the Arduino IDE.
+To upload code to your board via your jtag2updi enabled In-Circuit programmer board …
+Example
+Following these steps on my simple ATtiny 412 board yielded the 1/2 second blink example below. +
Congrats!
+You can now program any modern AVR Microcontrollers via UPDI and a jtag2updi enabled 328p-based board.
+Serial UPDI Programming with megaTinyCore
+Version 2.2.0 of the megaTinyCore library brings the implementation of a portable python implementation. This installation, based on pymcuprog, allows for a programming speed increase by a factor of 20 when compared to the prior jtag2udpi programming style. With this performance increase in addition to a smaller & cheaper hardware list, Serial UDPI programming with the megaTinyCore library is the most optimal form of programming I’ve used on my boards to date.
+The serial programming style relies on this prior mentioned portable python installation alongside a USB-Serial adapter acting as the programmer in this case. Though this section of the page will document this programming style via a pre-made USB-Serial adapter (in this case an FTDI chip) and some other hardware bits, please note the USB-C UPDI Serial Programmer board documented later on this page - this board is a set hardware piece for this Serial UPDI programming style, and provides a permanent hardware programming board. To engage the Serial UPDI programming method without a board like this you’ll need the required hardware…
+ __________________
+-----| UPDI---\/\/------>
+-----| Gnd 470 ohms (100 ~ 1k)
+-----| Vcc
+ |__________________
+
If not creating your own board, and there’s no inline UPDI resistor, you’ll need to include this resistor externally. With that said, wiring between your serial adapter and the target device is diagrammed in the schematics below.
+-------------------- To Target device
+ DTR| __________________
+ internal Rx |--------------,------------------| UPDI---\/\/------>
+ Tx---/\/\/\---Tx |-------|<|---' .--------| Gnd 470 ohms (100 ~ 1k)
+ resistor Vcc|---------------------------------| Vcc
+ typ. 1k CTS| .` |__________________
+ Gnd|--------------------' If you make a 3-pin connector, use this pinout
+--------------------
+
+or
+
+-------------------- To Target device
+ DTR| External 470 ohms (100 ~ 1k) __________________
+ internal Rx |--------------,--\/\/------------| UPDI------------->
+ Tx---/\/\/\---Tx |-------|<|---' .--------| Gnd
+ resistor Vcc|---------------------------------| Vcc
+ typ 1k CTS| .` |__________________
+ Gnd|--------------------'
+--------------------
+
-------------------- To Target device
+ DTR| __________________
+ no Rx |--------------,------------------| UPDI---\/\/------>
+ internal Tx |-------|<|---' .--------| Gnd 470 ohms (100 ~ 1k)
+ resistor Vcc|---------------------------------| Vcc
+ CTS| .` |__________________
+ Gnd|--------------------'
+--------------------
+
I rigged up the second included schematic on a breadboard as unfortunately the blinky board I’m programming doesn’t have a valid inline resistor I can use.
+
+
+
To program via your USB-Serial setup …
+Note - this serial programmer setup does not give you a serial monitor
+You’ll need to connect a serial adapter the normal way for that. The later documented USB-C UPDI Serial Programmer & ftdi2updi boards provide a switching feature between a serial programming and serial monitoring mode, allowing for all programming and monitoring work to be done without rework of connections. Be sure to check out the specific USB-C UPDI Serial Programmer usage section for use of this feature.
+Example
+For this example, I modified my prior used blink sketch to run a 5-second delay as opposed to the prior 0.5 seconds…
+I uploaded this via the three-step process listed above, yielding the successful results below.
+Congrats!
+You can now program any modern AVR Microcontrollers via UPDI with a simple USB-Serial adapter with a speed increase by a factor of twenty when compared with the prior jtag2updi method.
+I made countless PCBs during my cycle of the Fab Academy, one of the first being a tool to program the rest, an In-Circuit Programmer. Being one of the first boards I fabricated myself, from the PCB milling to soldering & stuffing, I hadn’t yet taken up the practice of designing my boards, and for this assignment, fabricated the In-Circuit Programmer design of one of my mentors, Dr. Adam Harris. This board is a specialized Arduino-like board, running on an ATMega 328p with a programmer sketch provided by the megaTinyCore library.
+Project Origins
+The In-Circuit Programmer I fabricated in Fab Academy’s operation is great, but due to new updates in the megaTinyCore library, the process can be optimized for faster speeds, and the board size and component requirements can be reduced. This board marks my first steps into the world of multi-layered PCB design and fabrication, a process I’m super pumped to pick up and apply to future projects.
+The USB-C UPDI Programmer is a specialized piece of hardware for use with the prior discussed serial programming method and has a couple of advantages over rigging a programmer up on a breadboard. A permanent piece of the hardware enables the serial programming method to require a bit less setup, once the board has been made. Following that, this board includes “modes”, allowing switching between serial programming and monitoring functions. When rigging a serial programmer up via a USB-serial adapter as documented prior, you cannot monitor serial from the board at the same time, but instead are required to require the board to the USB-serial adapter. The switching of “modes” on this programmer eliminates this extra hassle, handling all the required connections at the flip of a switch located on the board’s underside.
+It was this elimination of hassle that pushed me to create this piece of hardware, yielding a simple workflow when serial programming. The USB-C UPDI Serial Programmer is based on the FT232RL3 IC, handling the USB protocol and USB to serial data transfer on the programmer.
+ + +The FT232RL is broken out following the same wiring principals diagrammed in the prior serial programming documentation, converting the IC’s Rx and Tx lines to a UPDI line, routed to a programming pin. Just before this Rx and Tx junction, a Double-Pole Double-Through switch allows for the switching of this conversion to UPDI to straightforward Rx and Tx lines, routed each to their corresponding pin. Thus, the programmer board includes a UPDI, Rx, and Tx output pin, in addition to a VCC and GND line. This 5 pin programming pinout can be mimicked on any board containing a AVR Microcontroller, allowing for programming and monitoring functions to be switched without reworking connections between the programmer and board.
+
+
+
Then came the nesting process. Being my first double-sided board in Eagle, it took some work to get used to the use of vias between sides, but eventually, I worked out the process of changing Via’s drill class through Eagle’s Change -> Drill tool. I ended up using 0.6mm rivets for this board’s vias, using 8 on the board in total. I nested bards on the board, including both the FT232RL and the USB-C female adapter on the top side, along with some smoothing capacitors, and on the bottom, the UPDI programming component array, as well as the DPDT switch.
+
+
+
+
+
The nesting of the two highest pinout parts on the board’s topside inspired my next experiment with this board, Solder Paste Stencil making. Although I feel pretty confident in my SMD soldering skills, soldering pads this small wouldn’t only be a hassle, it would also be tedious time waste, and thus I settled on a solder paste stencil approach for the boards topside, while hand soldering the bottom half. I exported the Tcream layer of my programmer board from Eagle as a .pdf for cutting of the stencil from cardstock on a Epliog Fusion Pro 48 laser.
+
+
+
Bill of Matierals - USB-C UPDI
+Qty. | +Part | +Cost | +URL | +
---|---|---|---|
x1 | +SMD DPDT Switch | +$1.50 | +link | +
x1 | +CDBM1100-G | +$0.39 | +link | +
x1 | +470 ohm SMD Resistor | +$0.10 | +link | +
x1 | +1.5k ohm SMD Resistor | +$0.10 | +link | +
x1 | +100nf SMD Cap | +$0.18 | +link | +
x1 | +1uf SMD Cap | +$0.10 | +link | +
x1 | +DX07S016JA1R1500 | +$1.59 | +link | +
x1 | +FT232RL | +$4.19 | +link | +
x11 | +Header Pins | +$0.14 | +link | +
x1 | +Copper PCB Blank | +$0.70 | +link | +
Total Cost- $8.99
+In addition to the prior USB-C UPDI Serial Programmer board, I created an alternative hardware programmer that makes use of a pre-existing FTDI chip, enabling it with the same switching functions feature as the prior board. This provided a workaround to 2021’s silicone shortage, as due to backed-up supply chains, I wasn’t able to get my hands on the FT232RL right away.
+The board’s schematic is a cloned iteration of the prior programmer, but with the USB-C & FT232RL components removed, and replaced with headers for connection to an FTDI adapter, yielding the schematic below.
+
+
+
I was compelled to expand on the original shape of an FTDI serial adapter for this board, as it expands on the functionality of the adapter itself. I used Inkscape to create the board shape, allowing for meshing with an FTDI serial adapter, with the board aligning two of the sides of the adapter and then imported this board shape into Eagle via an ulp as documented on my Fab Academy Final Project page. I then nested the components on both sides of the board, aligning the FTDI connection pins allowing for proper seating of the FTDI serial adapter with the board.
+
+
+
+
+
Bill of Matierals - ftdi2updi
+Qty. | +Part | +Cost | +URL | +
---|---|---|---|
x1 | +SMD DPDT Switch | +$1.50 | +link | +
x1 | +CDBM1100-G | +$0.39 | +link | +
x1 | +470 ohm SMD Resistor | +$0.10 | +link | +
x11 | +Header Pins | +$0.14 | +link | +
x1 | +Copper PCB Blank | +$0.70 | +link | +
x1 | +FTDI Serial Adapter | +$14.95 | +link | +
Total Cost (W/out FTDI)- $2.83
+Final Cost- $17.78
+I milled my boards with a Bantam PCB mill and its Bantam Tools Desktop Milling Machine Software. The software handles all toolpath generation from my Eagle board file, and conveniently, when paired with Bantam’s PCB placement bracket, also handles the double-sided board milling process via a toggle switch in the interface. I followed the same milling process I have documented on my week 4 Fab Academy page, however after the top-side traces and holes were milled, I flipped the copper stock, aligning to the right-hand corner of the PCB alignment bracket as opposed to the left, and toggled the board to its bottom side in the Bantam Tools Desktop Milling Machine Software. With the stock realigned, I repeated the same milling process for the bottom side of the board. This whole process is showcased in this view from Bantam.
+I used a 0.005” PCB engraving bit for the ftdi2updi’s traces, and a 1/32” for its holes and outlines, yielding the milled results below.
++
+After the milling, I washed off my board with some soap and water. The Bantam Tools Desktop Milling Machine Software makes the milling of double-sided boards super straightforward, not much harder than a single-sided PCB, however, the boards require the extra step of riveting vias between both sides of the board before soldering. This article on PCB Rivets from the Fab Docs walks through the process down into a couple of steps.
+First the via has to be inserted into its corresponding hole, I used 0.6mm vias here. Then I used a V-Shaped nail to chamfer the top of the via and finally pressed it flush with a flat press, each step shown in the three assets/images below.
++ +
+Finally, to ensure a proper connection, I soldered over each side of the via and repeated this process for all four of the board’s vias.
+
+
+
+
I finished the stuffing and soldering of this board, a simple enough process due to the small component size.
+Note
+The board that is being documented here is an early iteration of the ftdi2updi and contains an extra resistor, and thus your final board may not look exactly like the ones on this page until the Programmer Usage section.
++
+I ran two tests on the ftdi2updi, one proving each of the board’s functions.
+Programming Test
+Beginning with its programming function, I uploaded a modified version of the same blink test sketch used above to my simple LED board …
+I uploaded this via the Programmer Usage process documented in the corresponding section below. The first upload was successful at a medium (230400) baudrate. Then I uploaded the test, and repeated it at the highest (TURBO 4.5v + 460800) baudrate, yielding the successful results below.
+Note
+The ftdi2updi serial adapter meshing headers were reversed in this iteration, and thus I attached the serial adapter upsidedown for this test, the proper orientation as outlined in the following Programmer Usage section.
+Serial Monitoring Test
+Next, I switched the programmer to its monitoring mode and hooked it up to Arduino RX & TX pins, shown below. Unfortunately, my simple LED board doesn’t have serial communication pins, and thus this Arduino was my next best testing option.
+I uploaded this super simple serial print sketch to the Arduino …
+and then opened the Arduino IDE’s serial monitor on my ftdi2updi port, which successfully read the serial output printed, shown below - and also was able to transmit via serial, shown by the Arduinos receiving LED.
+Although this first iteration of the ftdi2updi worked, there were a couple of design flaws (Noted above) I’ve flatted out in later versions including - a reversed FTDI header, oversized vias, an unnecessary 1k resistor, and improper meshing with an existing FTDI serial adapter. The final version of this programmer (and its CAM files) can be accessed in the repo linked by the download button at the bottom of the Fabrication & Testing section. Use this version as refrence whilst fabricating your own board.
+I ordered a couple of these final iteration boards from a PCB fab …
++
+Which turned out incredible. The Gerber files for these boards are included in the Repo linked via the download button at the bottom of the Fabrication & Testing section, along with an Eagle board file with silkscreen decals instead of milled ones. I soldered the components to this board, a process made even easier by the already plated vias, and lack of need to insert my own.
+
+
+
+
Pending Compleation
+As mentioned prior, due to 2021’s supply chain limitations, I cannot currently get my hands on an FT232RL, and thus, for now, the fabrication & testing sections will only include my ftdi2upid board. This section will be updated by future me once I can get an FT232RL.
+This USB-C UPDI Programmer Board is not yet complete
+Although you can download its files, the board is still in development and may not function properly. Again, this section will be updated upon its completion.
++
++
++
++
+Serial programming with the megaTinyCore library is incredibly straightforward, and when pair with the switching functionality of both of my hardware programmers, the process is streamlined. I’ll be using a final iteration ftdi2updi board for this Programmer Usage documentation, however, these steps will work for either programmer style included on this page, regardless of fabrication technique.
+Both Serial UPDI programmers rely on the prior documented megaTinyCore library, which must be installed for programmer usage. This process is outlined in the Package Installation section of this page.
+To use the UPDI programming function, toggle the programmers switch to UPDI as shown below, and then connect UPDI and GND lines to their corresponding pins. Here you can also run a VCC line to your target board, which provides 5v, shown in the wiring below.
+Note
+Connecting serial data lines here is totally ok, as the switch disconnects them from communication when in programming mode. The wiring shown here is just the required connections for UPDI programming.
+
+
+
+
+
Once connections are made between the programmer and the target board, you must configure your target board in your IDE. For this documentation, I’ll continue using the Arduino IDE, however other IDEs with the megaTinyCore installed can be used for this (I may do some tests with PlatformIO in the future, and will update this page accordingly).
+First, you must select your target board’s microcontroller by navigating to …
+ +and then selecting your microcontroller from the list, shown in the image below.
+Next, connect your programmer to your computer via a serial cable and, select your serial port by navigating to …
+ +and then select the serial port your programmer board is connected to (In my case this port was COM11 - shown below). If you’re on windows, you can find this connection on Device Manager before your selection in the IDE.
+Finally, select your programming style. For all programmers documented on this page, the Serial UPDI w/ 4.7k resistor or diode series of styles are used, and you can select between three baudrate/speed options (highlighted in the image below) …
+To use the serial monitoring function, toggle the programmers switch to Serial as shown below, and then connect Transmitting and Receiving Data lines as well as GND to their corresponding pins. Keep in Mind RX and TX lines must be switched between the programmer board and the target, with Transmitting of one going to Receiving of the other and vise versa. Here, as prior, you can also run a VCC line to your target board, which provides 5v.
+Note
+Connecting the UPDI line here is totally ok, as the switch disconnects it from communication when in monitoring mode. The wiring shown here is just the required connections for Serial monitoring.
+
+
+
+
+
To begin serial monitoring through the programmer in the Arduino IDE, first, ensure your programmer is connected to your computer via a serial cable, and the proper boart is selected in the IDE (as done in the prior programming section - and highlighted below). Then navigate to …
+ +as selected in the picture below
+This will open the IDE’s serial terminal, where incoming serial data is printed, and outgoing data can be transmitted via the input at the top of the window. I wired a programmer to a simple “Hello World” printing Arduino, yielding the received results below.
+Congrats!
+You now know the methods to UPDI programming with the megaTinyCore library, and may have a cool hardware programmer to show for it .
++ + + +
+ ++ + + + + + +
+ ++ + + +
+ + + ++ + + + + + +
+An AVR-based Bluetooth telegraphing shoe insole that lets you play chess in the way Hans Niemann has been accused!
+Project Sponsor
++
On September 4, 2022, 19-year-old rising chess superstar, Grandmaster Hans Moke Niemann, shocked the chess world when he ended the 8-time World Champion, and arguably the greatest player in world history, Magnus Carlsen’s unprecedented 53-game win streak at the Sinquefield Cup in St. Louis, Missouri. Niemann added insult to injury by accomplishing this as the lowest-ranked player in the tournament while playing with the black pieces, which possess a slight, but crucially important, disadvantage at the highest levels of competition.
+Soon after his loss, Carlsen withdrew from the Sinquefield Cup without explanation, a bizarre occurrence due to the remaining six rounds in the tournament. While chess enthusiasts on the internet grappled with possible reasons for Carlsen’s withdrawal, Carlsen posted the tweet below, depicting Portuguese football manager José Mourinho saying “If I speak I am in big trouble”, a brief innuendo to the accusations to come.
++I've withdrawn from the tournament. I've always enjoyed playing in the @STLChessClub, and hope to be back in the future https://t.co/YFSpl8er3u
— Magnus Carlsen (@MagnusCarlsen) September 5, 2022
+I've withdrawn from the tournament. I've always enjoyed playing in the @STLChessClub, and hope to be back in the future https://t.co/YFSpl8er3u
— Magnus Carlsen (@MagnusCarlsen) September 5, 2022
Carlsen’s message drove many chess fans around the globe quickly began to lob accusations of foul play at Niemann, who has had a history of cheating in online games, and speculate on how he could have cheated in an over-the-board match. A theory that Niemann used a wearable device to relay computer-generated moves was quickly popularized and became incredibly popular amongst chess fans and the broader internet. Despite the internet’s suspicions, no clear accusations were placed, nor did any solid evidence surface. Yet, on September 8th, 2022, Chess.com released the tweet seen below, confirming it had removed Hans Moke Niemann from its user base for cheating.
+— Chess.com (@chesscom) September 8, 2022+
— Chess.com (@chesscom) September 8, 2022+
These direct allegations from Chess.com spurred further allegations against Niemann, as well as his confession to cheating on two separate occasions, both in online games, once at age 12 and another at 16. Yet, Niemann denied ever cheating over the board, even offering to “strip fully naked”16 or “to play in a closed box with zero electronic transmission”16 to prove his innocence.
+To only further the drama, on Monday, September 26, 2022, the pair were re-matched in an online tournament in which Carlsen resigned after playing a single move. Later that night, Carlsen released his open accusations against Niemann claiming he believes that “Niemann has cheated more — and more recently — than he has publicly admitted.”18 Carlsen claims he derived his initial suspicions form Niemann’s rapid rise through the chess ranks. For reference, Niemann surged from being approximately 800 in the world, to within the top 50 over the 20 months leading up to the Sinquefield Cup. GM Hikaru Nakamura describes this rise as “unprecedented”14 and Chess.com claims that Niemann is the “fastest rising top player … in modern recorded history”13, yet others find it comparable to top junior ranked players. Carlsen outline in his formal accusation (found in the tweet below) that Niemann “wasn’t tense or even fully concentrating”18 while outplaying him using the black pieces “in a way I think only a handful of players can do”18 during the tournament.
++My statement regarding the last few weeks. pic.twitter.com/KY34DbcjLo
— Magnus Carlsen (@MagnusCarlsen) September 26, 2022
+My statement regarding the last few weeks. pic.twitter.com/KY34DbcjLo
— Magnus Carlsen (@MagnusCarlsen) September 26, 2022
The implications of such an unprecedented accusation against a player at the GM (Grandmaster) level are highly slanderous. Grandmaster Nigel Short notes that cheating at this level of chess is exceptionally rare, as any proven allegations would end a player’s career. GM Short told the BBC “I think in the absence of any evidence, statement or anything, then this is a very unfortunate way to go about things. It’s death by innuendo.”14 Furthering GM Short’s skepticism, Professor Kenneth Regan, widely considered to be the world’s leading expert on chess cheating, took it upon himself to analyze Niemann’s games and found no evidence of cheating.
+Naturally, Niemann isn’t taking kindly to these slanderous accusations, and has filed a federal lawsuit accusing Carlsen of “maliciously colluding with others to defame [him] and ruin his career.”1 Niemann is after at least $100 Million in damages from defendants Carlsen, his company Play Magnus Group, the online platform Chess.com and its leader, Danny Rensch, as well as grandmaster Hikaru Nakamura. The court filing, found below, accuses GM Nakamura and Chess.com of bolstering Carlsen’s “egregious” claims through their platforms.
+Niemann’s counterattack hasn’t ended in his pursuit of reparations, Niemann claims Carlsen couldn’t handle losing to him, implying through his court filing that Carlsen’s actions further support his notorious “inability to cope with defeat.”20 The court filing states that Carlsen’s actions were taken in an attempt to solidify his status as “king of chess”20 so he could complete his company’s buyout by Chess.com - a $82.9 million acquisition.21
+Niemann’s victory over the world champion, “should have propelled Niemann’s career to the next level and allowed him to continue realizing his enormous potential as the next great American chess player.”20 Yet, “Unbeknownst to Niemann at the time, Defendants would do whatever it took to ensure that this would never happen.”20
+It’s worth mentioning again that Niemann has publically admitted to cheating with aid from electronic devices in online matches, once at age 12 and again at age 16. Niemann referred to one of these instances as “an absolutely ridiculous mistake”22, while maintaining that he had never cheated in a tournament with prize money.
+A couple of weeks after their initial accusations, Chess.com released a formal, 72-page report (found below) outlining an investigation into Niemann’s play, and alleging that Niemann has likely cheated with electronic aid in more than 100 games, and as recently as 2020, including in matches where money was on the line. The magnitude of Niemann’s alleged cheating scandal, as presented in Chess.com’s report, proves to be much larger and longer-lasting than Niemann publically admitted. Chess.com’s investigation relied on a variety of analytical tools to compare the moves of Niemann to those recommended by chess engines, and noted “many remarkable signals and unusual patterns in Hans’ path as a player.”13 The site claims that “while [they] don’t doubt that Hans is a talented player, we note that his results are statistically extraordinary”13, and their investigation into Niemann’s gameplay has uncovered “blatant cheating”.13 The report states that Niemann privately confessed to these allegations and that his Chess.com account was subsequently closed in 2020.
+In a private letter to Niemann, Chess.com’s Chief Chess Officer, Danny Rechsch writes “We are prepared to present strong statistical evidence that confirms each of those cases above, as well as clear ‘toggling’ vs ‘non-toggling’ evidence, where you perform much better while toggling to a different screen during your moves”.13 While the report outlines that Chess.com has historically treated bans as a private matter, the ongoing accusations and Niemann’s ban from the site’s Global Championship spurred the platform to provide the investigation that provided justification for their decisions.
+While this evidence against Niemann appears to be overwhelming, it’s important to remember that the Sinquefield Cup is an over-the-board tournament. Cheating online and over the board are two entirely separate entities, no amount of online cheating in the world provides sufficient reason to accuse Hans of over-the-board cheating, as the act itself is a different task that would require extreme preparation to achieve. Thus, in face of a lack of evidence to support over-the-board cheating allegations against Niemann, the Von Niemann Probe was born. In an attempt to further the investigation into this scandal, we developed an AVR-based Bluetooth telegraphing shoe insole to test the feasibility of creating and using an over-the-board chess cheating aid.
+Cheating in Chess
+Cheating in chess, whether online or over the board, is wrong and ruins the game for everyone. This project has been published to showcase the possibility of such a device’s existence/use, and should not be recreated with the intent of using it for genuine foul play.
+Name Orgins
+The Von Niemann Probe is named after a theoretical self-replicating space probe known as the Von Neumann Probe, named after legendary 20th century Hungarian-American mathematician John Von Neumann. The Von Neumann Probe is regarded as the optimal way to explore the cosmos, as it can mine asteroids and leverage the exponential growth of its progeny to more efficiently visit star systems. And, coincidentally, probes are also medical devices that can be used to explore one’s bowels. Thus, we settled on naming our device the Von Niemann Probe.
+At the heart of the Von Niemann Probe lies an AVR ATtiny 412-based Bluetooth telegraph. This PCB is capable of interpreting Bluetooth serial data from our chess engine (see Step 3), and translating the signal to pulses of a vibration motor. Before starting any PCB design work in Autodesk EAGLE, I took some time to write out these expectations for the systems operating principle and then began the PCB schematic. The VNP mainboard is a barebones ATtiny 412 setup, including voltage regulation and smoothing capacitors, as well as headers for connection to a Bluetooth module, vibration motor, and battery power.
+The schematic includes headers for an HC-06, with serial connections to the ATTiny 412, and a shared power line with both the IC and Vibration Motor. This vibration motor is wired both to common GND on the PCB, as well as to Digital Pin 2, allowing the IC to pulse the motor to convey moves in morse code.
+With this schematic done, I moved on to generating my final board file. The PCB is built around the rectangular nature of the HC-06 Bluetooth module - one of these modules is placed in the center of the PCB, allowing for an as-compact-as-possible footprint ideal for fitting in the VNP’s discrete insole body (see Step 2). Just above the HC-06 module lies the ATtiny 412 circuit and UPDI programming pins, as well as a cutout and mounting points for the telegraph’s vibration motor. The entire PCB is designed to be mounted inside the VNP insole with M3 screws and has been designed to maintain a large, shared surface area with the 3D-printed insole to ensure the transfer of vibration from the telegraph.
+To prove the feasibility of the accusations placed against Hans Niemann, the Von Niemann Probe (VNP) must be robust enough to see consistent use, while remaining discrete enough to not be detected. With this in mind, we selected to place our Bluetooth telegraph inside the body of a parametric shoe insole. The VNP was designed in Autodesk’s Fusion 360, and makes heavy use of the software’s Parametric Engine, allowing a custom insole to be generated for all foot sizes. Using the shoe size standards found in the table below, an insole may be generated to fit your exact foot dimensions. Note - the sizes included in the table below are Mens, as that is the style of shoe both Jack and I wear - be sure to convert your shoe size accordingly.
+US Size | +UK Size | +European Size | +Japanese Size | +Length (SL) | +Width (SMW) | +
---|---|---|---|---|---|
6 | +5.5 | +39 | +25 | +23.5cm | +8.9cm | +
6.5 | +6 | +39/40 | +25.5 | +24.1cm | +9cm | +
7 | +6.5 | +40 | +26 | +24.4cm | +9.2cm | +
7.5 | +7 | +40/41 | +26.5 | +24.8cm | +9.4cm | +
8 | +7.5 | +41 | +27 | +25.4cm | +9.5cm | +
8.5 | +8 | +41/42 | +27.5 | +25.7cm | +9.7cm | +
9 | +8.5 | +42 | +28 | +26cm | +9.8cm | +
9.5 | +9 | +42/43 | +28.5 | +26.7cm | +10cm | +
10 | +9.5 | +43 | +29 | +27cm | +10.2cm | +
10.5 | +10 | +43/44 | +29.5 | +27.3cm | +10.3cm | +
11 | +10.5 | +44 | +30 | +28.9cm | +10.5cm | +
11.5 | +11 | +44/45 | +31 | +28.3cm | +10.6cm | +
12 | +11.5 | +45 | +32 | +28.6cm | +10.8cm | +
12.5 | +12 | +45/46 | ++ | 29.2cm | +11cm | +
13 | +12.5 | +46 | ++ | 29.5cm | +11.1cm | +
13.5 | +13 | +46/47 | ++ | 30.2cm | +11.3cm | +
14 | +13.5 | +47 | ++ | 31cm | +11.4cm | +
14.5 | +14 | +47/48 | ++ | 31cm | +11.6cm | +
15 | +14.5 | +48 | ++ | 31.4cm | +11.7cm | +
A custom insole will be generated after updating the model with your foot Length (SL) & Width (SMW) via Fusion’s Change Parameters tool. Paste in your foot length (SL) in the InsoleLegnth expression input, and repeat with your foot width (SMW) and the InsoleWidth expression input.
+After establishing the model’s parameters and extruding a basic shape, I drafted the insole’s outer edge to allow the insole to fit the angled inner walls of shoes, before using Fusion 360’s Surface workspace to ad a 3D profile to the top of the insole.
++
+The insole consists of two main parts, the body which is the bulk of the insole itself, and the lid, which screws to the bottom of the body, covering the electronics compartment. The body of the insole consists of mounting points for the main PCB, as well as a 1000mah LiPo battery, a USB-C LiPo charging board, a power switch, and a 3.3v to 5v boost converter. The lid not only hides the VNP’s electronics system from sight but also redistributes the load placed upon the insole when a user is standing on it.
+The Von Niemann Probe is useless without a competent artificial intelligence running the show behind the scenes, obviously requiring a hefty amount of code to get it to work properly. I decided to build the brains around Stockfish, a famous chess engine that already has a functioning Python integration and also happens to be the highest-rated engine at the time of writing. For reference, the engine plays at a 4000 level, while the current highest-rated player, Magnus Carlsen, is currently sitting at about 3200. Safe to say, Stockfish is more than sufficient for the players our insole will encounter who are obviously considerably worse than Carlsen.
+Python Dependencies
+Various Python dependencies are needed to run the chess engine script, but overall the installation is pretty lightweight. Install commands for all Python dependencies are below, any release past Python 3.7 will work.
+ +First, I downloaded Stockfish and extracted it locally on my Windows PC. I used Version 15 in this project. A more current version can be downloaded from stockfishchess.org or use this permanent download link of the version that I used during development.
+Next, I researched the Stockfish Python module and integrated it into a continuous loop in Python that would allow it to play games repeatedly without requiring the relaunching of the code. The module is pretty simple to instantiate, but it does feature a few optional parameters that can regulate its strength and how much hardware it occupies locally.
+stockfishPath = "C:/…" #replace with the path to your Stockfish exe.
+#Note - the path may only contain forward slashes, no backslashes.
+
I began by adding a path variable to my Python program that stores the local path of the Stockfish installation. The path can be found by navigating to the folder that stores Stockfish and finding the .exe file inside of the folder. I then placed this path into the variable, making sure to replace the backslashes that windows copies with for forward slashes. The code will not run with backslashes.
+fish = Stockfish(r"{0}".format(stockfishPath),
+depth=18, parameters={"Threads": 4, "Hash": 256, "UCI_LimitStrength": "false"}) #stockfish object declaration, can regulate strength
+
+print("WDL Accepted " + str(fish.does_current_engine_version_have_wdl_option()))
+
I then configured Stockfish inside of the program. The above snippet instantiates stockfish, creating an object called “fish” that can be called using the Python Stockfish module.
+ +The Python Stockfish module also features a function that prints a Unicode display of the current board state! This proved very useful during debugging to follow along with games that are not being played physically.
+while True:
+ isMate = False
+ print("side of stockfish:")
+ fishSide = input()
+ playGame(fishSide)
+
I then created an infinite loop that takes the side of the player wearing the insole that launches one of two loops that allow games to be played inside of the playGame() function.
+def playGame(side):
+ global legal; global legalMoves
+ global board; global isMate; global morseMove;
+ mate = False
+ turns = 0; i = 0
+ board = chess.Board()
+ print("fish playing as " + side)
+
Several declarations occur at the top of the playGame() function regardless of what side Stockfish is on. These lines help keep track of legality and reset the state of the board in the two modules that track it. The importance of these modules is detailed later on in this section.
+if side == "white":
+ while mate == False:
+ bestMove = fish.get_best_move(1000)
+ fish.make_moves_from_current_position([bestMove]);
+ chessMove = chess.Move.from_uci(bestMove) #create chessMove
+ print("whitefish plays " + bestMove)
+
I decided to start by writing code for games for when the engine is generating moves for the white pieces. Stockfish will immediately generate a move in this case so this made early development a bit easier. The above snippet generates the optimal move from the starting position and plays it.
+print("black move:") #request player move
+move = input()
+#The above lines request the move of the engine's opponent that is playing on the black pieces.
+
After black’s move is input, one turn has passed, and now it is time for the engine to respond to the human player’s move. But before that can happen, the program needs to check the legality of the Stockfish move. If the Stockfish module is passed an illegal move that cannot be played given a current board position, it crashes. So I needed to create a function to test the legality of moves before passing them to the Stockfish module to avoid this potential point of failure.
+While the Python Stockfish module is robust and does have many useful features, it does not natively feature a function to check the legality of a move. As such, I decided to add the python-chess module to run a legality check on each move before passing it to Stockfish, prompting the user to enter another move if a move is not legal, preventing crashes due to misinput.
+ +The above function call creates a Board object that allows for the calling of the many functions included in the python-chess module.
+The python-chess module features a board.is_legal() function that checks the legality of a formatted move object given the current state of a board object. It returns a boolean that reflects the legality of a move. However, it needs to be passed a chess.Move object which must be created using letters and numbers that can appear in chess moves. As such, any input that is incorrect, say “n9z0” would not create a move object and would trigger a crash. Therefore, it is necessary to verify that input only contains properly formatted characters that can actually exist in a chess move before trying to use the is_legal() function.
+badChars = ["i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
+"9", "0"] #chars that can't be in a legal chess move
+
I started by creating a dict that contains all of the characters that cannot appear in a legal chess move.
+for char in move: #check if badChars exist in move
+ i = 0 #reset iterating var
+ while i < len(badChars):
+ badChar = badChars[i]
+ if char == badChar:
+ print(char + ' is ILLEGAL')
+ noBadChars = False #set bool to reflect bad char
+ if char.isalpha() == True:
+ charCount += 1 #reflect that at least 1 char in string
+ if char.isdigit() == True:
+ numCount += 1 #reflect that at least one number in string
+ i += 1
+ #print(char + "is legal") #debug bad chars function
+
I then wrote some code to iterate through each character in a move received as input and verify that it contains only legal characters.
+if len(move) != 4 and len(move) != 5: #solve edge case where small string doesn't break other rules
+ noBadChars = False;
+
I also added a quick check to verify that a move actually contains 4 characters. A move object cannot be created by any other number of characters, so this check is useful in preventing crashes due to misinput.
+if noBadChars == True: #only creative move objects if correct formatting
+ myMove = chess.Move.from_uci(move)
+ legal = board.is_legal(myMove)
+ print("Legal? " + str(legal))
+
If the user input does not contain any illegal characters and is 4 characters in length, then it can be made into a chess.Move object in the python-chess module and passed to the is_legal() function. The above snippet does precisely that.
+if legal and noBadChars: #move can only happen if legal and doesn't contain illegal chars
+ fish.make_moves_from_current_position([move])
+ chessMove = chess.Move.from_uci(move)
+ board.push_san(move)
+ return #back to game loop
+
If the player’s move is legal, then it is added to the games being tracked by python-chess and Stockfish. After the move is played, the program returns to the playGame() parent function and the game will continue with a move from Stockfish.
+else:
+ print("illegal move, input new move:")
+ newMove = input()
+ getPlayerMove(newMove)
+ return #back to game loop
+
If the move is not legal, the function getPlayerMove() function will recursively call back to itself until a legal move is received, at which point it will return to the playGame() parent function and the game will continue.
+After getting the legality function to work, I began focusing on solving the core challenge of this project: sending the moves generated by Stockfish to a shoe insole. I initially wrote code to translate the moves into Morse Code, but quickly discovered that due to the short nature of chess moves I could save a lot of time by just pulsing a vibrating motor for each additional index in the alphabet or number line a certain character occupied.
+For example, a C in morse code is --, which would take 10 seconds to buzz assuming a dot length of 1 second where a 1:3 dot:dash ratio is established with a wait time of 1 dot between each character. This is standard. However, a simple *** of 0.1 second pulses with 0.05 second pauses in between accomplishes the same thing in much less time and is easily understood to be a C, because chess moves will always follow a character:number:character:number format. As such, I decided that this way would be faster and would not require me to learn 16 characters of Morse Code. Both encoding versions are in our Github repository for the project if for some reason you prefer Morse Code. For the sake of concision I am only going to include the code for the shorter encoding method that I described which is also the one that is used in all of our testing videos.
+morseDict = { 'a':'.', 'b':'..',
+ 'c':'...', 'd':'....', 'e':'.....',
+ 'f':'......', 'g':'.......', 'h':'........',
+ '1':'.', '2':'..', '3':'...',
+ '4':'....', '5':'.....', '6':'......',
+ '7':'.......', '8':'........'}
+
I began by creating a dict of all of the dot values for each letter and number.
+def toMorse(move): #convert move to morse code
+ ret = "" #empty morse conversion
+ newConvert = "" #empty mid-conversion string
+ for char in move:
+ #print("converting " + char) #debug print
+ newConvert = morseDict[char] #take key of char index in morse dict
+ ret += newConvert + ' ' #add morse for new char to morse string
+ print("Morse-Converted Move: " + ret)
+ return ret
+
The above function takes a move played by Stockfish and converts it to a format that is almost ready to be sent via Bluetooth to the insole.
+At this point the move “e2e4” would look like ”..... .. ..... ....” meaning it is ready to be pulsed to the wearer of the device once it is sent to and received by the insole.
+The job of the Python program each move ends with the sending of the optimal move to the user of the insole. This is accomplished by connecting the machine that the program is running on to the HC-05 or HC-06 Bluetooth module located in the device and sending the moves via a COM port.
+Whenever you connect to the Bluetooth module, it will take on a different COM port. This address can be found in Windows settings by searching “Device Manager” or pressing ⊞+x and navigating to Device Manager. Once in this interface, navigate to “Bluetooth” and find the Bluetooth module.
+ +Once you find the port, change the value of the port string to whatever value your computer reflects. The Bluetooth module will have a couple of values that it takes on on your machine, so you might not have to change it every time you reconnect, but it is certainly best practice to check just to make sure. These modules can be pretty buggy sometimes, but usually just forgetting the device and reconnecting solves the problem!
+ +The above snippet establishes a connection to the Bluetooth module at 9600 baud using the pre-specified port and prints a confirmation. After this runs successfully, a game can be started and the moves will be sent to the shoe insoel automatically.
+def sendMove(morse):
+ print(morse) #print morse move with spaces replaced with 9 - easier to parse on arduino side as empty bytes hard to work with
+ for char in morse:
+ tempChar = char.encode() #temporary placeholder set to current char in morse move
+ ser.write(tempChar) #send individual character of final morse message encoded in utf-8
+ print("sent move")
+ return
+
The above function is responsible for sending the moves. During testing, I found that sending one byte at a time is easier to parse on the insole, so this function simply iterates through the converted string and sends each byte one by one. After all of the bytes are sent, it returns to the parent function and the game continues.
+ +I realized that spaces can behave weirdly when sent over Bluetooth using UTF-8, so instead of further researching the problem I simply set all of the spaces to a value that cannot appear in a chess move before sending them to the insole. 9’s are simply treated as a constant delay in the C++ code that runs on the insole.
+At this point, the work of the Python function is complete. A player move has been input, checked for legality, and an engine move has been generated, converted, and sent to the insole. Once the player wearing the device makes the move on the board and the human player responds, this process will continue until Stockfish triumphs!
+Bluetooth Interfacing Chess Engine | |
---|---|
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 |
|
Chess Engine | |
---|---|
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 + 51 + 52 + 53 + 54 + 55 + 56 + 57 + 58 + 59 + 60 + 61 + 62 + 63 + 64 + 65 + 66 + 67 + 68 + 69 + 70 + 71 + 72 + 73 + 74 + 75 + 76 + 77 + 78 + 79 + 80 + 81 + 82 + 83 + 84 + 85 + 86 + 87 + 88 + 89 + 90 + 91 + 92 + 93 + 94 + 95 + 96 + 97 + 98 + 99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 |
|
Once a formatted move is sent to the shoe insole, it needs to use its vibrating motor to discretely tell its wearer what the best move is. As all of the major processing and translation is done in Python, all the ATTiny412 microcontroller in the insole does is receive a move via Bluetooth, parse it, and buzz it to the user, making its job considerably simpler.
+#include <SoftwareSerial.h> //software serial library, native in base installation of ide
+SoftwareSerial HC06(0, 1); //HC06-TX Pin 10, HC06-RX to Arduino Pin 11
+
The HC-06 cannot use the normal serial pins, so the SoftwareSerial library is required. The above snippet imports the library and establishes a transmitting line on pin 0 and a receiving line on pin 1.
+int buzzerPin = 2; //pin of buzzer/vibrating motor
+int dotLength = 200; //establish length of 1 dot
+
These lines establish the pin of the buzzer and specify the length of one dot. Because of the encoding method used here, it is not necessary to specify the length of a dash. The length of a dot is also used for pauses here, but another time could be added to further optimize the buzzing of moves.
+void setup() {
+ HC06.begin(9600); //Baudrate 9600 , Choose your own baudrate
+ pinMode(buzzerPin, OUTPUT);
+}
+
These lines establish a connection between the Bluetooth module and the machine that is running the Python program. It also initializes the buzzer as an output.
+Once the Bluetooth module is connected to the Python program and the buzzer is setup, the insole is ready to receive moves and buzz them on the internal vibrating motor.
+void loop(){
+ if(HC06.available() > 0)
+ {
+ char receive = HC06.read();
+ if(receive =='.'){
+ digitalWrite(buzzerPin, HIGH);
+ delay(dotLength);
+ digitalWrite(buzzerPin, LOW);
+ delay(dotLength);
+ }
+ if(receive =='9'){
+ digitalWrite(buzzerPin, LOW);
+ delay(dotLength * 2);
+ }
+ else {
+ digitalWrite(buzzerPin, LOW);
+ delay(5);
+ }
+ }
+}
+
The Python program sends bytes one at a time and they simply pile up in the stack on the ATTiny412. This allows us to interact with each byte one at a time and not touch the other ones until they are ready to be buzzed. This prevents the need for any local strings or storage for the moves, as each byte in a move is no longer necessary after it is buzzed once, which means that accessing these bytes just once is sufficient.
+The local char, receive, is set to each byte contained in the move, in the order that they are received. With our encoding method, each byte is either a “.” or a “9” or empty, so these are the only conditions necessary that will result in a buzz. Sometimes junk data is sent, so it is better to leave this final condition open-ended as an else statement instead of including another conditional checking for null bytes, as junk data would result in a crash in this case.
+I began the fabrication of the Von Niemann Probe through some prototype PCB milling on the Bantam Tools Desktop CNC Milling Machine …
+Leveraging these machines would allow me to test early designs before ordering final boards from PCBWay, allowing me to ensure their functionality early on in the design process. This process also makes it considerably easier to make changes, as I can test multiple iterations within several hours of each other, including the time to solder each board!
+
+
+
Next up, 3D Printing … and a lot of it. All prototype prints for the Von Niemann Probe were done on a Prusa I3 MK3S+ equipped with an 0.4mm E3D Nozzle X from White PETG.
+ + + + + +Similar to the PCB prototyping, I fabricated several prints while iterating on the insole’s CAD, before ordering the final iteration from PCBWay. Each print required over 14 hours of print time and numerous hours to complete the necessary changes to the design.
+
+
+
After finally arriving at a version of the insole that I was satisfied with, I was ready to assemble the device …
+Leaving me with the final product below!
+
+
+
+
https://www.npr.org/2022/10/21/1130442319/hans-niemann-sues-magnus-carlsen-for-100-million-accusing-him-of-defamation ↩
+https://youtu.be/eg5G1A_mTFg ↩
+https://twitter.com/hansmokeniemann ↩
+https://futurism.com/von-neumann-probe ↩
+https://ww1.microchip.com/downloads/en/DeviceDoc/ATtiny212-412-DataSheet-DS40001911B.pdf ↩
+https://components101.com/sites/default/files/component_datasheet/HC06%20Bluetooth%20Module%20Datasheet.pdf ↩
+https://components101.com/wireless/hc-06-bluetooth-module-pinout-datasheet ↩
+http://www.sizecharter.com/clothing-fit-and-measurement/understanding-shoe-sizing ↩
+https://www.researchgate.net/figure/The-Mean-of-Absolute-in-mm-and-Relative-in-FL-Foot-Dimensions-for-Both-Genders-a_tbl2_327021689 ↩
+https://www.researchgate.net/figure/Measurements-of-the-foot-and-the-inner-shoe-dimensions-a-Foot-Length-FL-and-Foot_fig5_280976288 ↩
+https://www.protalus.com/blogs/news/how-to-measure-feet ↩
+https://www.magnuscarlsen.com/en ↩
+https://www.chess.com/blog/CHESScom/hans-niemann-report ↩↩↩↩↩
+https://www.bbc.com/news/world-63043023 ↩
+https://cse.buffalo.edu/~regan/chess/fidelity/data/Niemann/ ↩
+https://twitter.com/MagnusCarlsen/status/1574482694406565888?s=20 ↩↩↩
+https://www.wsj.com/articles/chess-cheating-hans-niemann-report-magnus-carlsen-11664911524 ↩
+https://storage.courtlistener.com/recap/gov.uscourts.moed.198608/gov.uscourts.moed.198608.1.0.pdf ↩↩↩↩
+https://frontofficesports.com/top-chess-player-platform-join-forces-in-82-9m-deal/ ↩
+https://www.washingtonpost.com/sports/2022/10/05/chess-com-investigation-cheating-hans-niemann-magnus-carlsen/ ↩
+https://www.youtube.com/watch?v=5uDM3fPeNFM&t=224s ↩
+https://www.youtube.com/watch?v=QNuu8KTUEwU&t=390s ↩
+https://www.reddit.com/r/chess/comments/x6ixud/during_magnus_carlsens_current_unbroken_streak_as/ ↩
+https://pawnalyze.com/chess-drama/2022/09/05/Analyzing-Allegations-Niemann-Cheating-Scandal.html ↩
+https://www.chess.com/news/view/hans-niemann-us-junior-championship-annie-wang ↩
+https://www.mid-day.com/sports/other-sports/article/world-champion-magnus-carlsen-quits-game-amid-cheating-allegations-23246759 ↩
+https://www.fide.com/news/1968 ↩
+https://www.youtube.com/watch?v=TkUkvLqHfZM ↩
+https://www.youtube.com/watch?v=9wtvXoXh0VU ↩
+https://www.chess.com/events/2022-sinquefield-cup/03/Carlsen_Magnus-Niemann_Hans_Moke ↩
+https://www.youtube.com/watch?v=CJZuT-_kij0 ↩
+https://www.youtube.com/watch?v=VptbNKbHQiM&t=5s ↩
+https://www.youtube.com/watch?v=O6ML2b7IdD4&t=2s ↩
+https://www.youtube.com/watch?v=qjtbXxA8Fcc ↩
+https://www.youtube.com/watch?v=uCzwLk6fXXs ↩
+https://www.youtube.com/watch?v=LkXDhw-TuGw ↩
+https://www.nationalworld.com/news/offbeat/how-do-you-cheat-at-chess-cheating-player-hans-niemann-scandal-play-online-board-3870066 ↩
+https://www.nytimes.com/2022/12/04/business/chess-cheating-scandal-magnus-carlsen-hans-niemann.html ↩
+https://www.wsj.com/articles/chess-cheating-magnus-carlsen-hans-niemann-11663751262?mod=article_inline ↩
+https://www.buzzfeednews.com/article/kelseyweekman/chess-cheating-anal-beads-conspiracy-hans-niemann ↩
+https://www.youtube.com/watch?v=lpfWGyvO80o ↩
+https://www.youtube.com/watch?v=GLwyhmmEoAQ ↩
+https://www.youtube.com/watch?v=umaHIQJY6Tw ↩
+https://www.youtube.com/watch?v=aDUmS_MJceU ↩
+https://www.republicworld.com/world-news/rest-of-the-world-news/elon-musk-claims-niemann-may-have-used-anal-beads-to-beat-carlsen-in-chess-championship-articleshow.html ↩
+https://www.newsweek.com/hans-niemann-magnus-carlsen-chess-sex-toy-scandal-1749903 ↩
+https://www.youtube.com/watch?v=HdHWAuQRG7E ↩
+https://www.youtube.com/watch?v=J4_e12Md4Fg ↩
+https://www.youtube.com/watch?v=XjupJslRj5E ↩
+https://twitter.com/nigelshortchess/status/1573434084239593481 ↩
+https://twitter.com/hansmokeniemann/status/1583164606029365248 ↩
+