0

nRF8001 Breakout Board
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

nRF8001 Breakout Board

by phil_jermyn on Tue May 01, 2018 1:19 pm

I am using your nRF8001 breakout board (very nice!) for the development of a new product, and I have two questions please:

1) The board includes components for the on-chip DC to DC converter (PIN 32), and also the external 32.786KHz crystal for protocol timing. However neither of these appears to be enabled. Also, according to the Nordic datasheet (page 19), the DC to DC converter cannot be used when the crystal oscillator is enabled. To use it, the chip must be configured to use the internal RC oscillator or an external clock. Please would you clarify the situation? Why are the parts included but not enabled?

2) Please do you publish the configuration settings which you program into the nRF8001 using nRFgo Studio?

Many thanks!

Phil Jermyn.

phil_jermyn
 
Posts: 5
Joined: Tue May 01, 2018 1:08 pm

Re: nRF8001 Breakout Board

by phil_jermyn on Tue May 01, 2018 4:46 pm

It's OK, I think I've figured it out :)

phil_jermyn
 
Posts: 5
Joined: Tue May 01, 2018 1:08 pm

Re: nRF8001 Breakout Board

by phil_jermyn on Wed May 02, 2018 9:26 am

In case anyone else is interested, this is what I have found out. I apologize if this information is already on the web site somewhere and I missed it:

Contrary to what I had assumed, the nRF8001 does not come from Adafruit with pre-programmed settings in its One Time Programmable (OTP) memory. Instead the settings are programmed by the Adafruit drivers each time the device is started, and stored in the development RAM memory of the nRF8001, so that they can be changed. This is so obviously the sensible thing to do that I don't know why I didn't tumble to it sooner, since the nRF8001 has special provision for this.

The default settings provided by Adafruit select the internal 32.768KHz RC oscillator, rather than the external crystal. However the crystal is provided on the board in case it is needed. The DC-to-DC converter is also turned off by default.

Changing the settings is actually quite easy, by downloading nRFgo Studio from the Nordic web site. This is a nice little program for setting up the nRF8001, and comes bundled with some other software for transferring the settings to the chip outside Arduino. But most of us won't need that.

The settings are stored within the Adafruit_BLE_UART library under utlity/uart. The settings file itself is services.h, whilst UART_over_BLE.xml is a settings profile which can be opened by nRFgo Studio for modification. Within the program there is a tab for Hardware Settings, and once the required changes have been made, the program can generate a new services.h file by choosing nRF8001 Setup/Generate Source Files/Generate services.h. Two versions will be created, along with a log file. Services_lock.h is for programming the settings into the OTP memory, and should only be used if there is no need to change them again. When the new services.h file is substituted into the utlity/uart folder, the new settings will be used next time the nRF8001 is started (you will need to re-compile your Arduino sketch of course, to get the new settings into your main processor).

Please note that in order to use the DC-to-DC converter, the component FB1 must be removed from the Bluetooth breakout board, otherwise it will bypass the converter. FB1 is a black, 0805-sized ferrite device, located inline with the MISO pin. There is a brown capacitor (C9, same size but sideways) between FB1 and the MISO pin.

The datasheet claims that using the DC-to-DC converter will reduce power consumption by about 20%.

I hope this helps someone!

phil_jermyn
 
Posts: 5
Joined: Tue May 01, 2018 1:08 pm

Re: nRF8001 Breakout Board

by cs137 on Fri May 04, 2018 2:48 pm

Phil: Thank you for your insights. I'm using the same board and have generated a services.h file from nRFgo. I've set up a simple SPI interface using Atmel Studio to transfer instructions to the nRF8001.

Code: Select all | TOGGLE FULL SIZE
char transfer (uint8_t data)
{ SPDR = data;
while (!  (SPSR & (1<<SPIF)))
;
return SPDR;

}

The services.h file contains a bunch (20 in the version I have) of hex strings - most beginning with 31 (0x1F), which is the maximum of 32 bytes (less the length byte) that can be transferred at one time. The second byte is always 0x06 which is the op code for the setup command. The next 30 bytes are the setup data you get from nRFgo based on the services you ask for. I setup a pointer to each string and transfer the data to the nRF8001. Sometimes the chip sends data back - but not always.

The manual says:

This command returns a CommandResponseEvent followed by a DeviceStartedEvent upon
completion of the complete Setup sequence. Data returned in the CommandResponsEvent is:
• Command code: Setup
• Status:
• Status code
•Transaction continue
•Transaction complete
•(Error)
• Response data: None

The data that comes back (using logic analyzer) doesn't match the codes for a command response event (0x84) or a device started event (0x81). Not sure why. I'm missing something.

I'm hoping you may be able to shed some light.
Thanks

cs137
 
Posts: 10
Joined: Thu Feb 23, 2012 9:15 am

Re: nRF8001 Breakout Board

by phil_jermyn on Mon May 07, 2018 5:11 am

Thank you for this. I have not yet tried communicating with the nRF8001 outside the Arduino drivers provided by Adafruit, so I have not come across the same issue as you. I probably will in time however.

You say that the chip does not send back the values which the manual says that it should, but you don't say what you do get. Is it possible that you could post that here please? Do you always get the same thing back from the chip? If not then I would suspect a communication problem of some kind.

phil_jermyn
 
Posts: 5
Joined: Tue May 01, 2018 1:08 pm

Re: nRF8001 Breakout Board

by cs137 on Mon May 07, 2018 3:13 pm

Phil:

Here is the code:
Code: Select all | TOGGLE FULL SIZE

#include <avr/io.h>
#include <util/delay.h>

/*
Using 328p chip.  Pin assignments as follows:

b5 = clock = 19
b4 = miso = 18
b3 = mosi = 17
b2 = chip select = 16
b1 = reset = 15


  Not using these now
#define Test 0x01
#define GetTemperature 0x0C
#define Echo 0x02
#define WakeUp 0x05

*/

char transmit(uint8_t data)
{
   SPDR=data;
   
   while(! (SPSR & (1<<SPIF)))
   ;
   return SPDR;
}

void setup(void)
{
   
   DDRB = 0b00101111;//set data direction for port B
   SPCR = 0x72; //SPI on, LSB 1st, master on, polarity 0, phase 0, speed /128
   DDRD &= ~(1<<2);   //set PD 2 as an input - not using as Interrupt
   
}

//use pointer for data.  1st byte is length -1 so use that as limit in FOR statement
void SendCommand(uint8_t* pData)
{
   for (int i=0; i<= pData[0]; i++)
      transmit(pData[i]);
      
}


int main(void)
{
    /* Replace with your application code */
   setup();
   
   //these are the data you get from nRFgo.  1st byte is length -1 and 2nd byte is 0x06 - which is setup op code
   
   uint8_t data1[]={0x07,0x06,0x00,0x00,0x03,0x02,0x42,0x07};
   uint8_t data2[]={0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   uint8_t data3[]={0x1f,0x06,0x10,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x03,0x90,0x01,0xff};
   uint8_t data4[]={0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   uint8_t data5[]={0x05,0x06,0x10,0x54,0x00,0x00};
   uint8_t data6[]={0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,0x02,0x28,0x03,0x01,
      0x02,0x03,0x00,0x00,0x2a,0x04,0x04,0x14};
   uint8_t data7[]={0x1f,0x06,0x20,0x1c,0x09,0x00,0x03,0x2a,0x00,0x01,0x4d,0x79,0x20,0x44,0x65,0x76,0x69,0x63,0x65,0x69,0x2e,0x63,0x6f,0x6d,
      0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04};
   uint8_t data8[]={0x1f,0x06,0x20,0x38,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,0x00,0x05,0x2a,0x01,
      0x01,0x00,0x00,0x04,0x04,0x05,0x05,0x00};
   uint8_t data9[]={0x1f,0x06,0x20,0x54,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,0x04,0x01,0xff,0xff,
      0xff,0xff,0x00,0x00,0xff,0xff,0x04,0x04};
   uint8_t data10[]={0x1f,0x06,0x20,0x70,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,0x04,0x10,0x10,0x00,0x09,0x28,0x00,0x01,0x9e,0xca,
      0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3};
   uint8_t data11[]={0x1f,0x06,0x20,0x8c,0xa3,0xb5,0x01,0x00,0x40,0x6e,0x04,0x04,0x13,0x13,0x00,0x0a,0x28,0x03,0x01,0x00,0x0b,0x00,0x9e,0xca,
      0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3};
   uint8_t data12[]={0x1f,0x06,0x20,0xa8,0xa3,0xb5,0x02,0x00,0x40,0x6e,0x04,0x00,0x14,0x00,0x00,0x0b,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   uint8_t data13[]={0x1f,0x06,0x20,0xc4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x13,0x13,0x00,0x0c,0x28,0x03,0x01,0x00,0x0d,0x00,0x9e,
      0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93};
   uint8_t data14[]={0x1f,0x06,0x20,0xe0,0xf3,0xa3,0xb5,0x03,0x00,0x40,0x6e,0x04,0x00,0x14,0x00,0x00,0x0d,0x00,0x03,0x02,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   uint8_t data15[]={0x1f,0x06,0x20,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x13,0x13,0x00,0x0e,0x28,0x03,0x01,0x02,0x0f,0x00,
      0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0};
   uint8_t data16[]={0x1f,0x06,0x21,0x18,0x93,0xf3,0xa3,0xb5,0x05,0x00,0x40,0x6e,0x06,0x04,0x07,0x06,0x00,0x0f,0x00,0x05,0x02,0xff,0xff,0xff,
      0xff,0xff,0xff,0x04,0x04,0x13,0x13,0x00};
   uint8_t data17[]={0x1f,0x06,0x21,0x34,0x10,0x28,0x03,0x01,0x00,0x11,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x04,
      0x00,0x40,0x6e,0x04,0x00,0x09,0x00,0x00};
   uint8_t data18[]={0x11,0x06,0x21,0x50,0x11,0x00,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
   uint8_t data19[]={0x13,0x06,0x50,0x00,0x9e,0xca,0xdc,0x24,0x0e,0xe5,0xa9,0xe0,0x93,0xf3,0xa3,0xb5,0x00,0x00,0x40,0x6e};
   uint8_t data20[]={0x06,0x06,0xf0,0x00,0x03,0x47,0xa3};
   uint8_t advertise[]={0x05,0x0F,0x00,0x00,0x00,0x50};
      
      uint8_t* pToData; 
   
   
   
   
   
   
      
      
      
      
    while (1)
    {
      
      PORTB &= ~(1<<2);//chip select
      pToData=&data1[0];
      SendCommand(pToData);
      pToData=&data2[0];
      SendCommand(pToData);
      pToData=&data3[0];
      SendCommand(pToData);
      pToData=&data4[0];
      SendCommand(pToData);
      pToData=&data5[0];
      SendCommand(pToData);
      pToData=&data6[0];
      SendCommand(pToData);
      pToData=&data7[0];
      SendCommand(pToData);
      pToData=&data8[0];
      SendCommand(pToData);
      pToData=&data9[0];
      SendCommand(pToData);
      pToData=&data10[0];
      SendCommand(pToData);
      pToData=&data11[0];
      SendCommand(pToData);
      pToData=&data12[0];
      SendCommand(pToData);
      pToData=&data13[0];
      SendCommand(pToData);
      pToData=&data14[0];
      SendCommand(pToData);
      pToData=&data15[0];
      SendCommand(pToData);
      pToData=&data16[0];
      SendCommand(pToData);
      pToData=&data17[0];
      SendCommand(pToData);
      pToData=&data18[0];
      SendCommand(pToData);
      pToData=&data19[0];
      SendCommand(pToData);
      pToData=&data20[0];
      SendCommand(pToData);
      
      //advertise
      
      pToData=&advertise[0]
      ;
      SendCommand(pToData);
      PORTB |= 1<<2;
      
      //wait and then do it again
   
      _delay_ms(50);
      
      
      
    }
}



The 1st setup begins 0x07, 0x06, 0x00....

The nRF8001 sends back 0x01, 0x03, 0x84, 0x06, 0x01, 0x03, 0x02, 0x42,...

After the 1st 5 bytes it just echos whatever it received and that continues for the next set that begins with 1F (31 byte length) followed by 0x06..etc

After the 2nd set (data2[]) the echo stops. Not sure why.

Now the 0x84 is the Command Response Event code followed by the setup command - just like it is supposed to do - the 01 is a status code that I don't know what it means.

Maybe I'm supposed to send the stings one at a time and deselect the chip after each string. I'll give that try. Any ideas?

Thanks

cs137
 
Posts: 10
Joined: Thu Feb 23, 2012 9:15 am

Re: nRF8001 Breakout Board

by phil_jermyn on Mon May 07, 2018 3:18 pm

It is possible that the strings have to be sent one at a time. It might be worth having a look through the Adafruit drivers, as they definitely work.

phil_jermyn
 
Posts: 5
Joined: Tue May 01, 2018 1:08 pm

Re: nRF8001 Breakout Board

by cs137 on Sun May 13, 2018 3:44 pm

Phil:


I set it up so I transmit each instruction set (21 sets) separately and that works...sort of.

Here is what I found.

After you sent the first string - 7 bytes - the chip sends back 3 bytes. A command response, the opcode (0x06), and a value that indicates status (0x01), which in this case
means the transaction is continuing.

The next string is 31 bytes (32max with length) and the chip sends back 3 bytes - a command response, the 06 op code, and a CRC mismatch (0x88) - whatever that is.

Then it does something interesting. It pulls the READY pin high for exactly 25 ms, indicating that it isn't ready. Since my code didn't pay attention to this pin, I kept sending
instructions, which were apparently ignored.

After the 25 ms the chip comes ready and receives the remainder of the instructions with mostly no problem. Almost all strings give a 3 byte message back
- command response (0x84), 06 op code, 0x01 - transaction continues.

One string gave rise to a 84, 06, 82 - the 82 means command unknown. So maybe I made a mistake in trancribing the data from nRFgo - I need to check that.

That is as far as I've gone. The next step is to not transmit anything during the not ready - so I'll modify the code to wait for ready before sending anything - and look at the instruction that got a command unknown response.

cs137
 
Posts: 10
Joined: Thu Feb 23, 2012 9:15 am

Re: nRF8001 Breakout Board

by cs137 on Wed May 16, 2018 1:53 pm

I set the controller to wait for the ready to be pulled low after the Request line is pulled low.
After the first two sets (7 bytes followed by 31 bytes) of setup instructions the nRF8001 ready goes high for
25 msec (i.e. not ready). After that it goes ready for the remainder of the setup and I'm able to send the rest of the setup instructions followed by
an advertising command.

After each setup command the chip sends back 0x84 command response event, 0x06 opcode for setup, and 0x01 transaction continues.
No error codes. Which I think is what it is supposed to do.

At that point I tried to connect my phone but I don't think the chip is advertising because my phone doesn't find any
Bluetooth signals.

I noticed something odd regarding what I think is the advertise command. I think the last setup instruction is begin advertising/connect.
06 (6 bytes long), 06 setup op code, 0F connect op code (advertise), 00,00 no timeout limit, 50 (interval x .625 msec)

From the manual, the command to connect is 5 bytes long - 05, 0F, 00, 00, 50.

So is there a "setup" connect command and a non-setup connect command?
I've tried both and the chip doesn't seem to advertise.
I'm pretty sure I got through the setup without any errors but still don't understand why the chip isn't advertising.
Any ideas?

cs137
 
Posts: 10
Joined: Thu Feb 23, 2012 9:15 am

Please be positive and constructive with your questions and comments.