ds18b20.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. #include "freertos/FreeRTOS.h"
  14. #include "freertos/task.h"
  15. #include "driver/gpio.h"
  16. #include "esp32/rom/ets_sys.h"
  17. #include "ds18b20.h"
  18. #include "config.h"
  19. #ifdef ENABLE_DS18B20
  20. // OneWire commands
  21. #define GETTEMP 0x44 // Tells device to take a temperature reading and put it on the scratchpad
  22. #define SKIPROM 0xCC // Command to address all devices on the bus
  23. #define SELECTDEVICE 0x55 // Command to address all devices on the bus
  24. #define COPYSCRATCH 0x48 // Copy scratchpad to EEPROM
  25. #define READSCRATCH 0xBE // Read from scratchpad
  26. #define WRITESCRATCH 0x4E // Write to scratchpad
  27. #define RECALLSCRATCH 0xB8 // Recall from EEPROM to scratchpad
  28. #define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
  29. #define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
  30. // Scratchpad locations
  31. #define TEMP_LSB 0
  32. #define TEMP_MSB 1
  33. #define HIGH_ALARM_TEMP 2
  34. #define LOW_ALARM_TEMP 3
  35. #define CONFIGURATION 4
  36. #define INTERNAL_BYTE 5
  37. #define COUNT_REMAIN 6
  38. #define COUNT_PER_C 7
  39. #define SCRATCHPAD_CRC 8
  40. // DSROM FIELDS
  41. #define DSROM_FAMILY 0
  42. #define DSROM_CRC 7
  43. // Device resolution
  44. #define TEMP_9_BIT 0x1F // 9 bit
  45. #define TEMP_10_BIT 0x3F // 10 bit
  46. #define TEMP_11_BIT 0x5F // 11 bit
  47. #define TEMP_12_BIT 0x7F // 12 bit
  48. uint8_t DS_GPIO;
  49. uint8_t init=0;
  50. uint8_t bitResolution=12;
  51. uint8_t devices=0;
  52. DeviceAddress ROM_NO;
  53. uint8_t LastDiscrepancy;
  54. uint8_t LastFamilyDiscrepancy;
  55. bool LastDeviceFlag;
  56. /// Sends one bit to bus
  57. void ds18b20_write(char bit){
  58. if (bit & 1) {
  59. gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
  60. noInterrupts();
  61. gpio_set_level(DS_GPIO,0);
  62. ets_delay_us(6);
  63. gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT); // release bus
  64. ets_delay_us(64);
  65. interrupts();
  66. } else {
  67. gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
  68. noInterrupts();
  69. gpio_set_level(DS_GPIO,0);
  70. ets_delay_us(60);
  71. gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT); // release bus
  72. ets_delay_us(10);
  73. interrupts();
  74. }
  75. }
  76. // Reads one bit from bus
  77. unsigned char ds18b20_read(void){
  78. unsigned char value = 0;
  79. gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
  80. noInterrupts();
  81. gpio_set_level(DS_GPIO, 0);
  82. ets_delay_us(6);
  83. gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT);
  84. ets_delay_us(9);
  85. value = gpio_get_level(DS_GPIO);
  86. ets_delay_us(55);
  87. interrupts();
  88. return (value);
  89. }
  90. // Sends one byte to bus
  91. void ds18b20_write_byte(char data){
  92. unsigned char i;
  93. unsigned char x;
  94. for(i=0;i<8;i++){
  95. x = data>>i;
  96. x &= 0x01;
  97. ds18b20_write(x);
  98. }
  99. ets_delay_us(100);
  100. }
  101. // Reads one byte from bus
  102. unsigned char ds18b20_read_byte(void){
  103. unsigned char i;
  104. unsigned char data = 0;
  105. for (i=0;i<8;i++)
  106. {
  107. if(ds18b20_read()) data|=0x01<<i;
  108. ets_delay_us(15);
  109. }
  110. return(data);
  111. }
  112. // Sends reset pulse
  113. unsigned char ds18b20_reset(void){
  114. unsigned char presence;
  115. gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
  116. noInterrupts();
  117. gpio_set_level(DS_GPIO, 0);
  118. ets_delay_us(480);
  119. gpio_set_level(DS_GPIO, 1);
  120. gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT);
  121. ets_delay_us(70);
  122. presence = (gpio_get_level(DS_GPIO) == 0);
  123. ets_delay_us(410);
  124. interrupts();
  125. return presence;
  126. }
  127. bool ds18b20_setResolution(const DeviceAddress tempSensorAddresses[], int numAddresses, uint8_t newResolution) {
  128. bool success = false;
  129. // handle the sensors with configuration register
  130. newResolution = constrain(newResolution, 9, 12);
  131. uint8_t newValue = 0;
  132. ScratchPad scratchPad;
  133. // loop through each address
  134. for (int i = 0; i < numAddresses; i++){
  135. // we can only update the sensor if it is connected
  136. if (ds18b20_isConnected((DeviceAddress*) tempSensorAddresses[i], scratchPad)) {
  137. switch (newResolution) {
  138. case 12:
  139. newValue = TEMP_12_BIT;
  140. break;
  141. case 11:
  142. newValue = TEMP_11_BIT;
  143. break;
  144. case 10:
  145. newValue = TEMP_10_BIT;
  146. break;
  147. case 9:
  148. default:
  149. newValue = TEMP_9_BIT;
  150. break;
  151. }
  152. // if it needs to be updated we write the new value
  153. if (scratchPad[CONFIGURATION] != newValue) {
  154. scratchPad[CONFIGURATION] = newValue;
  155. ds18b20_writeScratchPad((DeviceAddress*) tempSensorAddresses[i], scratchPad);
  156. }
  157. // done
  158. success = true;
  159. }
  160. }
  161. return success;
  162. }
  163. void ds18b20_writeScratchPad(const DeviceAddress *deviceAddress, const uint8_t *scratchPad) {
  164. ds18b20_reset();
  165. ds18b20_select(deviceAddress);
  166. ds18b20_write_byte(WRITESCRATCH);
  167. ds18b20_write_byte(scratchPad[HIGH_ALARM_TEMP]); // high alarm temp
  168. ds18b20_write_byte(scratchPad[LOW_ALARM_TEMP]); // low alarm temp
  169. ds18b20_write_byte(scratchPad[CONFIGURATION]);
  170. ds18b20_reset();
  171. }
  172. bool ds18b20_readScratchPad(const DeviceAddress *deviceAddress, uint8_t* scratchPad) {
  173. // send the reset command and fail fast
  174. int b = ds18b20_reset();
  175. if (b == 0) return false;
  176. ds18b20_select(deviceAddress);
  177. ds18b20_write_byte(READSCRATCH);
  178. // Read all registers in a simple loop
  179. // byte 0: temperature LSB
  180. // byte 1: temperature MSB
  181. // byte 2: high alarm temp
  182. // byte 3: low alarm temp
  183. // byte 4: DS18B20 & DS1822: configuration register
  184. // byte 5: internal use & crc
  185. // byte 6: DS18B20 & DS1822: store for crc
  186. // byte 7: DS18B20 & DS1822: store for crc
  187. // byte 8: SCRATCHPAD_CRC
  188. for (uint8_t i = 0; i < 9; i++) {
  189. scratchPad[i] = ds18b20_read_byte();
  190. }
  191. b = ds18b20_reset();
  192. return (b == 1);
  193. }
  194. void ds18b20_select(const DeviceAddress *address){
  195. uint8_t i;
  196. ds18b20_write_byte(SELECTDEVICE); // Choose ROM
  197. for (i = 0; i < 8; i++) ds18b20_write_byte(((uint8_t *)address)[i]);
  198. }
  199. void ds18b20_requestTemperatures(){
  200. ds18b20_reset();
  201. ds18b20_write_byte(SKIPROM);
  202. ds18b20_write_byte(GETTEMP);
  203. unsigned long start = esp_timer_get_time() / 1000ULL;
  204. while (!isConversionComplete() && ((esp_timer_get_time() / 1000ULL) - start < millisToWaitForConversion())) vPortYield();
  205. }
  206. bool isConversionComplete() {
  207. uint8_t b = ds18b20_read();
  208. return (b == 1);
  209. }
  210. uint16_t millisToWaitForConversion() {
  211. switch (bitResolution) {
  212. case 9:
  213. return 94;
  214. case 10:
  215. return 188;
  216. case 11:
  217. return 375;
  218. default:
  219. return 750;
  220. }
  221. }
  222. bool ds18b20_isConnected(const DeviceAddress *deviceAddress, uint8_t *scratchPad) {
  223. bool b = ds18b20_readScratchPad(deviceAddress, scratchPad);
  224. return b && !ds18b20_isAllZeros(scratchPad) && (ds18b20_crc8(scratchPad, 8) == scratchPad[SCRATCHPAD_CRC]);
  225. }
  226. uint8_t ds18b20_crc8(const uint8_t *addr, uint8_t len){
  227. uint8_t crc = 0;
  228. while (len--) {
  229. crc = *addr++ ^ crc; // just re-using crc as intermediate
  230. crc = pgm_read_byte(dscrc2x16_table + (crc & 0x0f)) ^
  231. pgm_read_byte(dscrc2x16_table + 16 + ((crc >> 4) & 0x0f));
  232. }
  233. return crc;
  234. }
  235. bool ds18b20_isAllZeros(const uint8_t * const scratchPad) {
  236. for (size_t i = 0; i < 9; i++) {
  237. if (scratchPad[i] != 0) {
  238. return false;
  239. }
  240. }
  241. return true;
  242. }
  243. float ds18b20_getTempC(const DeviceAddress *deviceAddress) {
  244. ScratchPad scratchPad;
  245. if (ds18b20_isConnected(deviceAddress, scratchPad)){
  246. int16_t rawTemp = calculateTemperature(deviceAddress, scratchPad);
  247. if (rawTemp <= DEVICE_DISCONNECTED_RAW)
  248. return DEVICE_DISCONNECTED_C;
  249. // C = RAW/128
  250. // F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32
  251. return (float) rawTemp/128.0f;
  252. }
  253. return DEVICE_DISCONNECTED_C;
  254. }
  255. // reads scratchpad and returns fixed-point temperature, scaling factor 2^-7
  256. int16_t calculateTemperature(const DeviceAddress *deviceAddress, uint8_t* scratchPad) {
  257. int16_t fpTemperature = (((int16_t) scratchPad[TEMP_MSB]) << 11) | (((int16_t) scratchPad[TEMP_LSB]) << 3);
  258. return fpTemperature;
  259. }
  260. // Returns temperature from sensor
  261. float ds18b20_get_temp(void) {
  262. if(init==1){
  263. unsigned char check;
  264. char temp1=0, temp2=0;
  265. check=ds18b20_RST_PULSE();
  266. if(check==1)
  267. {
  268. ds18b20_send_byte(0xCC);
  269. ds18b20_send_byte(0x44);
  270. vTaskDelay(750 / portTICK_RATE_MS);
  271. check=ds18b20_RST_PULSE();
  272. ds18b20_send_byte(0xCC);
  273. ds18b20_send_byte(0xBE);
  274. temp1=ds18b20_read_byte();
  275. temp2=ds18b20_read_byte();
  276. check=ds18b20_RST_PULSE();
  277. float temp=0;
  278. temp=(float)(temp1+(temp2*256))/16;
  279. return temp;
  280. }
  281. else{return 0;}
  282. }
  283. else{return 0;}
  284. }
  285. void ds18b20_init(int GPIO) {
  286. DS_GPIO = GPIO;
  287. gpio_pad_select_gpio(DS_GPIO);
  288. init = 1;
  289. }
  290. //
  291. // You need to use this function to start a search again from the beginning.
  292. // You do not need to do it for the first search, though you could.
  293. //
  294. void reset_search() {
  295. devices=0;
  296. // reset the search state
  297. LastDiscrepancy = 0;
  298. LastDeviceFlag = false;
  299. LastFamilyDiscrepancy = 0;
  300. for (int i = 7; i >= 0; i--) {
  301. ROM_NO[i] = 0;
  302. }
  303. }
  304. // --- Replaced by the one from the Dallas Semiconductor web site ---
  305. //--------------------------------------------------------------------------
  306. // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
  307. // search state.
  308. // Return TRUE : device found, ROM number in ROM_NO buffer
  309. // FALSE : device not found, end of search
  310. bool search(uint8_t *newAddr, bool search_mode) {
  311. uint8_t id_bit_number;
  312. uint8_t last_zero, rom_byte_number;
  313. bool search_result;
  314. uint8_t id_bit, cmp_id_bit;
  315. unsigned char rom_byte_mask, search_direction;
  316. // initialize for search
  317. id_bit_number = 1;
  318. last_zero = 0;
  319. rom_byte_number = 0;
  320. rom_byte_mask = 1;
  321. search_result = false;
  322. // if the last call was not the last one
  323. if (!LastDeviceFlag) {
  324. // 1-Wire reset
  325. if (!ds18b20_reset()) {
  326. // reset the search
  327. LastDiscrepancy = 0;
  328. LastDeviceFlag = false;
  329. LastFamilyDiscrepancy = 0;
  330. return false;
  331. }
  332. // issue the search command
  333. if (search_mode == true) {
  334. ds18b20_write_byte(0xF0); // NORMAL SEARCH
  335. } else {
  336. ds18b20_write_byte(0xEC); // CONDITIONAL SEARCH
  337. }
  338. // loop to do the search
  339. do {
  340. // read a bit and its complement
  341. id_bit = ds18b20_read();
  342. cmp_id_bit = ds18b20_read();
  343. // check for no devices on 1-wire
  344. if ((id_bit == 1) && (cmp_id_bit == 1)) {
  345. break;
  346. } else {
  347. // all devices coupled have 0 or 1
  348. if (id_bit != cmp_id_bit) {
  349. search_direction = id_bit; // bit write value for search
  350. } else {
  351. // if this discrepancy if before the Last Discrepancy
  352. // on a previous next then pick the same as last time
  353. if (id_bit_number < LastDiscrepancy) {
  354. search_direction = ((ROM_NO[rom_byte_number]
  355. & rom_byte_mask) > 0);
  356. } else {
  357. // if equal to last pick 1, if not then pick 0
  358. search_direction = (id_bit_number == LastDiscrepancy);
  359. }
  360. // if 0 was picked then record its position in LastZero
  361. if (search_direction == 0) {
  362. last_zero = id_bit_number;
  363. // check for Last discrepancy in family
  364. if (last_zero < 9)
  365. LastFamilyDiscrepancy = last_zero;
  366. }
  367. }
  368. // set or clear the bit in the ROM byte rom_byte_number
  369. // with mask rom_byte_mask
  370. if (search_direction == 1)
  371. ROM_NO[rom_byte_number] |= rom_byte_mask;
  372. else
  373. ROM_NO[rom_byte_number] &= ~rom_byte_mask;
  374. // serial number search direction write bit
  375. ds18b20_write(search_direction);
  376. // increment the byte counter id_bit_number
  377. // and shift the mask rom_byte_mask
  378. id_bit_number++;
  379. rom_byte_mask <<= 1;
  380. // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
  381. if (rom_byte_mask == 0) {
  382. rom_byte_number++;
  383. rom_byte_mask = 1;
  384. }
  385. }
  386. } while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
  387. // if the search was successful then
  388. if (!(id_bit_number < 65)) {
  389. // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
  390. LastDiscrepancy = last_zero;
  391. // check for last device
  392. if (LastDiscrepancy == 0) {
  393. LastDeviceFlag = true;
  394. }
  395. search_result = true;
  396. }
  397. }
  398. // if no device found then reset counters so next 'search' will be like a first
  399. if (!search_result || !ROM_NO[0]) {
  400. devices=0;
  401. LastDiscrepancy = 0;
  402. LastDeviceFlag = false;
  403. LastFamilyDiscrepancy = 0;
  404. search_result = false;
  405. } else {
  406. for (int i = 0; i < 8; i++){
  407. newAddr[i] = ROM_NO[i];
  408. }
  409. devices++;
  410. }
  411. return search_result;
  412. }
  413. #endif // ENABLE_DS18B20