attiny84 |
After getting the attiny85 (8 pins) working with nRF24L01, I find that while this chip is nice and small, the lack of extra pins is a real hassle when I need to add any sensors/actuators to the MCU.
When I received my attiny84 ICs from Element14, now the fun begins...
attiny84 pinout |
As usual, I hook up the attiny84 and test a blink sketch to ensure the attiny84 is working correctly. The first thing I encounter is that the blink is very slow, about 8 to 10 secs slower and I was wondering why. By the way, I'm using this Arduino tiny-core https://code.google.com/p/arduino-tiny/ as there are other tiny-cores available on the net with different settings.
After posting my problems on Arduino forum, I found out I need to do a Tools->Burn Bootloader to set the correct speed and fuses on the attiny84. After the "Burn Bootloader", the attiny84 was operating correctly at 8Mhz without an external crystal.
attiny84 |
The "fun" starts when trying to get the SPI pinout for attiny84 for running the nRF24L01. Since it uses the same tiny core was the attiny85 and I got the attiny85 working, it should not be too difficult, I guess.
After hooking up the attiny84 according to the above image and flashed the hex into the attiny84, I did not get correct settings on the four register I was monitoring on the serial/debug monitor. For troubleshooting, I have enabled "TinyDebugSerial" to read the four register, namely RF_CH, RF_SETUP, TX_ADDR and RX_ADDR.
I always needed to verify these settings and proper communications to the nRF24L01 as I used many different data rate, channel/frequencies and TX/RX address on all these nRF24L01 radios all the time.
Mirf.readRegister(RF_CH, &rf_ch,sizeof(rf_ch));
Mirf.readRegister(RF_SETUP, &rf_setup, sizeof(rf_setup));
Mirf.readRegister(TX_ADDR, tx_addr, sizeof(tx_addr));
Mirf.readRegister(RX_ADDR_P1, rx_addr, sizeof(rx_addr));
I also hook up a Logic Analyzer to the SPI pins to "see" what is going on during those SPI transfers. A proper SPI transfer would look something like below, with Enable/Slave Select (SS) pin held low during active SPI with Clock (SCK) supplying the clockrate for the MOSI/MISO.
SPI transfers |
The issue seems to be SPI related as I do not get SPI patterns similar to the above, I immediately looked at SPI85 library that was downloaded from Arduino forum and it was working fine on the attiny85 on my earlier blog entry.
A bit about the SPI for the attiny, as the attiny does not have dedicated pins for SPI, it uses Universal Serial Interface (USI) for both SPI or I2C. See http://playground.arduino.cc/Code/USI-SPI for details on the USI-SPI on Arduino playground.
By viewing this link on Arduino Playground, it gives *hint* NOT to use the MOSI/MISO pins for attiny as they are ONLY used for In-Circuit Serial Programming (ICSP) only.
By looking at the SPI85.cpp codes, there are two lines that seems to differentiate between attiny85 and attiny84.
#if defined( __AVR_ATtiny85__ )
const static uint8_t SS = PB4;
const static uint8_t MOSI = PB1;
const static uint8_t MISO = PB0;
const static uint8_t SCK = PB2;
#endif
#if defined( __AVR_ATtiny84__ )
const static uint8_t SS = PA7;
const static uint8_t MOSI = PA6;
const static uint8_t MISO = PA5;
const static uint8_t SCK = PA4;
#endif
Here are some snapshot from the datasheets as like most of you, I only
will read through the datasheet as a last resort as they are not written for
normal people like myself. I always wonder if the author even understand what
he himself wrote if he reads it a few years later.
attiny x4 pinout |
attiny x4 pin alternate functions |
wrote the SPI85 library was just following putting support for attiny84 without actually
tested an attiny84 before as clearly it shows the pins was incorrect.
The pin PA5, while listed as MISO (for ICSP), was also USI-DO (data out) and PA6 while
listed as MOSI (for ICSP), was also USI-DI (data in). As stated above in Arduino
playground, for attiny, the MISO/MOSI is used only for ICSP and not for USI-SPI.
That was easy to solve, just swapped PA5 and PA6 and everything will work fine,
right.. but it turns out that the PA5 and PA6 is logically mapped to value of 5 and 6
and when the codes does an Arduino code of pinMode and digitalWrite, it execute
the wrong pins for the attiny. A Digital pin5 mapped to PA5 and Digital pin6 mapped
to PA4 (the pin used for the SCK/USCK).. no wonder the SPI display on the
logic analyzer goes haywire..
Once, I traced the issue and figure out the problems, I just had to hard code the Arduino digital pins
to the AVR_ATtiny84 defines as below and changed the MOSI/MISO source of confusing to
USI_DO and USI_DI :-
#if defined( __AVR_ATtiny84__ )
const static uint8_t SS = 3;
const static uint8_t USI_DO = 5;
const static uint8_t USI_DI = 4;
const static uint8_t SCK = 6;
#endif
After that, I was able to see the correct settings on the Serial Debug or the SPI patterns on the
logic analyzer. I do not know enough about how the tiny cores was written to put the
proper attiny84 pin names but it was finally working.
If you figure out on how to fix the attiny84 pins, please let me know. The nRF24L01 library
was located at the summary links below.
There is an example of attiny84 codes in the Mirf library at github repo.
Summary Links :-
Mirf (nRF24L01) libs for UNO/attiny84/attiny85 :- https://github.com/stanleyseow/arduino-nrf24l01
Arduino tiny-cores :- https://code.google.com/p/arduino-tiny/