<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ESP32-C3</title>
	<atom:link href="https://rodyne.com/?feed=rss2&#038;cat=163" rel="self" type="application/rss+xml" />
	<link>https://rodyne.com</link>
	<description></description>
	<lastBuildDate>Tue, 03 Feb 2026 22:50:50 +0000</lastBuildDate>
	<language>en-NZ</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.7</generator>

<image>
	<url>https://rodyne.com/wp-content/uploads/2015/11/web-header2.png</url>
	<title>ESP32-C3</title>
	<link>https://rodyne.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Don&#8217;t look Behind The Curtains!</title>
		<link>https://rodyne.com/?p=3574</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Fri, 30 Jan 2026 07:47:15 +0000</pubDate>
				<category><![CDATA[C Programming]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[ESP32-C3]]></category>
		<category><![CDATA[Other Programming]]></category>
		<category><![CDATA[Pascal Programming]]></category>
		<category><![CDATA[Philosophy]]></category>
		<category><![CDATA[PicoMite]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Retro]]></category>
		<category><![CDATA[RP2040]]></category>
		<category><![CDATA[RP2350]]></category>
		<category><![CDATA[Speculation]]></category>
		<category><![CDATA[Ramblings of an old man]]></category>
		<category><![CDATA[The Stack]]></category>
		<guid isPermaLink="false">https://rodyne.com/?p=3574</guid>

					<description><![CDATA[My recent goals to work with and learn some newer, more popular, micro-controllers, and to try some different programming languages, has made me also take another look at the ways things have progressed since I started my career. My programming &#8230; <a href="https://rodyne.com/?p=3574">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full is-resized"><img fetchpriority="high" decoding="async" width="359" height="506" src="https://rodyne.com/wp-content/uploads/image-2-1.jpg" alt="" class="wp-image-3590" style="aspect-ratio:0.7094743071171292;width:298px;height:auto" srcset="https://rodyne.com/wp-content/uploads/image-2-1.jpg 359w, https://rodyne.com/wp-content/uploads/image-2-1-213x300.jpg 213w" sizes="(max-width: 359px) 100vw, 359px" /></figure>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:60%">
<p class="wp-block-paragraph">My recent goals to work with and learn some newer, more popular, micro-controllers, and to try some different programming languages, has made me also take another look at the ways things have progressed since I started my career. My programming career started with Pet and ZX81 Basic at school, then Turbo Pascal for PC, and C for VMS/Unix at work/college. These were all languages I could easily grok. I still remember a magazine article where somebody poked a number into a memory location in the ZX81 and the letter &#8220;A&#8221; popped up on the screen, one line of code.. which mapped to one single CPU instruction! That was all it took for the light bulb to go on in my head.</p>
</div>
</div>



<p class="wp-block-paragraph">The 80&#8217;s were simpler times, and life at that point was easy, and things worked well.. But then came the 90&#8217;s and along came Windows! I vaguely remember the 100&#8217;s of lines of weird C++ code, calling this API, then that API, just to get a window on the screen with &#8220;Hello world&#8221;, it all made zero sense at the time, not just to me, but a lot of our more traditional programmers, and I knew from that point on things had changed big time for me; I would no longer be a part of that world, I never wanted to see it ever again, and (for me at least) Windows/C++ had tainted the simplicity of C.</p>



<p class="wp-block-paragraph">I guess this epiphany happened to a lot of other people too, as dozens of new programming languages, development environments, and operating systems, all sprung up around this time, each preaching a better and easier life than C/C++. My department however had committed to Windows, and we were all electronics engineers, so it was Visual Basic, then Delphi which won us over. Both languages hid the (high) complexity of Windows behind a simple event driven point and click interface, great for us engineers who simply wanted to get something done.</p>



<p class="wp-block-paragraph">Someone coming into programming in 2026 will likely be offered JavaScript or Python as their first development language, both require an OS, an IDE, an interpreter or a browser, and probably the equivalent of a 1980&#8217;s supercomputer just to print &#8220;Hello World&#8221;. No beginner is really going to have a clue how their <em>Print &#8220;Hello World&#8221;</em> got onto their screen, because doing so requires understanding a API stack a mile high; If this was where I had to start my programming journey, I might never have begun, as I like to understand how things work. To many, I expect the inner workings of the stack between their chosen programming language, and the work their program actually does, is still <em>black-magic</em>.</p>



<p class="wp-block-paragraph">I was lucky to have peeked behind the curtains early in my career, and have an intimate knowledge of CPU architectures, but even I have basically given up trying to understand the layers or stack. I read and write to whatever API is exposed, and hope the level below me knows what it is doing! Occasionally I have written parts of &#8216;the stack&#8217;, building hardware and writing a driver for Windows or Linux to support it, but even then I am conforming to a set of norms for the level above it, and I doubt anybody ever checked my code.</p>



<p class="wp-block-paragraph">Only with Micro-controller projects am I fully back in control, and with them (for me at least) there generally was no stack; My program <em>was</em> the stack! This was however back with older 8-bit or 16-bit micros, and micro-controllers were not immune from technologies progress. Today&#8217;s micro-processors are amazing pieces of technology that have improved in leaps and bounds, going to multi-core monsters, with layers of complexity and peripherals that would shame a 1980&#8217;s super-computers. Unlike software though, they have done this while improving there efficiency and lowering there cost. For me, the best thing about all of this is you don&#8217;t really have to use any of this new complexity, and a simple blinking LED can still be done in a few primitive lines of C.</p>



<figure class="wp-block-image size-full"><a href="https://rodyne.com/?p=1751"><img decoding="async" width="784" height="168" src="https://rodyne.com/wp-content/uploads/IMG_0508-ezgif.com-optimize.gif" alt="" class="wp-image-3540"/></a></figure>



<p class="wp-block-paragraph">From a blinking LED I can add in all the complexity, and use as many of these new peripherals as I like. This is <em>exactly</em> like I did back in 1980 with my first Z80 chip, no real need for a stack or an API.</p>



<p class="wp-block-paragraph">But API&#8217;s and stacks get added anyway, for convenience, reliability and speed of development. Abstracting away complex code behind a set of C SDK libraries, an RTOS, MicroPython, Arduino or even MMBasic, is a way of not having to learn the 1000&#8217;s of pages of CPU and peripheral datasheets. A lot of people are happy to take these easier options, including me, but lets not kid ourselves that we diligently read the libraries of source code that get compiled into our binaries, most of the time we are generally trusting the coders have done a good job.</p>



<p class="wp-block-paragraph">A modern micro-processor, or System-On-Chip (SOC), is a far different beast from a micro-controller, adding many more layers of complexity, security, memory management, cores and peripherals, such as PCIe, USB3, Ethernet, or even a GPU. They are so complex that they often require there own bootstrap program to even initialise everything before it even finds and runs even a single line of your code. Very few programmers are brave enough to work <em><a href="https://en.wikipedia.org/wiki/Bare_machine" target="_blank" rel="noreferrer noopener">bare-metal</a></em> at this level because often as not these SOC&#8217;s, unlike micro-controllers, hide or abstract everything behind NDA&#8217;s or binary API&#8217;s, this is why for example on your cell phone, real world people accept they are going to work through an operating system and use the provided API&#8217;s.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<p class="wp-block-paragraph">So, to segue again back to my first paragraph, if I was being honest with my real goals, I love the fact that when working with micro-controllers I am effectively going back to a simpler time, a time where I owned, and understood the stack, where the stack hardly ever changed, and when I turned my computer on I was running my program code within microseconds. I guess that is why there is a resurgence in retro-computing going on, people still want to know what is behind the curtains and understand how it all works!</p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<figure class="wp-block-image size-full"><img decoding="async" width="512" height="512" src="https://rodyne.com/wp-content/uploads/wizardoftech.jpg" alt="" class="wp-image-3607" srcset="https://rodyne.com/wp-content/uploads/wizardoftech.jpg 512w, https://rodyne.com/wp-content/uploads/wizardoftech-300x300.jpg 300w, https://rodyne.com/wp-content/uploads/wizardoftech-150x150.jpg 150w" sizes="(max-width: 512px) 100vw, 512px" /></figure>
</div>
</div>



<p class="wp-block-paragraph">I am one of those people, but I will never go back to using a retro-computer or retro-operating system for my daily drive, I am happy the stack is there and hundreds of thousands of people have stood on each others shoulders, to bring me the marvelous Linux and IOS GUI&#8217;s I have today. However there is a cost, and that cost is complexity, efficiency, and the fact that programmers (like me) take all these layers of code for granted without looking behind the curtain. A whole Eco-system based on the trust that somebody else has done your due diligence for you!</p>



<p class="wp-block-paragraph">This is especially scary once you realise how many bad actors are out there, examining every line of these stacks for code vulnerabilities. This is happening every hour of the day, and they are finding them with ease. AI, over-complicated programming styles, and dependency hell, are making it harder for the developers to miss these cracks in their code reviews, and easier for the bad guys to find them.</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:66.66%">
<figure class="wp-block-image size-full"><a href="https://news.ycombinator.com/item?id=46789913" target="_blank" rel=" noreferrer noopener"><img loading="lazy" decoding="async" width="518" height="213" src="https://rodyne.com/wp-content/uploads/vulnerabilities.jpg" alt="" class="wp-image-3613" srcset="https://rodyne.com/wp-content/uploads/vulnerabilities.jpg 518w, https://rodyne.com/wp-content/uploads/vulnerabilities-300x123.jpg 300w" sizes="auto, (max-width: 518px) 100vw, 518px" /></a></figure>



<p class="has-text-align-center has-small-font-size wp-block-paragraph"><a href="https://news.ycombinator.com/item?id=46789913" target="_blank" rel="noreferrer noopener">Hacker News Link and Comments For Story Above</a></p>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:33.33%">
<p class="wp-block-paragraph">Unfortunately, as always, it is up to you to balance the security, against the ease and convenience, or, like the vast majority of us, believe the myth that your system is secure and does not have these problems.</p>
</div>
</div>



<p class="has-text-align-center wp-block-paragraph"><em>Thanks to <a href="https://gemini.google/overview/image-generation/" target="_blank" rel="noreferrer noopener">Gemini</a> for the memes, but like AI vibe-coding it pays to look at the finer details </em><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p class="has-light-gray-background-color has-background wp-block-paragraph">The vulnerabilities of these programming stacks were one of the plot elements in my free sci-fi trilogy eBook <a href="https://rodyne.com/?p=1252">The Summer Of Reasoning</a>. I still think I did a good job in that book of explaining the problem, why it matters, and the consequences of when it fails.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>On-Time and Under-Budget. Where some IT projects are Probably Going Wrong.</title>
		<link>https://rodyne.com/?p=2074</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Tue, 25 Mar 2025 06:14:45 +0000</pubDate>
				<category><![CDATA[boz]]></category>
		<category><![CDATA[Boz NZ]]></category>
		<category><![CDATA[C Programming]]></category>
		<category><![CDATA[Electronics]]></category>
		<category><![CDATA[ESP32-C3]]></category>
		<category><![CDATA[IT Failures]]></category>
		<category><![CDATA[LoRa]]></category>
		<category><![CDATA[Motor Controllers]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[New Zealand]]></category>
		<category><![CDATA[NZ]]></category>
		<category><![CDATA[Other Programming]]></category>
		<category><![CDATA[Pascal Programming]]></category>
		<category><![CDATA[Project Management]]></category>
		<category><![CDATA[boz nz]]></category>
		<category><![CDATA[boznz]]></category>
		<category><![CDATA[C Programmer]]></category>
		<category><![CDATA[Delphi Developer NZ]]></category>
		<category><![CDATA[Delphi programmer]]></category>
		<category><![CDATA[Delphi Programmer NZ]]></category>
		<category><![CDATA[Electronics Design]]></category>
		<category><![CDATA[Electronics Design NZ]]></category>
		<category><![CDATA[Pascal Programmer]]></category>
		<category><![CDATA[SQL administrator]]></category>
		<category><![CDATA[SQL Developer NZ]]></category>
		<guid isPermaLink="false">https://rodyne.com/?p=2074</guid>

					<description><![CDATA[This will be a short post, and not technical like my usual ones, it is about many of the seemingly hundreds of failed IT projects out there, where companies have been let down by the big IT companies and consultants. &#8230; <a href="https://rodyne.com/?p=2074">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">This will be a short post, and not technical like my usual ones, it is about many of the seemingly hundreds of failed IT projects out there, where companies have been let down by the big IT companies and consultants. Feel free to hit the back button at this point or go and check out the rest of the site, as from this point it&#8217;s just going to be me whinging <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f642.png" alt="🙂" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p class="wp-block-paragraph">These big fails get all the attention of course, but I am sure that for each big fail, there are dozens of others simply swept under the rug. I can write this as I am almost at the end of my career, have seen many of these failures first hand, and I don&#8217;t have any particular agenda as I am no longer actively looking for major projects (though small gigs are still appreciated). I have also seen many successful projects, though mostly in terms of delivery rather than cost!</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">Tell me what you need, AND I will tell you how to get along without it. &#8211; Scott Adams</p>
</blockquote>



<p class="wp-block-paragraph">As a developer who specialises in writing systems for people who generally haven&#8217;t really got a clue what they want, I can usually tell the moment I walk in the room with them that they are either under or over-thinking the scope or complexity of their project. Yes, them not knowing exactly what they want makes life a bit harder for me, (though sometimes easier,) but what it doesn&#8217;t do and should never do, is give me the right to screw them over, or pretend I can do something when I cannot.</p>



<p class="wp-block-paragraph">So lets get some truisms out of the way. Firstly, your BIG system is probably not really that big. Wow it stores a billion records, or wow it has to support five hundred users. Let me tell you something, there are very few database servers that don&#8217;t give you this out-of-the-box, and the two biggest of these (Postgres and MySQL) are completely licence-free. Furthermore it is a pretty shitty system-level programmer in 2025 who does <em>not</em> know the protocols to support multiple users.</p>



<p class="wp-block-paragraph">Secondly your COMPLEX system is likely not even that complex. Small, or even lone developers like me have written many ERP, MRP or whatever the current buzz-word system it is. We are generally NOT re-inventing the wheel but re-using well proven techniques with some customisation and business logic added, so unless you are totally replacing everything, your system is unlikely to be this complex. With the advent of AI <a href="https://rodyne.com/?p=1828">this is even more truer</a> now than it was in the past.</p>



<p class="wp-block-paragraph">But, you say, it also needs to be up 99.99% of the time, 24&#215;7. Well welcome to modern IT, you can run hundreds of sessions easily on a low end local server, and you don&#8217;t need to go to AWS or whatever <em>cloud-de-jour</em> your consultant says it must be on. Remember, a cloud is just a server that you have no clue where it is physically located, and especially if you are a small player, you generally have no clue who to contact if there is a problem. Backups, fallback servers, docker containers, clusters are all well proven techniques that people like me and most small IT shops can install and configure with ease.</p>



<p class="wp-block-paragraph">But people like me will never tender for your BIG project. For while I, and many other small businesses like me, have a perfect track record of delivering BIG systems for customers, (and there a a shed-load of developers far better than me); We are everything you seem to hate, so lets get them into the open shall we:</p>



<p class="wp-block-paragraph">Firstly I am a one man shop, a lone developer. Yes I could easily obfuscate all this behind my web site; and on web sites I often see the third-person to talk about companies, where phrases like &#8220;we can do this&#8221; and &#8220;we specialise in that&#8221; hide the fact they have one or two developers behind layers of non-relevant management, sales and consultancy. I even do the same on my website, but I always make it very clear there is only me, and it will be <span style="text-decoration: underline;">only me</span> who will help specify, write, install and support your system. Good luck having <span style="text-decoration: underline;">that</span> person on speed-dial if you use a big company. If in doubt ask the question directly, but do not dismiss them because of it as even the biggest project probably relies on one or two key developers.</p>



<p class="wp-block-paragraph">Secondly, I am not going to fill out your 50 page tender document, which is probably mostly technically wrong and full of corporate speak that has no relevance whatsoever to the project you want me to do. As an individual I do not have the time for this, nor can I work with your liability clauses, nor do I have a company statement on my carbon neutrality, anti-slavery, how I am inclusive, or anything like that; You should start out trusting track-proven vendors meet the criteria, unless they give you a genuine reason not too.</p>



<p class="wp-block-paragraph">Then there is the technology that everyone seems so keen on specifying these days. This is despite the fact that it does nothing but exclude people who use much more mature technologies, and are likely to get the project done on time and budget. A lot of this is because your IT Manager or CTO heard about some new trend at their last &#8220;technical conference&#8221;, or they have paid an over-priced consultant to specify their new system, and to justify the extravagant cost they have hit all the buzz-words, or worse, have specified it so their own company or partner will be the only choice you will have to develop it. If the development tools and systems used are supported and you own all the code to the final system there is no real reason to reject something.</p>



<p class="wp-block-paragraph">Lastly, it is highly likely that by the time a big company has written a line of code, I, or someone like me, will have a prototype ready. This is not hubris, it is just the way I operate, in order to get an alpha-stage product in front of a customer quickly, as I know they have likely gotten something wrong, and they will see it quicker with something in front of them.</p>



<p class="wp-block-paragraph">Of course, I am not going to tender for replacing your big system, nor am I going to tender for our next government tax or social security system, but do not think for one minute it is because me, or another small business or developer like me cannot do it. Your system is NOT hard, it is <em>you</em> and <em>your procurement procedures</em> that are generally making it hard for small companies to help you, and it is you and your procurement systems and attitude that will likely make the project fail, be delayed or go over-budget.</p>



<p class="wp-block-paragraph">None of this is to say do not do your due diligence, just make sure you due diligence does not exclude us small players.</p>



<figure class="wp-block-image size-full"><a href="https://dilbert.com/" target="_blank" rel=" noreferrer noopener"><img loading="lazy" decoding="async" width="640" height="199" src="https://rodyne.com/wp-content/uploads/22373_strip.gif" alt="" class="wp-image-2132"/></a></figure>



<p class="has-text-align-center wp-block-paragraph">(<a href="https://dilbert.com/">Dilbert.com</a>)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Yet another boring small project (with an interesting back-story)</title>
		<link>https://rodyne.com/?p=1781</link>
		
		<dc:creator><![CDATA[admin]]></dc:creator>
		<pubDate>Wed, 05 Mar 2025 07:13:08 +0000</pubDate>
				<category><![CDATA[Bulls-i]]></category>
		<category><![CDATA[ESP32-C3]]></category>
		<category><![CDATA[Indevin]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://rodyne.com/?p=1781</guid>

					<description><![CDATA[As I sit at my desk in the clients winery, &#8220;working&#8221; vintage support, (a job where I mostly feel like Dumbo&#8217;s feather, ie a prop that gives the company confidence everything will be great, where as in reality I do &#8230; <a href="https://rodyne.com/?p=1781">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">As I sit at my desk in the clients winery, &#8220;working&#8221; vintage support, (a job where I mostly feel like <em>Dumbo&#8217;s feather</em>, ie a prop that gives the company confidence everything will be great, where as in reality I do very little. The client knows my feelings on this but are quite happy to pay for those <em>just in case</em> moments that might prove costly). Anyway, I thought, I need something big, which these guys can remember me by when I&#8217;m gone, and looking around the winery building I wondered what I could possibly contribute that would be both useful and memorable, and I thought a clock!</p>



<p class="wp-block-paragraph">So I thought I would design and build a clock, one which will reliably keep the time and be pretty well maintenance free for its hopefully long and boring life. But why would anybody need to design a clock today, surely every variation has been tried? Well, for one thing, this clock is going to be pretty big. Although it is only a seven-segment display, with two digits for hours and two for minutes, each segment is going to be a wine bottle. So 7 bottles are required per digit, in total 28 bottles.</p>



<p class="wp-block-paragraph">Inside each bottle will be an LED strip or similar so we can light the segment, therefore we need a circuit board that can drive 28 LED strips, also, to make the flashing colons that separate the hours and minutes, the ends of two bottles will be used, and so another output is required to drive the LED&#8217;s in those. That&#8217;s 29 drivers, 29 bottles, 2M x 1M in size minimum, and as a total package with some form of mounting, quite heavy I guess!</p>



<p class="wp-block-paragraph"><span style="text-decoration: underline;">The boring electronics prototype</span></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="674" height="542" src="https://rodyne.com/wp-content/uploads/clock-pcb.png" alt="" class="wp-image-1853" srcset="https://rodyne.com/wp-content/uploads/clock-pcb.png 674w, https://rodyne.com/wp-content/uploads/clock-pcb-300x241.png 300w" sizes="auto, (max-width: 674px) 100vw, 674px" /></figure>



<p class="wp-block-paragraph">The electronics for this were always going to be easy. Again it&#8217;s a project I would normally slap in an old PIC microcontroller and an RTC and have it designed in a few hours. But that was the old 1990&#8217;s Boz, the new 2025 Boz is on a mission to try out some of the new technologies out there, and the modern micro-controller for today will be (rolls-the-dice..) the ESP32-C3. Specifically the ESP32-C3-WROOM-02 a RISC-V 32-bit processor with Wi-Fi, Bluetooth, 400KB of RAM and 2MB of Flash all for $3.30. (A bit over-kill for a clock, but welcome to 2025!)</p>



<p class="wp-block-paragraph">So a brand-new processor I have never used before, or even seen before a few days ago should be exciting, or at least a bit risky? Maybe, maybe-not. Lets go on a journey together. For this journey, the AI of choice will be Googles Gemini 2.0, a competent, if pretty boring and sensible AI, so while Grok 3 may be considered your rebellious genius teenager, Gemini 2.0 is probably your quiet old uncle, the retired school teacher who lives in his shed and doesn&#8217;t really talk to many people, but also tends to be sensible.</p>



<p class="wp-block-paragraph"><span style="text-decoration: underline;">The Schematic.</span></p>



<figure class="wp-block-image size-full"><a href="https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05.png"><img loading="lazy" decoding="async" width="1652" height="1170" src="https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05.png" alt="" class="wp-image-1782" srcset="https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05.png 1652w, https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05-300x212.png 300w, https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05-1024x725.png 1024w, https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05-768x544.png 768w, https://rodyne.com/wp-content/uploads/Schematic_Indevin-Clock-V2_2025-03-05-1536x1088.png 1536w" sizes="auto, (max-width: 1652px) 100vw, 1652px" /></a></figure>



<p class="wp-block-paragraph">Yes, pretty boring and certainly not rocket science. An RTC, a serial input for a GPS (Not yet sure if I can get a signal where it is going to be located, but a good time-source never-the-less), and 29 open-collector outputs that can drive a few hundred milliamps at up to 24V, total BOM cost around $8 from LCSC</p>



<p class="wp-block-paragraph">Firstly, it is obvious that a lot of the big AI models have a good understanding of electronics, and simple questions, like how much power will this or that draw? or what are the maximum and minimum supply voltages for power and IO? are generally answered correctly. However, that accuracy is about 90% at best and 10% of answers will be confidently answered wrongly, with a quick and humble apology when the mistake is finally pointed out. Again the ability to feed a schematic into a AI would be fantastic, but we are not there yet. (or if we are I haven&#8217;t seen it!)</p>



<p class="wp-block-paragraph">Asking questions like, what capacitance would I require on VCC1 to keep the RTC running for 8-hours in the configuration shown was answered quite well with suitable workings out shown and the real-life circuit performing slightly better than the calculation </p>



<p class="wp-block-paragraph">There are a few grey areas out there which may lead to said AI&#8217;s not being too accurate, for example, if I decided to use the USB interface that the ESP32-C3 has for program/debug, would I still require the boot button to program it? The reference design does show almost every possible IO pin used for programming and makes you wonder if there would be any left afterwards. People building these boards on the internet tend to favour the serial port and use of the DTR and RTS of a serial to USB driver to program it, well I&#8217;m telling you now, two wires to a USB connector are all you need and you do not need to press the boot or reset switches ever. Also as I used my usual GPIO expansion technique for slowly changing output ports by using a series of shift registers so that was never an issue..</p>



<p class="wp-block-paragraph"><span style="text-decoration: underline;">Programming.</span></p>



<p class="wp-block-paragraph">This is where it got interesting. After bigging up the project to Gemini (it felt right to do so!), I told it I was using the Arduino IDE (as the VSCode extension for the ESP32 was, to say it politely, work in progress!), I got it all excited to help me. I then fed the following prompt into him/her/it..</p>



<pre class="wp-block-code"><code><mark style="background-color:#f1f1f1" class="has-inline-color">The ESP32-C3 is on a ESP32-C3-WROOM-02 board

The connections from the ESP32-C3 to the DS1302 are:

I/O (Pin 6 of DS1302) to GPIO 0
CE (Pin 5 of DS1302)  to GPIO 1
SCLK (Pin 7 of DS1302) to GPIO 3

The clock will output its time in the format HH:MM to a seven-segment display. It does this by sending 32 bytes of (7 segment) data out to four 74HC595 shift registers in series, the first shift register is hours x 10, the second shift register is hours x 1, the third shift register is minutes x 10, the last shift register is minutes x 1, The connections from the ESP32-C3 to the shift registers are as follows:

74HC595 pin 14 (DS) of first shift register to GPIO 6
74HC595 pin 12 (STCP) of all shift registers to GPIO 7
74HC595 pin 11 (SHCP) of all shift registers to GPIO 5

The 7-segments are connected to each 74HC595 as follows

Q0 = segment a
Q1 = segment b
Q2 = segment c
Q4 = segment d
Q5 = segment e
Q6 = segment f
Q7 = segment g

I want to be able to connect to the ESP32 Wi-Fi and set the time on the DS1302 through a web page, then update the LED outputs of to the shift register every time it changes

I would like to understand the code I am writing by not using any libraries where possible e.g. the DS1302 communication should be easy without libraries, though the Wi-Fi stuff might be a bit hard for me to understand.

Is this enough to go on?</mark>
</code></pre>



<p class="wp-block-paragraph">I literally downloaded the Arduino IDE, downloaded the ESP32 extension for it, copied the code it generated from the above prompt in and bugger me if it didn&#8217;t just work!</p>



<p class="wp-block-paragraph">Well, almost! It did kind of work, the clock counted and showed the time, the web-page worked and set the time, but of course the devil is always in the detail, the web-page was bloated and overkill and pretty ugly, it also only set the time, not the day and date, which I would require latter for daylight-savings calculations. Also as I lay there thinking about it, I thought, why would I want to type in the time from a web-page when I had a phone that already had the correct date and time down to the microsecond? I quickly corrected my prompt, asked it to separate out the networking part, into another module, change the Wi-Fi client into a Wi-Fi access point, made the web page into a simple button and bit of java-script to send the time/date, and manually tidied up the landing page a bit (All using AI prompts of course as I am really totally shit at this web stuff!) </p>



<p class="wp-block-paragraph">As a side rant, lets talk again about that bloat! 400KB Ram and 2MB ROM and 75% used. I wont even try to understand the reasoning behind the colossal use of resources, lets just say we are in 2025 and the future seems to be bloat! Seriously, nobody these days seems to give a rats-arse about throwing in libraries that go into thousands of lines of code they have no idea what any of it does. Sure it makes my life easier, but extrapolating the extra computation and resources required by computers these days the waste of power must be several power stations! Anyway, rant over, back to the project..</p>



<p class="wp-block-paragraph">The Arduino IDE itself is pretty bullet-proof; as I remember it from about 10 years earlier simply selecting the ESP32C3 dev module as my board, and setting the &#8220;USB CDC on Boot&#8221; to get debug information was all that was required, all refreshingly easy.</p>



<p class="wp-block-paragraph">OK, so by now you have noticed the lack of pictures of the actual epic bottle-hardware! well, this is only the first part of the post as I still have to mount those 28.5 wine bottles (the point five being the two bottle-ends for the colon) on a very large mount, shove the LED&#8217;s in them, and get a 24V power supply as everything so far has been with USB power and logic probes. A few friends have offered to help in this part as my artistic flair is about as shitty as my web skills!</p>



<p class="wp-block-paragraph">The code to the working board so far is below. It may change but as it stands it works as a stand-alone clock (just add big LED&#8217;s!)..</p>



<p class="wp-block-paragraph">To be continued..</p>



<p class="wp-block-paragraph"><strong>IndevinClock.ino</strong></p>



<pre class="wp-block-code"><code>// Colabaration between Boz and various AI's that provides the logic to 
// manage the DS1302 real-time clock and update the display through the
// shift register GPIO expander. And provide a web portal to set the time.
// Full Hardware design is/will be at rodyne.com
// All Designs relating to this project are Public Domain.

#include &lt;Arduino.h&gt;
#include "networking.h"

// Pin Definitions
#define DS1302_CE_PIN 1  // Chip Enable
#define DS1302_IO_PIN 0  // Data I/O
#define DS1302_SCLK_PIN 3 // Serial Clock
#define SHCP_PIN 5  // 74HC595 Shift Register Clock (SHCP)
#define DS_PIN 6    // 74HC595 Data Input (DS)
#define STCP_PIN 7  // 74HC595 Storage Register Clock (STCP)
#define COLON_PIN 10  // flashing colon output
#define DSTLED_PIN 4  // debug led

const char * DayOfWeek&#91;] =  { "ERR!","Mon","Tue","Wed","Thu","Fri","Sat","Sun" };

const uint8_t Lookup7seg&#91;] = { 0b00111111, 0b00000110, 0b01011011, 0b01001111, 0b01100110, 0b01101101, 0b01111101, 0b00000111, 0b01111111, 0b01101111 };

uint8_t RTCsec, RTCmin, RTChour, RTCday, RTCmonth, RTCyear, RTCdow, Colon; // global variables visible to networking module
uint8_t LastUpdate, LastMinVal; // local to this unit


// Function Prototypes
void ds1302_write(uint8_t address, uint8_t data);
uint8_t ds1302_read(uint8_t address);
void ds1302_setTime(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint8_t year, uint8_t dow);
void ds1302_getTime();
uint8_t bcdToDec(uint8_t val);
uint8_t decToBcd(uint8_t val);
void displayTime(); 
bool isDaylightSavings();

bool isDaylightSavings() 
{
  // New Zealand Daylight Saving Time (DST) rules: Starts: 2:00 a.m. on the last Sunday in September. Ends: 3:00 a.m. on the first Sunday in April.

  if (RTCmonth &lt; 4 || RTCmonth &gt; 9) 
  {
    return (RTCmonth &gt; 9); // DST is active from October to March
  } 
  else if (RTCmonth == 4) 
  {
    // Check if it's the first Sunday in April
    int firstSunday = 8 - RTCdow; // Calculate the date of the first Sunday
    if (RTCday &lt; firstSunday) 
    {
      return true; // DST is still active before the first Sunday
    } 
    else if (RTCday == firstSunday) 
    {
      return (RTChour &lt; 3); // DST ends at 3:00 a.m.
    } 
    else 
    {
      return false; // DST is not active after the first Sunday
    }
  } 
  else if (RTCmonth == 9) 
  {
    // Check if it's the last Sunday in September
    int lastSunday = 30 - ((RTCdow + (30 - RTCday)) % 7); // Calculate the date of the last Sunday
    if (RTCday &gt; lastSunday) 
    {
      return true; // DST is active after the last Sunday
    } 
    else if (RTCday == lastSunday) 
    {
      return (RTChour &gt;= 2); // DST starts at 2:00 a.m.
    } 
    else 
    {
      return false; // DST is not active before the last Sunday
    }
  }
  return false; // Should not reach here
}

void displayTime() 
{
  uint32_t displayData = 0;
  uint8_t  rawHour = RTChour;

  if(isDaylightSavings()) // convert hrs to DST for display
  {
    if(rawHour==0)
      rawHour=23;
    else
      rawHour--;
  }

  Serial.print(DayOfWeek&#91;RTCdow]); Serial.print(" ");
  Serial.print(rawHour); Serial.print(":");
  Serial.print(RTCmin); Serial.print(" ");
  Serial.print(RTCday); Serial.print("/");
  Serial.print(RTCmonth); Serial.print("/");
  Serial.print(RTCyear);
  if(isDaylightSavings()) // convert hrs to DST for display
    Serial.println(" (Daylight Savings Active)");
  else
    Serial.println("");


  uint8_t hoursTens = rawHour / 10;
  uint8_t hoursOnes = rawHour % 10;
  uint8_t minutesTens = RTCmin / 10;
  uint8_t minutesOnes = RTCmin % 10;

  // Combine digit data into a 32-bit value
  displayData |= (uint32_t)Lookup7seg&#91;minutesOnes];
  displayData &lt;&lt;= 8;
  displayData |= (uint32_t)Lookup7seg&#91;minutesTens];
  displayData &lt;&lt;= 8;
  displayData |= (uint32_t)Lookup7seg&#91;hoursOnes];
  displayData &lt;&lt;= 8;
  displayData |= (uint32_t)Lookup7seg&#91;hoursTens];

  // clock out data to shift registers
  for (int i = 31; i &gt;= 0; i--) 
  {
    digitalWrite(DS_PIN, (displayData &gt;&gt; i) &amp; 1);
    digitalWrite(SHCP_PIN, HIGH);
    digitalWrite(SHCP_PIN, LOW);
    delay(1);
  }

  // Latch data to outputs
  digitalWrite(STCP_PIN, HIGH);
  digitalWrite(STCP_PIN, LOW);
}

void ds1302_write(uint8_t address, uint8_t data) 
{
  digitalWrite(DS1302_CE_PIN, HIGH);
  shiftOut(DS1302_IO_PIN, DS1302_SCLK_PIN, LSBFIRST, address);
  shiftOut(DS1302_IO_PIN, DS1302_SCLK_PIN, LSBFIRST, data);
  digitalWrite(DS1302_CE_PIN, LOW);
}

uint8_t bcdToDec(uint8_t val) 
{
  return (val / 16 * 10) + (val % 16);
}

uint8_t decToBcd(uint8_t val) 
{
  return (val / 10 * 16) + (val % 10);
}

uint8_t ds1302_read(uint8_t address) 
{
  uint8_t data;
  digitalWrite(DS1302_CE_PIN, HIGH);
  shiftOut(DS1302_IO_PIN, DS1302_SCLK_PIN, LSBFIRST, address);
  pinMode(DS1302_IO_PIN, INPUT);
  data = shiftIn(DS1302_IO_PIN, DS1302_SCLK_PIN, LSBFIRST);
  pinMode(DS1302_IO_PIN, OUTPUT);
  digitalWrite(DS1302_CE_PIN, LOW);
  return data;
}

void ds1302_getTime() 
{
  ds1302_write(0x8F, 0x00); // Dummy write to DS1302 to prepare for read
  RTCsec = bcdToDec(ds1302_read(0x81) &amp; 0x7F);
  RTCmin = bcdToDec(ds1302_read(0x83));
  RTChour = bcdToDec(ds1302_read(0x85));
  RTCday = bcdToDec(ds1302_read(0x87));
  RTCmonth = bcdToDec(ds1302_read(0x89));
  RTCdow = bcdToDec(ds1302_read(0x8b));
  RTCyear = bcdToDec(ds1302_read(0x8D));
}

void ds1302_setTime(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint8_t year, uint8_t dow) 
{
  // no checks on data written!
  ds1302_write(0x8E, 0x00); // Disable DS1302 write protect
  ds1302_write(0x80, decToBcd(sec));   // 0..59
  ds1302_write(0x82, decToBcd(min));   // 0..59
  ds1302_write(0x84, decToBcd(hour));  // 0..23
  ds1302_write(0x86, decToBcd(day));   // 1..31
  ds1302_write(0x88, decToBcd(month)); // 1..12 
  ds1302_write(0x8A, decToBcd(dow));   // 1..7
  ds1302_write(0x8C, decToBcd(year));  // 0..99
  ds1302_write(0x8E, 0x80); // Re-enable DS1302 write protect
  ds1302_getTime();
  Serial.print(" Set Time ");
  Serial.print(RTChour); Serial.print(":");
  Serial.print(RTCmin); Serial.print(":");
  Serial.print(RTCsec); Serial.print(" - ");
  Serial.print(DayOfWeek&#91;RTCdow]); Serial.print(" ");
  Serial.print(RTCday); Serial.print("/");
  Serial.print(RTCmonth); Serial.print("/20");
  Serial.print(RTCyear);
  if(isDaylightSavings()) // convert hrs to DST for display
    Serial.println(" (Daylight Savings Time is Active)");
  else
    Serial.println("");
}

void setup() 
{
  Serial.begin(115200); // Remember to set IDE "USB CDC ON BOOT" to ENABLED or serial WONT work!

  // INIT DS1302
  pinMode(DS1302_CE_PIN, OUTPUT);
  pinMode(DS1302_IO_PIN, OUTPUT);
  pinMode(DS1302_SCLK_PIN, OUTPUT);
  digitalWrite(DS1302_CE_PIN, HIGH);
  digitalWrite(DS1302_SCLK_PIN, LOW);

  // check clock is running and if not set it running and with a default time/date
  ds1302_write(0x8F, 0x00); // Dummy write to prepare for read
  uint8_t RTCDisabled = ds1302_read(0x81) &amp; 0x80;
  if(RTCDisabled)
  {
    // default time
    ds1302_setTime(0, 0, 8, 1, 4, 25, 2);
  }

  // INIT shift reg
  pinMode(SHCP_PIN, OUTPUT);
  pinMode(DS_PIN, OUTPUT);
  pinMode(STCP_PIN, OUTPUT);
  pinMode(COLON_PIN, OUTPUT);
  pinMode(DSTLED_PIN, OUTPUT);
  digitalWrite(SHCP_PIN, LOW);
  digitalWrite(STCP_PIN, LOW);    

  // init WiFi
  initWiFi();

}

void loop() 
{
  ds1302_getTime();

  if(++LastUpdate&gt;10 || LastMinVal!=RTCmin ) // Update time every 10 seconds or if minutes change (so we can see flow-active LED flash)
  {
    LastUpdate=0;
    LastMinVal=RTCmin;
    displayTime();
  }

  // flash colon at 1 sec
  if (Colon==0) Colon=1; else Colon=0;
  digitalWrite(COLON_PIN, Colon);  
  digitalWrite(DSTLED_PIN, Colon);  

  server.handleClient();  // Handle any web client requests

  delay(1000);
}</code></pre>



<p class="wp-block-paragraph"><strong>networking.h</strong></p>



<pre class="wp-block-code"><code>// Colabaration between Boz and various AI's that provides the functionality to 
// connect to and set the clock using a wifi connection and web browser
// All Designs relating to this project are Public Domain.

#ifndef NETWORKING_H
#define NETWORKING_H

#include &lt;WiFi.h&gt;
#include &lt;WebServer.h&gt;

// Access Point settings
extern const char* ap_ssid;
extern const char* ap_password;
extern IPAddress local_ip;
extern IPAddress gateway;
extern IPAddress subnet;

extern uint8_t  RTCsec, RTCmin, RTChour, RTCday, RTCmonth, RTCyear, RTCdow; // global variables

extern void ds1302_setTime(uint8_t sec, uint8_t min, uint8_t hour, uint8_t day, uint8_t month, uint8_t year, uint8_t dow);
extern void displayTime(); 
extern bool isDaylightSavings();

extern WebServer server;

// Function declarations
void initWiFi();
void handleRoot();
void handleSetTime(); 
void handleNotFound();

#endif</code></pre>



<p class="wp-block-paragraph"><strong>networking.cpp</strong></p>



<pre class="wp-block-code"><code>// Colabaration between Boz and various AI's that provides the functionality to 
// connect to and set the clock using a wifi connection and web browser
// All Designs relating to this project are Public Domain.

#include "networking.h"
#include &lt;Arduino.h&gt;

// Access Point settings
const char* ap_ssid = "Bullsi-Clock";
const char* ap_password = "boz"; // actual password not required but add one here if req
IPAddress local_ip(192, 168, 4, 1);
IPAddress gateway(192, 168, 4, 1);
IPAddress subnet(255, 255, 255, 0);

// Create web server on port 80
WebServer server(80);

void handleRoot() // handler for landing page
{
  String html = "&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt;";
  html += "&lt;meta name='viewport' content='width=device-width, initial-scale=1'&gt;";
  html += "&lt;style&gt;";
  html += "body { font-family: Arial, sans-serif; text-align: center; margin: 20px; }";
  html += "h1 { color: #0066cc; font-size: 2em;}"; // Larger heading
  html += ".clock { font-size: 3em; margin: 20px 0; }"; // Larger clock
  html += "button {";
  html += "  background-color: #4CAF50;";
  html += "  color: white;";
  html += "  padding: 15px 30px;"; // Larger button
  html += "  border: none;";
  html += "  cursor: pointer;";
  html += "  font-size: 1.2em;"; // Larger font
  html += "}";
  html += "&lt;/style&gt;";
  html += "&lt;script&gt;";
  html += "function sendCurrentTime() {";
  html += "  const now = new Date();";
  html += "  const hours = now.getHours();";
  html += "  const minutes = now.getMinutes();";
  html += "  const seconds = now.getSeconds();";
  html += "  const year = now.getFullYear();";
  html += "  const month = now.getMonth() + 1;";
  html += "  const day = now.getDate();";
  html += "  const dow = now.getDay() === 0 ? 7 : now.getDay();";
  html += "  const url = `/settime?hours=${hours}&amp;minutes=${minutes}&amp;seconds=${seconds}&amp;year=${year}&amp;month=${month}&amp;day=${day}&amp;dow=${dow}` ;";
  html += "  fetch(url);";
  html += "}";
  html += "&lt;/script&gt;";
  html += "&lt;/head&gt;&lt;body&gt;";
  html += "&lt;h1&gt;Indevin Bulls-i Clock&lt;/h1&gt;";
  // Display current time
  html += "&lt;div class='clock'&gt;";
  html += String(RTChour / 10) + String(RTChour % 10) + ":" + (RTCmin &lt; 10 ? "0" : "") + String(RTCmin);
  html += "&lt;/div&gt;";
  html += "&lt;p&gt;This clock was designed and built by Boz, the author of the original Bulls-i program which ran vintages 2008-2025.&lt;/p&gt;";
  html += "&lt;p&gt;For more info on this device and what he's up to currently, goto &lt;b&gt;rodyne.com&lt;/b&gt; (when you're back on a normal network!)&lt;/p&gt;";
  html += "&lt;p&gt;&lt;button onclick='sendCurrentTime()'&gt;Set Date/Time from this Phone&lt;/button&gt;&lt;/p&gt;";
  html += "&lt;/body&gt;&lt;/html&gt;";
  server.send(200, "text/html", html);  
}

void handleSetTime() // Handler for the settime URL (linked from the SetupWifi() fn)
{
  if (server.hasArg("hours") &amp;&amp; server.hasArg("minutes") &amp;&amp; server.hasArg("seconds") &amp;&amp; server.hasArg("year") &amp;&amp; server.hasArg("month") &amp;&amp; server.hasArg("day") &amp;&amp; server.hasArg("dow")) 
  {
    RTChour = server.arg("hours").toInt();
    RTCmin = server.arg("minutes").toInt();
    RTCsec = server.arg("seconds").toInt();
    RTCyear = server.arg("year").toInt() - 2000;
    RTCmonth = server.arg("month").toInt();
    RTCday = server.arg("day").toInt();
    RTCdow = server.arg("dow").toInt();
    ds1302_setTime(RTCsec, RTCmin, RTChour, RTCday, RTCmonth, RTCyear, RTCdow); // Include dow
    server.send(200, "text/plain", "Date/Time set successfully");
  } 
  else 
    server.send(400, "text/plain", "Something went wrong. (Probably your shitty phone!)");  
}

// Handler for 404 errors
void handleNotFound() 
{
  // Redirect back to the root page
  server.sendHeader("Location", "/");
  server.send(302, "text/plain", "");
}

void initWiFi() 
{
  // Disconnect from any previous WiFi connections
  WiFi.disconnect();
  // Configure access point with static IP
  WiFi.mode(WIFI_AP);
  WiFi.softAPConfig(local_ip, gateway, subnet);
  // Start the access point
  if(WiFi.softAP(ap_ssid)) 
  {
    Serial.println("WiFi Access Point started successfully");
    Serial.print("AP Name: ");
    Serial.println(ap_ssid);
    Serial.print("AP IP address: ");
    Serial.println(WiFi.softAPIP());
  } 
  else 
    Serial.println("Failed to start WiFi Access Point.");
  // Set up the web server page routes
  server.on("/", handleRoot);
  server.on("/settime", handleSetTime);
  server.onNotFound(handleNotFound);
  // Start the web server
  server.begin();
  Serial.println("Web server started");
  Serial.println("Navigate to http://192.168.4.1 in your web browser to set time");
}</code></pre>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
