NRFLite + bluetooth + software serial - cannot parse string

I know the title sounds stupid but help me out :slight_smile:
I’m developing a project, i have 2 arduino boards that talk to each other with an nrf24l01, one is sending data once a second, the other one just receives it. the transmitter collects data from 2 flow meters, and sends it to the receiver, that i call the master.
the master has a Bluetooth module that it uses to talk to an app on a android tablet.
the code flow is as follows:
when first powered on the master sends a request thru Bluetooth to the tablet and asks for a configuration. that means it sends some text thru software serial and waits for a certain text to arrive. after the string is received it request the tablet battery level using the same ‚Äúprotocol‚ÄĚ and after that it starts collecting sensor data and sends it thru Bluetooth - serial communication.
this is the master:

this is the ‚Äúslave‚ÄĚ / transmitter:

and here is the problem:
when i use software serial for bluetooth communication i cannot parse the received string. nothing happens, the variable that was supposed to advance the code does not change. if i don’t use software serial, if i use the builtin serial it works.
the problem only arises after i initialize the radio.
here is the code:

#include <SPI.h>
#include <NRFLite.h>

#include <SoftwareSerial.h>
SoftwareSerial BT(10, 9);

//definire pini
const int turatie = 2;
const int viteza = 3;
const int move_state = 4;
const int priza_put = 5;
const int releu = 6;

//definire variabile nrf
const static uint8_t RADIO_ID = 0;       // Our radio's id.  The transmitter will send to this id.
const static uint8_t PIN_RADIO_CE = 7;
const static uint8_t PIN_RADIO_CSN = 8;
struct RadioPacket // Any packet up to 32 bytes can be sent.
{
    uint8_t FromRadioId;
    uint32_t debit;
    
};

NRFLite _radio;
RadioPacket _radioData;

//definire alte variabile
float tensiune = 0;
int val_a4 = 0;
int variabila_viteza = 4055;
byte move_s = 0;
byte priza_s = 0;
byte i = 0;
byte j = 0;
byte avansare = 0;
unsigned long previousMillis = 0;
const long interval = 1000;
byte PB_baterie = 0;
bool m_ON = false;
int consum = 255;
int init_radio = 0;

boolean dateNoi = false;
const byte numChars = 32;
char messageFromPC[numChars] = {0};
char receivedChars[numChars];
char tempChars[numChars];

byte pornire_incarcare = 0;
byte oprire_incarcare = 0;

//____________________________

//definire variabile pentru isr
float rev = 0;
int rpm;
int oldtime = 0;
int time;
float rev_v = 0;
int rpm_v;
//____________________________


void setup() {
  
  
  BT.begin(9600);
  BT.println("Hello from Master!!");
  //_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE250KBPS);
  pinMode(move_state, INPUT);
  pinMode(priza_put, INPUT);
  pinMode(releu, OUTPUT);
}

void loop() {
  

  if(avansare == 0) {
    
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;
  i++;
  }
  
  if (i == 1) 
  {
  BT.println("@SETARI:0;REQ$#");
  i = 0;
  }
  
  recvWithStartEndMarkers();
  
      if (dateNoi == true) 
      {
      strcpy(tempChars, receivedChars);
      salvare_date_noi();
      //showParsedData();
      avansare = 20;
      dateNoi = false;
      }
    
  }
  if(pornire_incarcare == 0 || oprire_incarcare == 0 || variabila_viteza == 0) {
    avansare = 0;
  }
  
  if (avansare >= 1 && avansare < 20) {
  if( init_radio == 0)
  {
    _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE250KBPS);
    init_radio = 1;
  }
  citire_turatii();
  citire_viteza();  
  citire_priza_putere();
  citire_tensiune();
  citire_consum();
  start_charge();
  j = 0;
  avansare++;
  }

  if (avansare == 20) {
  
    if (j == 0) {
     BT.println("@NIVBAT:0;REQ$#");  
     j++;
     }
    recvWithStartEndMarkers();
  
      if (dateNoi == true) 
      {
      strcpy(tempChars, receivedChars);
      save_bat_percent();
      //showParsedData_bat();
      dateNoi = false;
      avansare = 1;
      }
    
  }
  
  
}


  void salvare_date_noi()
  {
    char * strtokIndx; 

    strtokIndx = strtok(tempChars,":");      
    strcpy(messageFromPC, strtokIndx); 
 
    strtokIndx = strtok(NULL, ":"); 
    pornire_incarcare = atoi(strtokIndx);     

    strtokIndx = strtok(NULL, ":");
    oprire_incarcare = atoi(strtokIndx);     

    strtokIndx = strtok(NULL, ":");
    variabila_viteza = atoi(strtokIndx);     
  }

void recvWithStartEndMarkers() {
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '@';
    char endMarker = '*';
    char rc;

    while (BT.available() > 0 && dateNoi == false) {
        rc = BT.read();

        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; 
                recvInProgress = false;
                ndx = 0;
                dateNoi = true;
            }
        }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void showParsedData() {
    BT.print("Message ");
    BT.println(messageFromPC);
    BT.print("Pornire incarcare ");
    BT.println(pornire_incarcare);
    
    BT.print("Oprire incarcare ");
    BT.println(oprire_incarcare);
    
    BT.print("Variabila viteza ");
    BT.println(variabila_viteza);
    BT.println();
}



  void save_bat_percent()
  {
    char * strtokIndx; // this is used by strtok() as an index

    strtokIndx = strtok(tempChars,":");      // get the first part - the string
    strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
 
    strtokIndx = strtok(NULL, ":"); // this continues where the previous call left off
    PB_baterie = atoi(strtokIndx);     // convert this part to an integer

   }

 void start_charge()
 {
  if (PB_baterie < pornire_incarcare)
      {
        digitalWrite(releu, LOW);
      }
      if (PB_baterie > oprire_incarcare && m_ON == true) // && m_ON == true de adaugat verificarea starii motorului
      {
       digitalWrite(releu, HIGH); 
      }
      
 }


 void isr_viteza()
{
  rev_v++;
}

void citire_viteza()
{
  attachInterrupt(1,isr_viteza,RISING);
  delay(1000);
  detachInterrupt(1);                         
  time = millis()-oldtime;                   
  rpm_v = ((rev_v/time)*variabila_viteza)/10; 
  oldtime = millis();                         
  rev_v = 0;
  BT.print("@VITEZA:");
  move_s = digitalRead(move_state);
  if(move_s == false)
  {
    BT.print(rpm_v);
  }
  else 
  {
    BT.print("0");
  }
  BT.println(";INT$#");
  
 }

 void citire_tensiune()
 {
  val_a4 = analogRead(A4);
  tensiune = val_a4*0.49;
  if (tensiune < 25)
  {
  BT.println("@STARE_MOTOR:0;BOOL$#");
  m_ON = false;
  }
  if (tensiune > 25)
  {
  BT.println("@STARE_MOTOR:1;BOOL$#");
  m_ON = true;
  }
  BT.print("@BATERIE:");
  BT.print(tensiune, 0);
  BT.println(";FLOAT$#");
  delay(1000);
 }

 void isr_turatii()
{
  rev++;
}

void citire_turatii()
{
  attachInterrupt(0,isr_turatii,RISING);
  delay(1000);
  detachInterrupt(0);           
  time=millis()-oldtime;       
  rpm=(rev/time)*10000;    
  oldtime=millis();             
  rev=0;
  BT.print("@TURMOTOR:");
  BT.print(rpm); 
  BT.println(";INT$#");
}



 void citire_priza_putere()
 {
  val_a4 = analogRead(A4);
  tensiune = val_a4*0.0488758;
  priza_s = digitalRead(priza_put);
  if (priza_s == true && tensiune > 25)
  {
    BT.println("@PRZ_PUTERE:1;BOOL$#");
  }
  
  else
  {
    BT.println("@PRZ_PUTERE:0;BOOL$#");
  }
  delay(1000);
 }

 void citire_consum()
 {
  while (_radio.hasData())
    {
        _radio.readData(&_radioData); // Note how '&' must be placed in front of the variable name.

        consum = _radioData.debit;
        
    }
  BT.print("@CONSUM:");
  BT.print(consum);
  BT.println(";INT$#");
  delay(1000);
  
  
 }
}*/

i tried to initialize the radio later but once every 20 loops the master requests the tablet battery level so it can control its charging. i tried powering down the radio but my code no longer parses the string or increments the variable to advance the code.
so, if i don’t initialize the radio my code works, if i don’t use software serial and instead use hardware serial my code works.
HELP!

I couldn't read that mess. Put EVERY { on a line BY ITSELF. Put EVERY } on a line BY ITSELF. Use Tools + Auto Format to properly indent your code.

Why are you using SoftwareSerial when you are not using the hardware serial port for anything?

Your call to recvWithStartEndMarkers() should be directly in loop() and not subject to any IF statements or other limitation. It must be called every time loop() repeats.

And add some code to print the received data before it is parsed. When everything works you can remove that code.

…R

PS … leave Hardware Serial free for debug messages.

here is the auto formated code:

#include <SPI.h>
#include <NRFLite.h>

#include <SoftwareSerial.h>
SoftwareSerial BT(10, 9);

//definire pini
const int turatie = 2;
const int viteza = 3;
const int move_state = 4;
const int priza_put = 5;
const int releu = 6;

//definire variabile nrf
const static uint8_t RADIO_ID = 0;       // Our radio's id.  The transmitter will send to this id.
const static uint8_t PIN_RADIO_CE = 7;
const static uint8_t PIN_RADIO_CSN = 8;
struct RadioPacket // Any packet up to 32 bytes can be sent.
{
  uint8_t FromRadioId;
  uint32_t debit;

};

NRFLite _radio;
RadioPacket _radioData;

//definire alte variabile
float tensiune = 0;
int val_a4 = 0;
int variabila_viteza = 4055;
byte move_s = 0;
byte priza_s = 0;
byte i = 0;
byte j = 0;
byte avansare = 0;
unsigned long previousMillis = 0;
const long interval = 1000;
byte PB_baterie = 0;
bool m_ON = false;
int consum = 255;

boolean dateNoi = false;
const byte numChars = 32;
char messageFromPC[numChars] = {0};
char receivedChars[numChars];
char tempChars[numChars];

byte pornire_incarcare = 0;
byte oprire_incarcare = 0;

//____________________________

//definire variabile pentru isr
float rev = 0;
int rpm;
int oldtime = 0;
int time;
float rev_v = 0;
int rpm_v;
//____________________________


void setup() {


  BT.begin(9600);
  BT.println("Hello from Master!!");
  _radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE250KBPS);
  pinMode(move_state, INPUT);
  pinMode(priza_put, INPUT);
  pinMode(releu, OUTPUT);
}

void loop() {


  if (avansare == 0) {

    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      i++;
    }

    if (i == 1)
    {
      BT.println("@SETARI:0;REQ$#");
      i = 0;
    }

    recvWithStartEndMarkers();

    if (dateNoi == true)
    {
      strcpy(tempChars, receivedChars);
      salvare_date_noi();
      //showParsedData();
      avansare = 20;
      dateNoi = false;
    }

  }
  if (pornire_incarcare == 0 || oprire_incarcare == 0 || variabila_viteza == 0) {
    avansare = 0;
  }

  if (avansare >= 1 && avansare < 20) {
    citire_turatii();
    citire_viteza();
    citire_priza_putere();
    citire_tensiune();
    citire_consum();
    start_charge();
    j = 0;
    avansare++;
  }

  if (avansare == 20) {
    if (j == 0) {
      BT.println("@NIVBAT:0;REQ$#");
      j++;
    }
    recvWithStartEndMarkers();

    if (dateNoi == true)
    {
      strcpy(tempChars, receivedChars);
      save_bat_percent();
      //showParsedData_bat();
      dateNoi = false;
      avansare = 1;
    }

  }


}


void salvare_date_noi()
{
  char * strtokIndx;

  strtokIndx = strtok(tempChars, ":");
  strcpy(messageFromPC, strtokIndx);

  strtokIndx = strtok(NULL, ":");
  pornire_incarcare = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ":");
  oprire_incarcare = atoi(strtokIndx);

  strtokIndx = strtok(NULL, ":");
  variabila_viteza = atoi(strtokIndx);
}

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '@';
  char endMarker = '*';
  char rc;

  while (BT.available() > 0 && dateNoi == false) {
    rc = BT.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0';
        recvInProgress = false;
        ndx = 0;
        dateNoi = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

void showParsedData() {
  BT.print("Message ");
  BT.println(messageFromPC);
  BT.print("Pornire incarcare ");
  BT.println(pornire_incarcare);

  BT.print("Oprire incarcare ");
  BT.println(oprire_incarcare);

  BT.print("Variabila viteza ");
  BT.println(variabila_viteza);
  BT.println();
}



void save_bat_percent()
{
  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ":");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ":"); // this continues where the previous call left off
  PB_baterie = atoi(strtokIndx);     // convert this part to an integer

}

void start_charge()
{
  if (PB_baterie < pornire_incarcare)
  {
    digitalWrite(releu, LOW);
  }
  if (PB_baterie > oprire_incarcare && m_ON == true) // && m_ON == true de adaugat verificarea starii motorului
  {
    digitalWrite(releu, HIGH);
  }

}


void isr_viteza()
{
  rev_v++;
}

void citire_viteza()
{
  attachInterrupt(1, isr_viteza, RISING);
  delay(1000);
  detachInterrupt(1);                         //detaches the interrupt
  time = millis() - oldtime;                  //finds the time
  rpm_v = ((rev_v / time) * variabila_viteza) / 10; //calculates speed
  oldtime = millis();                         //saves the current time
  rev_v = 0;
  BT.print("@VITEZA:");
  move_s = digitalRead(move_state);
  if (move_s == false)
  {
    BT.print(rpm_v);
  }
  else
  {
    BT.print("0");
  }
  BT.println(";INT$#");

}

void citire_tensiune()
{
  val_a4 = analogRead(A4);
  tensiune = val_a4 * 0.49;
  if (tensiune < 25)
  {
    BT.println("@STARE_MOTOR:0;BOOL$#");
    m_ON = false;
  }
  if (tensiune > 25)
  {
    BT.println("@STARE_MOTOR:1;BOOL$#");
    m_ON = true;
  }
  BT.print("@BATERIE:");
  BT.print(tensiune, 0);
  BT.println(";FLOAT$#");
  delay(1000);
}

void isr_turatii()
{
  rev++;
}

void citire_turatii()
{
  attachInterrupt(0, isr_turatii, RISING);
  delay(1000);
  detachInterrupt(0);           //detaches the interrupt
  time = millis() - oldtime;    //finds the time
  rpm = (rev / time) * 10000;   //calculates rpm
  oldtime = millis();           //saves the current time
  rev = 0;
  BT.print("@TURMOTOR:");
  BT.print(rpm);
  BT.println(";INT$#");
}



void citire_priza_putere()
{
  val_a4 = analogRead(A4);
  tensiune = val_a4 * 0.0488758;
  priza_s = digitalRead(priza_put);
  if (priza_s == true && tensiune > 25)
  {
    BT.println("@PRZ_PUTERE:1;BOOL$#");
  }

  else
  {
    BT.println("@PRZ_PUTERE:0;BOOL$#");
  }
  delay(1000);
}

void citire_consum()
{
  while (_radio.hasData())
  {
    _radio.readData(&_radioData); // Note how '&' must be placed in front of the variable name.

    consum = _radioData.debit;

  }
  BT.print("@CONSUM:");
  BT.print(consum);
  BT.println(";INT$#");
  delay(1000);


}

i’m using software serial because i am programming the arduino nano board with an USB cable and i didn’t want to use jumpers to disconnect every time i needed to program it. but that is not the problem here.
i tried moving the recvWithStartEndMarkers() outside of any if statements but still can’t parse the string i receive. i don’t want it outside the if statement because i want to receive data only when i’m expecting it, leaving the processor free for the rest of the routines. i’m adding some serial.print to try and debug some stuff. the weird part is that i think software serial and nrflite libraries are conflicting somehow.

i don't want it outside the if statement because i want to receive data only when i'm expecting it,

This is nonsense. That's like locking your mailbox when you're not expecting a check from Grandma for your birthday.

You deal with the serial data that arrives WHEN IT ARRIVES. You deal with parsing the data when it makes sense. You deal with using the parsed data when it makes sense. You do NOT delay dealing with the incoming serial data.

either way that is not the problem.
i moved the routine outside the if statements, it's the first thing in the loop and it does the same thing. i narrowed it down to

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '@';
  char endMarker = '*';
  char rc;
  
  
  while (BT.available() > 0 && dateNoi == false) {
    rc = BT.read();

    if (recvInProgress == true) {
      Serial.print("recvInProgress: ");
      Serial.println(recvInProgress);
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0';
        recvInProgress = false;
        ndx = 0;
        dateNoi = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

if i replace in:
while (BT.available() > 0 && dateNoi == false) with
while (Serial.available() > 0 && dateNoi == false)
the code works.
i'm not a programming expert but software serial library uses some code from stream.h that has a public int called available and so does nrflite. perhaps NRFlite is modifying it and that is why it never becomes larger than 0?

L.E. actually nrflite does not have that variable.

i'm not a programming expert but software serial library uses some code from stream.h that has a public int called available and so does nrflite.

The SoftwareSerial class inherits from Stream. The Stream class has a public FUNCTION called available() that returns an int. It does NOT have a public int called available.

The radio library can not possibly step on the value returned by a function.

i narrowed the problem to a conflict between softwareserial and nrflite. and the problem is that when i call bt.available() the result is 0. something is overwriting what should have been the value there. here is another code, much simpler, that i tried that gives me the same result:

#include <SPI.h>
#include <NRFLite.h>

#include <SoftwareSerial.h>
SoftwareSerial BT(10, 9);

// Example 5 - Receive with start- and end-markers combined with parsing

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

// variables to hold the parsed data
char messageFromPC[numChars] = {0};
int integerFromPC = 0;
float floatFromPC = 0.0;

boolean newData = false;

//============

const static uint8_t RADIO_ID = 0;       // Our radio's id.  The transmitter will send to this id.
const static uint8_t PIN_RADIO_CE = 7;
const static uint8_t PIN_RADIO_CSN = 8;
struct RadioPacket // Any packet up to 32 bytes can be sent.
{
  uint8_t FromRadioId;
  uint32_t debit;

};

NRFLite _radio;
RadioPacket _radioData;

void setup() {
  Serial.begin(9600);
  Serial.println("This demo expects 3 pieces of data - text, an integer and a floating point value");
  Serial.println("Enter data in this style <HelloWorld, 12, 24.7>  ");
  Serial.println();
  BT.begin(9600);
  BT.println("Hello from Master!!");
  //_radio.init(RADIO_ID, PIN_RADIO_CE, PIN_RADIO_CSN, NRFLite::BITRATE250KBPS);
}

//============

void loop() {
  recvWithStartEndMarkers();
  
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    // this temporary copy is necessary to protect the original data
    //   because strtok() used in parseData() replaces the commas with \0
    parseData();
    showParsedData();
    newData = false;
  }
}

//============

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;
  int ads = BT.available();
  Serial.print("variabila cu lungimea la ce a primit: ");
  Serial.println(ads);
  
  while (BT.available() > 0 && newData == false) {
    rc = BT.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

//============

void parseData() {      // split the data into its parts

  char * strtokIndx; // this is used by strtok() as an index

  strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  integerFromPC = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ",");
  floatFromPC = atof(strtokIndx);     // convert this part to a float

}

//============

void showParsedData() {
  Serial.print("Message ");
  Serial.println(messageFromPC);
  Serial.print("Integer ");
  Serial.println(integerFromPC);
  Serial.print("Float ");
  Serial.println(floatFromPC);
}

if you remove the comment from radio.init the code no longer functions

i narrowed the problem to a conflict between softwareserial and nrflite.

So now would be a good time to post a link to the NRFLite library. I suspect that it is using pin change interrupts, the same as SoftwareSerial.

A board with more than one hardware serial port is in your future.

this is the library.

i hope i don't have to change the pcb as i already made 50 of them.
i tried with a different software serial library - NeoSWSerial, the same thing happens.
i tried with the basic_rx and basic_tx examples from nrflite library to send and receive data and send them thru bluetooth on my phone and it works. the problem is with receiving data from bluetooth.

The NRFLite library is using SPI to have the Arduino talk to the radio. That involves pins 10, 11, 12, and 13. You won't be able to do software serial on any of those pins while using the NRFLite library.

PaulS:
The NRFLite library is using SPI to have the Arduino talk to the radio. That involves pins 10, 11, 12, and 13. You won't be able to do software serial on any of those pins while using the NRFLite library.

That's not quite correct.

You don't need to use pin 10 as part of the SPI control - you can use any pin for Slave Select. BUT pin 10 must be set as OUTPUT to ensure the Arduino operates as SPI master.

In this case it seems that the OP is using pin 10 as SoftwareSerial RX which is an INPUT and that is likely to be the problem.

If he simply uses pins 10 and 9 for the nRF24 and pins 7 and 8 for SoftwareSerial he would probably have no problem.

...R

Robin2:
That's not quite correct.

You don't need to use pin 10 as part of the SPI control - you can use any pin for Slave Select. BUT pin 10 must be set as OUTPUT to ensure the Arduino operates as SPI master.

In this case it seems that the OP is using pin 10 as SoftwareSerial RX which is an INPUT and that is likely to be the problem.

If he simply uses pins 10 and 9 for the nRF24 and pins 7 and 8 for SoftwareSerial he would probably have no problem.

...R

i solved the issue by setting pin 10 as input in the setup :slight_smile:
thanx a million PaulS and Robin2. i don't have to change anything on my pcb and that is a great thing as i already made 50 of them and soldered most of the components.

klayus:
i solved the issue by setting pin 10 as input in the setup :slight_smile:

That should be output

...R

it should, but now it’s set as being an input, so both the bluetooth can receive strings and my nrf radio can comunicate.