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);
}