Ein Roboter mit bürstenlosem Antrieb, differenzial und NRF24L01 Funk. Großflächig gebaut um ein großes Solarpanel aufzunehmen. https://gitlab.informatik.hs-fulda.de/fdai5253/roboter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

396 lines
10 KiB

  1. /*
  2. This program is free software; you can redistribute it and/or
  3. modify it under the terms of the GNU General Public License
  4. version 2 as published by the Free Software Foundation.
  5. timingSearch3pin.ino by tong67 ( https://github.com/tong67 )
  6. This sketch can be used to determine the best settleTime values to use in RF24::csn().
  7. The used settleTimeValues are 100/20. Depend on used RC combiniation and voltage drop by LED.
  8. It is setup to be completely selfcontained, copied defines and code from RF24 library.
  9. The ATtiny85 uses the tiny-core by CodingBadly (https://code.google.com/p/arduino-tiny/)
  10. (Intermediate) results are written to TX (PB3, pin 2). For schematic see rf24ping85.ino
  11. */
  12. // nRF24L01.h copy
  13. /* Memory Map */
  14. #define CONFIG 0x00
  15. #define EN_AA 0x01
  16. #define EN_RXADDR 0x02
  17. #define SETUP_AW 0x03
  18. #define SETUP_RETR 0x04
  19. #define RF_CH 0x05
  20. #define RF_SETUP 0x06
  21. #define STATUS 0x07
  22. #define OBSERVE_TX 0x08
  23. #define CD 0x09
  24. #define RX_ADDR_P0 0x0A
  25. #define RX_ADDR_P1 0x0B
  26. #define RX_ADDR_P2 0x0C
  27. #define RX_ADDR_P3 0x0D
  28. #define RX_ADDR_P4 0x0E
  29. #define RX_ADDR_P5 0x0F
  30. #define TX_ADDR 0x10
  31. #define RX_PW_P0 0x11
  32. #define RX_PW_P1 0x12
  33. #define RX_PW_P2 0x13
  34. #define RX_PW_P3 0x14
  35. #define RX_PW_P4 0x15
  36. #define RX_PW_P5 0x16
  37. #define FIFO_STATUS 0x17
  38. #define DYNPD 0x1C
  39. #define FEATURE 0x1D
  40. /* Bit Mnemonics */
  41. #define MASK_RX_DR 6
  42. #define MASK_TX_DS 5
  43. #define MASK_MAX_RT 4
  44. #define EN_CRC 3
  45. #define CRCO 2
  46. #define PWR_UP 1
  47. #define PRIM_RX 0
  48. #define ENAA_P5 5
  49. #define ENAA_P4 4
  50. #define ENAA_P3 3
  51. #define ENAA_P2 2
  52. #define ENAA_P1 1
  53. #define ENAA_P0 0
  54. #define ERX_P5 5
  55. #define ERX_P4 4
  56. #define ERX_P3 3
  57. #define ERX_P2 2
  58. #define ERX_P1 1
  59. #define ERX_P0 0
  60. #define AW 0
  61. #define ARD 4
  62. #define ARC 0
  63. #define PLL_LOCK 4
  64. #define RF_DR 3
  65. #define RF_PWR 6
  66. #define RX_DR 6
  67. #define TX_DS 5
  68. #define MAX_RT 4
  69. #define RX_P_NO 1
  70. #define TX_FULL 0
  71. #define PLOS_CNT 4
  72. #define ARC_CNT 0
  73. #define TX_REUSE 6
  74. #define FIFO_FULL 5
  75. #define TX_EMPTY 4
  76. #define RX_FULL 1
  77. #define RX_EMPTY 0
  78. #define DPL_P5 5
  79. #define DPL_P4 4
  80. #define DPL_P3 3
  81. #define DPL_P2 2
  82. #define DPL_P1 1
  83. #define DPL_P0 0
  84. #define EN_DPL 2
  85. #define EN_ACK_PAY 1
  86. #define EN_DYN_ACK 0
  87. /* Instruction Mnemonics */
  88. #define R_REGISTER 0x00
  89. #define W_REGISTER 0x20
  90. #define REGISTER_MASK 0x1F
  91. #define ACTIVATE 0x50
  92. #define R_RX_PL_WID 0x60
  93. #define R_RX_PAYLOAD 0x61
  94. #define W_TX_PAYLOAD 0xA0
  95. #define W_ACK_PAYLOAD 0xA8
  96. #define FLUSH_TX 0xE1
  97. #define FLUSH_RX 0xE2
  98. #define REUSE_TX_PL 0xE3
  99. #define RF24_NOP 0xFF
  100. /* Non-P omissions */
  101. #define LNA_HCURR 0
  102. /* P model memory Map */
  103. #define RPD 0x09
  104. #define W_TX_PAYLOAD_NO_ACK 0xB0
  105. /* P model bit Mnemonics */
  106. #define RF_DR_LOW 5
  107. #define RF_DR_HIGH 3
  108. #define RF_PWR_LOW 1
  109. #define RF_PWR_HIGH 2
  110. /****************************************************************************/
  111. //ATTiny support code pulled in from https://github.com/jscrane/RF24
  112. #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
  113. // see http://gammon.com.au/spi
  114. # define DI 0 // D0, pin 5 Data In
  115. # define DO 1 // D1, pin 6 Data Out (this is *not* MOSI)
  116. # define USCK 2 // D2, pin 7 Universal Serial Interface clock
  117. # define SS 3 // D3, pin 2 Slave Select
  118. #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  119. // these depend on the core used (check pins_arduino.h)
  120. // this is for jeelabs' one (based on google-code core)
  121. # define DI 4 // PA6
  122. # define DO 5 // PA5
  123. # define USCK 6 // PA4
  124. # define SS 3 // PA7
  125. #endif
  126. #if defined (ARDUINO) && !defined (__arm__)
  127. #if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
  128. #define RF24_TINY
  129. #else
  130. // #include <SPI.h>
  131. #endif
  132. #endif
  133. #if defined(RF24_TINY)
  134. #include <stdio.h>
  135. #include <Arduino.h>
  136. #include <avr/pgmspace.h>
  137. #define SPI_CLOCK_DIV4 0x00
  138. #define SPI_CLOCK_DIV16 0x01
  139. #define SPI_CLOCK_DIV64 0x02
  140. #define SPI_CLOCK_DIV128 0x03
  141. #define SPI_CLOCK_DIV2 0x04
  142. #define SPI_CLOCK_DIV8 0x05
  143. #define SPI_CLOCK_DIV32 0x06
  144. //#define SPI_CLOCK_DIV64 0x07
  145. #define SPI_MODE0 0x00
  146. #define SPI_MODE1 0x04
  147. #define SPI_MODE2 0x08
  148. #define SPI_MODE3 0x0C
  149. #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  150. #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  151. #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  152. class SPIClass {
  153. public:
  154. static byte transfer(byte _data);
  155. // SPI Configuration methods
  156. inline static void attachInterrupt();
  157. inline static void detachInterrupt(); // Default
  158. static void begin(); // Default
  159. static void end();
  160. // static void setBitOrder(uint8_t);
  161. // static void setDataMode(uint8_t);
  162. // static void setClockDivider(uint8_t);
  163. };
  164. extern SPIClass SPI;
  165. #endif /* RF24_TINY */
  166. #if defined(RF24_TINY)
  167. void SPIClass::begin() {
  168. digitalWrite(SS, HIGH);
  169. pinMode(USCK, OUTPUT);
  170. pinMode(DO, OUTPUT);
  171. pinMode(SS, OUTPUT);
  172. pinMode(DI, INPUT);
  173. USICR = _BV(USIWM0);
  174. }
  175. byte SPIClass::transfer(byte b) {
  176. USIDR = b;
  177. USISR = _BV(USIOIF);
  178. do
  179. USICR = _BV(USIWM0) | _BV(USICS1) | _BV(USICLK) | _BV(USITC);
  180. while ((USISR & _BV(USIOIF)) == 0);
  181. return USIDR;
  182. }
  183. void SPIClass::end() {}
  184. #endif /* RF24_TINY */
  185. /****************************************************************************/
  186. uint8_t ce_pin; /**< "Chip Enable" pin, activates the RX or TX role */
  187. uint8_t csn_pin; /**< SPI Chip select */
  188. uint8_t csnHighSettle = 255;
  189. uint8_t csnLowSettle = 255;
  190. /****************************************************************************/
  191. void ce(bool level) {
  192. if (ce_pin != csn_pin) digitalWrite(ce_pin,level);
  193. }
  194. /****************************************************************************/
  195. void setCsnHighSettle(uint8_t level) {
  196. csnHighSettle = level;
  197. }
  198. /****************************************************************************/
  199. void setCsnLowSettle(uint8_t level) {
  200. csnLowSettle = level;
  201. }
  202. /****************************************************************************/
  203. void csn(bool mode) {
  204. if (ce_pin != csn_pin) {
  205. digitalWrite(csn_pin,mode);
  206. } else {
  207. if (mode == HIGH) {
  208. PORTB |= (1<<PINB2); // SCK->CSN HIGH
  209. delayMicroseconds(csnHighSettle); // allow csn to settle
  210. } else {
  211. PORTB &= ~(1<<PINB2); // SCK->CSN LOW
  212. delayMicroseconds(csnLowSettle); // allow csn to settle
  213. }
  214. }
  215. }
  216. /****************************************************************************/
  217. uint8_t read_register(uint8_t reg)
  218. {
  219. csn(LOW);
  220. SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
  221. uint8_t result = SPI.transfer(0xff);
  222. csn(HIGH);
  223. return result;
  224. }
  225. /****************************************************************************/
  226. uint8_t write_register2(uint8_t reg, uint8_t value)
  227. {
  228. uint8_t status;
  229. csn(LOW);
  230. status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
  231. SPI.transfer(value);
  232. csn(HIGH);
  233. return status;
  234. }
  235. /****************************************************************************/
  236. #if defined(RF24_TINY)
  237. #define CE_PIN 3
  238. #define CSN_PIN 3
  239. #else
  240. #define CE_PIN 7
  241. #define CSN_PIN 8
  242. #endif
  243. #define MAX_HIGH 100
  244. #define MAX_LOW 100
  245. #define MINIMAL 8
  246. void setup(void) {
  247. uint8_t status;
  248. // start serial port and SPI
  249. Serial.begin(9600);
  250. SPI.begin();
  251. // configure ce and scn as output when used
  252. ce_pin = CE_PIN;
  253. csn_pin = CSN_PIN;
  254. setCsnHighSettle(MAX_HIGH);
  255. setCsnLowSettle(MAX_LOW);
  256. // csn is used in SPI transfers. Set to LOW at start and HIGH after transfer. Set to HIGH to reflect no transfer active
  257. // SPI command are accepted in Power Down state.
  258. // ce represent PRX (LOW) or PTX (HIGH) mode apart from register settings. Start in PRX mode.
  259. ce(LOW);
  260. csn(HIGH);
  261. // nRF24L01 goes from to Power Down state 100ms after Power on Reset ( Vdd > 1.9V) or when PWR_UP is 0 in config register
  262. // Goto Power Down state (Powerup or force) and set in transmit mode
  263. write_register2(CONFIG, read_register(CONFIG) & ~_BV(PWR_UP) & ~_BV(PRIM_RX));
  264. delay(100);
  265. // Goto Standby-I
  266. // Technically we require 4.5ms Tpd2stby+ 14us as a worst case. We'll just call it 5ms for good measure.
  267. // WARNING: Delay is based on P-variant whereby non-P *may* require different timing.
  268. write_register2(CONFIG, read_register(CONFIG) | _BV(PWR_UP));
  269. delay(5) ;
  270. // Goto Standby-II
  271. ce(HIGH);
  272. Serial.print("Scanning for optimal setting time for scn");
  273. }
  274. void loop(void) {
  275. uint8_t status;
  276. uint8_t i;
  277. uint8_t j;
  278. uint8_t k;
  279. bool success = true;
  280. uint8_t csnHigh = MAX_HIGH;
  281. uint8_t csnLow = MAX_LOW;
  282. uint8_t bottom_success;
  283. bool bottom_found;
  284. uint8_t value[] = {5,10};
  285. uint8_t limit[] = {MAX_HIGH,MAX_LOW};
  286. uint8_t advice[] = {MAX_HIGH,MAX_LOW};
  287. // check max values give correct behavior
  288. for (k=0;k<2;k++) {
  289. bottom_found = false;
  290. bottom_success = 0;
  291. while(bottom_success < 255) {
  292. setCsnHighSettle(limit[0]);
  293. setCsnLowSettle(limit[1]);
  294. // check current values
  295. i = 0;
  296. while(i<255 & success) {
  297. for (j=0;j<2;j++) {
  298. write_register2(EN_AA, value[j]);
  299. status = read_register(EN_AA);
  300. if (value[j] != status) {
  301. success = false;
  302. }
  303. }
  304. i++;
  305. }
  306. // process result of current values
  307. if (!success) {
  308. Serial.print("Settle NOK. csnHigh=");
  309. Serial.print(limit[0],DEC);
  310. Serial.print(" csnLow=");
  311. Serial.println(limit[1],DEC);
  312. limit[k]++;
  313. bottom_found = true;
  314. bottom_success = 0;
  315. success = true;
  316. } else {
  317. Serial.print("Settle OK. csnHigh=");
  318. Serial.print(limit[0],DEC);
  319. Serial.print(" csnLow=");
  320. Serial.println(limit[1],DEC);
  321. if (!bottom_found) {
  322. limit[k]--;
  323. if (limit[k] == MINIMAL) {
  324. bottom_found = true;
  325. bottom_success = 0;
  326. success = true;
  327. }
  328. } else {
  329. bottom_success++;
  330. }
  331. }
  332. }
  333. Serial.print("Settle value found for ");
  334. if (k == 0) {
  335. Serial.print("csnHigh: ");
  336. } else {
  337. Serial.print("csnLow: ");
  338. }
  339. Serial.println(limit[k],DEC);
  340. advice[k] = limit[k] + (limit[k] / 10);
  341. limit[k] = 100;
  342. }
  343. Serial.print("Adviced Settle times are: csnHigh=");
  344. Serial.print(advice[0],DEC);
  345. Serial.print(" csnLow=");
  346. Serial.println(advice[1],DEC);
  347. while (true)
  348. {
  349. ;
  350. }
  351. }