Receiving and Sending Data Between Attiny85 (Arduino IDE 1.06) UPDATED Nov 2015

Published

Introduction: Receiving and Sending Data Between Attiny85 (Arduino IDE 1.06) UPDATED Nov 2015

About: I am a physician by trade. After a career in the pharmeceutical world I decided to take it a bit slower and do things I like. Other than my hobbies that involves grassroots medicine in S.E.&P Asia. I have bu...

I have struggled a lot with sending RF data between two Attiny85 chips, so I thought it might be helpful if I just explain how I did it. There are a number of such projects being described on the internet, but yet, it didn’t prove to be such a straightforward project, which i found to be mostly due to not using the right libraries and cores.

BOM
Transmitter:
Attiny85 - 0.82 euro/10
10k resistor
433 MHz transmittermodule - 1 euro per set
mini breadboard - 58 cts/piece

Receiver:
Attiny85
10k resistor
433 MHz Receiver module
mini breadboard
Optional: 2 wire LCD

There are two main libraries used to send and receive data on an Arduino platform: VirtualWire and Manchester code.
As Virtualwire is a bit older, no longer supported, and supposedly can only send characters (though there is a way around that) I decided to use Manchester code.

To make a long story short, it didn’t work. I had the MANCHESTER.h and MANCHESTER.cpp file and ran into a lot of trouble, until I discovered that was the wrong/old library, you need the Manchester.h and Manchester.cpp file from here. When I used that I got my transmitter to work, I could send data to an Arduino, that was already a big relief.

However....... whatever I did, I did not get my receiver to work. In testing something on an Attiny it is very frustrating to just stare at an LED that is supposed to light, but doesnt, without knowing what and why and how.
So i decided to add an LCD to the Attiny, so at least I could see what was happening..
However, the LCD on my attiny gave me other problems... and when I solved those, that proved to be the solution for my receive problem as well: I was using the wrong core. I was using the 'tiny core' rather than the 'attiny core'
The latter is the one from Highlowtech.
Also, I programmed the Attiny's with 8MHz internal oscillator by first 'burning the bootloader'

NOTE: it is generally agreed that the 'tiny core' works with the Manchester code and the attiny core does not, so it is possible that I mixed up the two. However, I had a line added to the Attiny core that I forgot about that will make it work with the Manchester code. Open up the "variants/tiny8/pins_arduino.h" file and add the line"#define __AVR_Attinyx5__" (See the picture)

NOTE2: Obviously it also works for the IDE 1.6.x but if you use the tiny core that does not come with a JSON file and as the core file folder structure for 1.6.x is different from 1.0.6 You need to do the install yourself. This website can help you with that. The attiny core comes with a json link that will do the install via the boards manager, but then you have to add the Attiny5__ definition as described above

Step 1: Receiving and Sending Data Between Attiny85: the Transmitter

The built of the transmitter is easy:
Plug the attiny chip into your breadboard,
Connect a 433 MHz Transmitter module with its data in to pin PB0 (that is pin 5 on the chip).
Connect Vcc and Ground of the transmitter module to Vcc (pin 8) and ground (pin 4) of the Attiny
Insert a 10 k resistor between pin 1 (Reset) and pin 8 (Vcc)
Connect Vcc and ground to 5 Volt
Take a 17 cm stiff wire and attach that to the antenna hole of the transmitter.
use the following program:

#include <Manchester.h>
/*
Manchester Transmitter example In this example transmitter will send one 16 bit number
per transmission.
Try different speeds using these constants, your maximum
possible speed will depend on various factors like transmitter
type, distance, microcontroller speed, ...
MAN_300 0 MAN_600 1 MAN_1200 2 MAN_2400 3 MAN_4800 4 MAN_9600 5 MAN_19200 6 MAN_38400 7
*/
#define TX_PIN 0 //pin where your transmitter is connected
uint16_t transmit_data = 2761;
void setup() { man.setupTransmit(TX_PIN, MAN_1200); }
void loop() { man.transmit(transmit_data); delay(200); }

Just a word on the 2716 that I am sending. The program is not mine, I found it as such and since it worked and I was very happy to see the '2716' appear in my Arduino after days of fruitless trying, I decided to leave it there as a tribute. (it might have found it here)

Step 2: Receiving and Sending Data Between Attiny85: the Receiver

Building the receiver is easy:
Put the programmed attiny chip in your breadboard.
Connect a 10 k resistor between pin 1 and pin 8
Put your 433 MHz Receiver module in the breadboard
Connect the datapin (usually either one of the two middle pins) to pin PB1 (physical pin6) on the attiny.
Connect the Vcc and Ground of the transmitter module to Vcc (pin 8) and Ground (pin4) of the Attiny
Connect the LCD interface to pin PB0 (pin 5) (Clock) and pin PB2 (pin 7) (Data/Enable)
Connect Vcc and ground of the LCD to Vcc and Ground.
Attach a 17 cm (1/4 lambda for 433 MHz) to the Receiver module.
Use the following program in your chip:

#include <Manchester.h>

#include <LiquidCrystal_SR.h>
LiquidCrystal_SR lcd(0,2,TWO_WIRE);
/*
  Manchester Receiver for Attiny
  In this example receiver will receive one 16 bit number per<br>  transmittion to switch a relay on or off. <br>  try different speeds using these constants, your maximum possible<br>  speed will depend on various factors like transmitter type, <br>  distance,  microcontroller speed, ...<br><br>  MAN_300 0
  MAN_600 1
  MAN_1200 2
  MAN_2400 3
  MAN_4800 4
  MAN_9600 5
  MAN_19200 6
  MAN_38400 7
*/

#define RX_PIN 1 //= pin 6
uint8_t moo = 1;

void setup()

{
lcd.begin(16,2);
lcd.home();
lcd.print("Receive");
lcd.setCursor(0,1);
  man.setupReceive(RX_PIN, MAN_1200);
  man.beginReceive();
}

void loop() {
  if (man.receiveComplete()) {
    uint16_t m = man.getMessage();
    man.beginReceive(); //start listening for next message right<br>                        //after you retrieve the message
   moo = ++moo % 2;
    lcd.print(m);
  }
}

The LCD is ofcourse optional. You can use an LED that gets the variable 'moo' send to its pin and thus will flash on complete receival of the signal, but I just wanted to make sure that what I got was what I sent

Step 3: Receiving and Sending Data Between Attiny85: Results

The results are good, no garbage is being received, but the reach is about 4-5 meters, with the antennas. The antenna on the receiver only makes a small difference. The one on the Transmitter makes a big difference.
Still, this is surprising as the transmitter module is capable of switching remote switches at greater distances even on different floors.

With regard to the length of the Antennas:

as f * λ= c (frequency * wavelength = lightspeed)
λ=c/f
λ= 299,792,458 /433,920,000
The wavelength is 0.690893386 meters.
Antenna would be λ/4= 0.172723346 meters (17.3 cm)
That is about 6.80013 inches.
If you would be using 315 MHz modules, the antenna would be: 0.238 m or 23.8 cm

You can also use the wavelength calculator.


Supposedly the transmitter module can take 12 Volts and still be steered by a 5 Volt microcontroller pin and will have a further reach then. Increasing the voltage on the receiver of course makes no difference

Once you have established The link between two attiny's, linking one of them with an arduino should not be a problem. I use mine to send data to an Arduino ( e,g. temperature, or the status of a tripwire), or to receive data from an Arduino to steer a servo or an RGB LED.

If you want to trigger a relay, you would do it like this:

void loop() {<br>  if (man.receiveComplete()) {
    uint16_t m = man.getMessage();
    man.beginReceive(); //start listening for next message right after you retrieve the message
    moo = ++moo % 2;
    lcd.print(m);
    if (m==2761){digitalWrite(Relay,HIGH);}
    if (m==0000){digitalWrite(Relay,LOW);}
  }

Ofcourse you need to define the Relay pin in the 'setup'

Step 4: Sending and Receiving Sensor Data With Attiny85/45: DHT11 and LDR Through Manchester Code

Sending a stationary number of course is fun at first, but isn’t much use. Below is a more practical example of sending 1 stationary value and 3 variable values through the ether.

/*
LDR=A1 RF433=D0 DHT11=D4 LED=D3 */ // libraries #include <dht11.h> #include <Manchester.h> dht11 DHT11; #define DHT11PIN 4 #define TX_PIN 0 //pin where your transmitter is connected //variables float h=0; float t=0; int transmit_data = 2761; int transmit_t = 0; int transmit_h = 0; int light=0;
void setup() {
  man.setupTransmit(TX_PIN, MAN_1200);
}
void loop() {
 int chk = DHT11.read(DHT11PIN);
 h=DHT11.humidity;
 t=DHT11.temperature;
 transmit_h=100*h;
 transmit_t=100*t;
  man.transmit(transmit_data);
  delay(200);
  man.transmit(transmit_h);
  delay(200);
  man.transmit(transmit_t);
 light= analogRead(A1);
 man.transmit(light);
}

It takes 3194 bytes so I could compile it in an Attiny45.

The transmitter is connected to D0 (pin 5). The DHT11 sensor is
connected to D4 (pin 3) and an LDR connected to A1 (pin 7), with the other end connected to either ground or Vcc and a corresponding pull up or pull down resistor, depending on your preference,

Variables h and t are floats that can have decimals. As I am only interested in 2 decimal accuracy, I multiply by 100 and turn them into integers. I then send a station identifier '2716', followed by 3 values: Humidity, temperature, light. The receiving station then can identify where it came from and process the incoming signals (starting by dividing them by 100 again)

5 People Made This Project!

Recommendations

  • Oil Contest

    Oil Contest
  • Clocks Contest

    Clocks Contest
  • Woodworking Contest

    Woodworking Contest
user

We have a be nice policy.
Please be positive and constructive.

Tips

1 Questions

0

Hi, thank you for this tutorial. I finally have 2 ATtiny85 talking together ! Next step will be sending data between my ATtiny "network" and a Raspberry Pi.

However I have a question, I can only send data from 0 to 255 using your code/libraries. Do you see any reason why I cannot send other data ? (Ex. If I try to send 256, I receive 0; when sending 2761 I receive 201 ...)

Thanks,

Dimitri

I understood in the mean time it was a matter of an 8 bit library right?

0

Problem solved. The manchester lib I downloaded seems to be only for 8 bits data.

I will try to change it in order to send more than 8 bits of data (or transmit/receive an "array of data" as I saw it in some forums.

Thanks.

0

Correct ! My mistake. I am going to try it this week and tell you .

ok, I checked your numbers and 201 is indeed 2761 with the high byte removed, so somewhere you defined a byte where it should be an integer

Frankly, I am not sure. I haven' t used the Manchester library for a long time as I went to use MQTT, but the code as I published worked for me. I can' t really see system in the changes you mention (256->0; 2761->201), but somehow it seems that what is supposed to be an integer, has become a byte. Have you maybe defined something as a byte that should be an integer?

125 Comments

Hello,

Since I managed to make LCD work I started working with the RF. I encounter the following issue. When I use the provided code the receiver display nothing. Although it work if I change the code in loop to:

void loop()

{

uint16_t m = man.getMessage();

Serial.println(m);

}

Probably something is wrong with this function:

if (man.receiveComplete())

Any ideas?

Hi guys,

I have spend the last 4 days trying to make this work but it doesnt. I realy need some help at this point

. The transmiter part seems to work. I attached a led on PIN0 and it lights up every time it sends data.

I am using arduino IDE 1.8.1, Attiny board manager 1.0.2, and I setup the internal core speed to 8mhz for both Attiny85 (receiver, transmiter). I upload the code using two arduino nano with "arduino as ISP"

Although the receiver refuse to work. I even build a homeade oscilloscope to check the data pins.

The receiver seems to stop for some time when the trasmiter send the signal. So I guess it receives the data but Attiny refuse to turn on the led.

===============Transmiter======================

#define TX_PIN 0 //pin where your transmitter is connected
uint16_t transmit_data = 2761;
void setup() {
pinMode(1, OUTPUT);
man.setupTransmit(TX_PIN, MAN_1200);
digitalWrite(1, LOW); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(1, HIGH); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
}
void loop() {
man.transmit(transmit_data);
digitalWrite(1, LOW); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(1, HIGH); // turn the LED off by making the voltage LOW
delay(100); // wait for a second

=====================================

===================Receiver==================

#define RX_PIN 1 //= pin 6
uint8_t moo = 1;
void setup()
{
pinMode(0, OUTPUT);
digitalWrite(0, LOW); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(0, HIGH); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
man.setupReceive(RX_PIN, MAN_1200);
man.beginReceive();
}void loop() {
if (man.receiveComplete()) {
digitalWrite(0, LOW); // turn the LED on (HIGH is the voltage level)
delay(100); // wait for a second
digitalWrite(0, HIGH); // turn the LED off by making the voltage LOW
delay(100); // wait for a second
uint16_t m = man.getMessage();
man.beginReceive(); //start listening for next message right
//after you retrieve the message
moo = ++moo % 2;
}
}

=====================================

2017-10-28 05_46_19-Channels 1, 2 and 3.png22882260_10212749079833950_2119770782_o.jpg
18 replies

Sorry to hear you have problems. Just a question, why all the delays? Did you try without?
Did you add the modification in the library I suggested?

The delays are for the led to blink. Can you please help me out to set up te I2C screen? I can't find a fit library

If you can't chat that's ok, I will continue here :) in your code you include

#include <LiquidCrystal_SR.h>

This on is not included in broHogan lib. What did you used?

no it says:

//#include <LiquidCrystal_SR.h>
//LiquidCrystal_SR lcd(3,4,TWO_WIRE);//resp pin 2 en 3

These are thus commented out.
look further down where the I2C is included

Ok, i am missing something here, in you code above you don't include

LiquidCrystal_I2C.h

but also I understand that some encoding issue translated // to <br>

The code below is what I see in your instructables. So what I have to cange/add?

#include <Manchester.h><br>#include <LiquidCrystal_SR.h>
LiquidCrystal_SR lcd(0,2,TWO_WIRE);
/*
Manchester Receiver for Attiny
In this example receiver will receive one 16 bit number per
transmittion to switch a relay on or off.
try different speeds using these constants, your maximum possible
speed will depend on various factors like transmitter type,
distance, microcontroller speed, ...

MAN_300 0
MAN_600 1
MAN_1200 2
MAN_2400 3
MAN_4800 4
MAN_9600 5
MAN_19200 6
MAN_38400 7
*/
#define RX_PIN 1 //= pin 6
uint8_t moo = 1;
void setup()
{
lcd.begin(16,2);
lcd.home();
lcd.print("Receive");
lcd.setCursor(0,1);
man.setupReceive(RX_PIN, MAN_1200);
man.beginReceive();
}<br>void loop() {
if (man.receiveComplete()) {
uint16_t m = man.getMessage();
man.beginReceive(); //start listening for next message right
//after you retrieve the message
moo = ++moo % 2;
lcd.print(m);
}
}

Also do you use pull ups 4.7k resistors at your sda and scl pins?

That depends on the LCD/LCDinterface you are using, often they have pullup resistors. If not you have to add pull up resisters

Ok, now I understand what I was missing. Let's start over then. I used the following:

core: http://highlowtech.org/?p=1695

Attiny85_BMP180_BroHogan.zip

TinyWireM

In TinyWireM I edited the clock speeds as it is set to 1mhz. Specifically I edited USI_TWI_Master.cpp and USI_TWI_Master.h

#define F_CPU 1000000UL -> #define F_CPU 8000000UL

and

#define SYS_CLK 1000.0 -> #define SYS_CLK 8000.0

For the bootloader I selected Attiny85, 8Mhz

See the attached image

I tested many other libs and I concluded that the resistores are nedeed. Without the resistors the screen does not light up

I took a part from Hogans lib and this is it:

=====================================

//The connection for Attiny & BMP180 are SDA pin 5 ,SCL pin 7 for I2C
//#include <LiquidCrystal_SR.h>
//LiquidCrystal_SR lcd(3,4,TWO_WIRE);//resp pin 2 en 3
// | |
// | \-- Clock Pin
// \---- Data/Enable Pin

#include "LiquidCrystal_I2C.h"
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <TinyWireM.h>

void setup() {
// Now set up the LCD
//lcd.begin(16,2); // initialize the lcd
lcd.init();
lcd.home (); // go home
lcd.print("Weatherstation");
lcd.setCursor ( 0, 1 ); // go to position
lcd.print("BMP180");
delay(2000);
}
void loop() {
lcd.home();
lcd.print(" Press ");
lcd.print(" Hum ");
}

=====================================

I uploaded the compiler error in pastebin

https://pastebin.com/59AtLvZ5


2017-10-28 22_23_14-hardware.png

I am a bit puzzled, I never felt the need to alter any frequencies in the TinyWireM library. What is more, my USI_TWI files dont even have the definitions you say you have changed. Are you sure you use the right library?

Ofcourse the resistors are needed, nobody is disputing that, in fact, I was telling you they were needed.
To
avoid talking about two different things again: ALL I2C lines need pull
up but as I said, the i2C to LCD adapter may already have pullups in
which case you do not need to add extra, but if it doesnt ofcourse you
need to add pullups yourself

Why would you be using 'part of the broHogan library' If you start using "parts" of a library you can expect problems

Judging from the compilation errors, It seems you are calling the library more than once.
To make sure I downloaded the link myself again and just compiled it. As you see, compiles without any problems.
I think that what might be happening is that somehow your system picks up on two libraries, so pls check if you are indeed using:

#include "LiquidCrystal_I2C.h"
and not

#include <LiquidCrystal_I2C.h>

if that is the case it should be OK, but in practice it isnt always. Check if your main LCD library (the one in your libraries folder) is perhaps called "LiquidCrystal_I2C.h" too. The Arduino IDE should be able to differentiate but it doesnt always. I suggest you temporarily rename those library files and try again.

brohoganproof.png

I apologize again for the reminder. Now, what I meant was that i'm using part of Hogans example. Sorry for that.

Indeed there was two libraries in different folders. Now I managed to compile it and upload the code. But again the screen is not printing anything.

The example mention:

//The connection for Attiny & BMP180 are SDA pin 5 ,SCL pin 7 for I2C

I connected the pins to the corresponding Attiny pins which are pin 7 = 2 and pin 5 = 0 with two 4.7k resistors.

Also, regarding the TinyWireM lib there are two out there, in one of them you can specify the speeds, in the other one there is this comment:

*Notes:
* - T4_TWI and T2_TWI delays are modified to work with 1MHz default clock
* and now use hard code values. They would need to change
* for other clock rates. Refer to the Apps Note.

-

So, since you are using the one with that the speed is not configurable, I used the same now. I download it from Arduino's IDE Library manager

23023634_10212760003667039_1551656505_n.jpg22901280_10212760001026973_910356290_n.jpg

Well apparently we are advancing.
With regard to 'not showing anything' are you using the right I2C address? Is the contrast potentiometer set right?

I used a scanner to get the address with the use of an arduino and it reported 0x27. Just to be on the safe side I also tried 0x20 which is also common. Now regarding the potentiometer I don't really know how much contrast is required so I tried a few settings without luck.

I read somewhere that in some I2C adapters the pins of the chip are inverted. I don't know if that's the case.

What the guy writes about the pins and he also provided a library with a fix.:

----------------------------------------------------

Where did you get that board?
There are some Chinese ebay boards using the PCF8574T with the pins swapped and so you can't use the original library for it.
I have one of this Chinese board and my address is 0x20.
Here is the library for the Chinese version.
Remember, you must remove from the libraries folder the older one and insert this new one.
Post results

-----------------------------------------------------

https://forum.arduino.cc/index.php?topic=219717.0

what LCD do you have? Did it come with an i2C module attached? Did you try it on an Arduino?

Hello,

This is my I2C adapter

https://www.ebay.com/itm/1602LCD-Display-IIC-I2C-T...

And this is my LCD

https://www.ebay.com/itm/NEW-DC-5V-HD44780-1602-LC...

Back in 2015 I made it work with an arduino UNO but I don'r remember much. I believe that I located in my computer the code that made it work for arduino.

Two possibilities here, either my TinyWireM lib is not correct or in the code bellow I changed the lcd address, but I don't recall doing the last part.

LiquidCrystal_I2Clcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); <-- seems the same to me with the original example

At this point, can you please share with me the exact TinyWireM (version and all) that you are using. Or just zip your lib and send it to me. Also please let me know the version of Arduino IDE that you used to compile the code with (I don't think that it matters but just to be on the safe side).

This is the code I used back then

-----------------------------------------------------

/*

** Example Arduino sketch for SainSmart I2C LCD Screen 16x2

** based on https://bitbucket.org/celem/sainsmart-i2c-lcd/src...

** by

** Edward Comer

** LICENSE: GNU General Public License, version 3 (GPL-3.0)

** This example uses F Malpartida's NewLiquidCrystal library. Obtain from:

** https://bitbucket.org/fmalpartida/new-liquidcryst...

** Modified - Ian Brennan ianbren at hotmail.com 23-10-2012 to support Tutorial posted to Arduino.cc

** Written for and tested with Arduino 1.0

**

** NOTE: Tested on Arduino Uno whose I2C pins are A4==SDA, A5==SCL

*/

#include <Wire.h>

#include <LCD.h>

#include <LiquidCrystal_I2C.h>

#define I2C_ADDR 0x27 // <<----- Add your address here. Find it from I2C Scanner

#define BACKLIGHT_PIN 3

#define En_pin 2

#define Rw_pin 1

#define Rs_pin 0

#define D4_pin 4

#define D5_pin 5

#define D6_pin 6

#define D7_pin 7

int n = 1;

LiquidCrystal_I2Clcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

void setup()

{

lcd.begin (16,2); // <<----- My LCD was 16x2

// Switch on the backlight

lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);

lcd.setBacklight(HIGH);

lcd.home (); // go home

lcd.print("SainSmartI2C16x2");

}

void loop()

{

// Backlight on/off every 3 seconds

lcd.setCursor (0,1); // go to start of 2nd line

lcd.print(n++,DEC);

}

-----------------------------------------------------

if you are now using that same module and LCD then you know it is working.

The program+library that I sent you works with this configuration

addr, en,rw,rs,d4,d5,d6,d7,bl,blpol *
0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE)

That is the same that you are using
the TinywireM version I am using is version 1.0.0

If you wonder how is that guy remember what he did 2 years ago, I don't :P !

I located a picture I send to my friend with the lcd working and the print in the lcd produced from the code that I found in my computer from back then

lcd.print("SainSmartI2C16x2");

So I'm positive that the screen is working somehow

11286594_10205859196071162_691224691_o.jpg

Hello again.

I tried to connect the lcd to arduino with the sketch and the lib I described above and it works.

Also another comment, I think that I used the pull ups wrong. Now my pull up resistors are connected between the pins and the 5v supply. When I connected back the screen to pins 5 and 7 of the Attiny as described in Hogans lib the screen start flickering

SDA pin 5 ,SCL pin 7 for I2C

When I reverse the pins the flickering stops. But again nothing shows up on the screen.

The only thing I can think is that this part of the code I used for arduino is setting the I2C pins correctly

LiquidCrystal_I2Clcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

23022374_10212768014307300_514786920_n.jpg23021960_10212768864608557_894855588_n.jpg