April 13, 2022

Umina Heights

I don't know how it came up, but one day I was checking if www.uminaheights.com was available, and it was. Now that I registered it, what to do with it?

I bring you Umina Heights, a services directory for Umina Beach on the NSW Central Coast.

Is this site just a magnet for advertising though? Possibly.

June 03, 2021

Peninsula Lighthouse

I have been helping with the new web site for Peninsula Lighthouse. Peninsula Lighthouse operates in Ettalong NSW, and provides support services for families dealing with domestic violence.

Great work Natasha!

November 30, 2020

Problem with your internet security

So I am aware of this scam because I have heard it before, but not everyone has. If you are familiar with the scam you are less likely to be caught by it. Also the scammer's cost is their time. I talked to them for 21 minutes and 30 seconds before I got bored.

09:36 The call starts with a recorded message (female voice, Australian accent) saying it is Telstra, and your IP address has had its security system compromised. Press 1 to talk to a technician.

Your internet service provider won't cold call you with a recorded message. Also I'm not a Telstra customer. This is the first warning that it's not real. They want the call to sound scary and urgent so that you'll do something.

I always dial 1 (unless I'm in a hurry).

09:37 I'm put through to a person with an accent. He launches into a pitch about how he is from Telstra and there is a problem with my security system and my IP address. How do you know the caller is really from Telstra? What if the caller wasn't?

I interrupt to say that I don't know what an IP address is. He says that suspicious traffic was detected coming from my IP. I tell him that I don't know what that means. Is it something to do with intellectual property? Oh it seems this is internet protocol. He wants it to sound technical, so that I'll think he knows what he's talking about. A scam requires you to trust the scammer.

09:38 He asks if my computer is connected to the internet. I play dumb and say that I think I have internet on my phone. He asks if I have a computer. I say yes. He asks if it is connected to the internet. I say I don't know. Scammers depend on you not really understanding.

09:39 He asks if I ever shared my wifi password. I tell him I don't know what that means. This is an effort to improve his credibility. Of course, don't go telling people your wifi password, but if you get hacked, it is most likely because of a virus or trojan installed on your PC, rather than someone using your wifi. At this point he puts me through to his supervisor.

09:40 I tell him that I'm concerned that if my internet is not secure, isn't it risky for me to let him look at stuff? Won't this just help the criminals? He says that these criminals have got into my internet connection. They are "overseas people". Practically it is likely that the scammer is calling from "overseas" where it would make it hard for Australian authorities to prosecute him.

09:42 I repeat my question. If the "overseas people" can get into my internet connection, shouldn't I just shut it down, not grant access to someone who just called me out of the blue. He assures me that we will lay a trap for the "overseas people" and to them, it will seem like my laptop is off.

09:43 He asks if I have a Windows or Apple Mac computer. I say I don't know, but it says "MacBook Pro" on the front. The scam is about trying to install software on my computer so that later they can do things like install ransomware, or steal personal data from me, so they want to know what kind of computer I have so they know how to attack it.

He asks me to open up Safari. I say I don't know what that is.

He asks me to open up Google Chrome. I say I don't know what that is. At this point he asks what I use the computer for. I say to play games, and to write letters to people.

09:45 He says to hover my mouse over the icons. Oh I see Google Chrome now! He says to open it. I say oh it came up with Facebook. Oh yeah I remember. I use this for Facebook.

He explains how to type in a web site www. Yes got that. Team Viewer. Is there a space? Oh no space. Yes OK got it. Now . and c o m. Oh yes .com I have heard of that. Team Viewer is a legitimate site that allows remote support. Scammers get you to run this to give them access to your computer.

09:46 Click enter. OK I read out the site to him. Sounds good. OK click the download link. I said I see "Windows" "Mac" "Line-ux" "Chrome OS". Oh "Chrome" is the one you said before. Should I click on that? No click in Mac it seems.

I said I got an error.

He asks what the error was. I said something about internet security.

He asks me to read it out, but I said sorry I already closed it. I'll need to go back. What was the site again? Team Security?

09:48 I click on the privacy policy link (next to the download link). He asks if the file downloaded. I read out the privacy policy to him. (He is very patient!) I tell him that maybe I clicked wrong.

09:50 I tell him I'm a bit concerned that I'm not actually a Telstra customer. This is a red flag. This should alert me that something is not right. He says that Telstra are the main internet service provider, and all other internet goes through them, so that is normal. Is that true? How could you make sure? You could hang up at this point, and call your internet service provider to double check.

09:52 He tells me that once I install the application it will say it is connected to Telstra's secure server. Think about it. This caller could be anyone. Anyone could make an app that says "You are connected to Telstra's secure server" and it means nothing.

I say I can't see the download (I didn't actually download anything. Don't download stuff that a stranger says to download!) He says to look in the top right corner and see if there is an arrow. I say that the top right corner has the date and time, and it says my batter is 100%. He asks if I see teamviewer.dmg. I say I don't see it.

He says check in the bottom left corner. I say I see icons in the bottom left, and one that looks like the Mac smiley face.

09:55 He says to hold down the control key (and talks me through how to find it). I say OK it's down. He says to press J at the same time. I'm not sure what this is supposed to do, but it doesn't do anything.

09:57 He's still trying to trouble shoot why team viewer didn't download.

I tell him that I need to go now, but that I think his company is dishonest for trying to scam people, and he shouldn't work for them.


August 30, 2020

Configuring Home Assistant for the Aeotec Z-Wave Stick

In theory Home Assistant's native support for Z-Wave is quite good. Plug and play.

In practice, not quite.

Start here of course: https://www.home-assistant.io/docs/z-wave/

Note: Make sure you follow the steps about configuring a network key if you want to add secure devices (which I do).

Home Assistant installs the required Python modules at runtime when you modify your configuration, so in theory there is nothing to install. It's just a bit slower at start up the very first time.

Unfortunately I had problems pretty quickly. The logs show that the openzwave module failed to install.

The solution was to install a required system library that was missing on my Ubuntu server system: libudev-dev. Details at https://community.home-assistant.io/t/aeon-labs-z-stick-gen5-on-hassbian/31687

The next problem, although obvious now, was that my homeassistant user didn't have permission to access the USB device. Add the user to the dialout group, but of course, that only works for new login shells. If Home Assistant runs via systemd, better to just reboot!

Now I see the Z-Wave section in my configuration screen.


If I go in there I only see 1 device (the USB stick). Here is the information screen.


It seems that HA lies about its zwave plus capabilities, and also the baud rate. Anyway, looks good.

The electrician is coming tomorrow morning.

Planning for Home Automation - lighting edition

I'm planning on connecting up the lighting in my flat to my home automation system. At my previous place I was renting, and I had normal BC bulbs, so smart bulbs was a good choice then.

Now that I'm not renting, I have more freedom, but also my lighting uses LED modules, so you can't just screw in a smart bulb. I have decided to go with a Z-Wave solution. It is a wireless solution that uses a mesh network. The standard guarantees compatibility between parts, and also it integrates well with my existing home automation system Home Assistant.

In choosing to go with Z-Wave, compatibility with Home Assistant was important (although it does support most things), as was the ability to have the system operate even if not connected to the internet. Note that Z-Wave is not cheap, but once you exclude solutions that are not approved for connection to Australian mains wiring, some of the cheaper options are ruled out already.

The first step in planning was to look at what lighting circuits I have, and what I need.


I have about 10 lighting circuits in total. A couple of those I won't connect up to home automation, such as the light in my bathroom, and the light in my laundry.

My existing switches are Clipsal C2000 rocker switches. While you can use rocker switches, I am going to swap these out for "bell press" switches.

I have one circuit that has a 2-way switch. One of those switches is next to the front door, and it would be really handy to have an automation rule that lets you use the front door switch to turn off everything. My research showed that common Z-Wave lighting controllers have 2 switch inputs, which would allow you to wire up the 2 existing switches to the same module, and have them do slightly different things.

The next step was to get an electrician. A friend recommended Ryan from It's On. He wanted to come and take a look first, to make sure he was happy that my project would be able to be done to completion. Apart from my 2-way switch concern, I wanted to check that the control modules would fit in the wall cavity (behind the switch). I 3D printed some mock-ups of common brands of controller so we could check. (You can download the designs at https://www.thingiverse.com/thing:4560264 )

All good. Ryan is happy to proceed.

The next step was to order the parts I needed. I ended up going with Oz Smart Things. They are local, and their prices are quite competitive. They have Clipsal bell press switches that match my existing switch plates. I ordered 6 Aeotec dimmers, and 1 Aeotec switch (my balcony light doesn't need dimming). For circuits with less than about 20W of load, Aeotec recommends a dimmer bypass, so I ordered a couple of those for my hallway circuits (that have only 1 x 10W LED module). Also Calum at Oz Smart Things has been really helpful with answering questions.

I'm going to use the Aeotec USB stick connected to my Intel NUC server to control everything. It supports secure devices.


So good when everything arrives!

The next step is to make sure everything works on the software side, so that I don't have any setup issues once we start to install them.



April 25, 2020

Toilet roll roller

This week someone kindly left a box of industrial sized toilet rolls in our building's foyer for people to take. The large size roll isn't going to fit in my bathroom, but maybe I can improvise something. Hey it was free!

My first thought was maybe I can wind some onto an empty roll. Perhaps there is a way to fit the roll to my drill to help wind.






While it looks broadly feasible, the fit is not good enough. Maybe I could make some kind of roll holder that attaches to the drill, and fits inside the cardboard roll to help roll it. At this point I'm thinking of just doing the minimum to get something working.

I have plenty of time at home at the moment, what with COVID-19 and isolation. Captain Over Engineering to the rescue. Why not just 3D print the roll itself, along with an attachment for the drill. I sketched it up to help with my thinking.


Maybe slots in the roll, and some kind of spoke things in the drill attachment. I made a design in OpenSCAD and printed a proof of concept.





It seems broadly feasible. My roll was a bit too thin, but the fit between the parts is good. Not too loose. Time to print the design at full size. A toilet roll is 10cm long, and 4cm in diameter.





With the roll a bit thicker (and so stiffer), the fit was tighter. I needed to sand the joints a bit.

I needed a way to spool the paper off the large roll easily. Luckily I still had some metal piping left over from my towel rail project. Add some chairs, and I'm in business.





Now it's winding time. I wondered how easy it would be to wind consistently. The tension is a bit tricky, but I didn't have any problems with side-to-side movement.





Cut the paper, and I have a bathroom-sized roll.





Now the end cap detaches until I'm ready for my next refill.





If you would like to print one yourself, the STL files (and the OpenSCAD source) are on Thingiverse at https://www.thingiverse.com/thing:4309439

March 09, 2020

Adding a second towel rail in the bathroom

My bathroom only has one towel rail. That's fine when there is only one person living here, but a bit inconvenient when there are two.

The company that makes the bathroom fittings do make a double towel rail, and you could probably get one for around $100. The down side is that they are very hard to find, and also the length is slightly different to the existing one. Once you had paid a tradesperson to tidy up the wall where they removed the old one, it is not going to be a quick job.

Enter the towel rail extension.


This is a bracket that attaches to the existing towel rail and allows you to attach a second one.

First you'll need a second rail that's similar to the first one.

This cost me $5.49 at Bunnings for a 900x19mm rail.

My existing rail is only 600mm so I needed to cut it to fit. This leaves a tube with open ends, so I designed and 3D printed some black end caps.


I worked out the angles and the rough design on paper, and then built it in OpenSCAD. I made the sizes customisable, so if you don't have the exact same diameter of tubing you can easily adjust it. The mock up in OpenSCAD looks like this.


I designed screw holes to put it together, and then I split the bracket into 3 pieces.


There's a piece that rests against the wall to hold the second rail in place. With the first 2 pieces attached it looks like this.


You can see the detail of how it is screwed together.


Now with 2 brackets in place I can fit my second rail and screw on the end pieces.


Works nicely.

If you are interested in making one you can see the design on Thingiverse.

Things I would do differently next time:
  • The angle is still not quite right. Making the wall pieces slightly shorter would work better.
  • I could incorporate an end cap into the bracket itself, rather than making it a ring around the second rail. That makes cutting the second rail to size more tricky though.
  • The bracket fits the existing rail just slightly too loosely. I would probably make it 0.5mm smaller, but it's close enough.


April 21, 2019

ePaper to display weather information


This project was to use an ePaper display to display weather information in my lounge room. Really it was an experiment to see what you could do with ePaper, because the ePaper module was an impulse buy while looking around Waveshare's web site.

The display module is a 4.2" monochrome display. Given I wanted this to connect by WiFi, it made sense to use their ESP8266 based driver board.

After connecting up the display to the driver, I powered it on to see the test mode. That seemed to work OK so I tried some code to display the current time.


You cannot really see from the photo, but the display is very thin. Thinner than LCD.

I had thought about designing and 3D printing a case for the display, but that's a bit above my Blender/OpenSCAD skill level. There are a couple of cool cases for similar boards on Thingiverse though.

In the end I repurposed a 6x4" photo frame. I cut a mask out of paper (just as a test), and it kind of looks OK.

The final version of the code has the time and date in the top left; the weather conditions in the centre left; the network status on the bottom left; and then the indoor and outdoor temperature on the right. You can see the source code (along with details on how it gets the temperature updates) at GitHubhttps://github.com/eb3nezer/mqtt_epaper

So of course now I have a photo frame with a micro-controller hanging out the back. I had a look around to see if anyone had designed a suitable case, but didn't see anything, so I ended up designing one myself.

I went through a few prototypes:


This is the final model:



The screw holes allow it to be mounted onto the stand of the photo frame:



If you are interested, the design for the case is available at https://www.thingiverse.com/thing:3576172

April 10, 2019

WiFi controlled fan - build

Warning: Home appliances have high voltages inside. Danger. Don't attempt a project like this unless you know what you're doing, and take appropriate safety precautions.

See also:
Inside of fan
In the picture above you can see the inside of the fan. Important components:
  • Rotary switch that used to control power to the motor windings (top left)
  • Capacitor to help motor start (black rectangle in top left)
  • Fan motor (behind the fan in the centre - the wires for the motor run up from the fan, obscured by the blade in this picture)
  • AC power cord (bottom)
  • 5V power supply (black rectangle in bottom left - 5V side not yet connected in this picture)
  • Relay board (top right)
  • NodeMCU board soldered to protoboard (bottom right - not yet connected to power supply or rotary switch)
Originally the capacitor was in the top right, but I needed to move it somewhere to make space.

Starter capacitor

This fan also had a mechanical timer switch in the top left. You could turn this, and it would supply power for (say) 30 minutes, and then disconnect the power.

Clockwork timer switch

I figured given this will be run by my home automation system I didn't need a clockwork timer any more, so maybe I could remove it, and move the capacitor there.

Out with the dremel tool. You know you're committed once you start chopping up appliances that were previously fully functional!


With the timer gone, now there was plenty of space to move the capacitor there. Fortunately the capacitor had a long-ish cable.

I needed to figure out how the existing wiring harness connected, plus I knew I would need to get AC power from somewhere. It was time to investigate what was behind these insulation bundles.


Removing the cable tie and the insulation revealed some crimp connectors.


Here brown is active and blue is neutral. I need to patch some wires in here to take AC power for my 5V power supply, so I'm going to need to take those connectors off.

I had a look in my tool box to see if I had any to replace them with, but I don't. Generally I don't trust crimp connectors, and so I solder them anyway. I added my wires to get an AC feed for my power supply, soldered the joins together, added heat shrink, and then put them back in their insulation bundle.

Then the other ends of those wires I added go to the AC in terminals of the 5V power supply.


Again covered with heat shrink, as I don't want any live wires hanging around. Make sure you don't solder to the wrong side of the power supply!

Here is the power supply back inside the fan.


It is loose for the moment, but I will hot glue it into the corner later.


Here you can see how the back of the rotary switch was connected. The connector on the bottom is the input (AC active), and the top 3 connectors are for the 3 different speeds. I tested which colour is connected for which speed so that I know how to wire up the relay outputs later.

The active wire previously connected first to the clockwork timer, and then to the rotary speed switch. With the timer removed I just joined the wires up in its place and put heat shrink over the join.


Now instead of the rotary speed switch, the active wire needs to go to the relay board to be switched on to each of the motor windings.


Here the active wire connects to the common terminal of the first relay, and then to the common terminals of each of the other relays.

The wires from the rotary switch to the motor were not quite long enough, so I needed to extend them, and then cover the join with heat shrink.


I had to buy a hair dryer for the heat shrink. I keep the hair dryer in the bathroom, but I should keep it in the tool cupboard, because I only ever use it for heat shrink.

Now to connect the motor wires to the relays.


Below the relays you can see the opt-isolators, diodes (to protect from back-current) and indicator LEDs.

The black wire goes to the oscillator motor, and then red for high speed, white for medium speed, and blue for low speed.

At this point all my AC wires are connected and insulated. (OK only mostly insulated. More on that later.)

Now it's time to connect up the low voltage logic wiring. I attached the NodeMCU board to some proto board. Although not necessary, I find this useful in terms of soldering.


Here you see red and black on the right to connect to +3.3V/0V for the relay board, and 4 wires for each of the logic level inputs to the board. (One each for oscillate, low, medium and high.)

Now to connect the other ends of the wires to the terminals on the relay board.


The relay board has screw terminals. The high voltage side was fine, but I kept having problems with the low voltage wires falling out. I ended up tinning the ends of the wires with solder, and this helped them stay in the screw terminals more securely.

I don't have the 5V power supply or the speed switch connected up yet, but it's probably worth doing a test to see that everything connects, and that I can still control the relays from inside Home Assistant. Prior to this I only tested the design on a breadboard.


While all my connectors are insulated, the underside of the relay board has exposed connectors from the through-hole components. Although I'm not connecting the AC here, I don't want any short circuits, so I improvised with some paper. (For the finished product I have some electrical insulation tape covering the under side of the relay board, with a layer of insulating foam covering that.)

At power on I get a power light on the relay board. So far so good.

The WiFi connect sequence for my code does a slow flash of the onboard LED while it connects to WiFi, and then quick flash while it logs in to MQTT. Once connected OK the LED goes off. All goes according to plan.

Now to test from Home Assistant. Power on, low power, and the low power relay clicks on! A test of the speed and oscillate combinations shows that the relays are working as expected!

Now to complete the wiring, I soldered wires to the 5V out of the power supply, and connected them to Vin and Ground on the MCU. Note that the NodeMCU board has an on-board voltage regulator, so a supply of more than 3.3V is OK for the Vin pins.

This is how the rotary switch looks.


The red wire goes to +3.3V, which connects to the terminal for high speed. Then a 1k resistor between high and medium, 1k between medium and low. There is actually another 1k resistor between the low terminal and the black wire, but it is hidden inside the heat shrink. I needed the voltage for low to be different to the voltage for off, so I didn't want low to connect directly to 0V. The orange wire connects to the "rotor" of the switch, which connects to the analog pin on the MCU.

Thus the resistors act as a voltage divider. The voltage on high speed is close to 3.3V, with less for medium, and less for low. I checked what reading the ESP8266 reads for each setting so that the code can determine where you positioned the switch, and if you changed it. Note that the ESP8266 itself wants a voltage between 0 and 1V for the analog pin, but the NodeMCU board lets you supply a voltage between 0 and 3.3V. This is handy, as the supply voltage is 3.3V.

You know what? I think I'm ready. Screw it all back together, for a test.

Be careful with AC wiring! We stood clear, turned on the power, and prepared for the release of magic smoke. With the smoke retained, I went to Home Assistant to try to get some airflow.


Thanks heaps to my assistant, and to the maker community at my workplace.

April 07, 2019

Wifi controlled fan - Design

A word of warning: If you proceed with making this project yourself, you run the risk of electrocuting yourself and dying. Fan motors use high voltages inside. More than enough to give you a serious shock.

See my previous post on what I'm trying to do, and why I chose this kind of fan.

My prototype circuit uses a NodeMCU ESP8266 board, and a 4-way 3.3V relay board to control the fans. The relay board should be able to safely switch the AC voltage your fan uses. (240V in my case.)

The MCU connects to the 3.3V relay board. The inputs for each of the relays connect to one of the digital data pins on the MCU. When the MCU sets that pin to high, the relay turns on. When the MCU sets that pin to low, the relay turns off. The relays will act in place of the original switch on the fan. Instead of sending power to the appropriate motor winding by turning the knob on the fan, the MCU will turn on the relay that connects to that motor winding.

My fan also has a switch for a little motor that makes the louvres on the front of the fan rotate, so I use the 4th relay to turn this motor on or off.

The fan is designed to work with my home automation system. I use Home Assistant, which includes an MQTT message bus. The code will connect to my MQTT bus and listen for updates, changing the relays as appropriate. Home Assistant provides a fan component that can send messages on MQTT to appropriate topics depending on the features of your fan. My code is written to support a fan that has 3 speeds ("high", "medium" and "low"), that can turn on and off (obviously), and that can turn the "oscillate" motor on and off.

My fan uses a 4-way rotary switch. (One of those settings is off, where it doesn't connect to anything.) My circuit diagram above shows 3 switches. How this actually connects will depend on what kind of switch your fan has, but you could mock up something on a breadboard to prototype.

Some fans have push buttons, where pushing one button in pops out any other button that was previously pushed in. In this case there are generally 4 buttons, where 3 of them connect to the 3 motor windings and the 4th button connects to nothing (for off).

The theory seems sound, so I ordered some parts.

These things are cheap and commonly available, but for the sake of illustration I have used Ali Express links.

I wired this up on a breadboard to test. Note that in this picture the speed control switch wasn't connected, so no 1k resistors.

The relay board needs +3.3V and ground from the MCU. I then connected the input lines on the relay board to digital output pins on the MCU. (If you were using an MCU based on a 5V system, like an Arduino, you could use a relay board that needed 5V, which are also readily available.)



Note that although the ESP8266 module runs on 3.3V, the NodeMCU board has an onboard voltage regulator. You can power the board from up to 12V pretty safely. I used a 5V power supply, knowing that this would work fine.

While prototyping I just powered the board from the micro-USB connector connected to the PC.

My ESP8266 code is available under a GPL 3.0 license. You can see it here: https://github.com/eb3nezer/mqtt-fan

Check out the README.md in the code to see what configuration changes you might need to make, depending on how you wire up your circuit. It also describes how the code will set up as a WiFi access point initially to let you complete the rest of the configuration via your web browser.

This is designed to work with Home Assistant, and so you need to add the fan component to Home Assistant. The configuration looks like:

fan:
  - platform: mqtt
    state_topic: "ha/boxfan/on/state"
    command_topic: "ha/boxfan/on/set"
    oscillation_state_topic: "ha/boxfan/osc/state"
    oscillation_command_topic: "ha/boxfan/osc/set"
    speed_state_topic: "ha/boxfan/speed/state"
    speed_command_topic: "ha/boxfan/speed/set"
    name: Box Fan

Note that the topics you configure in Home Assistant should match the topics you set in the web UI for the fan's access point.

Once installed in Home Assistant the control looks like this;


If you don't include the oscillation topics, then Home Assistant won't give you a control to turn oscillate on/off.

Time to test. Power on turns on the "high" relay. Change the speed to medium turns off the "high" relay, and turns on the "medium" relay. Turn on the Oscillate switch, and the oscillate relay turns on. Power off turns off all relays.

Success! Time to cut up a fan!

WiFi controlled fan - Options

My quest (spoiler: ultimately successful) to smart-ify a pedestal or box fan.

Spoiler: The finished product

Overview

I have a Xiaomi smart socket that could turn my fan on or off at the wall, and to be honest that's quite useful, but I wanted more. I wanted to be able to control the speed remotely as well. Fans are not that complicated right? It should be easy enough to modify the internals of a fan to support this.

My list of requirements:

  • The solution must work with a fan that is domestically available, and ideally not too expensive.
  • I need to be able to turn it on and off remotely, as well as control the speed remotely.
  • It should integrate with Home Assistant.
  • Ideally the existing controls on the fan should also work, so it can be controlled manually or remotely.
The first phase of this project was to find out how the speeds of these fans are normally controlled, and how they might be controlled by a micro-controller.

Pulse Width Modulation (PWM) for DC

For a fan that uses a DC motor, PWM might be a good solution. I'm planning on some kind of ESP8266 module as the MCU, and a circuit using the ESP8266's PWM output to switch a suitable MOSFET should work nicely. (I have used this approach for LED lighting in the past.)

While I'm sure they do exist, I looked around for a cheap fan with a DC motor, but didn't find one. I suspect this is partly because fans with 3-speed AC motors are cheap, very common, and they do the job.

If I were to find one, I would still like to build this kind of control. Your maximum speed is when your PWM is at 100% duty cycle. You'd need to do some testing to find out what your minimum duty cycle is for the fan you have. Below a certain minimum and you won't have enough torque to get it started.

PWM for AC

Dimmer circuits often use PWM, but you can't just vary the duty cycle at the 3kHz that your MCU supports. You need to vary it in phase with the AC (50 or 60 Hz). It is possible to get triacs that can switch higher AC voltages (240V for me).

I did explore this option a bit, but there were a few show stoppers for me:
  • Motors that have windings that suit this kind of control are not commonly used in cheap desktop cooling fans. (Common in ceiling fans though.)
  • In order to vary the duty cycle in phase, you need a circuit to detect when the voltage crosses zero, so you know when to turn your triac on and off. This is not such a complex circuit, but there's a high voltage side to this circuit, so a bit of extra care is involved. The former point was more of a problem really.

An AC motor with distinct windings

These kinds of motors are very common. The fan has a concrete number of speeds (generally 3). Each speed has its own winding inside the motor. The switch (or knob) selects which winding to supply power to.

Fan Motor Windings: Gene Haynes http://waterheatertimer.org/How-to-wire-3-speed-fan-switch.html
What if I swap out the speed switch for a set of relays (controlled by the MCU)? The relays would switch power to the windings. Then if I wire up the original switch as a voltage divider, I can get the MCU to detect the switch position by measuring the voltage. Thus the MCU can change the speed if someone moves the switch.

Sounds like a plan.