Skip to content

ricardocosme/ds18b20

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

C++11/17/20 driver to use the temperature sensor ds18b20 with AVR8. This is a header-only library offering a high level of abstraction to manipulate the temperature sensor with the zero-overhead principle in mind.

The user should expect an expressive code with a very small memory footprint.

Synchronous reading

This example illustrates the reading of the temperature using the synchronous or blocking approach. It’s considered that there is only one device with 12 bits of resolution using the bus and the temperature value is represented by a whole number.

#include <ds18b20.hpp>

int main() {
    ds18b20::sensor thermo{avr::io::pb3};

    while(true)
        if(auto temp = thermo.read())
            auto v = temp.value();
}

demo/c++17/read.cpp

Asynchronous reading

#include <ds18b20.hpp>

void do_something(uint8_t temp){}

int main() {
    ds18b20::sensor thermo{avr::io::pb3};

    while(true) 
        if(auto temp = thermo.async_read()) {
            if(temp.has_value())
                auto v = temp.value();
        }
}

demo/c++17/async_read.cpp

async_read() is a stackless coroutine that returns a lazy temperature value(temp) which has a done() method that returns false if the coroutine is running and true is it is completed.

Multiple devices on the same bus

#include <ds18b20.hpp>

int main() {
    using namespace ds18b20;
    sensor thermo_1{avr::io::pb3, Rom<40, 129, 145, 19, 10, 0, 0, 99>{}};
    sensor thermo_2{avr::io::pb3, Rom<40,  60,  44, 20, 10, 0, 0, 11>{}};

    while(true) {
        if(auto temp = thermo_1.async_read())
            if(temp.has_value())
                auto v1 = temp.value();
        if(auto temp = thermo_2.async_read())
            if(temp.has_value())
                auto v2 = temp.value();
    }
}

demo/c++17/multi.cpp

Temperature value with fractions

int main() {
    using namespace ds18b20;    
    sensor thermo{avr::io::pb3, skip_rom, with_decimal};
    
    while(true)
        if(auto temp = thermo.async_read()) {
            if(temp.has_value()) {
                auto whole = temp.value();
                auto decimal = temp.decimal();
            }
        }
}

demo/c++17/with_decimal.cpp

The library uses policies to enable optional features. The usage of policies helps to achieve the best memory footprint taking decisions at compile-time. In the end the user only pay for what he wants to use. One of the policies is responsible to enable the decimal part of a temperature value. This is what the parameter with_decimal do above when the object `thermo` is constructed. The integer type used to represent the decimal part is automatically choose based on the resolution used by the sensor, for example, the type uint16_t is picked up to 12bits resolution and the type uint8_t to 9bits resolution.

Reading the Rom code

void do_something_with_each_byte(uint8_t b){}

int main() {
    using thermo = ds18b20::sensor{avr::io::pb3};
    auto rom = thermo::rom();
    for(auto b : rom)
        do_something_with_each_byte(b);
}

demo/c++17/read_rom.cpp

Features

  1. Synchronous and asynchronous(coroutine) approach to read the temperature.
  2. Support at compile-time to 9, 10, 11 e 12 bits of resolution.
  3. Optional support at compile-time to handle temperature values with fractions.
  4. Optional support at compile-time to allow the usage of the internal pullup resistor of the MCU I/O pin that represents the bus(DQ port).
  5. Setup the resolution using only one call that saves the configuration in the EEPROM.
  6. Address any device in the bus using the Skip Rom command.
  7. Address specific devices in the bus using the Rom code.
  8. Reading of the Rom code.
  9. Support to multiple devices in the same bus(DQ port).

Features that aren’t supported

  1. Negative temperatures
  2. Search Rom
  3. Alarm
  4. Parasite power mode

How to use it?

This is a header only library. It should be enough to add the path to the include directory as also the path to the include directory of each dependency to your project:

  1. Check the requirements section.
  2. Add the include directory to your include path as also the path to the include directory related to each dependency.
  3. Ensure that the macro F_CPU is defined. [1]
  4. Include the header ds18b200.hpp (#include <ds18b200.hpp>) to your source and enjoy it!

How to build the demos?

  1. If you want to build the demos with support to C++11, then go to the directory demo/c++11, if you want C++17 then go to demo/c++17.
  2. Adjust at least the variables MCU and AVRDUDE_DEVICE at demo/common.mk to the appropriate values related to your microcontroller. Note, the demos are already ready to ATtiny85.
  3. Check the value of the macro F_CPU at demo/common.mk to reflect the clock speed used by the microcontroller. The default value is 1000000, which means a clock of 1Mhz.
  4. make

Supported microcontrollers

  1. ATtiny13A
  2. ATtiny85
  3. ATmega328P

Dependencies

  1. avrIO
  2. avr-libc 2.0

Requirements

  1. avr-gcc with at least -std=c++11. Note: If C++14, C++17 or C++20 is used then some additional features can be offered.

Contributions

All type of contributions are welcome. If you like what you see and you have interest to help, don’t hesitate to open a pull request, issue or contact me.

Releases

No releases published

Packages

No packages published

Languages