Skip to main content


Showing posts from 2021

Stealth port exclusions on Windows 10

I guess this is a perfect example of how people get cynical of software updates after going through the routine for awhile. And this is coming from someone who enjoys solving technical problems when he is in the right mood! So recently, I started having some long-running software complain that it can't bind to a certain TCP port because "the port is already in use". I immediately pulled out my trusty CurrPorts and check out which mysterious program is hogging the port behind my back (yeah I could use netstat , but who has time to memorize all those command line arguments, right?) To my surprise, nothing, nadda. No one is using that port. Yet that port is mysteriously barred from use. It's like you suddenly cannot open the door to your home with your existing key. Incredibly frustrating. Anyway, after 2 whole days of research, I finally found the culprit. Apparently after a certain Windows update (1809 or 2004 from various sources, I didn't care to verify), Window

ESPCLOCK4 - Deciding which direction to traverse to catch up with the present time

For more obvious cases eg. clock time is 12:05 and present time is 12:00, we don't have to think too hard to decide which direction to take the second hand to match up the two times. However, suppose the clock time is currently 12:00, and the present time is 6:00. We can move the second hand forward 8x, or backwards 4x. Which direction will result in quicker synchronization of the 2 times? For both directions, the number of seconds to traverse is 6 x 60 x 60 = 21600 seconds. If we take the forward direction, the time taken to traverse half the number of seconds i.e. 10800 is 1350 seconds. However, in that time, the present time would have advanced by the same amount, so the number of seconds left to traverse would be 10800 + 1350 = 12150 seconds. If we do this iteratively, we would find the total time required to achieve synchronization is 3085 seconds, with 4 seconds left to catch up. If we take the reverse direction, the time taken to traverse half would be 10800 / 4 = 2700 secon

ESPCLOCK4 - Dealing with low or removed batteries

One of the requirement of the ESPCLOCK project is to deal with persisting the clock time when the supply batteries run low, or when they are removed for battery change. For previous iterations of the project, a 0.47F supercap was attached to the ATtiny85 to keep it powered it long enough during a cut-off to write the clock time to flash memory. For the ESP32, I found out it is impossible to power the main processor with the supercap, even if WiFi is not activated. It is just too power hungry! However, it is able to keep the ULP powered for 5 to 6 minutes. I found this out by getting the ULP to toggle an output pin and monitoring the output with a logic analyzer. The 0.47F supercap is placed across the 3.3V and GND pins. Power is supplied via the 5V pin. When the supply is pulled, the ULP continues to produce output for a further 5 to 6 minutes. So the strategy I will adopt is this. The ULP will measure the supply voltage via a voltage divider. When the supply voltage drops below a cert

Analog clock torture test

After playing around with things a bit, I find that I am able to run the clock forward at 8x speed (125ms/tick), but only able to do so reliably in reverse at 4x speed (250ms/tick). So here is the "torture test" I have devised. It fastforwards the clock for 60 ticks, then reverse the direction for another 60 ticks. At the end of it, the second hand should return to the original position. By running this in a loop for many hours, I can confirm that there is no slippage for a given set of parameters. The parameters for this particular clock (another $2 clock I picked up from KMart after I accidentally stepped on and broke the Ikea one) are: Forward : 32ms pulse (9ms on, 1ms off) Reverse : 12ms pulse, 12ms wait, 28ms pulse The high-level code to implement the above looks like this: void forward_tick () { for ( int i = 0 ; i < 32 ; i ++ ) { digitalWrite(tickpin, HIGH); delayMicroseconds( 900 ); digitalWrite(tickpin, LOW); delayMicroseconds( 100 ); } tickpin =

Running an analog clock backwards

I didn't think it was possible, but recently I came across this YouTube video and its associated blog post (in Japanese, which I was able to understand thanks to Google Translate): Here's a diagram to contrast the pulses sent to the clock lines to turn the clock backwards, versus driving it forward: As you can see, during the first time step, instead of sending a single positive or negative pulse, you send a short pulse, wait a little, then send a longer pulse in the opposite direction. Then in the next time step, a mirror image of the pulses in the previous time step is sent. The duration of the pulses has to be experimentally determined for different clock motions. For example, I was able to use this follow code to move the second hand on my clock in a reverse motion reliably: int tickpin = 25 ; void rtick () { digitalWrite(tickpin, HIGH); delay( 10 ); digitalWrite(tickpin, LOW); delay( 10 ); tickpin = (tickpin == 25 ? 27 : 25 ); digitalWrite(tickpin, HIGH)

Portable OBDII Memory Saver

Tired of losing ECU and radio memory when I replace the car battery myself, I followed the instructions in this video and made my own ODBII memory saver. The gadget is extremely simple to make. I ordered the ODBII plug and A23 battery holder. The diode could be any small signal diode that you have around the toolbox (I am using 1N4148). Then simply solder: Battery holder GND => pins 4, 5 on OBDII Battery holder VCC => diode (+) Diode (-) => pin 16 on OBDII That's it. Stuff the battery holder into the empty part of the shell and reassemble. I didn't even bother to screw the shell together. You can check by inserting a battery and measuring the voltage across pin 4/5 and pin 16. It should be around 12.6V (for a fresh A23 battery) - 0.4V ~= 12.2V. Anything above 11V should work well enough to keep the ECU and radio memory while inserted. To use, first insert the memory saver into the OBDII port in the car. Then remove the car battery and perform the battery replacement. F

ESP32 D1 Mini with CH9102X UART

I noticed recently that there is a ESP32 D1 Mini board with a CH9102X UART, so I bought one to try. The CH9102X appears to be a Chinese clone of the CP2102 . Unfortunately, I couldn't get it to work. Connected via USB, and at a baudrate of 115200bps, I could only successfully upload a program 2/10 times. Other times, I get the " Failed to connect to ESP32: Timed out waiting for packet header ". I could program it without issue by plugging it into the FTDI programmer. It could deal with an upload speed of 912600bps 100% of the time. I found this webpage that talks about fixing the timeout error by adding a small capacitor between EN and GND , but I don't really have the need to try it because I am going to remove the UART module anyway for the ESPCLOCK4 project. Anyway, I will just stick with the CP2104 UART for future purchases. Update: I found that I could make it work by connecting GPIO0 to GND, and setting an upload speed of no greater than 115200. Terrible.

ESPCLOCK4 - Reduce operating current by removing UART module

The ESP32 Mini uses a CP2104 UART module to drive the USB port.  The CP2104 is configured in self-powered mode, which means that even if nothing is plugged into the USB port and the board is powered by a 3.3V source, it is still drawing ~100uA of current. I wanted to see the effect of removing this module on the power consumption of my test circuit. Removing the UART module means losing access to the USB port. However, I should still be able to program it using a standard FTDI programmer, which I wanted to verify. So I took out the same FTDI programmer that was used for programming the ESP8266, and built a custom holder for the ESP32 Mini. I started with the same connections as used with the ESP8266: ESP32 VIN <-> FTDI 3.3V ESP32 GND <-> FTDI GND ESP32 TX <-> FTDI RX ESP32 RX <-> FTDI TX However, I could not get it to work. After some fiddling around, I discovered I could only get it to work by connecting RX - RX and TX - TX. Not sure why. But now I am confiden

Arduino control of PTX4 remote

I wanted to control the opening and closing of my front gate using the ESP8266. The gate uses a standard PTX4 remote, which is readily available at many hardware stores. To my surprise, I couldn't find a hardware module that I can buy off-the-shelf and interface with the ESP8266. So I bought an extra remote, paired it with the gate receiver and proceeded to take it apart to see how I can use the circuitry inside. SW4 is the button I press to open/close the gate. Points (1) and (2) are the junctions I need to short using a relay to simulate a button press. I measured point (1) to be 12V, so I need a 12V relay for this to work. The one that's readily available to me is SY4032 . Since the operating voltage is 12V, I also need to use a MOSFET (the good ol' 2N7000) to drive the relay. The gate pin needs to be grounded with a resistor, otherwise a spurious signal might be sent to the relay when the MCU is first powered on. Another thing I did was to get rid of the A23 battery by

Link dump: Auto-ranging current measuring instrument for IoT devices

With more research, I am beginning to understand more about burden voltage, the difficulty of measuring the dynamic power draw of a circuit with a wide range of current consumption (a few uA all the way to hundreds of mA), as well as the limitations of the LTC4150 coulomb counter in dealing with this. Here are a list of devices that are designed to do just that, and that are not too expensive (<$200). I hope to acquire one of them to tinker with in the future: Power Profiler Kit 2 RocketLogger BattLab-One mikroAmpMeter

Update: Line adapter for Ozito Blade Trimmer

An update on using ordinary trimmer line for the Ozito battery trimmer. I finally found a super easy and robust way to do so. No need for any  3D-printed adaptor , which is simply not strong enough to withstand the amount of force we are dealing with. You should be able to start immediately with common tools that you already have. These are all the material/tools you need: 2.4mm trimmer line 0.75mm wire (just use any thin wire you have lying around) flat nose plier cutter (or scissors, to cut the trimmer line) Cut off a length of trimmer line about 18cm long and fold in the middle. Cut off a length of wire about 8cm long and wrap around the trimmer line near the top, creating a loop. The wrap should be tight enough to just stop the trimmer lines from sliding, but you should still be able to reduce the size of the loop by pulling on the ends of the line. The orientation of the wire wrap as shown in the photo above is important, because it prevents the wire from slipping off during opera

RBX - Robotics Brick Extension

RBX is a project that I have been working on for some time now. It is a robotics kit designed for young tinkerers. It consists of a set of Lego-compatible "bricks" made with common components, such as LED, pushbutton, servo, motor etc. The brick housings are printed using a 3D printer. The components are hooked up to a microcontroller via standardized "ports". Programming is done via a variant of Javascript (a port of Duktape ) on a browser-based IDE. I started the project because I found that block-based programming environment such as Lego Mindstorm are a little too simple for older kids (8 - 12 year old), yet the long compile-run cycle of Arduino is not suitable for tinkering and quick prototyping. Something that sits in the middle is needed. On the hardware side, one of the first obstacles for a child trying to break into microcontroller programming is hooking up the desired circuitry on a breadboard. Anything beyond the the introductory "Hello World"

ESPCLOCK4 - Monitoring supply voltage via ADC

To monitor the battery pack voltage (4 x AA; max ~6V), I hooked up GPIO32 (maps to ADC1_CHANNEL_4) to a voltage divider consisting of 2 x 10K resistors. This divides the max voltage in half, giving us 3V, which is clear of the max 3.3V input voltage accepted by the ESP32 ADC pins. To initialize the ADC channel so that it can be used by ULP code, this function is used: void init_adc () { adc1_config_width(ADC_WIDTH_BIT_12); adc1_config_channel_atten(ADC1_CHANNEL_4, ADC_ATTEN_DB_11); adc1_ulp_enable(); } I created 2 new RTC_SLOW_MEM variables: enum { ... VDD_ADC, // Supply voltage measured by ADC VDD_LOW, // Low voltage threshold } The ADC reading ranges from 0 to 4095 in a slightly non-linear mapping, so I use this code to figure out the right ADC value for the low voltage threshold for the battery pack (target: 1.05V x 4 = 4.2V). #define SUPPLY_VLOW (1050*4) // 4 x 1.05V // Map given ADC value to corresponding voltage uint32_t adc_to_voltage ( uin

ESPCLOCK4 - A Simpler Reset Module

In ESPCLOCK3, the following reset circuitry was used: This generates a short low pulse for the RST pin on the ESP8266 even if the switch is held down, so that the program can read the switch pin after reset. If it it found that the switch is still held down, it can perform a factory reset. In the ESPCLOCK4, I wanted to try a software-only approach with the ULP. The main idea is the ULP will check the switch (with a little software debounce processing). If it finds the switch depressed, it will wake the main processor, which will then perform a software reset.  This means we will only need a single pushbutton, with one end connected to an input pin (pulled up), and the other end connected to GND. No need for additional resistors/capacitors. I connect the reset button to GPIO4/GND, and add the following definitions: #define RESETBTN_PIN RTCIO_GPIO4_CHANNEL #define RESETBTN_PIN_GPIO GPIO_NUM_4 #define WAKE_RESET_BUTTON 1 The following code is added to init_gpio()

ESPCLOCK4 - A Rethink On Tick Pulse Generation

Having dabbled recently with PWM (Pulse Width Modulation) for motor control, it struck me that maybe the same technique can be applied for pulsing the Lavet stepper motor in the analog clock. Just a recap. The Lavet stepper motor within the analog clock is design to function at ~1.5V. However, the output on the ESP8266 and ESP32 is 3.3V, and in ESPCLOCK3, the ATtiny85 is powered at ~3V. For reasons I don't fully understand, the pulse width needs to be as long as 100ms in this case, otherwise the clock will not tick reliably. This also leads to high power draw, because higher voltage + longer pulse width. In contrast, the original clock signal is 32ms pulse width at ~1.5V (which can go as low as ~1.1V since it is running on a normal AA battery). So in ESPCLOCK3 , a diode bridge is introduced, where 2 diodes in each direction drops the 3V output by the ATtiny85 down to ~1.8V (3V - 0.6V x 2), which worked remarkably well in reducing the power draw and making the clock tick with 100% r

ESPCLOCK4 - Generating Tick Pulses

Hardware I settled on the ESP32 Mini for this project: A couple of reasons why I chose this board: - It has a much smaller form factor than the canonical ESP32 dev board , yet have a good number of pins exposed through its double-row header layout.  - It is one of the cheaper ESP32 dev boards. I got mine for ~A$6 (including shipping) on AliExpress . Generating Tick Pulses using the ULP The platformio.ini file looks like this: [platformio] default_envs = wemos_d1_mini32 [env:wemos_d1_mini32] platform = espressif32 framework = arduino platform_packages = framework-arduinoespressif32 @ board = wemos_d1_mini32 upload_speed = 912600 monitor_speed = 115200 Here's the test code: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 6

ESPCLOCK4 - Design

The idea for ESPCLOCK4 came after encountering  this article . It made me realize the successor to the ESP8266 - the ESP32 - has an ultra low power (ULP) coprocessor that can perform simple processing eg. toggle pins, read ADC etc. while the power hungry main CPU is in deep sleep.  After reading through the specs, it seems the ULP can substitute for the ATtiny85 in the ESPCLOCK3 design. The advantage is that the I2C bus is not longer required, and the circuitry can be vastly simplified.  Just like the watchdog timer on the ATtiny85, it appears the real-time clock (RTC) that drives the ULP is not very accurate (5% jitter). However, I think I can use the same calibration technique employed to adjust OCR1A on the ATtiny85 in the ESPCLOCK2 design to dynamically tune the RTC. Basically, by using the difference between the computed network time and actual network time, the RTC counter can be increased or decreased accordingly. So here's the preliminary design. The ESP32 will again ser


Here are the latest changes to the ESPCLOCK3 project. Migration to PlatformIO I have moved to PlatformIO for new projects, and migrated some of my older projects to PlatformIO as well. PlatformIO offers a lot of advantages over the Arduino IDE, including: Intellisense quick info and code completion Easy to target specific library versions in platform.ini Easy to have multiple targets in the same project. For ESPCLOCK, this means target for ESP8266 and ATtiny85 in the same project. There are minor pitfalls though. For example, to set fuse settings for ATtiny85 (eg. 1MHz clock, retain EEPROM, disable BOD), they have to be manually computed and added to platform.ini . This was not very intuitive and took me some time to figure out. Dealing with low battery In the original design, the ATtiny85 checks the VCC voltage level and writes vital info to EEPROM when voltage falls below 2.8V.  The problem is, the discharge characteristics of NiMH battery is such that it operates at ~1.2V for most o