/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
noInterrupts();
^~~~
warning: 'taskEXIT_CRITICAL(mux)' is deprecated in ESP-IDF, consider using 'portEXIT_CRITICAL(mux)'
interrupts();
^~
/Users/thomaschef/Documents/Develop/ESP32/HomeEnergyMeter/main/ds18b20.c: In function 'ds18b20_reset':
/Users/thomaschef/Documents/Develop/ESP32/HomeEnergyMeter/main/ds18b20.c:123:13: warning: 'taskENTER_CRITICAL(mux)' is deprecated in ESP-IDF, consider using 'portENTER_CRITICAL(mux)'
noInterrupts();
^~~~
/Users/thomaschef/Documents/Develop/ESP32/HomeEnergyMeter/main/ds18b20.c:131:13: warning: 'taskEXIT_CRITICAL(mux)' is deprecated in ESP-IDF, consider using 'portEXIT_CR
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp32/rom/ets_sys.h"
#include "ds18b20.h"
#include "config.h"
#ifdef ENABLE_DS18B20
// OneWire commands
#define GETTEMP 0x44 // Tells device to take a temperature reading and put it on the scratchpad
#define SKIPROM 0xCC // Command to address all devices on the bus
#define SELECTDEVICE 0x55 // Command to address all devices on the bus
#define COPYSCRATCH 0x48 // Copy scratchpad to EEPROM
#define READSCRATCH 0xBE // Read from scratchpad
#define WRITESCRATCH 0x4E // Write to scratchpad
#define RECALLSCRATCH 0xB8 // Recall from EEPROM to scratchpad
#define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
#define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
// Scratchpad locations
#define TEMP_LSB 0
#define TEMP_MSB 1
#define HIGH_ALARM_TEMP 2
#define LOW_ALARM_TEMP 3
#define CONFIGURATION 4
#define INTERNAL_BYTE 5
#define COUNT_REMAIN 6
#define COUNT_PER_C 7
#define SCRATCHPAD_CRC 8
// DSROM FIELDS
#define DSROM_FAMILY 0
#define DSROM_CRC 7
// Device resolution
#define TEMP_9_BIT 0x1F // 9 bit
#define TEMP_10_BIT 0x3F // 10 bit
#define TEMP_11_BIT 0x5F // 11 bit
#define TEMP_12_BIT 0x7F // 12 bit
uint8_t DS_GPIO;
uint8_t init=0;
uint8_t bitResolution=12;
uint8_t devices=0;
DeviceAddress ROM_NO;
uint8_t LastDiscrepancy;
uint8_t LastFamilyDiscrepancy;
bool LastDeviceFlag;
/// Sends one bit to bus
void ds18b20_write(char bit){
if (bit & 1) {
gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
noInterrupts();
gpio_set_level(DS_GPIO,0);
ets_delay_us(6);
gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT); // release bus
ets_delay_us(64);
interrupts();
} else {
gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
noInterrupts();
gpio_set_level(DS_GPIO,0);
ets_delay_us(60);
gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT); // release bus
ets_delay_us(10);
interrupts();
}
}
// Reads one bit from bus
unsigned char ds18b20_read(void){
unsigned char value = 0;
gpio_set_direction(DS_GPIO, GPIO_MODE_OUTPUT);
noInterrupts();
gpio_set_level(DS_GPIO, 0);
ets_delay_us(6);
gpio_set_direction(DS_GPIO, GPIO_MODE_INPUT);
ets_delay_us(9);
value = gpio_get_level(DS_GPIO);
ets_delay_us(55);
interrupts();
return (value);
}
// Sends one byte to bus
void ds18b20_write_byte(char data){
unsigned char i;
unsigned char x;
for(i=0;i<8;i++){
x = data>>i;
x &= 0x01;
ds18b20_write(x);
}
ets_delay_us(100);
}
// Reads one byte from bus
unsigned char ds18b20_read_byte(void){
unsigned char i;
unsigned char data = 0;
for (i=0;i<8;i++)
{
if(ds18b20_read()) data|=0x01<> 4) & 0x0f));
}
return crc;
}
bool ds18b20_isAllZeros(const uint8_t * const scratchPad) {
for (size_t i = 0; i < 9; i++) {
if (scratchPad[i] != 0) {
return false;
}
}
return true;
}
float ds18b20_getTempC(const DeviceAddress *deviceAddress) {
ScratchPad scratchPad;
if (ds18b20_isConnected(deviceAddress, scratchPad)){
int16_t rawTemp = calculateTemperature(deviceAddress, scratchPad);
if (rawTemp <= DEVICE_DISCONNECTED_RAW)
return DEVICE_DISCONNECTED_C;
// C = RAW/128
// F = (C*1.8)+32 = (RAW/128*1.8)+32 = (RAW*0.0140625)+32
return (float) rawTemp/128.0f;
}
return DEVICE_DISCONNECTED_C;
}
// reads scratchpad and returns fixed-point temperature, scaling factor 2^-7
int16_t calculateTemperature(const DeviceAddress *deviceAddress, uint8_t* scratchPad) {
int16_t fpTemperature = (((int16_t) scratchPad[TEMP_MSB]) << 11) | (((int16_t) scratchPad[TEMP_LSB]) << 3);
return fpTemperature;
}
// Returns temperature from sensor
float ds18b20_get_temp(void) {
if(init==1){
unsigned char check;
char temp1=0, temp2=0;
check=ds18b20_RST_PULSE();
if(check==1)
{
ds18b20_send_byte(0xCC);
ds18b20_send_byte(0x44);
vTaskDelay(750 / portTICK_RATE_MS);
check=ds18b20_RST_PULSE();
ds18b20_send_byte(0xCC);
ds18b20_send_byte(0xBE);
temp1=ds18b20_read_byte();
temp2=ds18b20_read_byte();
check=ds18b20_RST_PULSE();
float temp=0;
temp=(float)(temp1+(temp2*256))/16;
return temp;
}
else{return 0;}
}
else{return 0;}
}
void ds18b20_init(int GPIO) {
DS_GPIO = GPIO;
gpio_pad_select_gpio(DS_GPIO);
init = 1;
}
//
// You need to use this function to start a search again from the beginning.
// You do not need to do it for the first search, though you could.
//
void reset_search() {
devices=0;
// reset the search state
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
for (int i = 7; i >= 0; i--) {
ROM_NO[i] = 0;
}
}
// --- Replaced by the one from the Dallas Semiconductor web site ---
//--------------------------------------------------------------------------
// Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
// search state.
// Return TRUE : device found, ROM number in ROM_NO buffer
// FALSE : device not found, end of search
bool search(uint8_t *newAddr, bool search_mode) {
uint8_t id_bit_number;
uint8_t last_zero, rom_byte_number;
bool search_result;
uint8_t id_bit, cmp_id_bit;
unsigned char rom_byte_mask, search_direction;
// initialize for search
id_bit_number = 1;
last_zero = 0;
rom_byte_number = 0;
rom_byte_mask = 1;
search_result = false;
// if the last call was not the last one
if (!LastDeviceFlag) {
// 1-Wire reset
if (!ds18b20_reset()) {
// reset the search
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
return false;
}
// issue the search command
if (search_mode == true) {
ds18b20_write_byte(0xF0); // NORMAL SEARCH
} else {
ds18b20_write_byte(0xEC); // CONDITIONAL SEARCH
}
// loop to do the search
do {
// read a bit and its complement
id_bit = ds18b20_read();
cmp_id_bit = ds18b20_read();
// check for no devices on 1-wire
if ((id_bit == 1) && (cmp_id_bit == 1)) {
break;
} else {
// all devices coupled have 0 or 1
if (id_bit != cmp_id_bit) {
search_direction = id_bit; // bit write value for search
} else {
// if this discrepancy if before the Last Discrepancy
// on a previous next then pick the same as last time
if (id_bit_number < LastDiscrepancy) {
search_direction = ((ROM_NO[rom_byte_number]
& rom_byte_mask) > 0);
} else {
// if equal to last pick 1, if not then pick 0
search_direction = (id_bit_number == LastDiscrepancy);
}
// if 0 was picked then record its position in LastZero
if (search_direction == 0) {
last_zero = id_bit_number;
// check for Last discrepancy in family
if (last_zero < 9)
LastFamilyDiscrepancy = last_zero;
}
}
// set or clear the bit in the ROM byte rom_byte_number
// with mask rom_byte_mask
if (search_direction == 1)
ROM_NO[rom_byte_number] |= rom_byte_mask;
else
ROM_NO[rom_byte_number] &= ~rom_byte_mask;
// serial number search direction write bit
ds18b20_write(search_direction);
// increment the byte counter id_bit_number
// and shift the mask rom_byte_mask
id_bit_number++;
rom_byte_mask <<= 1;
// if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
if (rom_byte_mask == 0) {
rom_byte_number++;
rom_byte_mask = 1;
}
}
} while (rom_byte_number < 8); // loop until through all ROM bytes 0-7
// if the search was successful then
if (!(id_bit_number < 65)) {
// search successful so set LastDiscrepancy,LastDeviceFlag,search_result
LastDiscrepancy = last_zero;
// check for last device
if (LastDiscrepancy == 0) {
LastDeviceFlag = true;
}
search_result = true;
}
}
// if no device found then reset counters so next 'search' will be like a first
if (!search_result || !ROM_NO[0]) {
devices=0;
LastDiscrepancy = 0;
LastDeviceFlag = false;
LastFamilyDiscrepancy = 0;
search_result = false;
} else {
for (int i = 0; i < 8; i++){
newAddr[i] = ROM_NO[i];
}
devices++;
}
return search_result;
}
#endif // ENABLE_DS18B20