Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
6 years ago.
Failure to read with temperature sensor DS18B20
Hi all, I am trying to read from the DS18B20 temperature sensor using this library: https://os.mbed.com/users/hudakz/code/DS1820/ .
The picture above shows the main function but it doesn't work. The "begin()" function always returns false and the program terminates. This happens because the "search" function doesn't ends properly.
begin()
bool DS1820::begin(void) { oneWire.reset_search(); wait_ms(250); if(!oneWire.search(addr)) { #if DEBUG serial.printf("No addresses.\r\n"); #endif oneWire.reset_search(); wait_ms(250); return false; } #if DEBUG serial.printf("ROM ="); for(uint8_t i = 0; i < 8; i++) { serial.printf(" %x", addr[i]); } serial.printf("\r\n"); #endif if(OneWire::crc8(addr, 7) == addr[7]) { present = true; // the first ROM byte indicates which chip switch(addr[0]) { case 0x10: model_s = true; #if DEBUG serial.printf("DS18S20 or old DS1820\r\n"); #endif break; case 0x28: model_s = false; #if DEBUG serial.printf("DS18B20\r\n"); #endif break; case 0x22: model_s = false; #if DEBUG serial.printf("DS1822\r\n"); #endif break; default: present = false; #if DEBUG serial.printf("Device doesn't belong to the DS1820 family\r\n"); #endif return false; } return true; } else { #if DEBUG serial.printf("Invalid CRC!\r\n"); #endif return false; } }
search()
uint8_t OneWire::search(uint8_t *newAddr) { uint8_t id_bit_number; uint8_t last_zero, rom_byte_number, 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 = 0; // if the last call was not the last one if (!LastDeviceFlag) { // 1-Wire reset if (!reset()) { // reset the search LastDiscrepancy = 0; LastDeviceFlag = false; LastFamilyDiscrepancy = 0; return false; } // issue the search command write(0xF0); // loop to do the search do { // read a bit and its complement id_bit = read_bit(); cmp_id_bit = read_bit(); // 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 write_bit(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]) { LastDiscrepancy = 0; LastDeviceFlag = false; LastFamilyDiscrepancy = 0; search_result = false; } for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; return search_result; }
Does someone have any suggestion and can help me to understand why it isn't working?
Question relating to:
5 Answers
5 years, 8 months ago.
Hi,
Did you resolve your issue? Because I have the same problem with STM32L072CZ board
5 years, 11 months ago.
Hi, I have the same problem. Did you solved the problem?
Thank you
I have found some issues since I did a recent MBED OS2 update, I could no longer read more than one sensor. Revert back to a 2016 version and works fine. Looks like there are some timing issues, RTC also has a problem now.
posted by 18 Jan 2019Thank you Paul. I'm sorry, when you say MBED OS2, you mean MBED OS 5.2 ? https://github.com/ARMmbed/mbed-os/releases/tag/mbed-os-5.2.0
Thanks
posted by 18 Jan 2019No, the classic OS2 libraries here:
https://os.mbed.com/users/mbed_official/code/mbed-dev/
posted by 18 Jan 2019I have had a bit of a result, try this MBED-DEV version:
https://os.mbed.com/users/maxxir/code/mbed-dev/
I have my sensors back and RTC working.
posted by 18 Jan 2019OK, Thank you again Paul. I'm sorry but i'm having trouble to use this version of MBED-dev. The online version of MBED get stuck when i try to import this library to a new empty project.
Then i tryed using mbed-cli on my linux machine:
mbed new empty3 mbedlib force-mbed2-tools
mbed add http://os.mbed.com/users/mbed_official/code/mbed-dev/
mbed add http://os.mbed.com/users/Sissors/code/DS1820/
Then I add a simple main.cpp file
mbed compile -t GCC_ARM -m DISCO_L072CZ_LRWAN1
The copilation get stuck on a python error : "in find_build_profile if MBED_SDK_REV_MAP.has_key(build): AttributeError: 'dict' object has no attribute 'has_key' "
Could you suggest me the right way to do that?
Thank you for your time
posted by 19 Jan 2019I should have found the correct way to apply the mbed-dev:
$mbed import http://os.mbed.com/users/hudakz/code/DS1820_Hello/
$mbed remove mbed
$mbed add http://os.mbed.com/users/maxxir/code/mbed-dev/
$mbed compile -t GCC_ARM -m DISCO_L072CZ_LRWAN1 flash
But unfortunately the board still do not found the DS1820 sensor.. Any suggestion?
posted by 19 Jan 20195 years, 6 months ago.
Hello,
have you resolved this problem for DISCO-L072CZ-LRWAN1? Because I have same situation with the latest DS1820 library and latest mbed-os release (5.12.4). I'm trying same code on DISCO-STM32F769I and it works. Any suggestions?
6 years ago.
You could try this library:
https://os.mbed.com/users/Sissors/code/DS1820/
I have 8 sensors working with no problems.
No but it is ST (STM32L476) so in theory and hopefully it should work with your board, some of my sensors are on over 15meters of cable and does push RFI boundaries. I will say that there are many libraries for this 1 wire device, some work better than others. I would suggest to try a basic 'hello world' to confirm functionality first then implement in your program.
This applies to all attached devices, basic 'hello world' first on each device, then implementation. This procedure saved most of my hair :)
posted by 06 Dec 20186 years ago.
Hello Marco,
- Make sure that a 4.7k Ohm resistor is connected between the DS1820's data pin and the +3.3V pin.
- Unfortunately it takes several microseconds in MBED to change a GPIO from output to input. In addition that's MCU specific. So my suggestion is:
Try to tune (increase/decrease) the time thatOneWire
is waiting for DS1820 to pull up/down the wire
OneWire.cpp
//... uint8_t OneWire::read_bit(void) { uint8_t r; wire.output(); wire = 0; wire.input(); // To execute this takes several us. The actual delay depends on the speed of used MCU. wait_us(8); // Try to tune this. Nnormally it would be about 13us but because of the delay due to 'wire.input()' it should be reduced. r = wire.read(); wait_us(54); return r; } //...
I am trying to do in this way. Decreasing the delay to 4-5 us it seems to read something but it continues not finding the ds18b20 sensor. This is what it reads (I added some debug print):
0x0
0x1
0x0
0x1
0x0
0x1
0x1
0x0
0x1
0x1
No addresses. No DS1820 sensor found!
(The prints before "No addresses" are right after the wire.read() command in read_bit() function)
Do you have any other suggestion?
posted by 06 Dec 2018I think you are very close to make it work. printf
is a very complex routine, hence it takes long time to execute. That could introduce unwanted delays. I'd suggest to tune without debug prints
, just change the delay by 1us at a time. Make sure you use external 4k7 resistor. The internal pull up resistor has much greater resistance and the voltage (after changing the GPIO from output to input) might increase at a rate which is slower than the one required by the one-wire protocol.
I have modified the OneWire library to make it less dependent on the speed of used MCU. The right moment for bit sampling is now calculated based on the time needed to change the GPIO from output to input:
uint8_t OneWire::read_bit(void) { uint8_t r; wire.output(); wire = 0; timer.start(); wire.input(); // the time this takes depends on the used MCU wait_us(12 - timer.read_us()); // wait the time remaining to 12us r = wire.read(); timer.stop(); timer.reset(); wait_us(54); return r; }