First working project using the Semitek SE8R01 low cost nRF24l01+ "replacement chips"

This is my first project using what I'd thought were Nordic nRF24l01+ however what I got was Semitek SE8R01 which is pin compatible with Nordic nRF24l01+ but not software compatible! 

The nRF24l01+ use less power and are generally thought better but these Semitek SE8R01 are fine for less demanding roles when the power consumption, range are within the Semitek SE8R01 capabilities - They are ideal for really low-cost hobby work IMHO but remember the Nordic nRF24l01+  libraries and sample code will not work on the Semitek SE8R01 units!

Yes the Nordic chips are better in many (most) ways but these tiny units are low power, reliable and CHEAP less than 20cent US per unit and they support 1 to many and quite sophticated ACK models all in hardware. Ideal for linking up parts of a system were bluetooth and WiFi are not ideal eg. when making a wireless system with local nodes. Of course you can drop in a $2 ESP8266 Microcontroller and Wifi SoC with one of these for a web / Wifi gateway.

This is the first project I made using this part a remote controlled relay for a heat pump
  1.  The local transmitter connected to a zero vault switch (relay control line normally open and closed when heat pump needs to send a signal)
  2. Thr remote receiver gets a 1 or 0 from the transmitter   (first byte of payload) and turns a local relay on/ on off. This relay output controls the control line to a remote heat pump
This code is based on the sample from GitHub I just saved 2 copies of the demo project one for sending and one for receiving. The demo program has a toggle set at compile time to build a transmitter program or a receiver program. Of course, you need 2 arduinos and 2 of the Semitek SE8R01 connect to each one working as a transmitter the other a receiver.

The other files in the project were not changed (headers etc for the Semitek SE8R01 library) I did later change functtioner.ino I changed Tx power to max the original value is commented out. Refer to the Semitek SE8R01 datasheet for more info


        SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_RF_SETUP,0x4F);

        //SPI_RW_Reg(iRF_CMD_WRITE_REG|iRF_BANK0_RF_SETUP,0x48);

One item of note I had my test transmitter near a working 433mHz receiver based remote plug socket and the remote 433mHz receiver would not work when the Semitek SE8R01 was working sending data every few seconds at FULL POWER. The final setup for this project was not near any 433mHz installations so this is not a problem in my case but just to let you know the Semitek SE8R01 might interfere with non-related frequencies. I understand the Semitek SE8R01 are 2.4gHz

Taken from the datasheet intro (Refer to the Semitek SE8R01 datasheet for more info)


"TheSE8R01 is a single chip 2.4GHz transceiver with an embedded baseband protocol engine, suitable for ultralow power wireless applications. The SE8R01 is designed for operation in the world wide ISM frequency band at 2.400 - 2.4835GHz. To design a radio system with the SE8R01, you simply need an MCU (microcontroller) and a few external passive components. You can operate and configure the SE8R01 through a Serial Peripheral Interface (SPI). The register map, which is accessible through the SPI, contains all configuration registers in the SE8R01 and is accessible in all operation modes of the chip. The embedded baseband protocol engine is based on packet communication and supports various modes from manual operation to advanced autonomous protocol operation. Internal FIFOs ensure a smooth data flow between the radio front end and the system’s MCU. Protocol engine reduces system cost by handling all the high speed link layer operations. The radio front end uses GFSK modulation. It has user configurable parameters like frequency channel, output power and air data rate. SE8R01 supports an air data rate of 500kbps, 1Mbps and 2Mbps. The high air data rates combined with two power saving modes make the SE8R01 very suitable for ultralow power designs. The addition of internal filtering to SE8R01 has improved the margins for meeting RF regulatory standards. Internal voltage regulators ensure a high Power Supply Rejection Ratio (PSRR) and a wide power supply range"

Code for Sender (Sender and pull down resistor for the input pin)

#include "se8r01.h"
const int powerswitchPin = 2;
byte gtemp[5];
byte k=0;
//***************************************************
#define TX_ADR_WIDTH    4   // 5 unsigned chars TX(RX) address width
#define TX_PLOAD_WIDTH  6  // 32 unsigned chars TX payload

unsigned char TX_ADDRESS[TX_ADR_WIDTH]  = 
{
  0x34,0x43,0x10,0x10
}; // Define a static TX address


byte mode ='t';      //r=rx, t=tx
int switchState = 0;         // variable for reading the power switch status
unsigned char rx_buf[TX_PLOAD_WIDTH] = {0}; // initialize value
unsigned char tx_buf[TX_PLOAD_WIDTH] = {0};
boolean toggle=true;
//***************************************************
void setup() 
{

   // initialize the pushbutton pin as an input:
  pinMode(powerswitchPin, INPUT);
  pinMode(CEq,  OUTPUT);
  pinMode(SCKq, OUTPUT);
  pinMode(CSNq, OUTPUT);
  pinMode(MOSIq,  OUTPUT);
  pinMode(MISOq, INPUT);
  pinMode(IRQq, INPUT);

  Serial.begin(9600);
  init_io();                        // Initialize IO port
  unsigned char status=SPI_Read(STATUS);
  Serial.print("status = ");    
  Serial.println(status,HEX);     
  Serial.println("*******************Radio starting*****************");

  digitalWrite(CEq, 0);
  delay(1);
  se8r01_powerup();
  se8r01_calibration();
  se8r01_setup();
  radio_settings();
 //tx mode
 SPI_RW_Reg(WRITE_REG|iRF_BANK0_CONFIG, 0x3E);
 Serial.println("*******************TX****************************");
 digitalWrite(CEq, 1);
}

void loop() 
{

  // read the state of the pushbutton value:
  switchState = digitalRead(powerswitchPin);
  Serial.print("Switch state is "); 
  Serial.println(switchState); 
  
  // Logic to test the if the switch is on: Control line closed. If it is, the buttonState is HIGH:
  if (switchState == HIGH) 
  {
    // turn on:
    //if (k==1) toggle=false; else toggle=true; /Uncomment this line to transmit data only when state changes current code keeps resending the status every few seconds
    k=1; // Set global variable used in transit code the value of k is sent to the reciver
    TXX();
    delay(1000);
  } 
  else 
  {
    // turn off:
    //if (k==0) toggle=false; else toggle=true; /Uncomment this line to transmit data only when state changes current code keeps resending the status every few seconds
    k=0;// Set global variable used in transit code the value of k is sent to the reciver
    TXX();
    delay(1000);
  }
}

void TXX()
 {
  //if (toggle==true)
 // {//Uncomment this line to transmit data only when state changes current code keeps resending the status every few seconds
       for(byte i=0; i
        tx_buf[i] = k; 
        
    unsigned char status = SPI_Read(STATUS); 
    
  
      SPI_RW_Reg(FLUSH_TX,0);
      SPI_Write_Buf(WR_TX_PLOAD,tx_buf,TX_PLOAD_WIDTH);     
    
    SPI_RW_Reg(WRITE_REG+STATUS,0xff);   // clear RX_DR or TX_DS or MAX_RT interrupt flag
    Serial.println(status,HEX);    
    delay(3000);
  //}/Uncomment this line to transmit data only when state changes current code keeps resending the status every few seconds
 }


void radio_settings()
{
        
SPI_RW_Reg(WRITE_REG|iRF_BANK0_EN_AA, 0x01);          //enable auto acc on pip 1
SPI_RW_Reg(WRITE_REG|iRF_BANK0_EN_RXADDR, 0x01);      //enable pip 1
SPI_RW_Reg(WRITE_REG|iRF_BANK0_SETUP_AW, 0x02);        //4 byte adress
SPI_RW_Reg(WRITE_REG|iRF_BANK0_SETUP_RETR, B00001010);        //lowest 4 bits 0-15 rt transmisston higest 4 bits 256-4096us Auto Retransmit Delay
SPI_RW_Reg(WRITE_REG|iRF_BANK0_RF_CH, 40);
SPI_RW_Reg(WRITE_REG|iRF_BANK0_RF_SETUP, 0x4f);        //2mps 0x4f
//SPI_RW_Reg(WRITE_REG|iRF_BANK0_DYNPD, 0x01);          //pipe0 pipe1 enable dynamic payload length data
//SPI_RW_Reg(WRITE_REG|iRF_BANK0_FEATURE, 0x07);        // enable dynamic paload lenght; enbale payload with ack enable w_tx_payload_noack
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);  //from tx
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width
        
}
        
    


Code for Receiver (Receiver and Relay board)

#include "se8r01.h"
byte gtemp[5];
byte k=0;
//***************************************************
#define TX_ADR_WIDTH    4   // 5 unsigned chars TX(RX) address width
#define TX_PLOAD_WIDTH  6  // 32 unsigned chars TX payload

unsigned char TX_ADDRESS[TX_ADR_WIDTH]  = 
{
  0x34,0x43,0x10,0x10
}; // Define a static TX address


byte mode ='r';      //r=rx, t=tx

unsigned char rx_buf[TX_PLOAD_WIDTH] = {0}; // initialize value
unsigned char tx_buf[TX_PLOAD_WIDTH] = {0};
//***************************************************



int relaycontrolline = 7;


void setup() 
{
 pinMode(relaycontrolline, OUTPUT);
  digitalWrite(relaycontrolline, HIGH); // Default the relay to off
  pinMode(CEq,  OUTPUT);
  pinMode(SCKq, OUTPUT);
  pinMode(CSNq, OUTPUT);
  pinMode(MOSIq,  OUTPUT);
  pinMode(MISOq, INPUT);
  pinMode(IRQq, INPUT);
  Serial.begin(9600);
  init_io();                        // Initialize IO port
  unsigned char status=SPI_Read(STATUS);
  Serial.print("status = ");    
  Serial.println(status,HEX);     
  Serial.println("*******************Radio starting*****************");
  digitalWrite(CEq, 0);
  delay(1);
  se8r01_powerup();
  se8r01_calibration();
  se8r01_setup();
  radio_settings();

   //rx mode
   SPI_RW_Reg(WRITE_REG|iRF_BANK0_CONFIG, 0x3f); 
   Serial.println("*******************RX mode************************"); 
   digitalWrite(CEq, 1);
}



void loop() 
{
  RXX();
}


void RXX()
{
//  Grab incoming data check the value being recived,report this to the serial print device and write the value to the relay control pin to set the relay On / Off as needed
//   Code only reads the first byte of payload.

    if(digitalRead(IRQq)==LOW)
    {
    delay(1);      //read reg too close after irq low not good
    unsigned char status = SPI_Read(STATUS);    
    if(status&STA_MARK_RX)                                           // if receive data ready (TX_DS) interrupt
    {
      SPI_Read_Buf(RD_RX_PLOAD, rx_buf, TX_PLOAD_WIDTH);             // read playload to rx_buf
      SPI_RW_Reg(FLUSH_RX,0); // clear RX_FIFO
     //Serial.print("rx_buf[i]");      
      for(byte i=0; i<1 font="" i="">
      {
          //Serial.print(" : ");
          //Serial.print(rx_buf[i]);                              // print rx_buf
          if  (rx_buf[1]==0) 
          {
            Serial.println("Recived Zero, Turn relay OFF");
            digitalWrite(relaycontrolline, HIGH);
          }
            else
          {
            Serial.println("Recived One, Turn relay ON");
            digitalWrite(relaycontrolline, LOW);
          }  
      }
      //Serial.println(" ");
      SPI_RW_Reg(WRITE_REG+STATUS,0xff);
    }
     else
      {
        SPI_RW_Reg(WRITE_REG+STATUS,0xff);
     }  
    }
  delay(1);
}

void radio_settings()
{        
SPI_RW_Reg(WRITE_REG|iRF_BANK0_EN_AA, 0x01);          //enable auto acc on pip 1
SPI_RW_Reg(WRITE_REG|iRF_BANK0_EN_RXADDR, 0x01);      //enable pip 1
SPI_RW_Reg(WRITE_REG|iRF_BANK0_SETUP_AW, 0x02);        //4 byte adress
SPI_RW_Reg(WRITE_REG|iRF_BANK0_SETUP_RETR, B00001010);        //lowest 4 bits 0-15 rt transmisston higest 4 bits 256-4096us Auto Retransmit Delay
SPI_RW_Reg(WRITE_REG|iRF_BANK0_RF_CH, 40);
SPI_RW_Reg(WRITE_REG|iRF_BANK0_RF_SETUP, 0x4f);        //2mps 0x4f
//SPI_RW_Reg(WRITE_REG|iRF_BANK0_DYNPD, 0x01);          //pipe0 pipe1 enable dynamic payload length data
//SPI_RW_Reg(WRITE_REG|iRF_BANK0_FEATURE, 0x07);        // enable dynamic paload lenght; enbale payload with ack enable w_tx_payload_noack
SPI_Write_Buf(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);  //from tx
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); // Use the same address on the RX device as the TX device
SPI_RW_Reg(WRITE_REG + RX_PW_P0, TX_PLOAD_WIDTH); // Select same RX payload width as TX Payload width     
}