Martin's corner on the web

Running the Attiny84 @ 4Mhz with the internal oscillator

I am experimenting with running the TinySensor at 4Mhz with power saving in mind. There is a really nice article on power saving techniques here that also was an inspiration. The 4Mhz is the lowest possible limit for the RFM12b module to work as well, so I won’t go any lower than that.

In theory, the ATTiny84 can work down to 1.8V on 4Mhz, so that is another advantage.

The RFM12B module, on the other side, can only work down to 2.2V according to the datasheet, given that you set the low battery warning to that value as well by issuing the following rf12 control:

// Adjust low battery voltage to 2.2V
 rf12_control(0xC040);

So, to do this using the internal oscillator only, we need the fuses set to 8Mhz internal oscillarot and later in the software we will set the prescaler value. Chose that option in the Arduino IDE with Tiny Core installed and perform “burn bootloader” to set the fuses. This doesn’t actually burn any bootloader for the ATTiny84, but rather sets the fuses of the chip.

So the rest of the job will be done in the Software side with some code like this:

// Change to 4 MHz by changing clock prescaler to 2
 cli(); // Disable interrupts
 CLKPR = (1<<CLKPCE); // Prescaler enable
 CLKPR = (1<<CLKPS0); // Clock division factor 2 (0001)
 sei(); // Enable interrupts

Since we are changing CPU speed on the run, the delays and other runtime defined stuff runs twice as slow, because the sketch was compiled for 8Mhz speed. To adjust for this, we need to set the F_CPU to 4Mhz, I place this code on top of my sketch:

#ifdef F_CPU 
#undef F_CPU
#endif 
#define F_CPU 4000000 // 4 MHz

I then tried to compile the sketch, but to no luck.. I got some strange Serial related errors from the JeeLib that I use for the RFM21B communication, although my sketch doesn’t use any serial..oh well, seems that the Jeelib depends on Serial stuff, but why isn’t it available when the Tiny Core supports it? I reviewd the code and it seems that the Attiny84 core only supports CPU speeds of 1,8 and 16Mhz, if the F_CPU is anything else there is no Serial support.. and hence the JeeLib fails.

So my solution was to modify a bit the Tiny Core’s TinyDebugSerial.h file. I opened the file and located the section that defines the serial procedures for the different CPU speeds and used quite a dirty hack to get my sketch run. Serial will *not* work on 4Mhz, but at least the sketch will compile ok:

#if F_CPU == 1000000L
 typedef TinyDebugSerialWriter_1_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
 typedef TinyDebugSerialWriter_1_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
 typedef TinyDebugSerialWriter_1_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
 #define TINY_DEBUG_SERIAL_SUPPORTED 1

I inserted here the 4Mhz definitions:

#elif F_CPU == 4000000L
 typedef TinyDebugSerialWriter_1_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
 typedef TinyDebugSerialWriter_1_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
 typedef TinyDebugSerialWriter_1_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
 #define TINY_DEBUG_SERIAL_SUPPORTED 1

.. and the code continues

#elif F_CPU == 8000000L
 typedef TinyDebugSerialWriter_8_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
 typedef TinyDebugSerialWriter_8_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
 typedef TinyDebugSerialWriter_8_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
 #define TINY_DEBUG_SERIAL_SUPPORTED 1
#elif F_CPU == 16000000L
 typedef TinyDebugSerialWriter_16_9600<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_9600;
 typedef TinyDebugSerialWriter_16_38400<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_38400;
 typedef TinyDebugSerialWriter_16_115200<TINY_DEBUG_SERIAL_REGISTER,TINY_DEBUG_SERIAL_BIT> TinyDebugSerialWriter_115200;
 #define TINY_DEBUG_SERIAL_SUPPORTED 1

So with these modifications in place, I am now running a TinySensor at 4Mhz. The effect is yet to be measured.