MKR 1000 for DS18B20 sensors

Hello. Next week I will take a crack at my first Arduino project and would appreciate pointers. I plan to use a MKR1000 to read a pair of DS18B20 sensors and make them available over MQTT all summer. I would like to have as low power consumption as possible, hopefully getting a whole summer's worth of measurements off of the battery. I plan to use C, but am open to other suggestions. Which libraries should I focus on or any other general guidance?

For the task, I've got a basic Ubuntu 20.04 LTS x86 machine set up with version 1.8.12 of the Arduino IDE and have added MKR1000 in the board manager there. I've also added the Arduino-Temperature-Control-Library there. One MKR1000 and two DS18B20s should arrive next week (famous last words). I have a Raspberry Pi Zero W available to connect using 2.4GHz Wifi. I've used the DS18B20 with a Raspberry Pi and Python3 but, again, this will be my first exposure to Arduino and embedded systems. I've read through the Arduino FAQ, the Ubuntu installation instructions, the 2015 edition Arduino in a Nutshell booklet, and a few other pages.

I am new to embedded devices. In principle I a retired librarian with some teaching, research, and development of what I'll call networked information services. I've used microcomputers since the 1970s and networked computers since the tail end of the 1980s. My background in programming is long but not in depth and I'll admit to SNOBOL4, UCSD Pascal, Icon, Perl, POSIX shell, and an even smaller amount of Python, C, and 6502 and Z80 assembly.

As with any coding endeavor, start as small as you can. Prove to yourself that you can upload code to the device: hello world in Arduino world is probably the blink example that comes with the IDE.

Then perhaps, try to connect to wifi. Again there are examples that you can configure for your network and try.

DS18B20s are pretty easy to get going although I've failed several times by getting the wiring wrong. Again, you should find example code easily enough.

For extending battery life, you're likely going to need to have the Arduino sleep as much as possible. Take a look at Nick Gammon's page on the topic: here.

Grab an MQTT library and see if you can hit your broker over the wifi you already got working.

With those things accomplished, you're probably ready to build the mark one version of your project.

I've gotten the board running with the Blink example and have been changing that little. So that's the first item off the list:

  • Blink LED
  • Sleep LED
  • Wifi
  • MQTT
  • MQTT + TLS
  • DS18B20

Though I had to solder the headers myself and they ended up with a very slight camber. Can't really see it but it can be felt on insertion into a breadboard. No matter. I think I see the way forward with the programming now.

Though I had to solder the headers myself and they ended up with a very slight camber.

Next time I suggest you push the headers into breadboard first, put the board on them and get everything lined up straight before soldering.

Blink LED

It drives me mad that the first thing beginners are taught is to use delay. Hopefully with your experience you won't continue using delay in your project, but just in case: don't use delay.

Good luck with your project.

Thanks for the tips. I'm still wondering about how to acquire the AVR libraries mentioned on Nick Gammon's page linked above. How related are they to ArduinoLowPower.h in the Manage Libraries utility?

The Arduino development environment has been mostly a series of pleasant surprises. I went through series of the examples and my own sketches and by the end of the first, longish session had an MQTT client on the MKR1000 sending temperatures unencrypted to an MQTT broker. Not counting what I've done on the receiver(s), with chart plotting and all on a RPiZeroWH, I've gone through these steps on the MKR1000:

  • blink built-in LED
  • sleep LED
  • WiFi connection
  • MQTT test over WiFi
  • DS18B20 temperatures to serial console
  • DS18B20 temperatures over MQTT
  • temperatures + RTC epoch over MQTT
  • deep sleep between measurements
  • reconnect wifi after deep sleep or wifi outage

What's left are these:

  • do measurements on the 10-minute mark
  • MQTT over TLS
  • power saving

I appreciate any advice on those next steps, though the TLS might not be possible from what I read.

For context, here is my current sketch, the 14th along the way:

/*
  MKR1000
*/

#include <SPI.h>                  // for built-in WiFi shield
#include <WiFi101.h>              // WiFi support
#include <RTCZero.h>              // Real-time Clock
#include <PubSubClient.h>         // MQTT client
#include <OneWire.h>              // for DS18B20
#include <DallasTemperature.h>    // also for DS18B20   https://www.milesburton.com/Dallas_Temperature_Control_Library
#include <ArduinoLowPower.h>      // 

#define ONE_WIRE_BUS 0            // data wire is on pin 0 on this Arduino

OneWire oneWire(ONE_WIRE_BUS);        // for any OneWire devices, not just Maxim/Dallas
DallasTemperature sensors(&oneWire);  // pass reference to Dallas Temperature IC

RTCZero rtc;

#include "arduino_secrets.h"
// these connection data come from arduino_secrets.h
char ssid[] = SECRET_SSID;      // network SSID (name)
char pass[] = SECRET_PASS;      // network password
int status = WL_IDLE_STATUS;

void mqttpubcallback(char* topic, byte* payload, unsigned int length) {
  // handle message delivered
}

void setup() {
  WiFi.hostname("mkr1000");
  Serial.begin(115200);

  // low power mode??
  for (int ledPin = 0; ledPin <= 21; ledPin++) {
    pinMode(ledPin, OUTPUT);
    digitalWrite(ledPin, LOW);
  }

  // check if the WiFi module works
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue if the hardware is missing or broken:
    while (true);
  }

  // attempt to connect to WiFi network:
  while ( status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }

  rtc.begin();

  unsigned long epoch;
  int numberOfTries = 0, maxTries = 6;
  do {
    epoch = WiFi.getTime();
    numberOfTries++;
  }
  while ((epoch == 0) && (numberOfTries < maxTries));

  if (numberOfTries == maxTries) {
    Serial.print("NTP unreachable!!");
    while (1);
  }
  else {
    Serial.print("Epoch received: ");
    Serial.println(epoch);
    rtc.setEpoch(epoch);

    Serial.println();
  }

  sensors.begin();    // start Dallas Temperature IC Control Library

  DeviceAddress deviceAddress;
  int devicecount = sensors.getDeviceCount();
  for (int i = 0; i < devicecount; i++) {
    if (sensors.getAddress(deviceAddress, i)) {
      Serial.print("Device ");
      Serial.println(i);
      sensors.setResolution(deviceAddress, 12);     // set temperature resolution (9 through 12)
    }
  }
}

void dummy() {
  // This function will be called once on device wakeup
  // You can do some little operations here (like changing variables which will be used in the loop)
  // Remember to avoid calling delay() and long running functions since this functions executes in interrupt context
}

IPAddress mqttserver(192, 168, 1, 140);
WiFiClient mqtt;
PubSubClient mqttclient(mqttserver, 1883, mqttpubcallback, mqtt);
String topic = "temperatures";

void loop() {
  status = WiFi.status();
  if (status != WL_CONNECTED) {
    Serial.print("Attempting to reconnect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network.
    status = WiFi.begin(ssid, pass);
    delay(2000);
  }
  Serial.print("WiFI status: ");
  Serial.print(status);
  Serial.print("\t");

  // get Epoch to send along with temperatures
  unsigned long epoch = rtc.getEpoch();
  Serial.print(epoch);
  Serial.print("~");

  // get temperature readings of each device on the bus
  sensors.requestTemperatures();
  float t0 = sensors.getTempCByIndex(0);
  float t1 = sensors.getTempCByIndex(1);

  Serial.print(" Temperature is: ");
  Serial.print(t0);
  Serial.print(" ");
  Serial.print(t1);

  Serial.print("\n");
  // send temperatures if possible
  if (mqttclient.connect("arduinoClient", "ds18b20", "arduino44")) {
    String temperatures = String(epoch) + "\t3\t" + String(t0);
    mqttclient.publish(topic.c_str(), String(temperatures).c_str());

    temperatures = String(epoch) + "\t4\t" + String(t1);
    mqttclient.publish(topic.c_str(), String(temperatures).c_str());

    mqttclient.disconnect();
  }
  LowPower.deepSleep(60000);
}

I'll increase the sleep period later as the details get ironed out.