Optimized high speed nRF24L01+ driver class documentation v1.4.8
TMRh20 2020 - Optimized fork of the nRF24L01+ driver
Loading...
Searching...
No Matches
examples/rf24_ATTiny/timingSearch3pin/timingSearch3pin.ino

2014 Contribution by tong67
Updated 2020 by 2bndy5 for the SpenceKonde ATTinyCore
The RF24 library uses the ATTinyCore by SpenceKonde

This sketch can be used to determine the best settle time values to use for RF24::csDelay in RF24::csn() (private function).

See also
RF24::csDelay

The settle time values used here are 100/20. However, these values depend on the actual used RC combination and voltage drop by LED. The intermediate results are written to TX (PB3, pin 2 – using Serial).

For schematic details, see introductory comment block in the rf24ping85.ino sketch.

1
8/*
9 * This sketch can determine the best settle time values to use for
10 * macros, defined as RF24_CSN_SETTLE_HIGH_DELAY and RF24_CSN_SETTLE_LOW_DELAY,
11 * in RF24::csn().
12 * The settle time values used here are 100/20. However, these values depend
13 * on the actual used RC combiniation and voltage drop by LED. The
14 * intermediate results are written to TX (PB3, pin 2 -- using Serial).
15 *
16 * For schematic details, see introductory comment block in the
17 * examples/rf24_ATTiny/rf24ping85/rf24ping85.ino sketch.
18 */
19
20#include <stdio.h>
21#include <SPI.h>
22#include <Arduino.h>
23#include <nRF24L01.h>
24
25
26#if defined(ARDUINO) && !defined(__arm__)
27#if defined(__AVR_ATtinyX5__) || defined(__AVR_ATtinyX4__)
28#define RF24_TINY
29#endif
30#endif
31
32/****************************************************************************/
33
34#if defined(RF24_TINY)
35
36// when Attiny84 or Attiny85 is detected
37#define CE_PIN 3
38#define CSN_PIN 3
40#else
41// when not running on an ATTiny84 or ATTiny85
42#define CE_PIN 7
43#define CSN_PIN 8
45#endif
46
47#define MAX_HIGH 100
48#define MAX_LOW 100
49#define MINIMAL 8
50
51// Use these adjustable variables to test for best configuration to be used on
52// the ATTiny chips. These variables are defined as macros in the library's
53// RF24/utility/ATTiny/RF24_arch_config.h file. To change them, simply define
54// the corresponding macro(s) before #include <RF24> in your sketch.
55uint8_t csnHighSettle = MAX_HIGH; // defined as RF24_CSN_SETTLE_HIGH_DELAY
56uint8_t csnLowSettle = MAX_LOW; // defined as RF24_CSN_SETTLE_LOW_DELAY
57
58/****************************************************************************/
59void ce(bool level) {
60 if (CE_PIN != CSN_PIN) digitalWrite(CE_PIN, level);
61}
62
63/****************************************************************************/
64void csn(bool mode) {
65 if (CE_PIN != CSN_PIN) {
66 digitalWrite(CSN_PIN, mode);
67 } else {
68 // digitalWrite(SCK, mode);
69 if (mode == HIGH) {
70 PORTB |= (1 << PINB2); // SCK->CSN HIGH
71 delayMicroseconds(csnHighSettle); // allow csn to settle
72 } else {
73 PORTB &= ~(1 << PINB2); // SCK->CSN LOW
74 delayMicroseconds(csnLowSettle); // allow csn to settle
75 }
76 }
77}
78
79/****************************************************************************/
80uint8_t read_register(uint8_t reg) {
81 csn(LOW);
82 SPI.transfer(R_REGISTER | reg);
83 uint8_t result = SPI.transfer(0xff);
84 csn(HIGH);
85 return result;
86}
87
88/****************************************************************************/
89void write_register(uint8_t reg, uint8_t value) {
90 csn(LOW);
91 SPI.transfer(W_REGISTER | reg);
92 SPI.transfer(value);
93 csn(HIGH);
94}
95
96/****************************************************************************/
97void setup(void) {
98
99#ifndef __AVR_ATtinyX313__
100 // not enough memory on ATTiny4313 or ATTint2313(a) to use Serial I/O for this sketch
101
102 // start serial port and SPI
103 Serial.begin(115200);
104 SPI.begin();
105 // configure CE and CSN as output when used
106 pinMode(CE_PIN, OUTPUT);
107 if (CSN_PIN != CE_PIN)
108 pinMode(CSN_PIN, OUTPUT);
109
110 // csn is used in SPI transfers. Set to LOW at start and HIGH after transfer. Set to HIGH to reflect no transfer active
111 // SPI command are accepted in Power Down state.
112 // CE pin represent PRX (LOW) or PTX (HIGH) mode apart from register settings. Start in PRX mode.
113 ce(LOW);
114 csn(HIGH);
115
116 // nRF24L01 goes from to Power Down state 100ms after Power on Reset ( Vdd > 1.9V) or when PWR_UP is 0 in config register
117 // Goto Power Down state (Powerup or force) and set in transmit mode
118 write_register(NRF_CONFIG, read_register(NRF_CONFIG) & ~_BV(PWR_UP) & ~_BV(PRIM_RX));
119 delay(100);
120
121 // Goto Standby-I
122 // Technically we require 4.5ms Tpd2stby+ 14us as a worst case. We'll just call it 5ms for good measure.
123 // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
124 write_register(NRF_CONFIG, read_register(NRF_CONFIG) | _BV(PWR_UP));
125 delay(5);
126
127 // Goto Standby-II
128 ce(HIGH);
129 Serial.print("Scanning for optimal setting time for csn");
130
131
132 /************************** Main program *********************************/
133
134 uint8_t result; // used to compare read/write results with read/write cmds
135 bool success = true;
136 uint8_t bottom_success;
137 bool bottom_found;
138 uint8_t value[] = { 5, 10 };
139 uint8_t limit[] = { MAX_HIGH, MAX_LOW };
140 uint8_t advice[] = { MAX_HIGH, MAX_LOW };
141
142 // check max values give correct behavior
143 for (uint8_t k = 0; k < 2; k++) {
144 bottom_found = false;
145 bottom_success = 0;
146 while (bottom_success < 255) {
147 csnHighSettle = limit[0];
148 csnLowSettle = limit[1];
149 // check current values
150 uint8_t i = 0;
151 while (i < 255 && success) {
152 for (uint8_t j = 0; j < 2; j++) {
153 write_register(EN_AA, value[j]);
154 result = read_register(EN_AA);
155 if (value[j] != result) {
156 success = false;
157 }
158 }
159 i++;
160 }
161 // process result of current values
162 if (!success) {
163 Serial.print("Settle Not OK. csnHigh=");
164 Serial.print(limit[0], DEC);
165 Serial.print(" csnLow=");
166 Serial.println(limit[1], DEC);
167 limit[k]++;
168 bottom_found = true;
169 bottom_success = 0;
170 success = true;
171 } else {
172 Serial.print("Settle OK. csnHigh=");
173 Serial.print(limit[0], DEC);
174 Serial.print(" csnLow=");
175 Serial.println(limit[1], DEC);
176 if (!bottom_found) {
177 limit[k]--;
178 if (limit[k] == MINIMAL) {
179 bottom_found = true;
180 bottom_success = 0;
181 success = true;
182 }
183 } else {
184 bottom_success++;
185 }
186 }
187 } // while (bottom_success < 255)
188 Serial.print("Settle value found for ");
189 if (k == 0) {
190 Serial.print("csnHigh: ");
191 } else {
192 Serial.print("csnLow: ");
193 }
194 Serial.println(limit[k], DEC);
195 advice[k] = limit[k] + (limit[k] / 10);
196 limit[k] = 100;
197 } // for (uint8_t k = 0; k < 2; k++)
198 Serial.print("Advised Settle times are: csnHigh=");
199 Serial.print(advice[0], DEC);
200 Serial.print(" csnLow=");
201 Serial.println(advice[1], DEC);
202
203#endif // not defined __AVR_ATtinyX313__
204}
205
206
207void loop(void) {} // this program runs only once, thus it resides in setup()
#define pinMode(pin, direction)
#define _BV(x)
#define HIGH
#define OUTPUT
#define delay(milisec)
#define delayMicroseconds(usec)
#define LOW
#define digitalWrite(pin, value)
#define PRIM_RX
Definition nRF24L01.h:61
#define W_REGISTER
Definition nRF24L01.h:105
#define EN_AA
Definition nRF24L01.h:28
#define NRF_CONFIG
Definition nRF24L01.h:27
#define PWR_UP
Definition nRF24L01.h:60
#define R_REGISTER
Definition nRF24L01.h:104