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.

293 lines
7.7 KiB

  1. /*
  2. Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. version 2 as published by the Free Software Foundation.
  6. */
  7. /**
  8. * Example RF Radio Ping Star Group
  9. *
  10. * This sketch is a more complex example of using the RF24 library for Arduino.
  11. * Deploy this on up to six nodes. Set one as the 'pong receiver' by tying the
  12. * role_pin low, and the others will be 'ping transmit' units. The ping units
  13. * unit will send out the value of millis() once a second. The pong unit will
  14. * respond back with a copy of the value. Each ping unit can get that response
  15. * back, and determine how long the whole cycle took.
  16. *
  17. * This example requires a bit more complexity to determine which unit is which.
  18. * The pong receiver is identified by having its role_pin tied to ground.
  19. * The ping senders are further differentiated by a byte in eeprom.
  20. */
  21. #include <SPI.h>
  22. #include <EEPROM.h>
  23. #include "nRF24L01.h"
  24. #include "RF24.h"
  25. #include "printf.h"
  26. //
  27. // Hardware configuration
  28. //
  29. // Set up nRF24L01 radio on SPI bus plus pins 9 & 10
  30. RF24 radio(9,10);
  31. // sets the role of this unit in hardware. Connect to GND to be the 'pong' receiver
  32. // Leave open to be the 'pong' receiver.
  33. const int role_pin = 7;
  34. //
  35. // Topology
  36. //
  37. // Radio pipe addresses for the nodes to communicate. Only ping nodes need
  38. // dedicated pipes in this topology. Each ping node has a talking pipe
  39. // that it will ping into, and a listening pipe that it will listen for
  40. // the pong. The pong node listens on all the ping node talking pipes
  41. // and sends the pong back on the sending node's specific listening pipe.
  42. const uint64_t talking_pipes[5] = { 0xF0F0F0F0D2LL, 0xF0F0F0F0C3LL, 0xF0F0F0F0B4LL, 0xF0F0F0F0A5LL, 0xF0F0F0F096LL };
  43. const uint64_t listening_pipes[5] = { 0x3A3A3A3AD2LL, 0x3A3A3A3AC3LL, 0x3A3A3A3AB4LL, 0x3A3A3A3AA5LL, 0x3A3A3A3A96LL };
  44. //
  45. // Role management
  46. //
  47. // Set up role. This sketch uses the same software for all the nodes
  48. // in this system. Doing so greatly simplifies testing. The hardware itself specifies
  49. // which node it is.
  50. //
  51. // This is done through the role_pin
  52. //
  53. // The various roles supported by this sketch
  54. typedef enum { role_invalid = 0, role_ping_out, role_pong_back } role_e;
  55. // The debug-friendly names of those roles
  56. const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};
  57. // The role of the current running sketch
  58. role_e role;
  59. //
  60. // Address management
  61. //
  62. // Where in EEPROM is the address stored?
  63. const uint8_t address_at_eeprom_location = 0;
  64. // What is our address (SRAM cache of the address from EEPROM)
  65. // Note that zero is an INVALID address. The pong back unit takes address
  66. // 1, and the rest are 2-6
  67. uint8_t node_address;
  68. void setup(void)
  69. {
  70. //
  71. // Role
  72. //
  73. // set up the role pin
  74. pinMode(role_pin, INPUT);
  75. digitalWrite(role_pin,HIGH);
  76. delay(20); // Just to get a solid reading on the role pin
  77. // read the address pin, establish our role
  78. if ( digitalRead(role_pin) )
  79. role = role_ping_out;
  80. else
  81. role = role_pong_back;
  82. //
  83. // Address
  84. //
  85. if ( role == role_pong_back )
  86. node_address = 1;
  87. else
  88. {
  89. // Read the address from EEPROM
  90. uint8_t reading = EEPROM.read(address_at_eeprom_location);
  91. // If it is in a valid range for node addresses, it is our
  92. // address.
  93. if ( reading >= 2 && reading <= 6 )
  94. node_address = reading;
  95. // Otherwise, it is invalid, so set our address AND ROLE to 'invalid'
  96. else
  97. {
  98. node_address = 0;
  99. role = role_invalid;
  100. }
  101. }
  102. //
  103. // Print preamble
  104. //
  105. Serial.begin(115200);
  106. printf_begin();
  107. printf("\n\rRF24/examples/starping/\n\r");
  108. printf("ROLE: %s\n\r",role_friendly_name[role]);
  109. printf("ADDRESS: %i\n\r",node_address);
  110. //
  111. // Setup and configure rf radio
  112. //
  113. radio.begin();
  114. //
  115. // Open pipes to other nodes for communication
  116. //
  117. // The pong node listens on all the ping node talking pipes
  118. // and sends the pong back on the sending node's specific listening pipe.
  119. if ( role == role_pong_back )
  120. {
  121. radio.openReadingPipe(1,talking_pipes[0]);
  122. radio.openReadingPipe(2,talking_pipes[1]);
  123. radio.openReadingPipe(3,talking_pipes[2]);
  124. radio.openReadingPipe(4,talking_pipes[3]);
  125. radio.openReadingPipe(5,talking_pipes[4]);
  126. }
  127. // Each ping node has a talking pipe that it will ping into, and a listening
  128. // pipe that it will listen for the pong.
  129. if ( role == role_ping_out )
  130. {
  131. // Write on our talking pipe
  132. radio.openWritingPipe(talking_pipes[node_address-2]);
  133. // Listen on our listening pipe
  134. radio.openReadingPipe(1,listening_pipes[node_address-2]);
  135. }
  136. //
  137. // Start listening
  138. //
  139. radio.startListening();
  140. //
  141. // Dump the configuration of the rf unit for debugging
  142. //
  143. radio.printDetails();
  144. //
  145. // Prompt the user to assign a node address if we don't have one
  146. //
  147. if ( role == role_invalid )
  148. {
  149. printf("\n\r*** NO NODE ADDRESS ASSIGNED *** Send 1 through 6 to assign an address\n\r");
  150. }
  151. }
  152. void loop(void)
  153. {
  154. //
  155. // Ping out role. Repeatedly send the current time
  156. //
  157. if (role == role_ping_out)
  158. {
  159. // First, stop listening so we can talk.
  160. radio.stopListening();
  161. // Take the time, and send it. This will block until complete
  162. unsigned long time = millis();
  163. printf("Now sending %lu...",time);
  164. radio.write( &time, sizeof(unsigned long) );
  165. // Now, continue listening
  166. radio.startListening();
  167. // Wait here until we get a response, or timeout (250ms)
  168. unsigned long started_waiting_at = millis();
  169. bool timeout = false;
  170. while ( ! radio.available() && ! timeout )
  171. if (millis() - started_waiting_at > 250 )
  172. timeout = true;
  173. // Describe the results
  174. if ( timeout )
  175. {
  176. printf("Failed, response timed out.\n\r");
  177. }
  178. else
  179. {
  180. // Grab the response, compare, and send to debugging spew
  181. unsigned long got_time;
  182. radio.read( &got_time, sizeof(unsigned long) );
  183. // Spew it
  184. printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time);
  185. }
  186. // Try again 1s later
  187. delay(1000);
  188. }
  189. //
  190. // Pong back role. Receive each packet, dump it out, and send it back
  191. //
  192. if ( role == role_pong_back )
  193. {
  194. // if there is data ready
  195. uint8_t pipe_num;
  196. if ( radio.available(&pipe_num) )
  197. {
  198. // Dump the payloads until we've gotten everything
  199. unsigned long got_time;
  200. bool done = false;
  201. while (!done)
  202. {
  203. // Fetch the payload, and see if this was the last one.
  204. done = radio.read( &got_time, sizeof(unsigned long) );
  205. // Spew it
  206. printf("Got payload %lu from node %i...",got_time,pipe_num+1);
  207. }
  208. // First, stop listening so we can talk
  209. radio.stopListening();
  210. // Open the correct pipe for writing
  211. radio.openWritingPipe(listening_pipes[pipe_num-1]);
  212. // Retain the low 2 bytes to identify the pipe for the spew
  213. uint16_t pipe_id = listening_pipes[pipe_num-1] & 0xffff;
  214. // Send the final one back.
  215. radio.write( &got_time, sizeof(unsigned long) );
  216. printf("Sent response to %04x.\n\r",pipe_id);
  217. // Now, resume listening so we catch the next packets.
  218. radio.startListening();
  219. }
  220. }
  221. //
  222. // Listen for serial input, which is how we set the address
  223. //
  224. if (Serial.available())
  225. {
  226. // If the character on serial input is in a valid range...
  227. char c = Serial.read();
  228. if ( c >= '1' && c <= '6' )
  229. {
  230. // It is our address
  231. EEPROM.write(address_at_eeprom_location,c-'0');
  232. // And we are done right now (no easy way to soft reset)
  233. printf("\n\rManually reset address to: %c\n\rPress RESET to continue!",c);
  234. while(1) ;
  235. }
  236. }
  237. }
  238. // vim:ai:ci sts=2 sw=2 ft=cpp