295abb37ee
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.
450 lines
10 KiB
C++
450 lines
10 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 WII5Setup.cpp
|
|
* @brief Boot-time hardware bring-up: pin defaults, peripherals, and serial ports.
|
|
*/
|
|
|
|
/*
|
|
|
|
Setup - Turn everything on etc
|
|
|
|
*/
|
|
|
|
#include <Arduino.h>
|
|
#include <TimeLib.h>
|
|
#include <WII5.h>
|
|
#include <WII5Setup.h>
|
|
#include <avr/wdt.h>
|
|
|
|
// Debugging etc - move to header file
|
|
#define DEBUG_SLEEP
|
|
|
|
void WII5Setup::beginSafe() {
|
|
|
|
// WDT
|
|
#ifdef WDT_RESET
|
|
pinMode(WDT_RESET, OUTPUT);
|
|
digitalWrite(WDT_RESET, LOW);
|
|
#endif
|
|
|
|
// Make buzzer OUTPUT and OFF
|
|
#ifdef POWER_BUZZER_PIN
|
|
pinMode(POWER_BUZZER_PIN, OUTPUT);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
#endif
|
|
|
|
// 5V - FORCE On until sure Maths is off
|
|
#ifdef SHARED_5VOLT_ON
|
|
pinMode(SHARED_5VOLT_PIN, OUTPUT);
|
|
digitalWrite(SHARED_5VOLT_PIN, HIGH);
|
|
#endif
|
|
|
|
// Maths - FORCE On until sure Maths is off
|
|
#ifdef POWER_MATHS_PIN
|
|
pinMode(POWER_MATHS_PIN, OUTPUT);
|
|
digitalWrite(POWER_MATHS_PIN, HIGH);
|
|
#endif
|
|
|
|
// SD: Power
|
|
#if POWER_STORAGE_1_PIN>0
|
|
pinMode(POWER_STORAGE_1_PIN, OUTPUT);
|
|
digitalWrite(POWER_STORAGE_1_PIN, HIGH);
|
|
#endif
|
|
#if POWER_STORAGE_2_PIN>0
|
|
pinMode(POWER_STORAGE_2_PIN, OUTPUT);
|
|
digitalWrite(POWER_STORAGE_2_PIN, HIGH);
|
|
#endif
|
|
|
|
// SD: Buffers
|
|
#ifdef STORAGE_SD1_MATHS_PIN
|
|
pinMode(STORAGE_SD1_MATHS_PIN, OUTPUT);
|
|
digitalWrite(STORAGE_SD1_MATHS_PIN, HIGH);
|
|
pinMode(STORAGE_SD2_MATHS_PIN, OUTPUT);
|
|
digitalWrite(STORAGE_SD2_MATHS_PIN, LOW);
|
|
#endif
|
|
|
|
// Sub 1 and 2
|
|
#ifdef POWER_SUBBOARD_1_PIN
|
|
pinMode(POWER_SUBBOARD_1_PIN, OUTPUT);
|
|
digitalWrite(POWER_SUBBOARD_1_PIN, LOW);
|
|
#endif
|
|
#ifdef POWER_SUBBOARD_2_PIN
|
|
pinMode(POWER_SUBBOARD_2_PIN, OUTPUT);
|
|
digitalWrite(POWER_SUBBOARD_2_PIN, LOW);
|
|
#endif
|
|
|
|
// GPS
|
|
pinMode(POWER_GPS_PIN, OUTPUT);
|
|
digitalWrite(POWER_GPS_PIN, LOW);
|
|
|
|
// Iridium
|
|
pinMode(POWER_COMMS_PIN, OUTPUT);
|
|
digitalWrite(POWER_COMMS_PIN, LOW);
|
|
|
|
// Batt2
|
|
#ifdef BATTERY_2_PIN
|
|
pinMode(BATTERY_2_PIN, OUTPUT);
|
|
digitalWrite(BATTERY_2_PIN, LOW);
|
|
#endif
|
|
|
|
// Radio
|
|
#ifdef WII5_RADIO_LORA
|
|
pinMode(POWER_RADIO_PIN, OUTPUT);
|
|
digitalWrite(POWER_RADIO_PIN, LOW);
|
|
#endif
|
|
|
|
// Strobe
|
|
pinMode(POWER_STROBE1_ON, OUTPUT);
|
|
digitalWrite(POWER_STROBE1_ON, LOW);
|
|
|
|
#ifdef TIMING_SPARTON_RUN
|
|
pinMode(TIMING_SPARTON_RUN, OUTPUT);
|
|
#endif
|
|
#ifdef TIMING_SPARTON_CHAR
|
|
pinMode(TIMING_SPARTON_CHAR, OUTPUT);
|
|
#endif
|
|
#ifdef TIMING_SPARTON_RECORD
|
|
pinMode(TIMING_SPARTON_RECORD, OUTPUT);
|
|
#endif
|
|
#ifdef TIMING_SD_WRITE
|
|
pinMode(TIMING_SD_WRITE, OUTPUT);
|
|
#endif
|
|
}
|
|
|
|
void WII5Setup::bootbeep() {
|
|
#ifdef POWER_BUZZER_PIN
|
|
#ifdef SHARED_5VOLT_ON
|
|
digitalWrite(SHARED_5VOLT_PIN, HIGH);
|
|
#endif
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(250);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(250);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(250);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
#endif
|
|
}
|
|
|
|
void WII5Setup::shutdownbeep() {
|
|
#ifdef POWER_BUZZER_PIN
|
|
#ifdef SHARED_5VOLT_ON
|
|
digitalWrite(SHARED_5VOLT_PIN, HIGH);
|
|
#endif
|
|
delay(250);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, HIGH);
|
|
delay(125);
|
|
digitalWrite(POWER_BUZZER_PIN, LOW);
|
|
#endif
|
|
}
|
|
|
|
void WII5Setup::begin() {
|
|
// TODO 2024 - Check state of button 2 is on
|
|
// if so set special Maths flag - alwayson?
|
|
// If button 2 goes off at any point or button1 on, then always off is forever off?
|
|
setupConsole();
|
|
setupPower();
|
|
setupIO();
|
|
setupNetwork();
|
|
setupWII5();
|
|
|
|
#ifdef WII5_STORAGE_SDBLOCK
|
|
sdBlock.debug = false;
|
|
sdBlock.stream = &Serial;
|
|
sdBlock.begin(wii5Config.getDeviceId());
|
|
#endif
|
|
}
|
|
|
|
|
|
#ifdef WII5_DEBUG_SERIAL
|
|
void cb(uint8_t l, char *buf) {
|
|
switch(l) {
|
|
case LOG_INFO:
|
|
SerialDebug.print(F("LOG:INFO:"));
|
|
break;
|
|
case LOG_WARN:
|
|
SerialDebug.print(F("LOG:WARN:"));
|
|
break;
|
|
case LOG_ERROR:
|
|
SerialDebug.print(F("LOG:ERROR:"));
|
|
break;
|
|
case LOG_DEBUG:
|
|
SerialDebug.print(F("LOG:DEBUG:"));
|
|
break;
|
|
case LOG_FATAL:
|
|
SerialDebug.print(F("LOG:FATAL:"));
|
|
break;
|
|
default:
|
|
SerialDebug.print(F("LOG:?:"));
|
|
break;
|
|
};
|
|
SerialDebug.print(buf);
|
|
SerialDebug.println();
|
|
}
|
|
#endif
|
|
|
|
void WII5Setup::setupPower() {
|
|
if (_setupPower) return;
|
|
_setupPower = true;
|
|
}
|
|
|
|
void WII5Setup::setupConsole() {
|
|
if (_setupConsole) return;
|
|
_setupConsole = true;
|
|
SerialConsole.begin(SerialConsole_Baud);
|
|
|
|
// Hard coded BAD - Where to put this for reuse in WII5 buoys
|
|
// Maybe a macro in the Board file?
|
|
console.begin(wii5BufferConsolePrint, WII5_BUFFER_CONSOLE_PRINT, wii5BufferConsoleCmd, WII5_BUFFER_CONSOLE_CMD);
|
|
// TODO ? console.enableNmea();
|
|
|
|
// Here we add the main console as an OUTPUT only
|
|
#if defined(WII5_DEBUG_SERIAL) && defined(WII5_DEBUG_SERIAL_CONSOLE)
|
|
console.add(&SerialConsole, CONSOLE_DIRECTION_OUTPUT);
|
|
#else
|
|
console.add(&SerialConsole);
|
|
#endif
|
|
|
|
// NOTE: We are using Iridium as it is currently only Binary code we need
|
|
#ifdef WII5_GPS
|
|
console.setBinaryBuffer(wii5BinaryIridium, WII5_IRIDIUM_BIN_MAX);
|
|
#endif
|
|
#ifdef WII5_DEBUG_SERIAL
|
|
SerialDebug.begin(WII5_DEBUG_SERIAL_BAUD);
|
|
#ifdef WII5_DEBUG_SERIAL_CONSOLE
|
|
console.add(&SerialDebug, CONSOLE_DIRECTION_BOTH);
|
|
#else
|
|
console.setCallbackFunction(cb);
|
|
console.setCallbackLevel(LOG_FATAL);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef WII5_STATUS_SERIAL
|
|
SerialStatus.begin(WII5_STATUS_SERIAL_BAUD);
|
|
#endif
|
|
|
|
#ifdef WII5_MATHS_SERIAL
|
|
SerialMaths.begin(WII5_MATHS_SERIAL_BAUD);
|
|
console.add(&SerialMaths, CONSOLE_DIRECTION_BOTH);
|
|
#endif
|
|
|
|
console.setLevel(LOG_INFO);
|
|
}
|
|
|
|
void WII5Setup::setupNetwork() {
|
|
if (_setupNetwork) return;
|
|
_setupNetwork = true;
|
|
#ifdef WII5_RADIO_LORA
|
|
wii5RadioLoRa.begin();
|
|
#endif
|
|
}
|
|
|
|
void WII5Setup::setupIO() {
|
|
if (_setupIO) return;
|
|
_setupIO = true;
|
|
// IO - LED, Buttons et al
|
|
sh3dNodeIO.begin(LED_1, LED_2, LED_3, LED_4, BUTTON_1, BUTTON_2, BUTTON_3, BUTTON_4);
|
|
|
|
// SET LED to Fast Flash
|
|
#if LED_1>0
|
|
sh3dNodeIO.led1Set( LED_SHORT );
|
|
sh3dNodeIO.led1SetDefault(LED_SHORT);
|
|
sh3dNodeIO.led1SetTimeout(300000);
|
|
#endif
|
|
#if LED_2>0
|
|
#ifdef POWER_BUZZER_PIN
|
|
// Off after 5 seconds
|
|
sh3dNodeIO.led2Set( LED_OFF );
|
|
sh3dNodeIO.led2SetDefault(LED_OFF);
|
|
sh3dNodeIO.led2SetTimeout(10000);
|
|
#else
|
|
sh3dNodeIO.led2Set( LED_SLOW );
|
|
sh3dNodeIO.led2SetDefault(LED_SLOW);
|
|
sh3dNodeIO.led2SetTimeout(10000);
|
|
#endif
|
|
#endif
|
|
#if LED_3>0
|
|
sh3dNodeIO.led3Set( LED_SLOW );
|
|
sh3dNodeIO.led3SetDefault(LED_SLOW);
|
|
sh3dNodeIO.led3SetTimeout(10000);
|
|
#endif
|
|
#if LED_4>0
|
|
sh3dNodeIO.led4Set( LED_SLOW );
|
|
sh3dNodeIO.led4SetDefault(LED_SLOW);
|
|
sh3dNodeIO.led4SetTimeout(10000);
|
|
#endif
|
|
|
|
}
|
|
|
|
void WII5Setup::setupWII5() {
|
|
if (_setupWII5) return;
|
|
_setupWII5 = true;
|
|
wii5Config.begin();
|
|
#ifdef WII5_RTC
|
|
wii5RTC.begin();
|
|
#endif
|
|
wii5Commands.begin();
|
|
wii5Battery.begin();
|
|
#ifdef WII5_GPS
|
|
wii5Gps.begin();
|
|
#endif
|
|
#ifdef WII5_COMMS_IRIDIUM
|
|
wii5Iridium.begin();
|
|
#endif
|
|
wii5Maths.begin();
|
|
// wii5MPU9250.begin();
|
|
wii5Weather_18B20.begin();
|
|
#ifdef WII5_IMU_SPARTON
|
|
wii5Sparton.begin();
|
|
#endif
|
|
wii5Communications.begin();
|
|
}
|
|
|
|
void WII5Setup::sleepBefore(bool MathsON) {
|
|
// Tell devices they are really off.
|
|
wii5Sparton.stop(true);
|
|
wii5Iridium.stop(true);
|
|
wii5Gps.off();
|
|
sdBlock.cardForceClose();
|
|
|
|
#ifdef WII5_WDT_INTERNAL
|
|
wdt_disable();
|
|
#endif
|
|
|
|
// Turn off Shared, and Maths CPU
|
|
pinMode(SHARED_5VOLT_PIN, OUTPUT);
|
|
pinMode(POWER_MATHS_PIN, OUTPUT);
|
|
if (MathsON) {
|
|
digitalWrite(SHARED_5VOLT_PIN, HIGH);
|
|
digitalWrite(POWER_MATHS_PIN, HIGH);
|
|
}
|
|
else {
|
|
digitalWrite(SHARED_5VOLT_PIN, LOW);
|
|
digitalWrite(POWER_MATHS_PIN, LOW);
|
|
}
|
|
|
|
// Storage SD Card
|
|
#if POWER_STORAGE_1_PIN>0
|
|
pinMode(POWER_STORAGE_1_PIN, OUTPUT);
|
|
digitalWrite(POWER_STORAGE_1_PIN, LOW);
|
|
#endif
|
|
#if POWER_STORAGE_2_PIN>0
|
|
pinMode(POWER_STORAGE_2_PIN, OUTPUT);
|
|
digitalWrite(POWER_STORAGE_2_PIN, LOW);
|
|
#endif
|
|
|
|
// GPS, Radio, MPU and Strobe
|
|
pinMode(POWER_GPS_PIN, OUTPUT);
|
|
digitalWrite(POWER_GPS_PIN, LOW);
|
|
pinMode(POWER_COMMS_PIN, OUTPUT);
|
|
digitalWrite(POWER_COMMS_PIN, LOW);
|
|
pinMode(POWER_RADIO_PIN, OUTPUT);
|
|
digitalWrite(POWER_RADIO_PIN, LOW);
|
|
pinMode(POWER_STROBE1_ON, OUTPUT);
|
|
digitalWrite(POWER_STROBE1_ON, LOW);
|
|
|
|
// Misc Controlling lines
|
|
pinMode(STORAGE_SD1_MATHS_PIN, INPUT);
|
|
pinMode(STORAGE_SD2_MATHS_PIN, INPUT);
|
|
pinMode(SPARTON_RESET, INPUT);
|
|
pinMode(RADIO_CS, INPUT);
|
|
pinMode(STORAGE_CS, INPUT);
|
|
|
|
// LEDs 2024 Updated to OUTPUT LOW
|
|
#if LED_1>0
|
|
pinMode(LED_1, OUTPUT);
|
|
digitalWrite(LED_1, LOW);
|
|
#endif
|
|
#if LED_2>0
|
|
pinMode(LED_2, OUTPUT);
|
|
digitalWrite(LED_2, LOW);
|
|
#endif
|
|
#if LED_3>0
|
|
pinMode(LED_3, OUTPUT);
|
|
#endif
|
|
|
|
// Weather
|
|
pinMode(POWER_WEATHER_18B20_PIN, INPUT);
|
|
pinMode(POWER_WEATHER_PIN, INPUT);
|
|
}
|
|
|
|
void WII5Setup::sleepAfter() {
|
|
// Really make sure still output
|
|
pinMode(SHARED_5VOLT_PIN, OUTPUT);
|
|
pinMode(POWER_MATHS_PIN, OUTPUT);
|
|
|
|
// Storage SD Card
|
|
#if POWER_STORAGE_1_PIN>0
|
|
pinMode(POWER_STORAGE_1_PIN, OUTPUT);
|
|
digitalWrite(POWER_STORAGE_1_PIN, HIGH);
|
|
#endif
|
|
#if POWER_STORAGE_2_PIN>0
|
|
pinMode(POWER_STORAGE_2_PIN, OUTPUT);
|
|
#endif
|
|
|
|
// GPS, Radio, MPU and Strobe
|
|
pinMode(POWER_GPS_PIN, OUTPUT);
|
|
pinMode(POWER_COMMS_PIN, OUTPUT);
|
|
pinMode(POWER_RADIO_PIN, OUTPUT);
|
|
pinMode(POWER_STROBE1_ON, OUTPUT);
|
|
|
|
// Misc Controlling lines
|
|
pinMode(STORAGE_SD1_MATHS_PIN, OUTPUT);
|
|
pinMode(STORAGE_SD2_MATHS_PIN, OUTPUT);
|
|
pinMode(SPARTON_RESET, OUTPUT);
|
|
pinMode(RADIO_CS, OUTPUT);
|
|
pinMode(STORAGE_CS, OUTPUT);
|
|
|
|
// LEDs
|
|
pinMode(LED_1, OUTPUT);
|
|
#if LED_2>0
|
|
pinMode(LED_2, OUTPUT);
|
|
#endif
|
|
#if LED_3>0
|
|
pinMode(LED_3, OUTPUT);
|
|
#endif
|
|
|
|
// Weather
|
|
pinMode(POWER_WEATHER_18B20_PIN, OUTPUT);
|
|
pinMode(POWER_WEATHER_PIN, OUTPUT);
|
|
|
|
#ifdef WII5_WDT_INTERNAL
|
|
wdt_enable(WDTO_8S);
|
|
#endif
|
|
}
|
|
|
|
WII5Setup wii5Setup;
|