Advertisement
Guest User

Untitled

a guest
Nov 10th, 2017
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.53 KB | None | 0 0
  1.  
  2.  
  3. ////////////const byte version = 27; // firmware version divided by 10 e,g 16 = V1.6
  4. // These variables control the transmit timing of the emonTH
  5. const unsigned long WDT_PERIOD = 80; // mseconds.
  6. const unsigned long WDT_MAX_NUMBER = 690; // Data sent after WDT_MAX_NUMBER periods of WDT_PERIOD ms without pulses:
  7. // 690x 80 = 55.2 seconds (it needs to be about 5s less than the record interval in emoncms)
  8.  
  9. const unsigned long PULSE_MAX_NUMBER = 100; // Data sent after PULSE_MAX_NUMBER pulses
  10. const unsigned long PULSE_MAX_DURATION = 50;
  11.  
  12.  
  13. #define RF69_COMPAT 1 // Set to 1 if using RFM69CW or 0 is using RFM12B
  14. #include <JeeLib.h> // https://github.com/jcw/jeelib - Tested with JeeLib 3/11/14
  15.  
  16. const boolean debug=1; // Set to 1 to few debug serial output, turning debug off increases battery life
  17.  
  18. #define RF_freq RF12_433MHZ // Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.
  19. int nodeID = 10; // EmonTH temperature RFM12B node ID - should be unique on network
  20. const int networkGroup = 210; // EmonTH RFM12B wireless network group - needs to be same as emonBase and emonGLCD
  21. // DS18B20 resolution 9,10,11 or 12bit corresponding to (0.5, 0.25, 0.125, 0.0625 degrees C LSB),
  22. // lower resolution means lower power
  23.  
  24. const int TEMPERATURE_PRECISION=12; // 9 (93.8ms),10 (187.5ms) ,11 (375ms) or 12 (750ms) bits equal to resplution of 0.5C, 0.25C, 0.125C and 0.0625C
  25. #define ASYNC_DELAY 750 // 9bit requres 95ms, 10bit 187ms, 11bit 375ms and 12bit resolution takes 750ms
  26. // See block comment above for library info
  27. ////////#include <avr/power.h>
  28. ////////#include <avr/sleep.h>
  29. #include <OneWire.h>
  30. #include <DallasTemperature.h>
  31. #include "DHT.h"
  32. ////////ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Attached JeeLib sleep function to Atmega328 watchdog -enables MCU to be put into sleep mode inbetween readings to reduce power consumption
  33.  
  34. // Hardwired emonTH pin allocations
  35. ////////const byte DS18B20_PWR= 5;
  36. ////////const byte DHT22_PWR= 6;
  37. const byte LED= 9;
  38. ////////const byte BATT_ADC= 1;
  39. ////////const byte DIP_switch1= 7;
  40. ////////const byte DIP_switch2= 8;
  41. const byte pulse_countINT= 1; // INT 1 / Dig 3 Screw Terminal Block Number 4 on emonTH V1.5 - Change to INT0 DIG2 on emonTH V1.4
  42. const byte pulse_count_pin=3; // INT 1 / Dig 3 Screw Terminal Block Number 4 on emonTH V1.5 - Change to INT0 DIG2 on emonTH V1.4
  43. #define ONE_WIRE_BUS 19
  44. #define DHTPIN 18
  45.  
  46. // Humidity code adapted from ladyada' example // emonTh DHT22 data pin
  47. // Uncomment whatever type you're using!
  48. // #define DHTTYPE DHT11 // DHT 11
  49. #define DHTTYPE DHT22 // DHT 22 (AM2302)
  50. DHT dht(DHTPIN, DHTTYPE);
  51. boolean DHT22_status; // create flag variable to store presence of DS18B20
  52.  
  53. OneWire oneWire(ONE_WIRE_BUS);
  54. DallasTemperature sensors(&oneWire);
  55. boolean DS18B20; // create flag variable to store presence of DS18B20
  56.  
  57. // Note: Please update emonhub configuration guide on OEM wide packet structure change:
  58. // https://github.com/openenergymonitor/emonhub/blob/emon-pi/configuration.md
  59. typedef struct { // RFM12B RF payload datastructure
  60. int temp;
  61. int temp_external;
  62. int humidity;
  63. //////////// int battery;
  64. unsigned long pulsecount;
  65. } Payload;
  66. Payload emonth;
  67.  
  68. int numSensors;
  69. //addresses of sensors, MAX 4!!
  70. byte allAddress [4][8]; // 8 bytes per address
  71.  
  72. volatile unsigned long pulseCount;
  73. unsigned long WDT_number;
  74. boolean p;
  75.  
  76. unsigned long now = 0;
  77.  
  78. //################################################################################################################################
  79. //################################################################################################################################
  80. void setup() {
  81. //################################################################################################################################
  82.  
  83. pinMode(LED,OUTPUT); digitalWrite(LED,HIGH); // Status LED on
  84.  
  85. //READ DIP SWITCH POSITIONS - LOW when switched on (default off - pulled up high)
  86. ////////////pinMode(DIP_switch1, INPUT_PULLUP);
  87. ////////////pinMode(DIP_switch2, INPUT_PULLUP);
  88. ////////////boolean DIP1 = digitalRead(DIP_switch1);
  89. ////////////boolean DIP2 = digitalRead(DIP_switch2);
  90.  
  91. ////////////if ((DIP1 == HIGH) && (DIP2 == HIGH)) nodeID=nodeID;
  92. ////////////if ((DIP1 == LOW) && (DIP2 == HIGH)) nodeID=nodeID+1;
  93. ////////////if ((DIP1 == HIGH) && (DIP2 == LOW)) nodeID=nodeID+2;
  94. ////////////if ((DIP1 == LOW) && (DIP2 == LOW)) nodeID=nodeID+3;
  95.  
  96. rf12_initialize(nodeID, RF_freq, networkGroup); // Initialize RFM12B
  97.  
  98. // Send RFM69CW test sequence (for factory testing)
  99. for (int i=10; i>-1; i--)
  100. {
  101. emonth.temp=i;
  102. rf12_sendNow(0, &emonth, sizeof emonth);
  103. delay(100);
  104. }
  105. rf12_sendWait(2);
  106. emonth.temp=0;
  107. // end of factory test sequence
  108.  
  109. ////////////rf12_sleep(RF12_SLEEP);
  110. if (debug==1)
  111. {
  112. Serial.begin(9600);
  113. //////////// Serial.print(DIP1); Serial.println(DIP2);
  114. Serial.println("OpenEnergyMonitor.org");
  115. ////////////Serial.print("emonTH - Firmware V"); Serial.println(version*0.1);
  116. #if (RF69_COMPAT)
  117. Serial.println("RFM69CW Init> ");
  118. #else
  119. Serial.println("RFM12B Init> ");
  120. #endif
  121. Serial.print("Node: ");
  122. Serial.print(nodeID);
  123. Serial.print(" Freq: ");
  124. if (RF_freq == RF12_433MHZ) Serial.print("433Mhz");
  125. if (RF_freq == RF12_868MHZ) Serial.print("868Mhz");
  126. if (RF_freq == RF12_915MHZ) Serial.print("915Mhz");
  127. Serial.print(" Network: ");
  128. Serial.println(networkGroup);
  129. delay(100);
  130. }
  131.  
  132. ////////pinMode(DHT22_PWR,OUTPUT);
  133. ////////pinMode(DS18B20_PWR,OUTPUT);
  134. ////////////pinMode(BATT_ADC, INPUT);
  135. ////////digitalWrite(DHT22_PWR,LOW);
  136. pinMode(pulse_count_pin, INPUT_PULLUP);
  137.  
  138. //################################################################################################################################
  139. // Power Save - turn off what we don't need - http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
  140. //################################################################################################################################
  141. //////// ACSR |= (1 << ACD); // disable Analog comparator
  142. ////////if (debug==0) power_usart0_disable(); //disable serial UART
  143. ////////power_twi_disable(); //Disable the Two Wire Interface module.
  144. // power_timer0_disable(); //don't disable necessary for the DS18B20 library
  145. ////////power_timer1_disable();
  146. ////////power_spi_disable();
  147.  
  148. //################################################################################################################################
  149. // Test for presence of DHT22
  150. //################################################################################################################################
  151. ////////digitalWrite(DHT22_PWR,HIGH);
  152. ////////dodelay(2000); // wait 2s for DH22 to warm up
  153. dht.begin();
  154. float h = dht.readHumidity(); // Read Humidity
  155. float t = dht.readTemperature(); // Read Temperature
  156. ////////digitalWrite(DHT22_PWR,LOW); // Power down
  157.  
  158. if (isnan(t) || isnan(h)) // check if returns are valid, if they are NaN (not a number) then something went wrong!
  159. {
  160. Sleepy::loseSomeTime(1500);
  161. float h = dht.readHumidity(); float t = dht.readTemperature();
  162. if (isnan(t) || isnan(h))
  163. {
  164. if (debug==1) Serial.println("No DHT22");
  165. DHT22_status=0;
  166. }
  167. }
  168. else
  169. {
  170. DHT22_status=1;
  171. if (debug==1) Serial.println("Detected DHT22");
  172. }
  173.  
  174. //################################################################################################################################
  175. // Setup and for presence of DS18B20
  176. //################################################################################################################################
  177. ////////digitalWrite(DS18B20_PWR, HIGH); delay(50);
  178. sensors.begin();
  179. ////////////sensors.setWaitForConversion(false); //disable automatic temperature conversion to reduce time spent awake, conversion will be implemented manually in sleeping http://harizanov.com/2013/07/optimizing-ds18b20-code-for-low-power-applications/
  180. numSensors=(sensors.getDeviceCount());
  181.  
  182. byte j=0; // search for one wire devices and
  183. // copy to device address arrays.
  184. while ((j < numSensors) && (oneWire.search(allAddress[j]))) j++;
  185. ////////digitalWrite(DS18B20_PWR, LOW);
  186.  
  187. if (numSensors==0)
  188. {
  189. if (debug==1) Serial.println("No DS18B20");
  190. DS18B20=0;
  191. }
  192. else
  193. {
  194. DS18B20=1;
  195. if (debug==1) {
  196. Serial.print("Detected "); Serial.print(numSensors); Serial.println(" DS18B20");
  197. if (DHT22_status==1) Serial.println("DS18B20 & DHT22 found, assume DS18B20 is external");
  198. }
  199. }
  200. if (debug==1) delay(200);
  201.  
  202. //################################################################################################################################
  203. // Serial.print(DS18B20); Serial.print(DHT22_status);
  204. // if (debug==1) delay(200);
  205.  
  206. digitalWrite(LED,LOW);
  207.  
  208. emonth.pulsecount = 0;
  209. pulseCount = 0;
  210. WDT_number=720;
  211. p = 0;
  212.  
  213. attachInterrupt(pulse_countINT, onPulse, RISING);
  214. } // end of setup
  215.  
  216.  
  217. //################################################################################################################################
  218. //################################################################################################################################
  219. void loop()
  220. //################################################################################################################################
  221. {
  222.  
  223. if (p) {
  224. Sleepy::loseSomeTime(PULSE_MAX_DURATION);
  225. p=0;
  226. }
  227.  
  228. if (Sleepy::loseSomeTime(WDT_PERIOD)==1) {
  229. WDT_number++;
  230. }
  231.  
  232. if (WDT_number>=WDT_MAX_NUMBER || pulseCount>=PULSE_MAX_NUMBER)
  233. {
  234. cli();
  235. emonth.pulsecount += (unsigned int) pulseCount;
  236. pulseCount = 0;
  237. sei();
  238.  
  239. if (DS18B20==1)
  240. {
  241. ////////digitalWrite(DS18B20_PWR, HIGH); dodelay(50);
  242. for(int j=0;j<numSensors;j++) sensors.setResolution(allAddress[j], TEMPERATURE_PRECISION); // and set the a to d conversion resolution of each.
  243. sensors.requestTemperatures(); // Send the command to get temperatures
  244. dodelay(ASYNC_DELAY); //Must wait for conversion, since we use ASYNC mode
  245. float temp=(sensors.getTempC(allAddress[0]));
  246. //////// digitalWrite(DS18B20_PWR, LOW);
  247. if ((temp<125.0) && (temp>-40.0))
  248. {
  249. if (DHT22_status==0) emonth.temp=(temp*10); // if DHT22 is not present assume DS18B20 is primary sensor (internal)
  250. if (DHT22_status==1) emonth.temp_external=(temp*10); // if DHT22 is present assume DS18B20 is external sensor wired into terminal block
  251. }
  252. }
  253.  
  254. if (DHT22_status==1)
  255. {
  256. ////////digitalWrite(DHT22_PWR,HIGH); // Send the command to get temperatures
  257. ////////dodelay(2000); //sleep for 1.5 - 2's to allow sensor to warm up
  258. // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  259. emonth.humidity = ((dht.readHumidity())*10);
  260.  
  261. float temp=(dht.readTemperature());
  262. if ((temp<85.0) && (temp>-40.0)) emonth.temp = (temp*10);
  263.  
  264. ////////digitalWrite(DHT22_PWR,LOW);
  265. }
  266.  
  267. ////////////emonth.battery=int(analogRead(BATT_ADC)*0.03225806); //read battery voltage, convert ADC to volts x10
  268.  
  269. //Enhanced battery monitoring mode. In this mode battery values
  270. //sent in x*1000 mode instead of x*10. This allows to have more accurate
  271. //values on emonCMS x.xx instead of x.x
  272. // NOTE if you are going to enable this mode you need to
  273. // 1. Disable x*10 mode. By commenting line above.
  274. // 2. Change multiplier in line 353 Serial.print(emonth.battery/10.0);
  275. // 3. Change scales factor in the emonhub node decoder entry for the emonTH
  276. // See more https://community.openenergymonitor.org/t/emonth-battery-measurement-accuracy/1317
  277. //emonth.battery=int(analogRead(BATT_ADC)*3.222);
  278.  
  279. if (debug==1)
  280. {
  281. if (DS18B20)
  282. {
  283. Serial.print("DS18B20 Temperature: ");
  284. if (DHT22_status) Serial.print(emonth.temp_external/10.0);
  285. if (!DHT22_status) Serial.print(emonth.temp/10.0);
  286. Serial.print("C, ");
  287. }
  288.  
  289. if (DHT22_status)
  290. {
  291. Serial.print("DHT22 Temperature: ");
  292. Serial.print(emonth.temp/10.0);
  293. Serial.print("C, DHT22 Humidity: ");
  294. Serial.print(emonth.humidity/10.0);
  295. Serial.print("%, ");
  296. }
  297.  
  298. //////////// Serial.print("Battery voltage: ");
  299. //////////// Serial.print(emonth.battery/10.0);
  300. Serial.print("V, Pulse count: ");
  301. Serial.print(emonth.pulsecount);
  302. Serial.println("n");
  303.  
  304. unsigned long last = now;
  305. now = millis();
  306.  
  307. delay(100);
  308. }
  309.  
  310.  
  311. ////////////power_spi_enable();
  312.  
  313. ////////////rf12_sleep(RF12_WAKEUP);
  314. ////////////dodelay(100);
  315. rf12_sendNow(0, &emonth, sizeof emonth);
  316. // set the sync mode to 2 if the fuses are still the Arduino default
  317. // mode 3 (full powerdown) can only be used with 258 CK startup fuses
  318. rf12_sendWait(2);
  319. ////////////rf12_sleep(RF12_SLEEP);
  320. ////////////dodelay(100);
  321. ////////////power_spi_disable();
  322. //digitalWrite(LED,HIGH);
  323. //dodelay(100);
  324. //digitalWrite(LED,LOW);
  325.  
  326. WDT_number=0;
  327. }
  328.  
  329. } // end loop
  330.  
  331. void dodelay(unsigned int ms)
  332. {
  333. ////////////byte oldADCSRA=ADCSRA;
  334. ////////////byte oldADCSRB=ADCSRB;
  335. ////////////byte oldADMUX=ADMUX;
  336.  
  337. Sleepy::loseSomeTime(ms); // JeeLabs power save function: enter low power mode for x seconds (valid range 16-65000 ms)
  338.  
  339. ////////////ADCSRA=oldADCSRA; // restore ADC state
  340. ////////////ADCSRB=oldADCSRB;
  341. ////////////ADMUX=oldADMUX;
  342. }
  343.  
  344. // The interrupt routine - runs each time a rising edge of a pulse is detected
  345. void onPulse()
  346. {
  347. p=1; // flag for new pulse set to true
  348. pulseCount++; // number of pulses since the last RF sent
  349. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement