<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Firmware on project392.net</title>
        <link>https://www.project392.net/tags/firmware/</link>
        <description>Recent content in Firmware on project392.net</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en-us</language>
        <lastBuildDate>Sun, 16 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.project392.net/tags/firmware/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Dishwasher: Firmware</title>
        <link>https://www.project392.net/p/dishwasher-firmware/</link>
        <pubDate>Sun, 16 Aug 2026 00:00:00 +0000</pubDate>
        
        <guid>https://www.project392.net/p/dishwasher-firmware/</guid>
        <description>&lt;img src="https://www.project392.net/dishwasher/dishwasher-code.jpg" alt="Featured image of post Dishwasher: Firmware" /&gt;&lt;h1 id=&#34;a-quick-and-dirty-cleaning-routine&#34;&gt;A Quick And Dirty Cleaning Routine
&lt;/h1&gt;&lt;p&gt;With the &lt;a class=&#34;link&#34; href=&#34;https://www.project392.net/p/dishwasher-controller-board/&#34; &gt;controller board&lt;/a&gt; built and the &lt;a class=&#34;link&#34; href=&#34;https://www.project392.net/p/dishwasher-hardware-modifications/&#34; &gt;hardware&lt;/a&gt; of my repaired &lt;a class=&#34;link&#34; href=&#34;https://www.project392.net/p/dishwasher-introduction/&#34; &gt;dishwasher&lt;/a&gt; ready to go, the time has come conclude this blog series. This last write-up is about the little piece of software that saved the day and released me from the burden of manual dish washing.&lt;/p&gt;
&lt;p&gt;The program is very simple and not well designed. It was also not tested extensively. I even spotted a bug while writing this piece. In this post I will go over some aspects of the humble program that I think are worth noting. After that, I reveal how well my revitalized dishwasher performs.&lt;/p&gt;
&lt;h2 id=&#34;yuck-prevention&#34;&gt;Yuck Prevention
&lt;/h2&gt;&lt;p&gt;I mentioned in the first post of this series that my dishwasher&amp;rsquo;s float switch had caused some headaches in the past. After observing the device without its cover for a while, I think I&amp;rsquo;ve identified the culprit.&lt;/p&gt;
&lt;p&gt;The float switch in the HEDW44004 connects to the dish compartment via a small rubber hose. I haven&amp;rsquo;t torn down enough dishwashers to know whether this is common practice, but I see at least one major drawback to this approach. When water circulates the system, pressure variations cause the water in the hose to slosh back and forth. If the water was nice and clean, this would not be much of a problem. However, it&amp;rsquo;s a dishwasher; the water inside is not going to be clean. What would be the point? This means that, eventually, bits of food waste will migrate through the hose and accumulate inside the float switch.&lt;/p&gt;
&lt;p&gt;I try to mitigate this by preheating the water before the pump starts in the pre-wash cycle. My reasoning is that hot water will be better   at dissolving (primarily) fatty particles. Even if it won&amp;rsquo;t completely prevent residue accumulation from happening, it probably will reduce it.&lt;/p&gt;
&lt;h2 id=&#34;testing-the-waters&#34;&gt;Testing The Waters
&lt;/h2&gt;&lt;p&gt;The analog multiplexing of the float switch caused some minor issues that had to be smoothed out. The program compares the float switch voltage with predefined numbers. Those represent each of the float switch&amp;rsquo;s discrete states. To account for tolerances in the resistances and inaccuracies in the conversion, each level has an upper and lower limit defined. If a value is within one of the ranges, the result will be represented as a number from 1 to 3. Values that are outside of the expected ranges have no meaning to the program and cause an error. Causes of unexpected values could be incorrect resistors or loose wires. But there is another one. One I could have foreseen, but that came to bite me nonetheless.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s have another look at the float switch schematic from the previous post.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.project392.net/dishwasher/analog-mux.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Analog mux circuit&#34;
	
	
&gt;&lt;em&gt;Things get murky with the multiplexer&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Mechanical switches exhibit contact bounce: the contacts don&amp;rsquo;t settle on one state or the other immediately. Instead, they bounce back and forth joyfully for some tens of microseconds before they reach their steady state. There is also the situation where the switch travels from one position to another and is momentarily unconnected to either resistor of the voltage divider. In that case, the lower resistor acts as a pull-down resistor and the &lt;abbr title=&#34;Analog to Digital Converter&#34;&gt;ADC&lt;/abbr&gt; reads zero. As a quick fix I added a check to discard values below the lowest demultiplexer threshold and added a counter to trigger an error when too many such samples occur. It made the level sensing work in most of the cases, but it still fails occasionally.&lt;/p&gt;
&lt;p&gt;As a noise mitigation method, the program averages multiple samples at fixed intervals, creating something close to a low pass filter. However, if the ADC is sampled at too short an interval, there is still the possibility of multiple samples being taken during switch bounce. These samples may average out at a value somewhere between the expected thresholds. The program takes 16 samples at a 2ms interval. That&amp;rsquo;s a total sampling time of only 30ms. This will occasionally overlap with the switch settling time. Ideally I should fix this but, it works most of the time.&lt;/p&gt;
&lt;p&gt;Increasing the time constant of the &lt;abbr title=&#34;Resistor Capacitor&#34;&gt;RC&lt;/abbr&gt; filter at the input would also help to reduce the glitches, but that would make the input slower for digital signals. Improved filtering in software is a better solution.&lt;/p&gt;
&lt;h2 id=&#34;rinse-but-dont-repeat&#34;&gt;Rinse, But Don&amp;rsquo;t Repeat
&lt;/h2&gt;&lt;p&gt;Firmware that runs on microcontrollers is often designed to run indefinitely. If a task has been completed and the right trigger arrives, then it dutifully starts over again. Rinse and Repeat seems like a fitting idiom (certainly   for a dishwasher). An important provision for running a program indefinitely is that both hardware and software can be trusted to run reliably. There is no user to click OK on that error message, or to restart the program in case it freezes.&lt;/p&gt;
&lt;p&gt;With this dishwasher firmware, that I quickly cobbled together in a couple of afternoons, I&amp;rsquo;m not so confident that everything will run that smoothly. I felt like playing safe. The machine hides not only a high power heating element, but also a water valve. The latter can bring more water to my apartment floor than I care to mop up. So, instead of allowing the program to restart at the (second) press of a button, it only runs once. Then it waits until the device is powered down, and blinks its status &lt;abbr title=&#34;Light Emitting Diode&#34;&gt;LED&lt;/abbr&gt; happily while it waits. Another reason to stimulate powering down the device, is the fact that its stand-by power consumption is rather high. This due to the &lt;abbr title=&#34;Alternating Current&#34;&gt;AC&lt;/abbr&gt; transformer, which is less efficient than a switching converter.&lt;/p&gt;
&lt;h2 id=&#34;cleaning-instructions&#34;&gt;Cleaning Instructions
&lt;/h2&gt;&lt;p&gt;To at least give the impression of professionalism, I present you: the flow chart(s).&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.project392.net/p/dishwasher-firmware/flow-prewash.png&#34;
	width=&#34;794&#34;
	height=&#34;1123&#34;
	srcset=&#34;https://www.project392.net/p/dishwasher-firmware/flow-prewash_hu14777633326717112382.png 480w, https://www.project392.net/p/dishwasher-firmware/flow-prewash_hu18031335894389237593.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;70&#34;
		data-flex-basis=&#34;169px&#34;
	
&gt;  &lt;img src=&#34;https://www.project392.net/p/dishwasher-firmware/flow-wash.png&#34;
	width=&#34;794&#34;
	height=&#34;1123&#34;
	srcset=&#34;https://www.project392.net/p/dishwasher-firmware/flow-wash_hu2107211351754747269.png 480w, https://www.project392.net/p/dishwasher-firmware/flow-wash_hu14401495248400331614.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;70&#34;
		data-flex-basis=&#34;169px&#34;
	
&gt;  &lt;img src=&#34;https://www.project392.net/p/dishwasher-firmware/flow-rinse.png&#34;
	width=&#34;794&#34;
	height=&#34;1123&#34;
	srcset=&#34;https://www.project392.net/p/dishwasher-firmware/flow-rinse_hu7094757822364565988.png 480w, https://www.project392.net/p/dishwasher-firmware/flow-rinse_hu1215304252507165184.png 1024w&#34;
	loading=&#34;lazy&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;70&#34;
		data-flex-basis=&#34;169px&#34;
	
&gt;&lt;/p&gt;
&lt;p&gt;After the pre-wash cycle the program waits for the door to be opened and closed again. Why is that, you ask? One of the many luxuries the HEDW44004 lacks, is one of those soap compartments that automagically open to dispense more soap after pre-wash. Dispensing soap remains the sole responsibility of the human wishing clean plates. Also, the less than perfect filter system will be clogged up by last evening&amp;rsquo;s spaghetti, so that will need emptying too.&lt;/p&gt;
&lt;p&gt;Another thing that&amp;rsquo;s missing is the ability to dry. Drying can be done by keeping the heater element on for a while after the rinse cycle. Water on the freshly cleaned plates and pots then evaporates and condensates on the colder surfaces inside the dish compartment. (The door, in my case, because the rest is now snugly wrapped in fluffy, insulating material). I choose not to add the drying functionality because I stripped the machine of its ability to apply rinse aid. Drying without rinse aid would leave water spots on my kitchenware. Drying with a tea towel feels like an acceptable sacrifice now that I don&amp;rsquo;t have wash by hand anymore.&lt;/p&gt;
&lt;p&gt;You may also have notice that there are no checks on the door being opened mid-cycle. If the door opens, the timer just keeps running, even while there is no longer any water flowing through the system. Leaving the door open for too long effectively leads to a shortened wash cycle.&lt;/p&gt;
&lt;h2 id=&#34;wishy-washy&#34;&gt;Wishy-Washy
&lt;/h2&gt;&lt;p&gt;So, does it work? Kind of. The repaired dishwasher gets dishes cleaned most of the time. The results aren&amp;rsquo;t perfect, but that&amp;rsquo;s mostly because it&amp;rsquo;s just not the finest piece of equipment ever produced. One issue that I have (and have had in the past) with the HEDW44004 is that it comes with a very crude water filter. Particles of up to roughly 1 millimeter in diameter (like seeds or ground coffee) pass through the filter. They keep being circulated during the wash (and rinse) cycle. Eventually they end up in some hard to reach corner, or on that one piece of cutlery that I urgently need. I don&amp;rsquo;t think the controller or firmware can really prevent that, so the problem isn&amp;rsquo;t in my repair job.&lt;/p&gt;
&lt;p&gt;On the whole, even a sub-perfect, but working dishwasher is better than none at all. So I consider myself satisfied.&lt;/p&gt;
&lt;p&gt;Some things that I would like to (but probably never will) improve are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Timeouts for filling, to prevent spills.&lt;/li&gt;
&lt;li&gt;Periodic checks on the water level, to detect leaks.&lt;/li&gt;
&lt;li&gt;Detection hardware for leaked water (and software responding to that).&lt;/li&gt;
&lt;li&gt;Proper switch debouncing.&lt;/li&gt;
&lt;li&gt;Better software filtering for the ADC.&lt;/li&gt;
&lt;li&gt;Detection of the door being opened during a wash cycle, and a good pause-and-resume routine.&lt;/li&gt;
&lt;li&gt;The option to choose different programs (e.g. longer or shorter cycles).&lt;/li&gt;
&lt;li&gt;A nice sequence of &lt;abbr title=&#34;Pulse-code Modulation&#34;&gt;PCM&lt;/abbr&gt; beeps!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;you-can-rescue-a-dishwasher-too&#34;&gt;You Can Rescue a Dishwasher, Too!
&lt;/h2&gt;&lt;p&gt;Both the hardware design and the firmware are on my &lt;a class=&#34;link&#34; href=&#34;https://codeberg.org/project392/dishwasher-project&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Codeberg repository&lt;/a&gt;. Feel free to build and program your own dishwasher controller, if you ever need one!&lt;/p&gt;
&lt;p&gt;The program I discussed here is the one that I share on my public repository. I published it as is, with all the quirks and limitations it has. Whoever decides to build a copy of the controller and use this code should be forewarned: it is very far from perfect. I would not recommend leaving it unattended. In fact, I myself never leave the house when it runs.&lt;/p&gt;
&lt;p&gt;Happy washing!&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
