Tuesday, November 25, 2014

Communicating between 2 trinkets with nrf24l01+ using 3 pins

Based upon http://nerdralph.blogspot.com/2014/01/nrf24l01-control-with-3-attiny85-pins.html

Following the instructions in that post can only receive data, but cannot be used to send data. After much searching, I could not find any working instructions.
So after much frustration, and some trial and error, this is my working schematic and sketch for communicating between two trinkets using nrf24l01+ with only 3 pins.

I am new to arduinos, and this is the second sketch I have ever written, so if you figure out a better way of doing this, please share it with the world, and let me know so I can delete this post.

I am not an engineer and do not understand how any of this works, so if you have any questions, I probably will not be able to answer them.

As this is a test sketch, there's a lot of blinking lights, disable the flash_color() calls as necessary.
I've already disabled a few of my earlier testing blinks, and my test is currently running as I type this, one blinking yellow as the sending loop runs, and the other blinking green as it receives the expected test value.

My modified schematic - CE is connected to CSN instead of VCC.

My full circuit:

Edit these functions in Mirf85.cpp:
void Nrf24l::ceHi(){
  //digitalWrite(cePin,HIGH);
}
void Nrf24l::ceLow(){
  //digitalWrite(cePin,LOW);
}
void Nrf24l::csnHi(){
  PORTB |= (1<<PINB2); // SCK->CSN HIGH
  delayMicroseconds(64);  // allow csn to settle
}
void Nrf24l::csnLow(){
  PORTB &= ~(1<<PINB2);  // SCK->CSN LOW
  delayMicroseconds(8);  // allow csn to settle
}

#include <spi85.h>
#include <mirf85.h>
#include <mirfhardwarespidriver85.h>
#include <adafruit_neopixel.h>

#define PIN 4
Adafruit_NeoPixel strip = Adafruit_NeoPixel(1, PIN, NEO_GRB + NEO_KHZ800);
uint32_t c_red = strip.Color(255, 0, 0);
uint32_t c_green = strip.Color(0, 255, 0);
uint32_t c_blue = strip.Color(0, 0, 255);
uint32_t c_yellow = strip.Color(255, 255, 0);
uint32_t c_magenta = strip.Color(255, 0, 255);
uint32_t c_cyan = strip.Color(0, 255, 255);

#define SEND 0
#define GET 1
#define WHICH 0 //change between 1 and 0 for each trinket

void setup(){
  Mirf.spi = &MirfHardwareSpi;
  Mirf.init();

  if (WHICH == GET) {
    Mirf.setRADDR((byte *)"test1");
    Mirf.setTADDR((byte *)"test2");
  } else {
    Mirf.setRADDR((byte *)"test2");
    Mirf.setTADDR((byte *)"test1");
  }
  //Although this example sketch only sends one way, I found with later experiments that this circuit can be used to send data both ways, so I've included the reverse "test2" here.

  Mirf.payload = sizeof(byte); //1
  Mirf.channel = 80;
  Mirf.config();

  strip.begin();
  strip.show();
}

void loop(){
  uint8_t nrfStatus;
  nrfStatus = Mirf.getStatus();
  nrfStatus = Mirf.getStatus();
  if((byte)nrfStatus == 14) flash_color(c_blue); //blue means okay
  else flash_color(c_magenta); //magenta means very bad

  if (WHICH == GET) get_it();
  else send_it();

  delay(100);
}

void send_it(){
  byte v = 3;
  flash_color(c_yellow); //yellow indicates the loop is running

  Mirf.send(&v);

  while( Mirf.isSending() ) {
//    flash_color(c_green); //green once is good, continuous green is bad
  }
}

void get_it() {
  byte c;

  if( Mirf.dataReady() ) {
    Mirf.getData((byte *)&c);

    if (c == 3) {
      flash_color(c_green); //green means good
    } else {
      flash_color(c_red); //red means very bad
    }
  } else {
//    flash_color(c_yellow); //yellow means nothing is happening
  }
}

void flash_color(uint32_t color) {
  strip.setPixelColor(0, color);
  strip.show();
  delay(200);
  strip.setPixelColor(0, strip.Color(0, 0, 0));
  strip.show();
  delay(200);
}

7 comments:

  1. Nice fritzing diagram. I try to use standard colors for Gnd/Vcc - i.e. green for ground, orange for 3.3V, & red for 5V.

    p.s. it would be nice if you turned off captcha for non-anonymous comments.

    ReplyDelete
    Replies
    1. The circuit shows exactly how my breadboard was wired, including wire colours.

      Delete
  2. p.p.s. Maybe you could update your post to indicate CE can't be tied high to send data when enhanced shockburst (EN_AA) is enabled.

    ReplyDelete
    Replies
    1. We're not all as smart as you. I have no idea what enhanced shockburst is, and there's nothing in your post about it.

      All I know is that your post does not work for me, and my post does.

      Maybe you could make a new post with a full tutorial of how to send and receive data between two attiny85s.

      Added: Wait, YOU'RE the one who said that CE should be tied high - you are the one who should edit their post regarding this.

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Thanks Jackson for compiling NerdRalphs blog about the NRF, being very new to Arduino, I quickly got lost in all the comments. Your Fritzing pic really helped me understand the schematic.

    I've got two trinkets wired up like your pic. I've installed attiny_nRF24L01 and RF24 folders into my library folder. The functions in Mirf85.cpp were changed as you instructed. I've copied and pasted your code. Changed the #include section to look like this:
    #include ""
    #include "Mirf85.h"
    #include "MirfHardwareSpiDriver85.h"
    #include "Adafruit_NeoPixel.h"

    But when I go to verify the sketch I get:

    _150508_TEST1.ino: In function 'void setup()':
    _150508_TEST1:21: error: 'Mirf' was not declared in this scope
    _150508_TEST1:21: error: 'MirfHardwareSpi' was not declared in this scope

    Any help would be greatly appreciated.

    ReplyDelete
    Replies
    1. Like I said I'm a noob and I don't know why parts of my posts are not showing up.

      So all my #includes have "less than" and "greater than" signs instead of the quotes. And the first #include is SPI85.h.

      Please accept my apologies.

      Delete