RF link display using the ATtiny85

I wanted to display my weather station data in other rooms in my house without using wires:


I chose a simple and cheap(AUD5.6 for tx/rx pair) 433.92 MHz link:


They are really only meant for things like a garage door controller.

The frequency response is very limited, I run them at 2000 b/sec.

I use VirtualWire(modified) library for the Transmitter which uses a ATmega328:

//Transmitter. Sends integer as 2 bytes once per second

#include <VirtualWire.h>
#undef round

uint16_t data =0; //the integer to send

void setup()
vw_setup(); // 2000 Bits per sec

void loop()
data +=1;
uint8_t number[2] ;
number[0] = data;
number[1] = data >> 8; //send 2 bytes
vw_send(number, 2);
vw_wait_tx(); // Wait until the whole message is gone
delay(1000); //send every second

I further modified this library to get VirtualWireTiny library to work with the ATtiny85.
It handles receive only at 2000 b/sec.

The display is 4 digits of 7 segments. I use my SEVENtiny library.


The receive code is very simple for the ATtiny85 RX:

//Receiver. Waits to receive two bytes. Displays the integer.

#include <SEVENtiny.h>
#include <VirtualWireTiny.h>
#undef round

void setup()
vw_setup(); // 2000 Bits per sec
vw_rx_start(); // Start the receiver PLL running
}//end of setup

void loop()
uint8_t buf[VW_MAX_MESSAGE_LEN];//message length defined as 12 bytes
uint8_t buflen = VW_MAX_MESSAGE_LEN;

vw_rx_start(); // Start the receiver PLL running
if (vw_get_message(buf, &buflen)) // Non-blocking
uint16_t data = buf[1];
data =(data << 8) | buf[0];
}//end of got data
}//end of loop

This code only uses 1756 bytes of Flash.

To program the ATtiny85 I use:


The lfuse must be set to 0xE2.

Download tinyRFlink.zip from:


Cool project!

I can think of some ways to use an affordable RF link at 2000 b/s

Thanks theepdinker.

It does have some limitations like I cant use it to monitor my Oregon weather station.

It uses 433.92 but needs a 10 kb/s to get an output.

Why you used modified library for the ATmega328 Transmitter? This lib works on it perfectly (at least for me.).

Yes it works perfectly for me to when I use a 328(with xtal) to TX and a 328(with xtal) to RX.

When I used a ATtiny85 with an internal clock for RX I got a lot of dropouts. I guessed it was because the setting of Timer1 in VirtualWire was not quite right.

I tried using Timer2 in the 328 transmitter and this seemed to give much more reliable results.

When I used a ATtiny85 with an internal clock for RX I got a lot of dropouts.

Did you "tune" the internal clock?

Thanks for you reply.

Thats a reasonable response to a fixed frequency error. OSCCAL can be set to change the internal oscillator frequency.

VirtualWire works by setting a timer to give a fixed frequency interupt. 62.5 usec is the default. Compare mode to OCRA is used to generate the interupt. OCRR1A default set is 125. So we could tune the bit rate using a set of OCR1A or OSCCAL.

The problem was that it was not a fixed frequency error. The transmission would work fine for many hours and then have dropouts for an hour. It seemed to be ambient temperature related.

The frequency is temperature related as per Figure 22-41 of the data sheet.

With my change of ambient we should only have a change from 7.93 to 7.95 Mhz. This should not be enough to cause problems to VirtualWire unless the origional TX frequency is on the edge of the default 62.5 usec value.

When I changed the transmitter to timer2 with 62.5 usec interupts the problem was solved.

Having solved my problem I did not chase down any further answers like provided in your reply.


Hi carl47, thanks for the very handy post. I'm trying to use your library but get a bunch of errors when I compile the transmitter example. The receiver example compiled fine. I tried replacing the entire VirtualWire library with your version and also tried replacing just the 2 .cpp and .h files and I'm not quite sure what else to do. Any advice would be greatly appreciated!

Error messages; ...VirtualWire.cpp: In function 'void vw_setup()': ...VirtualWire.cpp:257: error: 'TCCR2A' was not declared in this scope ...VirtualWire.cpp:258: error: 'TCCR2B' was not declared in this scope ...VirtualWire.cpp:259: error: 'OCR2A' was not declared in this scope ...VirtualWire/VirtualWire.cpp:262: error: 'TIMSK2' was not declared in this scope ...VirtualWire/VirtualWire.cpp:268: error: 'DDRD' was not declared in this scope ... VirtualWire/VirtualWire.cpp: In function 'void vw_tx_stop()': ... VirtualWire/VirtualWire.cpp:299: error: 'PORTD' was not declared in this scope ... VirtualWire/VirtualWire.cpp: In function 'void TIMER2_COMPA_vect()': ... VirtualWire/VirtualWire.cpp:409: error: 'PIND' was not declared in this scope ... VirtualWire/VirtualWire.cpp:426: error: 'PORTD' was not declared in this scope ...VirtualWire/VirtualWire.cpp:428: error: 'PORTD' was not declared in this scope

Sorry I took so long I have been on holidays.

I have the folders:




In the arduino librarys folder:


The transmitter compliles OK for me.

There is a big problem when we use modified librarys along with new functions.
Its hard to keep everything in order. Checkout microsofts .dll hell for example.

Sorry it does not work. I no longer use any version of virtual wire I wrote my own library.


This does not have problems with compilation.

Thanks for the reply carl47. It was actually my oversight because I didn't set the appropriate board before compiling. Your other library sounds good and am keen to have a play. Hope you had a good holiday :)

Hi carl47, the VW transmitter code works well on the Arduino but I'm having some trouble getting the receiver bit working on the ATtiny85. I've modified the code to blink an LED when data is received but nothing happens.

I'm using the same pair of RF modules and the MIT method (http://hlt.media.mit.edu/?p=1229 ) of programming the tiny. Is the issue that we're using different cores?

I had a look at MIT’s attiny45_85.zip .

It’s written by the same bloke David A. Mellis, however my copy of the core is quite different.

The core that I use is in the Manchester.zip.

Have a try with my core and see.

When I get a problem like this I forget about the final project and go back to basic switch LED on/off.
Then add tiny bits of the final program.

Just a thought.

It's written by the same bloke David A. Mellis,

Minor correction ... he spells his name Alessandro Saporetti. (David Mellis updated the package for Arduino 0022)

I normally would not mention it but Alessandro really does deserve credit for his work.

I,m very sorry to leave out Alessandro's name.

However in the MIT core I could only find:

Copyright (c) 2007 David A. Mellis Copyright (c) 2008 David A. Mellis. All right reserved. Copyright (c) 2005-2006 David A. Mellis

The core which I use comes from the site you list:


In the core from arduino-tiny-0022-0008.zip I could only find:

Copyright 2010 Rowdy Dog Software. Copyright (c) 2006 Nicholas Zambetti. All right reserved. Copyright (c) 2007 David A. Mellis Copyright (c) 2010 Hernando Barragan. All right reserved.

carl47: However in the MIT core I could only find

Alessandro marked only the files he modified (pins_arduino.c, pins_arduino.h, WInterrupts.c, etcetera) (A.Saporetti and Saposoft).

The core which I use comes from the site you list

His credit is also in that core in the same places.

I do need to apologize. In my mind, it is Alessandro's core because he is responsible for getting it to work on the ATtinyX5 processors. The reality is that the core is the product of many people (including, of course, David Mellis). It is a shining example of what open source is meant to be. So, I apologize to David Mellis and Hernando Barragan. By emphasizing Alessandro's contribution I did not mean to diminish your contributions.

Thanks Coding Badly for your answer. You have helped me out on more than one occasion.

I can see the references you point out.

It would be nice if there were a complete history of the Arduino development - hardware and software.

I have looked at:


Is there a more complete history of the software and hardware development anywhere?

You are welcome!

I'm afraid I can't help with that question.

The library does not allow VirtualWireTiny.h ATTINY85 use as a transmitter (TX)

Errors when trying to:

attiny85_RF_transmiter.cpp: In function 'void setup ()': attiny85_RF_transmiter: 11: error: 'vw_set_tx_pin' was not declared in this scope E: \ arduino-0022 \ libraries \ VirtualWireTiny / VirtualWireTiny.h: 65: error: too many arguments to function 'void vw_setup ()' attiny85_RF_transmiter: 12: error: at this point in file attiny85_RF_transmiter.cpp: In function 'void loop ()': attiny85_RF_transmiter: 21: error: 'vw_send' was not declared in this scope attiny85_RF_transmiter: 22: error: 'vw_wait_tx' was not declared in this scope

You are right I did not modify virtual wire to use the 85 as the Tx.

I wrote another library to use the 85 as Tx or Rx.


I have been using your Manchester library for TX on an ATtiny85 and RX on an Arduino Uno. However, I am keen to get VirtualWire working as this uses an interrupt driven approach that avoids the sender/receiver having to block while sending/receiving.

I have made an attempt to get VirtualWire working for TX/RX on ATtiny85/Arduino Uno. The code is compiling and I am fairly sure I have used the correct timer settings but I don't seem to be receiving any valid messages on my Arduino.

I am programming my ATtiny85 using the instructions on this site (http://hlt.media.mit.edu/?p=1695) but with the ATtiny85 core from http://code.google.com/p/arduino-tiny/.

All of my code is up on github:

https://github.com/mchr3k/arduino/tree/master/libraries/VirtualWireNewTiny https://github.com/mchr3k/arduino/blob/master/wsn_arduino_vw/wsn_arduino_vw.ino https://github.com/mchr3k/arduino/blob/master/wsn_attiny_vw/wsn_attiny_vw.ino

As you can see, the TX is trying to send 10x"D" ("D" = 0x44). My receiver consistently receives strings like "0 10 0 C 1D C 1D A 28 0 C1 3 E 0 1 0 2 5D 0 C1 2 33 0 2 0 0 0 A 0". The first part of each received "message" is consistently "0 10 0 C 1D C 1D A 28 0 C1 3 E 0 1 0 2 5D 0 C1" for the first few minutes.

Can you suggest how I should debug this or what could be going wrong?

EDIT: A friend has pointed out that the ATtiny has 8 bit counters vs the ATmega 16 bit counters.

I’m trying to do 1000 bit/second which gives the following maths.

uint16_t ocr1a = (F_CPU / 8UL) / speed; ( 8000000 / 8 ) / 1000 = 1000

This value of 1000 won't fit in the ocr1a register so the timing will be totally wrong. I will need to adjust the clock frequency scaling to ensure the ocr1a value is lower on the ATtiny. I will hopefully try this out tonight.