mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-15 06:53:07 +01:00
Implementation of sunrise and sunset
This commit is contained in:
267
lib/obp60task/OBP60Extensions.cpp
Normal file
267
lib/obp60task/OBP60Extensions.cpp
Normal file
@@ -0,0 +1,267 @@
|
||||
#ifdef BOARD_NODEMCU32S_OBP60
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "SunRise.h" // Lib for sunrise and sunset calculation
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Hardware.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
// Please dont forget to declarate the fonts in OBP60ExtensionPort.h
|
||||
#include "Ubuntu_Bold8pt7b.h"
|
||||
#include "Ubuntu_Bold12pt7b.h"
|
||||
#include "Ubuntu_Bold16pt7b.h"
|
||||
#include "Ubuntu_Bold20pt7b.h"
|
||||
#include "Ubuntu_Bold32pt7b.h"
|
||||
#include "DSEG7Classic-BoldItalic16pt7b.h"
|
||||
#include "DSEG7Classic-BoldItalic20pt7b.h"
|
||||
#include "DSEG7Classic-BoldItalic30pt7b.h"
|
||||
#include "DSEG7Classic-BoldItalic42pt7b.h"
|
||||
#include "DSEG7Classic-BoldItalic60pt7b.h"
|
||||
|
||||
MCP23017 mcp = MCP23017(MCP23017_I2C_ADDR);
|
||||
|
||||
// SPI pin definitions for E-Ink display
|
||||
GxIO_Class io(SPI, OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST); // SPI, CS, DC, RST
|
||||
GxEPD_Class display(io, OBP_SPI_RST, OBP_SPI_BUSY); // io, RST, BUSY
|
||||
|
||||
// Global vars
|
||||
int outA = 0; // Outport Byte A
|
||||
int outB = 0; // Outport Byte B
|
||||
bool blinkingLED = false; // Enable / disable blinking flash LED
|
||||
int uvDuration = 0; // Under voltage duration in n x 100ms
|
||||
|
||||
void MCP23017Init()
|
||||
{
|
||||
mcp.init();
|
||||
mcp.portMode(MCP23017Port::A, 0b00110000); // Port A, 0 = out, 1 = in
|
||||
mcp.portMode(MCP23017Port::B, 0b11110000); // Port B, 0 = out, 1 = in
|
||||
|
||||
// Extension Port A set defaults
|
||||
setPortPin(OBP_DIGITAL_OUT1, false); // PA0
|
||||
setPortPin(OBP_DIGITAL_OUT2, false); // PA1
|
||||
setPortPin(OBP_FLASH_LED, false); // PA2
|
||||
setPortPin(OBP_BACKLIGHT_LED, false); // PA3
|
||||
setPortPin(OBP_POWER_50, true); // PA6
|
||||
setPortPin(OBP_POWER_33, true); // PA7
|
||||
|
||||
// Extension Port B set defaults
|
||||
setPortPin(PB0, false); // PB0
|
||||
setPortPin(PB1, false); // PB1
|
||||
setPortPin(PB2, false); // PB2
|
||||
setPortPin(PB3, false); // PB3
|
||||
}
|
||||
|
||||
void setPortPin(uint pin, bool value){
|
||||
if(pin <=7){
|
||||
outA &= ~(1 << pin); // Clear bit
|
||||
outA |= (value << pin); // Set bit
|
||||
mcp.writeRegister(MCP23017Register::GPIO_A, outA);
|
||||
}
|
||||
else{
|
||||
pin = pin - 8;
|
||||
outB &= ~(1 << pin); // Clear bit
|
||||
outB |= (value << pin); // Set bit
|
||||
mcp.writeRegister(MCP23017Register::GPIO_B, outB);
|
||||
}
|
||||
}
|
||||
|
||||
void togglePortPin(uint pin){
|
||||
if(pin <=7){
|
||||
outA ^= (1 << pin); // Set bit
|
||||
mcp.writeRegister(MCP23017Register::GPIO_A, outA);
|
||||
}
|
||||
else{
|
||||
pin = pin - 8;
|
||||
outB ^= (1 << pin); // Set bit
|
||||
mcp.writeRegister(MCP23017Register::GPIO_B, outB);
|
||||
}
|
||||
}
|
||||
|
||||
void blinkingFlashLED(){
|
||||
if(blinkingLED == true){
|
||||
togglePortPin(OBP_FLASH_LED);
|
||||
}
|
||||
}
|
||||
|
||||
void setBlinkingLED(bool on){
|
||||
blinkingLED = on;
|
||||
}
|
||||
|
||||
uint buzzerpower = 50;
|
||||
|
||||
void buzzer(uint frequency, uint duration){
|
||||
if(frequency > 8000){ // Max 8000Hz
|
||||
frequency = 8000;
|
||||
}
|
||||
if(buzzerpower > 100){ // Max 100%
|
||||
buzzerpower = 100;
|
||||
}
|
||||
if(duration > 1000){ // Max 1000ms
|
||||
duration = 1000;
|
||||
}
|
||||
|
||||
pinMode(OBP_BUZZER, OUTPUT);
|
||||
ledcSetup(0, frequency, 8); // Ch 0, ferquency in Hz, 8 Bit resolution of PWM
|
||||
ledcAttachPin(OBP_BUZZER, 0);
|
||||
ledcWrite(0, uint(buzzerpower * 1.28)); // 50% duty cycle are 100%
|
||||
delay(duration);
|
||||
ledcWrite(0, 0); // 0% duty cycle are 0%
|
||||
}
|
||||
|
||||
void setBuzzerPower(uint power){
|
||||
buzzerpower = power;
|
||||
}
|
||||
|
||||
// Show a triangle for trend direction high (x, y is the left edge)
|
||||
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color){
|
||||
display.fillTriangle(x, y, x+size*2, y, x+size, y-size*2, color);
|
||||
}
|
||||
|
||||
// Show a triangle for trend direction low (x, y is the left edge)
|
||||
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color){
|
||||
display.fillTriangle(x, y, x+size*2, y, x+size, y+size*2, color);
|
||||
}
|
||||
|
||||
// Show header informations
|
||||
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time){
|
||||
|
||||
static bool heartbeat = false;
|
||||
static unsigned long usbRxOld = 0;
|
||||
static unsigned long usbTxOld = 0;
|
||||
static unsigned long serRxOld = 0;
|
||||
static unsigned long serTxOld = 0;
|
||||
static unsigned long tcpSerRxOld = 0;
|
||||
static unsigned long tcpSerTxOld = 0;
|
||||
static unsigned long tcpClRxOld = 0;
|
||||
static unsigned long tcpClTxOld = 0;
|
||||
static unsigned long n2kRxOld = 0;
|
||||
static unsigned long n2kTxOld = 0;
|
||||
int textcolor = GxEPD_BLACK;
|
||||
|
||||
if(commonData.config->getBool(commonData.config->statusLine) == true){
|
||||
|
||||
if(commonData.config->getString(commonData.config->displaycolor) == "Normal"){
|
||||
textcolor = GxEPD_BLACK;
|
||||
}
|
||||
else{
|
||||
textcolor = GxEPD_WHITE;
|
||||
}
|
||||
|
||||
// Show status info
|
||||
display.setTextColor(textcolor);
|
||||
display.setFont(&Ubuntu_Bold8pt7b);
|
||||
display.setCursor(0, 15);
|
||||
if(commonData.status.wifiApOn){
|
||||
display.print(" AP ");
|
||||
}
|
||||
// If receive new telegram data then display bus name
|
||||
if(commonData.status.tcpClRx != tcpClRxOld || commonData.status.tcpClTx != tcpClTxOld || commonData.status.tcpSerRx != tcpSerRxOld || commonData.status.tcpSerTx != tcpSerTxOld){
|
||||
display.print("TCP ");
|
||||
}
|
||||
if(commonData.status.n2kRx != n2kRxOld || commonData.status.n2kTx != n2kTxOld){
|
||||
display.print("N2K ");
|
||||
}
|
||||
if(commonData.status.serRx != serRxOld || commonData.status.serTx != serTxOld){
|
||||
display.print("183 ");
|
||||
}
|
||||
if(commonData.status.usbRx != usbRxOld || commonData.status.usbTx != usbTxOld){
|
||||
display.print("USB ");
|
||||
}
|
||||
if(commonData.config->getBool(commonData.config->useGPS) == true && date->valid == true){
|
||||
display.print("GPS");
|
||||
}
|
||||
// Save old telegram counter
|
||||
tcpClRxOld = commonData.status.tcpClRx;
|
||||
tcpClTxOld = commonData.status.tcpClTx;
|
||||
tcpSerRxOld = commonData.status.tcpSerRx;
|
||||
tcpSerTxOld = commonData.status.tcpSerTx;
|
||||
n2kRxOld = commonData.status.n2kRx;
|
||||
n2kTxOld = commonData.status.n2kTx;
|
||||
serRxOld = commonData.status.serRx;
|
||||
serTxOld = commonData.status.serTx;
|
||||
usbRxOld = commonData.status.usbRx;
|
||||
usbTxOld = commonData.status.usbTx;
|
||||
|
||||
// Heartbeat as dot
|
||||
display.setTextColor(textcolor);
|
||||
display.setFont(&Ubuntu_Bold32pt7b);
|
||||
display.setCursor(205, 14);
|
||||
if(heartbeat == true){
|
||||
display.print(".");
|
||||
}
|
||||
else{
|
||||
display.print(" ");
|
||||
}
|
||||
heartbeat = !heartbeat;
|
||||
|
||||
// Date and time
|
||||
display.setTextColor(textcolor);
|
||||
display.setFont(&Ubuntu_Bold8pt7b);
|
||||
display.setCursor(230, 15);
|
||||
if(date->valid == true){
|
||||
String acttime = formatValue(time, commonData).svalue;
|
||||
acttime = acttime.substring(0, 5);
|
||||
String actdate = formatValue(date, commonData).svalue;
|
||||
display.print(acttime);
|
||||
display.print(" ");
|
||||
display.print(actdate);
|
||||
display.print(" ");
|
||||
if(commonData.config->getInt(commonData.config->timeZone) == 0){
|
||||
display.print("UTC");
|
||||
}
|
||||
else{
|
||||
display.print("LOT");
|
||||
}
|
||||
}
|
||||
else{
|
||||
display.print("No GPS data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sunset und sunrise calculation
|
||||
SensorData calcSunsetSunrise(double time, double date, double latitude, double longitude, double timezone){
|
||||
SensorData returnset;
|
||||
SunRise sr;
|
||||
int secPerHour = 3600;
|
||||
int secPerYear = 86400;
|
||||
sr.hasRise = false;
|
||||
sr.hasSet = false;
|
||||
time_t sunR = 0;
|
||||
time_t sunS = 0;
|
||||
int inthrSR = 0;
|
||||
int intminSR = 0;
|
||||
int inthrSS = 0;
|
||||
int intminSS = 0;
|
||||
|
||||
// Calculate local time
|
||||
time_t t = (date * secPerYear) + (time + int(timezone * secPerHour));
|
||||
|
||||
// api->getLogger()->logDebug(GwLog::DEBUG,"... PageClock: Lat %f, Lon %f, at: %d, next SR: %d (%s), next SS: %d (%s)", latitude, longitude, t, sunR, sSunR, sunS, sSunS);
|
||||
|
||||
if (!isnan(time) && !isnan(date) && !isnan(latitude) && !isnan(longitude) && !isnan(timezone)) {
|
||||
sr.calculate(latitude, longitude, t); // LAT, LON, EPOCH
|
||||
// Sunrise
|
||||
if (sr.hasRise) {
|
||||
sunR = (sr.riseTime + int(timezone * secPerHour) + 30) % secPerYear; // add 30 seconds: round to minutes
|
||||
inthrSR = int (sunR / secPerHour);
|
||||
intminSR = int((sunR - inthrSR * secPerHour)/60);
|
||||
}
|
||||
// Sunset
|
||||
if (sr.hasSet) {
|
||||
sunS = (sr.setTime + int(timezone * secPerHour) + 30) % secPerYear; // add 30 seconds: round to minutes
|
||||
inthrSS = int (sunS / secPerHour);
|
||||
intminSS = int((sunS - inthrSS * secPerHour)/60);
|
||||
}
|
||||
}
|
||||
// Return values
|
||||
returnset.sunsetHour = inthrSS;
|
||||
returnset.sunsetMinute = intminSS;
|
||||
returnset.sunriseHour = inthrSR;
|
||||
returnset.sunriseMinute = intminSR;
|
||||
|
||||
// api->getLogger()->logDebug(GwLog::DEBUG,"... PageClock: at t: %d, hasRise: %d, next SR: %d '%s', hasSet: %d, next SS: %d '%s'\n", t, sr.hasRise, sr.riseTime, sSunR, sr.hasSet, sr.setTime, sSunS);
|
||||
return returnset;
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user