Advertisement
Guest User

Untitled

a guest
May 14th, 2018
164
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.74 KB | None | 0 0
  1. #include <avr/sleep.h>
  2. #include <avr/power.h>
  3. #include <avr/wdt.h>
  4. #include <SPI.h>
  5. #include <OneWire.h>
  6. #include <DallasTemperature.h>
  7. #include "RF24.h"
  8.  
  9. #define RF24_PA_LEVEL RF24_PA_MIN
  10. #define RF24_CHANNEL 7
  11. #define RF24_DATARATE RF24_250KBPS
  12. #define RF24_CRCLENGTH RF24_CRC_16
  13. #define RF24_CE_PIN 9
  14. #define RF24_CS_PIN 10
  15.  
  16. #define ONE_WIRE_BUS 3
  17.  
  18. #define PWR_ADAPT_TRIES 5
  19. #define FAILED_TXS_LIMIT 5
  20. #define ON_SLEEP_CYCLES 7 //1 cycle is 8 seconds + a little delay, 7 would be around 1 minute
  21. #define OFF_SLEEP_CYCLES 15*ON_SLEEP_CYCLES
  22.  
  23. const byte base_address[6] = "RX000";
  24. uint8_t node_address;
  25.  
  26. struct frame {
  27. byte address;
  28. float temperature;
  29. uint8_t power;
  30. };
  31.  
  32. uint8_t failed_txs = 0;
  33. const uint8_t frame_size = sizeof(frame);
  34. volatile uint8_t cycles = 0;
  35.  
  36. RF24 radio(RF24_CE_PIN, RF24_CS_PIN);
  37.  
  38. OneWire oneWire(ONE_WIRE_BUS);
  39. DallasTemperature sensors(&oneWire);
  40.  
  41. void setup() {
  42. power_all_disable();
  43. power_spi_enable();
  44. power_timer0_enable();
  45.  
  46. //Setup the NRF24L01 radio
  47. radio.begin();
  48. radio.setPALevel(RF24_PA_LEVEL);
  49. radio.setChannel(RF24_CHANNEL);
  50. radio.setDataRate(RF24_DATARATE);
  51. radio.setCRCLength(RF24_CRCLENGTH);
  52. radio.openWritingPipe(base_address);
  53. radio.startListening();
  54.  
  55. //Setup the WDT
  56. MCUSR &= ~(1 << WDRF); // Clear the reset flag.
  57. WDTCSR |= (1 << WDCE) | (1 << WDE); //to change WDE or the prescaler, we need to set WDCE (This will allow updates for 4 clock cycles).
  58. WDTCSR = (1 << WDP3) | (1 << WDP0); // set the prescaler, so the period is 8.0 seconds
  59. WDTCSR |= (1 << WDIE); //enable WDT interrupts
  60.  
  61. //Setup the DS18B20 temperature sensor
  62. delay(100);
  63. sensors.begin();
  64. sensors.setResolution(12);
  65. DeviceAddress temp;
  66. sensors.getAddress(temp, 0);
  67. node_address = temp[7]; //use sensor's hardware address as radio node identifier
  68. }
  69.  
  70. bool sendData() {
  71. //Read temperature from the sensor
  72. sensors.requestTemperatures();
  73. float node_temp = sensors.getTempCByIndex(0);
  74.  
  75. //Get NRF24L01+ PA level
  76. uint8_t node_power = radio.getPALevel();
  77.  
  78. //Form a data packet
  79. frame packet = {node_address, node_temp, node_power};
  80.  
  81. //Send the packet by the radio
  82. radio.stopListening();
  83. bool tx_sent = radio.write( &packet, frame_size );
  84. radio.startListening();
  85.  
  86. return tx_sent;
  87. }
  88.  
  89. bool adaptPower() {
  90. for (int8_t tmp_power = RF24_PA_MAX; tmp_power >= RF24_PA_MIN; --tmp_power) {
  91. uint8_t tx_sent = 0;
  92. radio.setPALevel(tmp_power);
  93.  
  94. for (uint8_t i = 0; i < PWR_ADAPT_TRIES; ++i) {
  95. tx_sent += sendData();
  96. sleep_tight(ON_SLEEP_CYCLES);
  97. }
  98.  
  99. if (tx_sent == 0) {
  100. if (tmp_power == RF24_PA_MAX) {
  101. sleep_tight(OFF_SLEEP_CYCLES); //assume RX is off and go for a long nap
  102. return false;
  103. } else {
  104. radio.setPALevel(tmp_power + 1); //adjust power to the last working level
  105. break;
  106. }
  107. }
  108. }
  109. return true;
  110. }
  111.  
  112. void loop() {
  113. if (adaptPower()) {
  114. failed_txs = 0;
  115. while (failed_txs < FAILED_TXS_LIMIT) {
  116. if (sendData()) {
  117. failed_txs = 0; //reset counter
  118. } else {
  119. ++failed_txs;
  120. }
  121. sleep_tight(ON_SLEEP_CYCLES);
  122. }
  123. }
  124. }
  125.  
  126. void sleep_tight(uint8_t sleep_cycles) {
  127. cycles = 0;
  128.  
  129. radio.powerDown();
  130. set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  131. sleep_enable();
  132. /* Now enter sleep mode. */
  133. while (cycles != sleep_cycles) {
  134. sleep_mode();
  135. }
  136.  
  137. /* The program will continue from here after the WDT timeout*/
  138. sleep_disable(); /* First thing to do is disable sleep. */
  139. radio.powerUp();
  140.  
  141. /* Re-enable the peripherals. */
  142. power_spi_enable();
  143. power_timer0_enable();
  144. }
  145.  
  146. ISR(WDT_vect) {
  147. ++cycles;
  148. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement