element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Summer of Green Tech Design Challenge
  • Challenges & Projects
  • Design Challenges
  • Summer of Green Tech Design Challenge
  • More
  • Cancel
Summer of Green Tech Design Challenge
Blog Cool Wave - Testing temperature sensors for use with the Seeeduino XIAO
  • Blog
  • Forum
  • Documents
  • Leaderboard
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Summer of Green Tech Design Challenge to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Alistair
  • Date Created: 1 Oct 2023 7:16 PM Date Created
  • Views 3253 views
  • Likes 11 likes
  • Comments 14 comments
  • summer of green tech design challenge
Related
Recommended

Cool Wave - Testing temperature sensors for use with the Seeeduino XIAO

Alistair
Alistair
1 Oct 2023
Cool Wave - Testing temperature sensors for use with the Seeeduino XIAO

For this project I need to measure the temperature both inside and outside. So far I have one sensor working, and I need two. One for inside and one for outside. Rather than deep dive into all of them I'd decided to do some preliminary tests to see what worked well and what did not. These are the results.

A selection of temperature sensors

Thermistor

First let’s start old school with a good old thermistor. It simply changes resistance in line with the temperature, so with the aid of a fixed resistor we can create a potential divider. The fact you are reading this blog post probably means you likely know all about thermistors, but I will include it for completeness.

A thermistor being tested

In this example I have used a 4.7K resistor to GND and the thermistor to 3v3 to create a potential divider. The analog pin on the Seeeduino XIAO is pin 0 on the hardware, but internally is GPIO 2, and the latter is needed in MicroPython.

If you have got here searching for Seeeduino XIAO, MicroPython and ADC in the hopes to find out why you are getting errors when trying to use the read() method, then I have also been there. The solution is to use read_u16() instead. This test code works for reading analogue values from the A0 pin.

from machine import Pin, ADC
import time

adc = ADC(Pin(2))

while True:
    print(adc.read_u16());
    time.sleep(1)

To be useful the value needs to be calibrated and converted into an actual temperature, but that calculation depends on the thermistor and resistor used. As this is an “also ran” experiment I am not going to bother to do this for the evaluation.

DHT11

This DHT11 is the ubiquitous temperature sensor that is the base of many projects needing to know the temperature. It uses a 40-bit serial output at a data rate around 10kbps. The data rate varies depending on the data because of the encoding used.

Sadly this is not currently a viable option to use in Micropython on the Seeeduino XIAO.

Because the custom protocol is not supported by most hardware natively, and the speed required is faster than most microcontrollers can support if written in MicroPython, the DHT11 functionality is built into MicorPython and the C level [https://docs.micropython.org/en/latest/samd/quickref.html]. It however is not currently compiled into the SAMD21 build, and that is the base build that is used by the Seeeduino XIAO distribution that we are using.

I gave it a go, and kudos to Robert H for some great test code, but it was just not functional.

If using the DHT11 on the Seeeduino XIAO is important then using the C and Arduino libraries would be a more appropriate solution over using MicorPython.

DHT12

The DHT12 is a more modern, more accurate, and all round improved version of the DHT11. It supports both the original 40-bit serial output (that is of no use to us), and I²C like the DHT20 we tested in the last blog post.

The DHT12

The hardware layer communications protocol I²C is supported directly by the Seeeduino XIAO but we still need a library to convert the numbers in to a temperature. I used https://github.com/mcauser/micropython-dht12 for this and it works well.

Here is the test code. The delay is important as the device will fail if the device is queried any faster. This will not be a problem in the final project as we will be sampling every few seconds at best.

import time
from machine import Pin, I2C
from dht12 import DHT12
i2c = I2C(0, scl=Pin(9), sda=Pin(8))
    
dht12 = DHT12(i2c, 0x5c)
while True:
    dht12.measure()
    temper = dht12.temperature()
    humidity = dht12.humidity()
    print("temper : " + str(temper))
    print("humidity : " + str(humidity))
    time.sleep_ms(40)

Like the DHT20 this works well and is a serious contender for the final solution. It also uses a different I²C address so can be used with the DHT20 without needing to add more circuitry.

DHT20

The DHT20 sensor

We covered this before in this blog post so you can read that for further details. In short it is like the DHT12. Slightly more accurate in fact. It is another serious contender.

Grove Infrared Temperature Sensor 1.2

This is a non-contact IR heat sensor and is, in my personal opinion, really cool. I really wanted to use this sensor in the Cool Wave project just to experiment with it, but in reality the sensor is for measuring the temperature of an object and not the ambient temperature, so is not appropriate. We can still give it a test and a quick evaluation here.

For the test I simply connected GND (Black) to GND, VCC (Red) to V3V, and OBJ (White) to 0 (A0). The output from the module is a simple analogue voltage, and here is some simple code to display the approximate temperature of the object directly in front of the sensor.

from machine import Pin, ADC
import time

adc = ADC(Pin(2))

while True:
    print(adc.read_u16()*1.1/1023);
    time.sleep(1)

It at first appears to work well, and for a lot of projects this simple reading will be appropriate, but it is not as accurate as the module can be. There are in fact two sensors on the module, the IR sensor, and an ambient sensor. To get a more accurate reading from the IR sensor we need to calibrate it using the ambient sensor. The documents about this can be downloaded from https://wiki.seeedstudio.com/Grove-Infrared_Temperature_Sensor/. As the Seeeduino XIAO only has one analogue input we can not access both sensors at the same time without an external ADC.

Update: According to the SAM D21 datasheet (section 33.8.8) the ADC can be mapped to different pins. This allows us to switch between different input pins and to read multiple analogue inputs over time. This means both inputs can be used without external circuitry. 

Yes, I know I could use this ambient sensor for the project, but it is like using a Ferrari to store the garden tools when I already have a number of garden sheds.

DS18B20

The DS18B20 style sensor is also commonly seen because of its low cost, durability and comparative accuracy. 

Natively they come in a TO-92 package, but they are often potted in a waterproof stainless steel package for measuring the temperature of liquids and more harsh environments. For communication it uses the 1-Wire bus protocol, which as the name suggests uses one wire for all communication.

By default it operates at 15.4 kbps, and unfortunately like the DHT11, the 1-Wire code is not currently compiled into the SAMD21 build MicroPython. Sadly this makes it impractical to use these sensors under MicroPython on the Seeeduino XIAO.

The DS18B20 being tested

I have tried proting the https://github.com/robert-hh/Onewire_DS18X20 library but it is just not able to communicate with the DS18B20. My hope is that in time the issues in the Seeeduino XIAO build of MicroPython will be addressed.

Conclusion

At this point, assuming I am going to stick with using MicroPython, the solution for Cool Wave is to use a DHT12 and a DHT20.

If I consider moving away from MicroPython then I would give serious consideration to using the DS18B20. What I gain is better weather protection without needing to develop a more complex enclosure. When I lose is the ability to monitor humidity. Although I was not planning on using humidity now it is something that may be useful to know in the future.

For the record I chose a Python based solution as the language that is most accessible to the community who will be able to utilise my work, and I chose MicroPython over CircuitPython because I am more familiar with it. Creating a C based firmware instead of Python would give me more sensor options, but I am currently happy with the DHT12 and a DHT20 options so I have decided not to pivot the design.

  • Sign in to reply

Top Comments

  • javagoza
    javagoza over 1 year ago in reply to shabaz +1
    Driven by curiosity this weekend, I decided to translate the library for communicating with the DHT11 sensor from Arduino code to MicroPython. I tested it with a Raspberry Pi Pico, and indeed, Alistair…
  • ntewinkel
    ntewinkel over 1 year ago

    Great overview of temperature sensors.

    Good point about the MicroPython limitations - I didn't even stop to think that this might be an issue. I've been planning to move more to MicroPython, but it might not be a simple thing to do Thinking

    You might also like the BME280 (temp+humidity+pressure) or BMP280 (temp+pressure). They are quite affordable too, and easy to use in Arduino - Adafruit has boards, examples, and libraries. I don't know how well supported they would be for MicroPython. I did find I had to reset the power to them under certain conditions for long-term use, so I power it via a GPIO pin and give it a reboot if it fails to come online for the regular temperature/humidity updates my sensor does.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • javagoza
    javagoza over 1 year ago in reply to javagoza

    I deleted the previous comment, it cannot be edited.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • javagoza
    javagoza over 1 year ago in reply to shabaz

    I will prepare a blog this weekend if I have some free time. Meanwhile, I leave here a small sketch of what the solution with interruptions would be. With the pico it works quite well, whenever the sensor responds it obtains the data correctly. 

    Negative temperatures are still untested

    import machine
    import time
    import array
    import micropython
    micropython.alloc_emergency_exception_buf(100)
    
    # Read data from a DHT11 sensor using bitbanging and hardware interrupts
    # TODO adjust negative temps
    # microPython
    # Author : Enrique Albertos
    
    class DHT11Interrupt:
        
        def __init__(self, pin):
            EDGES = const(42) # number of edges to register
            BIT_THRESHOLD = const(100) # time under BIT_THRESHOLD is considered bit 0 and over bit 1
            RECEIVE_TIMEOUT_US = const(20000)
            self.pin = machine.Pin(pin, machine.Pin.OUT)
            self.data = [0,0,0,0,0] # register for the 5 byte data received
            self.edgeindex = -1 # edfe counter
            self.laps= array.array('i', (0 for _ in range(EDGES))) # time laps between falling edges
            
        def _handle_edge_interrupt(self, pin):
            self.edgeindex = self.edgeindex + 1  # increment edge index 
            self.laps[self.edgeindex] = time.ticks_us()  # store time lap
            
    
        def read_data(self):       
            
            try:
                self.edgeindex = -1
                self.data = [0,0,0,0,0]
                self.laps= array.array('i', (0 for _ in range(EDGES)))
                # send start signal
                self.pin.init(machine.Pin.OUT)
                self.pin(0) # pull low data-bus
                time.sleep_ms(20) #  at least 18 ms
                # set a hardware interrupt ISR for falling edges
                self.pin.irq(handler=self._handle_edge_interrupt, trigger=machine.Pin.IRQ_FALLING )
                self.pin.init(machine.Pin.IN) # pull up and wait for response
                self.pin(1)  # pull high data-bus
                
    
            except Exception as e:
                return False
            
            # wait for data received or timeout
            start =  time.ticks_us() 
            while (self.edgeindex < EDGES - 1 and time.ticks_us() - start < RECEIVE_TIMEOUT_US): 
                continue
            
            # return false if timeout
            if self.edgeindex < EDGES - 1 : # timeout
                return False
            
            
            self.pin.irq(handler=None)
            i = 2
            
            while i <= self.edgeindex:                    
                bytenumber = (i-2) // 8  # calculate data byte index 8-bit pet byte
                self.data[bytenumber] <<= 1 # left shift
                self.data[bytenumber] |= (0 if (self.laps[i] - self.laps[i-1]  < BIT_THRESHOLD) else 1) # append new bit
                i = i + 1
            
            # check for data checksum integrity
            if (self.data[0] + self.data[1] + self.data[2] + self.data[3]) & 0xFF == self.data[4]:
                error = True
            else:
                error = False            
            
            return error
        
        # returns Temperature in degrees centigrades
        #TODO check temperatures under 0C
        def get_temperature(self):
            if ((self.data[2] & (1<<8)) == (1<<8)) :
                return -1 * (self.data[2] & 0b01111111 + (self.data[3] / 10.0))
            else:
                return self.data[2] + (self.data[3] / 10.0)
        
        #returns %rel humidity
        def get_humidity(self):
            return self.data[0] + (self.data[1] / 10.0)
    
    # Usage:
    dht = DHT11Interrupt(pin=14)  # Replace with your actual GPIO pin number
    for i in range(10):
        if dht.read_data():
            print("Temperature: {}°C".format(dht.get_temperature()))
            print("Humidity: {}%".format(dht.get_humidity()))
        else:
            print("Failed to read data from the DHT11 sensor.")
        time.sleep_ms(2000)
    
    

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 1 year ago in reply to javagoza

    Glad it's working to a decent extent! I've added a few of these DS2484 to the shopping basket, just in case I ever need to do this again. I think 1-wire is for sure great for where it is needed, but for on-board temperature sensors I'd much rather use I2C etc, something that doesn't rely on a small number of usec level criticality. Most chassis-based products I've seen use I2C for on-board sensors (e.g. temperature and pressure sensors).

    My use-case is that I wanted to read/write 1-wire memory (it's not my product) and needed something quite rock-solid, so I am using external parts to convert the 1-Wire to two wires for now (and run the 1-wire at the max voltage for a bit more immunity), and the DS2484 can be a backup if there are any issues.

    I've written the C code, will hopefully test it soon!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Alistair
    Alistair over 1 year ago in reply to javagoza

    That is impressive work. Very much pushing things to the limit. I am with you with the interpreted language thing. I am using MicroPython here as it seems to be for more accessible to the average tinkerer, but I am far more comfortable with cold hard C myself.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube