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.
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
// 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;
|
||||
Reference in New Issue
Block a user