Files
WII5Firmware/WII5Weather_18B20.cpp
T
scottp 295abb37ee Initial public release of WII5 Buoy firmware
Firmware for an autonomous wave-measurement buoy (ATmega2560-based
WII5 v2 board). Reads wave motion from a Sparton AHRS-M1/M2 IMU,
samples GPS and battery state, and reports back over Iridium SBD
satellite telemetry. Originally developed 2012-2024.

This is the first public release. Code, documentation, and field-tested
operating modes (Capture, Sleep, Position, ManualTest, SelfTest,
LowBattery) are licensed under Apache 2.0 — see LICENSE and NOTICE.

See README.md for an overview and build instructions, CONTRIBUTING.md
for how to contribute, and DEPLOYMENTS.md for the field-deployment log.
2026-05-07 16:27:18 +10:00

192 lines
5.3 KiB
C++

// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2012-2024 Scott Penrose <scottp@dd.com.au> and WII5 Buoy contributors
//
// This file is part of WII5 Buoy firmware.
// See LICENSE for full terms.
/**
* @file WII5Weather_18B20.cpp
* @brief Dallas DS18B20 temperature sensor driver (OneWire).
*/
/*
WII5Weather_18B20
TODO 2024 - Check when this is running as it blocks all other use
TODO:
Should be Weather / Temperature then drivers.
WII5Weather
WII5Weather::Temperature
age()
value();
value({n}) - which sensor?
WII5Weather::Pressure
WII5Weather::Humidity
...
*/
#include <Arduino.h>
#include <WII5Weather_18B20.h>
OneWire ds(WEATHER_18B20_DATA);
void WII5Weather_18B20::begin() {
powerSetPin(POWER_WEATHER_18B20_PIN, POWER_WEATHER_18B20_ON);
powerOff(true); // Force power off at boot
stepWait = 300001;
age = WII5TIME_1WEEK * 1000;
}
void WII5Weather_18B20::loop() {
// WII5 - removing this loop for now, temperature has to be an active decision.
/*
// If at lest been 5 minutes (maybe make this bigger later)
if (stepWait > 300000) {
if ( (minute() > 0) && ((minute() % 7) == 0) ) {
if (wii5Sparton.captureRunning()) {
console.log(LOG_DEBUG, F("Weather: Skipped - capture running. Min=%d"), minute());
}
else {
// REMEMBER - This blocks a bit.
if (temperatureRead()) {
console.log(LOG_DEBUG, F("Weather: Temperature Read. Min=%d"), minute());
}
else {
console.log(LOG_DEBUG, F("Weather: Failed to read temperature (unknown). Min=%d"), minute());
}
}
stepWait = 0;
}
}
*/
}
// TODO - This is a blocking libary. Fix it.
bool WII5Weather_18B20::temperatureRead() {
// (check we have nothing else on) return false;
powerOn();
// Give power time
delay(250);
currentTemperature = 2000;
console.log(LOG_DEBUG, F("currentTemperature=%d"), int(currentTemperature));
ds.reset_search();
// TODO Rework code - make it so it will seaerch over 10 minutes or so
// But then just queries those, no more searching, or maybe research and
// try and find more devices once every hour.
// What about lost devices?
/*
inside OneWire seems to be only small delayMicroseconds.
With the exception of one 400 - (half 1 millisecond)
This means that we could easily write a state machine here with a 1ms loop time
Is that fast enough for other things - then this can be non blocking, even for
large number of temperature sensors.
*/
for(byte count = 0; count < 3; count++) {
if ( ds.search(addr)) {
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
// TODO Gah... this should be background !
// wii5Controller.safeDelay(1000); // maybe 750ms is enough, maybe not
delay(1000);
ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( byte i = 0; i < 9; i++) // we need 9 bytes
data[i] = ds.read();
int16_t raw = (data[1] << 8) | data[0];
byte cfg = (data[4] & 0x60);
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
currentTemperature = (float)raw / 16.0;
// FIND and STORE them
/*
bool found = false;
for (byte i = 0; i < countTemperature; i++) {
if (ByteArrayCompare(addr, lastTemperature[i].addr, 8)) {
found = true;
lastTemperature[i].age = 0;
// Convert to Decidegrees
lastTemperature[i].celsius = currentTemperature;
}
}
*/
/*
if (!found) {
if (countTemperature < maxTemperature) {
lastTemperature[countTemperature].age = 0;
// Convert to Decidegrees
lastTemperature[countTemperature].celsius = currentTemperature;
memcpy( lastTemperature[countTemperature].addr, addr, 8 ); // TODO length?
countTemperature++;
}
else {
console.printf(F("ERROR: Maximum temperature probes found\r\n"));
// TODO Too many errors this requires a complete reset
// TODO Make it so if we get this 10 times, we reset the
// whole list and start again. e.g. change countTemperature = 0
// Reset for next time...
countTemperature = 0;
return true;
}
}
*/
// Temporary hard coded to one sensor
if (count == 0) {
console.log(LOG_DEBUG, F("Temperature: %02x%02x%02x%02x%02x%02x%02x%02x count=%d currentTemperature=%d.%02d*"),
addr[0],
addr[1],
addr[2],
addr[3],
addr[4],
addr[5],
addr[6],
addr[7],
count,
int(currentTemperature),
abs(int(currentTemperature * 100) % 100)
);
}
}
}
// copy to rest of places
powerOff();
console.log(LOG_DEBUG, F("currentTemperature=%d"), int(currentTemperature));
// TODO value is int32_t, but int16_t should be heaps?
value = int(currentTemperature * 100);
age = 0;
wii5Display.atCommandSend(F("status"), F("temperature=%d"),
int(value)
);
wii5Display.atCommandSend(F("status"), F("update"));
// TODO ?Move
return true;
}
WII5Weather_18B20 wii5Weather_18B20;