Tuesday, 21 February 2017

Attiny85 timer programming using Timer1

This Arduino sketch uses Timer1 to drive the LED blinker:

 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
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>

bool timer1 = false, led = true;

// Interrupt service routine for timer1
ISR(TIMER1_COMPA_vect)
{
  timer1 = true;
}

void setup() {

  // Setup output pins
  pinMode(1, OUTPUT);
  
  // Turn off unused modules to save power
  ADCSRA &= ~(1<<ADEN); // Disable ADC so that we can shut it down
  PRR = 1<<PRUSI | 1<<PRADC; // Shutdown USI and ADC to save power
  set_sleep_mode(SLEEP_MODE_IDLE);

  // Setup timer1 to interrupt every second
  TCCR1 = 0; // Stop timer
  TCNT1 = 0; // Zero timer
  GTCCR = _BV(PSR1); // Reset prescaler
  OCR1A = 243; // T = prescaler / 1MHz = 0.004096s; OCR1A = (1s/T) - 1 = 243
  OCR1C = 243; // Set to same value to reset timer1 to 0 after a compare match
  TIMSK = _BV(OCIE1A); // Interrupt on compare match with OCR1A
  // Start timer in CTC mode; prescaler = 4096; 
  TCCR1 = _BV(CTC1) | _BV(CS13) | _BV(CS12) | _BV(CS11);
  sei();
}

void loop() {
  if (timer1) {
    timer1 = false;
    digitalWrite(1, led ? HIGH : LOW);
    led = !led;
  }
  sleep_enable();
  sleep_cpu(); // CPU goes to sleep here; will be woken up by timer1 interrupt
}

The internal RC oscillator can have a factory variance of up to 10%. I observe that my blinker pulsed slightly faster than 1Hz.

Thankfully, unlike the watchdog oscillator, the internal RC oscillator can be calibrated by using the OSCCAL register, or adjusting the value of OCR1A. I believe it should not be too difficult to automatically calibrate the oscillator between NTP calls by taking the difference in actual time and clock time (in seconds) and adjust OCR1A accordingly to get as close to 1Hz as possible.

So on initial startup, the ESPCLOCK may not be pulsing at 1Hz, but after 15 or 30 minutes, it should be fully calibrated.

The downside with this approach is we can only use SLEEP_MODE_IDLE to keep Timer1 running during sleep, which is not as power efficient  as using the Watchdog Timer.

Monday, 20 February 2017

ATtiny85 timer programming using the Watchdog Timer

This Arduino sketch uses the watchdog timer on the ATtiny85 to interrupt every second to pulse the LED:

 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
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>

bool led = true;

void setup() {
  // Misc setup
  pinMode(1, OUTPUT);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);

  // Setup watchdog timer to interrupt every second
  MCUSR &= ~_BV(WDRF);
  WDTCR |= (_BV(WDCE) | _BV(WDE));
  WDTCR = _BV(WDP1) | _BV(WDP2);
  WDTCR |= _BV(WDIE);
  sei();
}

ISR(WDT_vect) {
  sleep_disable();
  digitalWrite(1, led ? HIGH : LOW);
  led = !led;
  // Execution continues in loop()
}

void loop() {
  sleep_enable();
  sleep_cpu(); // MCU goes to sleep here; wake up by watchdog timer interrupt
}

The advantage of this approach is I can use the SLEEP_MODE_PWR_DOWN mode to put the MCU to sleep to save the maximum amount of power when there is nothing to be done. The watchdog timer clocks on its own 128kHz oscillator, and can be setup to wake the MCU every second via an interrupt, something that cannot be done using Timer0 or Timer1.

Unfortunately, it appears the 128kHz oscillator  is not terribly accurate and can range between between 96 and 119kHz. In my test, the LED pulsed slightly slower than 1Hz, and start losing track after about 15 second ticks. There is also no way to calibrate the watchdog timer oscillator as far as I can tell.


Thursday, 16 February 2017

Test programming the ATtiny85

Just got my ATtiny85 chip today from the postman and playing with it now.

There are quite a number of ways to program the ATtiny85, from the very cheap (USBasp, Tiny AVR Programmer, USBtinyISP) to the more expensive (AVRISP mkII). The Tiny AVR Programmer is probably the most convenient of the lot because it targets the ATtiny family specifically, so no cables are required. Just plug the chip into the provided socket.

Since I already have a spare Arduino Uno lying around, I am going the no-cost way, using the Uno to program the ATtiny85. You basically need to hook up the Uno to the ATtiny85 on a breadboard via 6 jumper wires. It's actually easier than it sounds, and took all of a couple of minutes to do.

Arduino Uno ➜ ATtiny85
   5V           Vcc
   Gnd          Gnd
   Pin 13       Pin 2
   Pin 12       Pin 1
   Pin 11       Pin 0
   Pin 10       Reset


The breadboard looks like this:


Configuring the Uno to become an ISP


The next step is crucial. You need to upload a sketch to the Uno so that it has the necessary code to become an ISP. That's how you can then program the ATtiny85 through the Uno.

The first step is to load the ArduinoISP sketch from the built-in examples:


Make sure you have the board type selected as "Arduino Uno"


Now click "Sketch, Upload" and the upload should be completed without errors.

Installing ATtiny85 support


Under "File, Preferences", in the "Additional Boards Manager URLs" field, add this URL: https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json


Then under "Tools, Board. Boards Manager...", type in "attiny" in the Filter field. You should see "attiny by David A. Mellis". Select and install.


Now that we have ATtiny85 support, under "Tools, Board", scroll to the end of the menu and select "Attiny 25/45/85".


Under "Tools, Processor", select "ATtiny85".

 
Under "Tools, Programmer", select "Arduino as ISP".


We are now ready to program the ATtiny85! Open up the sample "Blink" sketch:


 Change all references of LED_BUILTIN to 1. So the code looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(1, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(1, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000); // wait for a second
  digitalWrite(1, LOW); // turn the LED off by making the voltage LOW
  delay(1000); // wait for a second
}

Select "Sketch, Uploading Using Programmer" to upload the compiled sketch to the ATtiny85. Using "Upload Using Programmer" is important, as it indicates to upload the sketch through the Uno which we have setup as an ISP.


Once the sketch is successfully upload, we can connect a LED to the ATtiny85 (longer lead (+) to Pin 1, shorter lead (-) to GND) and watch it blink.


ESPCLOCK V2.0 - Design

I previously started a project to hack an analog clock to sync with NTP. I call the project ESPCLOCK, because it uses the ESP8266 chip (or more specifically, the ESP-12E development board for the ESP8266) to integrate with the analog clock.

From a usability viewpoint, I like the fact that there is no need to mess with timezones during setup. Basically when setting up the WiFi, the setup page grabs the timezone from your browser automatically. So setup is as simple as entering the WiFi credentials, and the clock will start keeping accurate time and handle daylight saving automagically.

However, in its current state, there are two issues with the clock:

1. The battery life is awful. Connected to a 2400mAh USB battery pack, it can only last for about 27 hours. A typical analog wall clock will run for at least a year on a single AA battery.

2. To deal with possible power loss, it writes the current clock time to EEPROM every second. Since the EEPROM has a limited number of write cycles, this is clearly not practical. We can of course simply not write to the EEPROM, but that means having to setup the current clock time after every power loss.

I have been thinking about tackling both problems in version 2 of the ESPCLOCK. While waiting for the parts to arrive, I am going to document the initial design I have in mind.

Instead of using only the ESP8266, which is rather power hungry, I am thinking of delegating the clock module to the ATtiny85. This is a diminutive chip that has a normal power consumption of 2.5mA and a sleep mode consumption of only 0.5µA. It is also extremely low cost, priced at slightly over $1 if purchased individually.

The idea is to have the ATtiny85 drive the hands of the clock, as well as communicate with the ESP-12 via I2C. This can be achieved via the TinyWire library. It will only need to respond to 3 commands from the ESP-12:
  • Get current clock time
  • Set current clock time
  • Set current NTP time
The ATtiny85 will effectively act as the "brain" of the clock and automatically catches up with NTP time if necessary. Given its power consumption parameters, it will theoretically last for about 200 days on a 2400mAh battery (assuming 200ms of uptime, and 800ms of sleep time per 1s cycle).

To deal with the EEPROM issue, a 0.47F capacitor will be connected in parallel to the power supply. The ATtiny85 will constantly monitor the voltage of its power supply. When power loss occurs and voltage drops below a certain level (say 3V), the capacitor will provide the ATtiny85 with enough residual power to write the current clock time to the EEPROM. That way, it can keep track of the current clock time accurately in the event of a power loss, without maxing out the write cycle budget of its EEPROM.

The ESP8266 will sleep most of the time, wake up every 30 minutes (probably make this configurable), get the current NTP time (and convert to local time), send it to the ATtiny85 via I2C, then sleep again.

I have ordered another ESP8266 development board, the Wemos D1 Mini, because it seems to have better unmodified deep sleep characteristics (low current draw of 170µA during deep sleep) compared to the ESP-12E. Assuming an average current draw of 70mA over a 10s active uptime (this is just a wild estimate; I could be totally off the ballpark here), it should theoretically be able to last 180 days on a 2400mAh battery.

Putting the two results together, the entire concoction should last about 95 days on a 2400mAh battery. Put it another way, a 10,000mAh battery should be able to drive the clock for a year on a full charge. Given the low prices of USB battery packs, or even a pack of 4 x 2500mAh NiMH rechargeable batteries, an Internet-connected analog clock that runs for a year on batteries alone seems less a pipe dream!
Wemos-D1-Mini
Wemos-D1-Mini
Wemos D1 mini

Friday, 10 February 2017

High Intensity Interval Training

To maintain my body weight, I have been using the Fast Diet (once a week), which is cheap, easy to perform and does not require any special equipment or supplement. So far it has been working great for me.

Recently, while watching the latest series of Trust Me, I am a Doctor, I come across something called High Intensity Interval Training, or HIIT:


Basically, 15 minutes of high intensity training daily is good enough to maintain body fitness and can substitute for much longer moderate intensity exercise.

Like the Fast Diet, I am attracted to this method of training because we are all time-poor these days, and having to devote 30 minutes or more each day for walking or other forms of exercise is next to impossible. In addition, no special equipment is required and it can be done anywhere with a bit of room.

I have started doing this HIIT routine daily:


Let's see whether I can maintain the regime like I do with the Fast Diet.

Monday, 6 February 2017

Refreshing Android MediaStore

The Android MediaStore maintains the metadata of audio, video and image files in the underlying filesystem for convenient consumption by relevant Android apps (eg. music player).

The problem is when manipulating the SD card content with an Android file manager, sometimes the metadata cache becomes out of sync with the actual filesystem. So for example if you rename or delete a folder using a file manager, then connect the device via a USB cable to your PC to be accessed via MTP, the old folder may appear in Windows Explorer. Clicking "Refresh" does not work to update the content. The only way to refresh the cache is to reboot the device.

Another method I found recently is to run an app that forces MediaStore to refresh its cache. There are many apps available for this purpose if you search for "rescan sd" in the app store. A lot of them won't work with Android 6.x (Mashmallow) and will crash when you try. One ad-free app that works  under Mashmallow is Rescan SD Card.



It is a very simple app, but it does take a while to rescan the entire SD card. For my case with a few thousand files, it took 3 to 4 minutes to complete the process.

On the topic of MTP, it is a horrible protocol for file transfer. We used to have USB mass storage, where the SD card is mounted as a drive under Windows Explorer. But this is all but gone in the latest devices and can only be found in some custom ROMs.

Anyway, mounting the SD card as a drive has its own problems because it needs to dismount the storage from Android apps during the usage duration, which can cause all sorts of unexpected problems. Recent devices mostly only support PTP (which is practically useless for anything) and MTP.

MTP is horrible because it is extremely finicky. It can hang when transferring large files. It can hang when you are just renaming a folder. When it hangs, the only workaround is to reboot the device.

Why not use wireless? Wireless transfer apps such as AirDroid or SendAnywhere is not practical when you are trying to transfer large files (eg. video files > 500MB). In addition, when you are out and about, and your PC is connected to a WiFi hotspot, while your phone is connected to 4G, it is a pain to juggle the connections so that the quota on your 4G broadband will not be affected. Simplest is to use a USB cable, which is fast and reliable. Too bad the underlying protocol is garbage.

We need a better standard for wired file transfer over USB, and so far none is forthcoming.

Thursday, 12 January 2017

How to disable Firefox "Open in new window" context menu item

I can't remember how many times I have accidentally clicked on "Open in New Window" when I meant to select "Open in new tab" when using Firefox. Finally irritated me enough to find a solution.

Locate C:\Documents and Settings\<username>\ Application Data\Mozilla\Firefox\Profiles. There should be two files: userChrome-example.css and userContent-example.css. Copy userChrome-example.css to a new file called userchrome.css and open it in a text editor.

Add the following lines to the end of the file:

/* Never show “Open in New Window” when right clicking */
#context-openlink {display: none !important;}


I also added this block to remove "Open in New Private Window":

/* Never show "Open in New Private Window" when right clicking */
#context-openlinkprivate { display: none !important; }




Now my Firefox context menu shows only "Open Link in New Tab":


Great!