Skip to main content


Showing posts from March, 2021

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

Sweeping Analog Clock Analysis

The subject of this analysis is the $2 Ikea Stomma wall clock. Unlike the Rusch wall clock that had been the object of my experimentation all along, this clock uses a sweeping clock mechanism, which means the second hand appears to move continuously instead of every second. This also means it is quieter and does not produce the familiar tick-tock sound. Note: Both clocks appear to have been discontinued at the time of writing. There is only one $2 clock on sale at their website now, which is the Tromma clock . I don't particularly like this clock, because the second hand is missing, which makes it difficult to tell if the clock is working at any instant. The hacking process of the Stomma clock is quite similar to that of the Rusch clock , so no suprises there.  Remove front plastic cover Remove hour, minute and second hands Remove clock mechanism Open up clock mechanism. As before, keep the spindle side up helps keep the gear formation in one piece. Solder 2 wires to the solder p