Sunday, 5 February 2012

Wireless sensor node - background rx (6)

I have started to think a bit more about deploying my wireless sensor network. My plan is still to deploy multiple cheap ATtiny85 based RF transmitting, battery powered sensor nodes. These will talk to an Arduino base station which will receive the readings. 

The base station needs to save the readings to an SD card, allow bulk uploads over Bluetooth and will possibly in future drive a screen. None of these things will be possible if the Arduino has to spend all its time blocked listening for readings from the sensor nodes. Therefore, following on from my last post, I decides to upgrade the Manchester library I have been using to do interrupt based RF message reception. 

I'm quite pleased with the results. The old API for receiving data looked like this. 

// This call blocks until a timeout or a message is received
// to avoid missing any messages the caller must either set no
// timeout or immediately call this method again after a timeout. 
unsigned int data = MANCHESTER.Receive();

Old API on Github.

This has now been improved to work as follows. 

// The MANRX code receives a single message in the background
// This call checks whether there is a message ready for us
// to get. 
if (MANRX_ReceiveComplete())
  // We extract the message
  unsigned int data = MANRX_GetMessage();
  // And tell MANX to start receiving the next message
  // in the background
  // Handle data...
New API on Github.

While working on this code upgrade I also spent some time improving my breadboard setup. I had previously wired my main breadboard to act as the RF RX and an ATtiny ISP. I then manually moved the ATtiny board onto a second breadboard which was battery powered and acted as the RF TX.

It turns out that the ISP circuit leaves a couple of pins free on the ATtiny which is just enough to run the RF TX circuit which I have been using. As a result, I was able to put together the following neat color coded setup on a single breadboard.

This is color coded as follows.
  • Yellow - GND
  • Orange - VCC
  • Black - ISP connections
  • Red - RF data connections
  • Green - RF antenna
The LED included in the breadboard isn't normally part of a circuit.but is wired up to ground so that I can connect a data output to the LED VCC and see visually the state of that data output.

To test my RF code I have to use the following steps.
  • Program the Arduino with the ISP sketch
  • Program the ATtiny with my RF TX code using the Arduino as an ISP
  • Program the Arduino with my RF RX code
Comparison with VirtualWire

Now that I have added interrupt driven RX logic to the Manchester library it is worth considering what differences still remain between the Manchester library which I am using and the more popular VirtualWire library.
  • TX - VirtualWire uses interrupt based TX to allow for non blocking message sending. Manchester does not.
  • Variable message size - VirtualWire sends a message length so the receiver can receive messages of any length. Manchester allows different message lengths but the receiver must explicitly expect to receive the same size of message as the sender is sending.
  • Checksums - VirtualWire includes a built in checksum. Manchester does not.
  • Efficiency - VirtualWire uses 4->6 bit encoding. Manchester uses 1->2 bit encoding.
  • Clock Skew - VirtualWire is more sensitive to clock skew than the Manchester library.
This final point is the reason why I really like using the Manchester code. According to section 21.4.1 of the ATtiny85 datasheet the ATtiny is shipped with a clock of 8MHz which is only accurate to ±10%. It is possible to calibrate the clock to be more accurate but it will still vary depending on temperature and supply voltage. Given that I want to use my ATtiny85s in battery powered sensor nodes across a range of temperatures it is important that I use an RF library which can handle noticeable clock skew.


  1. Better late than never :-)
    This is exactly what I was looking for.
    Tried it - works perfectly.


  2. Has anyone got this working doing Reception on an aTTiny85 or 84? I have used your library successfully going from ArduinoMega to Arduino Uno. Receiving on pin 2. I can also get the code to compile onto an 85 using SetRXPin(4). But as soon as I call SetupReceive() basically something happens that locks up the thing. I know it is a pill to trouble shoot in comments. But I am just looking for at least an up or down, should it work?


    1. I am one more step along the way. I needed to make the change of ISR(TIMER1_COMPA_vect) so that the the interrupt has something to run against. Original code is ISR(TIMER2_COMPA_vect)works on atMega since it is using timer2. But hte aTtiny setsup Timer1. (best I can figure)

      Now my issues moves to actually getting data. With some rudimentary troubleshooting I can establish the receiver is getting transmissions. By just passing through a readDigital to an LED I can see the data pin providing in sync with the transmitter.

      But the ISR function is never stepping past RX_MODE_SYNC. It fails one of the tests and falls back to pre. So even ReceiveComplete never returns true. Any notions why this might be? I will keep hammering but any notions would be awesome.

    2. Hi,
      I have same problem and have also detected same thing as you did. If you get some results, please post them here.

      Thank you

    3. I've just accepted a Manchester patch ( that fixes the ISR(TIMER1_COMPA_vect) issue. However, I've never actually tested with an ATTiny being the RX node so I'm not sure what issue you might be hitting.

      If you are never completing sync you may be getting some kind of interference.

    4. Hi,
      I have been testing with patched version, and it now moves a bit further. It does not block any more, but...
      1. sync is never completed, even if I connect transmiter pin with receiver pin without RF modules (no interference..)
      2. when I was debuging, I have set 1s delay before each command, and led on/off. Now after command MANRX_SetupReceive(), delay(1000) lasts 1/16th second (if I put 16000 in delay, it lasts 1s).
      I do not have big knowledge on such programming, so I am lost here :(

    5. My co-worker and I have been working on this still. He solved it here:

      Arduino Mega sending, ATTiny85 receiving with the MIT Tiny85 Arduino Core loaded onto it.

      I have not confirmed this myself but he has had this working. It was very much in synchronizing the timers. I have some time next week to dig into his work and will be back to report!

    6. That's great news! I'm reviewing the changes here:

  3. what happens when multiple TX units try to send data to the same RX at the same time?

    1. You will likely receive a corrupt message. TX nodes should send each message two or more times with random gaps to make it likely that each message gets through at least once.