New hardware setup for OBP60 V2
This commit is contained in:
parent
0db52fefa2
commit
a97a69c3f7
|
@ -1,6 +1,10 @@
|
|||
#ifdef BOARD_OBP60S3
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <FastLED.h> // Driver for WS2812 RGB LED
|
||||
#include <PCF8574.h> // Driver for PCF8574 output modul from Horter
|
||||
#include <Wire.h> // I2C
|
||||
#include <RTClib.h> // Driver for DS1388 RTC
|
||||
#include "SunRise.h" // Lib for sunrise and sunset calculation
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Hardware.h"
|
||||
|
@ -18,68 +22,85 @@
|
|||
#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
|
||||
|
||||
// Horter I2C moduls
|
||||
PCF8574 pcf8574_Out(PCF8574_I2C_ADDR1); // First digital output modul PCF8574 from Horter
|
||||
|
||||
// RTC DS1388
|
||||
RTC_DS1388 ds1388;
|
||||
|
||||
// Define the array of leds
|
||||
CRGB fled[NUM_FLASH_LED]; // Flash LED
|
||||
CRGB backlight[NUM_BACKLIGHT_LED]; // Backlight
|
||||
|
||||
// Global vars
|
||||
int outA = 0; // Outport Byte A
|
||||
int outB = 0; // Outport Byte B
|
||||
bool blinkingLED = false; // Enable / disable blinking flash LED
|
||||
bool statusLED = false; // Actual status of flash LED on/off
|
||||
int uvDuration = 0; // Under voltage duration in n x 100ms
|
||||
|
||||
void MCP23017Init()
|
||||
void hardwareInit()
|
||||
{
|
||||
mcp.init();
|
||||
mcp.portMode(MCP23017Port::A, 0b00110000); // Port A, 0 = out, 1 = in
|
||||
mcp.portMode(MCP23017Port::B, 0b11110000); // Port B, 0 = out, 1 = in
|
||||
// Init power rail 5.0V
|
||||
setPortPin(OBP_POWER_50, true);
|
||||
|
||||
// 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
|
||||
// Init RGB LEDs
|
||||
FastLED.addLeds<WS2812B, OBP_FLASH_LED, GRB>(fled, NUM_FLASH_LED);
|
||||
FastLED.addLeds<WS2812B, OBP_BACKLIGHT_LED, GRB>(backlight, NUM_BACKLIGHT_LED);
|
||||
FastLED.setBrightness(255);
|
||||
fled[0] = CRGB::Red;
|
||||
FastLED.show();
|
||||
|
||||
// Extension Port B set defaults
|
||||
setPortPin(PB0, false); // PB0
|
||||
setPortPin(PB1, false); // PB1
|
||||
setPortPin(PB2, false); // PB2
|
||||
setPortPin(PB3, false); // PB3
|
||||
// Init PCF8574 digital outputs
|
||||
Wire.setClock(I2C_SPEED); // Set I2C clock on 10 kHz
|
||||
if(pcf8574_Out.begin()){ // Initialize PCF8574
|
||||
pcf8574_Out.write8(255); // Clear all outputs
|
||||
}
|
||||
|
||||
// Init DS1388 RTC
|
||||
if(ds1388.begin()){
|
||||
uint year = ds1388.now().year();
|
||||
if(year < 2023){
|
||||
ds1388.adjust(DateTime(__DATE__, __TIME__)); // Set date and time from PC file time
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, value);
|
||||
}
|
||||
|
||||
void togglePortPin(uint pin){
|
||||
if(pin <=7){
|
||||
outA ^= (1 << pin); // Set bit
|
||||
mcp.writeRegister(MCP23017Register::GPIO_A, outA);
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, !digitalRead(pin));
|
||||
}
|
||||
|
||||
void setFlashLED(bool status){
|
||||
statusLED = status;
|
||||
FastLED.setBrightness(255); // Brightness for flash LED
|
||||
if(statusLED == true){
|
||||
fled[0] = CRGB::Red; // Backlight LED on in red
|
||||
}
|
||||
else{
|
||||
pin = pin - 8;
|
||||
outB ^= (1 << pin); // Set bit
|
||||
mcp.writeRegister(MCP23017Register::GPIO_B, outB);
|
||||
fled[0] = CRGB::Black; // Backlight LED off
|
||||
}
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
void blinkingFlashLED(){
|
||||
if(blinkingLED == true){
|
||||
togglePortPin(OBP_FLASH_LED);
|
||||
statusLED != statusLED;
|
||||
FastLED.setBrightness(255); // Brightness for flash LED
|
||||
if(statusLED == true){
|
||||
fled[0] = CRGB::Red; // Backlight LED on in red
|
||||
}
|
||||
else{
|
||||
fled[0] = CRGB::Black; // Backlight LED off
|
||||
}
|
||||
FastLED.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
#include <GxIO/GxIO_SPI/GxIO_SPI.h> // GxEPD lip for SPI display communikation
|
||||
#include <GxIO/GxIO.h> // GxEPD lip for SPI
|
||||
|
||||
// Extension port
|
||||
void MCP23017Init();
|
||||
|
||||
// E-Ink display
|
||||
extern GxEPD_Class display; // E-Ink display functions
|
||||
|
||||
|
@ -27,12 +24,15 @@ extern const GFXfont DSEG7Classic_BoldItalic42pt7b;
|
|||
extern const GFXfont DSEG7Classic_BoldItalic60pt7b;
|
||||
|
||||
// Gloabl functions
|
||||
void hardwareInit();
|
||||
|
||||
void setPortPin(uint pin, bool value); // Set port pin for extension port
|
||||
|
||||
void togglePortPin(uint pin); // Toggle extension port pin
|
||||
|
||||
void blinkingFlashLED(); // Blinking function for LED on extension port
|
||||
void setBlinkingLED(bool on); // Set blinking LED active
|
||||
void setFlashLED(bool status); // Set flash LED
|
||||
void blinkingFlashLED(); // Blinking function for flash LED
|
||||
void setBlinkingLED(bool on); // Set blinking flash LED active
|
||||
|
||||
void buzzer(uint frequency, uint duration); // Buzzer function
|
||||
void setBuzzerPower(uint power); // Set buzzer power
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
// General hardware definitions
|
||||
// CAN bus pin definitions see obp60task.h
|
||||
// CAN and RS485 bus pin definitions see obp60task.h
|
||||
|
||||
// Direction pin for RS485 NMEA0183
|
||||
#define OBP_DIRECTION_PIN 27
|
||||
// SeaTalk
|
||||
#define OBP_SEATALK_TX 2
|
||||
#define OBP_SEATALK_RX 15
|
||||
// I2C (MCP23017, BME280, BMP280, SHT21)
|
||||
#define OBP_I2C_SDA 21
|
||||
#define OBP_I2C_SCL 22
|
||||
// Extension Port MCP23017
|
||||
#define MCP23017_I2C_ADDR 0x20 // Addr. 0 is 0x20
|
||||
#define OBP_DIRECTION_PIN 18
|
||||
// I2C
|
||||
#define I2C_SPEED 10000UL // 10kHz clock speed on I2C bus
|
||||
#define OBP_I2C_SDA 47
|
||||
#define OBP_I2C_SCL 21
|
||||
// DS1388 RTC
|
||||
#define DS1388_I2C_ADDR 0xD0 // Addr. 0xD0
|
||||
// BME280
|
||||
#define BME280_I2C_ADDR 0x76 // Addr. 0x76 (0x77)
|
||||
// BMP280
|
||||
|
@ -26,13 +24,15 @@
|
|||
#define INA226_I2C_ADDR1 0x41 // Addr. 0x41 (fix A0 = 5V, A1 = GND) for battery
|
||||
#define INA226_I2C_ADDR2 0x44 // Addr. 0x44 (fix A0 = GND, A1 = 5V) for solar panels
|
||||
#define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
|
||||
// Horter modules
|
||||
#define PCF8574_I2C_ADDR1 0x20 // First digital out module
|
||||
// SPI (E-Ink display, Extern Bus)
|
||||
#define OBP_SPI_CS 5
|
||||
#define OBP_SPI_DC 17
|
||||
#define OBP_SPI_RST 16
|
||||
#define OBP_SPI_BUSY 4
|
||||
#define OBP_SPI_CLK 18
|
||||
#define OBP_SPI_DIN 23
|
||||
#define OBP_SPI_CS 39
|
||||
#define OBP_SPI_DC 40
|
||||
#define OBP_SPI_RST 41
|
||||
#define OBP_SPI_BUSY 42
|
||||
#define OBP_SPI_CLK 38
|
||||
#define OBP_SPI_DIN 48
|
||||
#define SHOW_TIME 6000 // Show time for logo and WiFi QR code
|
||||
#define FULL_REFRESH_TIME 600 // Refresh cycle time in [s][600...3600] for full display update (very important healcy function)
|
||||
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
|
||||
|
@ -42,54 +42,36 @@
|
|||
#define FONT4 "DSEG7Classic_BoldItalic80pt7b"
|
||||
|
||||
// GPS (NEO-6M, NEO-M8N)
|
||||
#define OBP_GPS_TX 35 // Read only GPS data
|
||||
// TTP229 Touch Pad Controller (!!No I2C!!)
|
||||
#define TTP_SDO 25
|
||||
#define TTP_SCL 33
|
||||
#define OBP_GPS_RX 2
|
||||
#define OBP_GPS_TX 1
|
||||
// 1Wire (DS18B20)
|
||||
#define OBP_1WIRE 32 // External 1Wire
|
||||
#define OBP_1WIRE 6 // External 1Wire
|
||||
// Buzzer
|
||||
#define OBP_BUZZER 19
|
||||
#define OBP_BUZZER 16
|
||||
#define TONE1 1500 // 1500Hz
|
||||
#define TONE2 2500 // 2500Hz
|
||||
#define TONE3 3500 // 3500Hz
|
||||
#define TONE4 4000 // 4000Hz
|
||||
// Analog Input
|
||||
#define OBP_ANALOG0 34 // Voltage power supplay
|
||||
#define OBP_ANALOG1 36 // Analog In 1
|
||||
#define OBP_ANALOG2 39 // Analog In 2
|
||||
#define OBP_ANALOG0 4 // Voltage power supplay
|
||||
#define MIN_VOLTAGE 9.0 // Min voltage for under voltage detection (then goto deep sleep)
|
||||
#define POWER_FAIL_TIME 2 // in [ms] Accept min voltage until 2 x 1ms (for under voltage gaps by engine start)
|
||||
// Extension Port PA
|
||||
#define PA0 0 // Digital Out 1
|
||||
#define PA1 1 // Digital Out 2
|
||||
#define PA2 2 // Flash LED
|
||||
#define PA3 3 // Backlight LEDs
|
||||
#define PA4 4 // Digital In 1
|
||||
#define PA5 5 // Digital In 2
|
||||
#define PA6 6 // Power Rail 5.0V
|
||||
#define PA7 7 // Power Rail 3.3V
|
||||
// Extension Port PB
|
||||
#define PB0 8 // Extension Connector
|
||||
#define PB1 9 // Extension Connector
|
||||
#define PB2 10 // Extension Connector
|
||||
#define PB3 11 // Extension Connector
|
||||
#define PB4 12 // Extension Connector
|
||||
#define PB5 13 // Extension Connector
|
||||
#define PB6 14 // Extension Connector
|
||||
#define PB7 15 // Extension Connector
|
||||
// Touch buttons
|
||||
#define TOUCHTHRESHOLD 50000// Touch sensitivity, lower values more sensitiv
|
||||
#define TP1 14 // Left outside
|
||||
#define TP2 13
|
||||
#define TP3 12
|
||||
#define TP4 11
|
||||
#define TP5 10
|
||||
#define TP6 9 // Right ouside
|
||||
|
||||
// Flash LED (1x WS2812B)
|
||||
#define NUM_FLASH_LED 1 // Number of flash LED
|
||||
#define OBP_FLASH_LED 7 // GPIO port
|
||||
// Backlight LEDs (6x WS2812B)
|
||||
#define NUM_BACKLIGHT_LED 6 // Numebr of Backlight LEDs
|
||||
#define OBP_BACKLIGHT_LED 15 // GPIO port
|
||||
// Power Rail
|
||||
#define OBP_POWER_50 5
|
||||
|
||||
// Extension Port Digital Out
|
||||
#define OBP_DIGITAL_OUT1 PA0
|
||||
#define OBP_DIGITAL_OUT2 PA1
|
||||
// Extension Port LED
|
||||
#define OBP_FLASH_LED PA2
|
||||
// Extension Port Backlight LEDs
|
||||
#define OBP_BACKLIGHT_LED PA3
|
||||
// Extension Port Digital In
|
||||
#define OBP_DIGITAL_IN1 PA4
|
||||
#define OBP_DIGITAL_IN2 PA5
|
||||
// Extension Port Power Rails
|
||||
#define OBP_POWER_50 PA6
|
||||
#define OBP_POWER_33 PA7
|
||||
|
||||
|
|
|
@ -6,13 +6,8 @@
|
|||
|
||||
// Global vars
|
||||
|
||||
// Routine for TTP229-BSF (!!! IC use not a I2C bus !!!)
|
||||
//
|
||||
// 8 Key Mode
|
||||
//
|
||||
// Key number {0, 1, 2, 3, 4, 5, 6, 7, 8}
|
||||
// Scan code {0, 8, 7, 1, 6, 2, 5, 3, 4}
|
||||
int keyposition[9] = {0, 3, 5, 7, 8, 6, 4, 2, 1}; // Position of key in raw data, 0 = nothing touched
|
||||
// Touch keypad over ESP32 touch sensor inputs
|
||||
|
||||
int keypad[9]; // Raw data array from TTP229
|
||||
int key; // Value of key [0|1], 0 = touched, 1 = not touched
|
||||
int keycode = 0; // Keycode of pressed key [0...8], 0 = nothing touched
|
||||
|
@ -27,32 +22,65 @@ long starttime = 0; // Start time point for pressed key
|
|||
|
||||
int readKeypad() {
|
||||
int keystatus = 0; // Status of key [0...11], 0 = processed, 1...8 = key 1..8, 9 = right swipe , 10 = left swipe, 11 keys disabled
|
||||
|
||||
pinMode(TTP_SDO, INPUT);
|
||||
pinMode(TTP_SCL, OUTPUT);
|
||||
keycode = 0;
|
||||
// Read key code from raw data
|
||||
|
||||
// Read key code
|
||||
if(touchRead(14) > TOUCHTHRESHOLD){ // Touch pad 1
|
||||
keypad[1] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[1] = 0;
|
||||
}
|
||||
if(touchRead(13) > TOUCHTHRESHOLD){ // Touch pad 2
|
||||
keypad[2] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[2] = 0;
|
||||
}
|
||||
if(touchRead(12) > TOUCHTHRESHOLD){ // Touch pad 3
|
||||
keypad[3] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[3] = 0;
|
||||
}
|
||||
if(touchRead(11) > TOUCHTHRESHOLD){ // Touch pad 4
|
||||
keypad[4] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[4] = 0;
|
||||
}
|
||||
if(touchRead(10) > TOUCHTHRESHOLD){ // Touch pad 5
|
||||
keypad[5] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[5] = 0;
|
||||
}
|
||||
if(touchRead(9) > TOUCHTHRESHOLD){ // Touch pad 6
|
||||
keypad[6] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[6] = 0;
|
||||
}
|
||||
// Nothing touched
|
||||
if(keypad[1] == 0 && keypad[2] == 0 && keypad[3] == 0 && keypad[4] == 0 && keypad[5] == 0 && keypad[6] == 0){
|
||||
keypad[0] = 1;
|
||||
}
|
||||
else{
|
||||
keypad[0] = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
digitalWrite(TTP_SCL, LOW);
|
||||
// delay(1); // 0ms clock
|
||||
delayMicroseconds(100);
|
||||
keypad[i] = digitalRead(TTP_SDO);
|
||||
if(i > 0){
|
||||
// Invert keypad
|
||||
// Convert keypad to keycode
|
||||
if(keypad[i] == 1){
|
||||
key = 0;
|
||||
key = 1;
|
||||
}
|
||||
else{
|
||||
key = 1;
|
||||
key = 0;
|
||||
}
|
||||
keycode += key * i;
|
||||
}
|
||||
digitalWrite(TTP_SCL, HIGH);
|
||||
// delay(1); // 0ms clock
|
||||
delayMicroseconds(100);
|
||||
}
|
||||
// Remapping keycode
|
||||
keycode = keyposition[keycode];
|
||||
|
||||
// Detect short keynumber
|
||||
if (keycode > 0 ){
|
||||
|
|
|
@ -33,9 +33,10 @@ void underVoltageDetection(){
|
|||
}
|
||||
if(millis() > starttime + POWER_FAIL_TIME){
|
||||
Timer1.stop(); // Stop Timer1
|
||||
/*
|
||||
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
|
||||
setPortPin(OBP_FLASH_LED, false); // Flash LED Off
|
||||
setPortPin(OBP_POWER_33, false); // Power rail 3.3V Off
|
||||
setFlashLED(false); // Flash LED Off
|
||||
*/
|
||||
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
|
||||
setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off
|
||||
// Shutdown EInk display
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -96,7 +96,7 @@ class PageBME280 : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -144,7 +144,7 @@ class PageBattery : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -144,7 +144,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "Pb" && (raw >= 11.8 && raw <= 14.8)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// Limits for Gel battery
|
||||
if(String(batType) == "Gel" && (raw < 11.8 || raw > 14.4)){
|
||||
|
@ -152,7 +152,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "Gel" && (raw >= 11.8 && raw <= 14.4)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// Limits for AGM battery
|
||||
if(String(batType) == "AGM" && (raw < 11.8 || raw > 14.7)){
|
||||
|
@ -160,7 +160,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "AGM" && (raw >= 11.8 && raw <= 14.7)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// Limits for LiFePo4 battery
|
||||
if(String(batType) == "LiFePo4" && (raw < 12.0 || raw > 14.6)){
|
||||
|
@ -168,7 +168,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "LiFePo4" && (raw >= 12.0 && raw <= 14.6)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -81,7 +81,7 @@ class PageDST810 : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -81,7 +81,7 @@ class PageFourValues : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -81,7 +81,7 @@ class PageFourValues2 : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging voltage value
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -47,7 +47,7 @@ class PageOneValue : public Page{
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -115,7 +115,7 @@ public:
|
|||
// Limits for roll
|
||||
if(value1*360/(2*PI) > -1*rolllimit && value1*360/(2*PI) < rolllimit){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
else{
|
||||
setBlinkingLED(true);
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -57,7 +57,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging voltage value
|
||||
|
|
|
@ -70,7 +70,7 @@ class PageThreeValues : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -59,7 +59,7 @@ class PageTwoValues : public Page
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "Pb" && (raw >= 11.8 && raw <= 14.8)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// Limits for Gel battery
|
||||
if(String(batType) == "Gel" && (raw < 11.8 || raw > 14.4)){
|
||||
|
@ -106,7 +106,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "Gel" && (raw >= 11.8 && raw <= 14.4)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// Limits for AGM battery
|
||||
if(String(batType) == "AGM" && (raw < 11.8 || raw > 14.7)){
|
||||
|
@ -114,7 +114,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "AGM" && (raw >= 11.8 && raw <= 14.7)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// Limits for LiFePo4 battery
|
||||
if(String(batType) == "LiFePo4" && (raw < 12.0 || raw > 14.6)){
|
||||
|
@ -122,7 +122,7 @@ public:
|
|||
}
|
||||
if(String(batType) == "LiFePo4" && (raw >= 12.0 && raw <= 14.6)){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ class PageWhite : public Page{
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -130,7 +130,7 @@ public:
|
|||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setPortPin(OBP_FLASH_LED, false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
|
|
|
@ -0,0 +1,516 @@
|
|||
// A library for handling real-time clocks, dates, etc.
|
||||
// 2010-02-04 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
|
||||
// 2012-11-08 RAM methods - idreammicro.com
|
||||
// 2012-11-14 SQW/OUT methods - idreammicro.com
|
||||
// 2012-01-12 DS1388 support
|
||||
// 2013-08-29 ENERGIA MSP430 support
|
||||
// 2023-11-24 Return value for begin() to RTC presence check - NoWa
|
||||
|
||||
#include <Wire.h>
|
||||
// Energia support
|
||||
#ifndef ENERGIA
|
||||
// #include <avr/pgmspace.h>
|
||||
#else
|
||||
#define pgm_read_word(data) *data
|
||||
#define pgm_read_byte(data) *data
|
||||
#define PROGMEM
|
||||
#endif
|
||||
#include "RTClib.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// utility code, some of this could be exposed in the DateTime API if needed
|
||||
|
||||
static const uint8_t daysInMonth [] PROGMEM = {
|
||||
31,28,31,30,31,30,31,31,30,31,30,31
|
||||
};
|
||||
|
||||
// number of days since 2000/01/01, valid for 2001..2099
|
||||
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
|
||||
if (y >= 2000)
|
||||
y -= 2000;
|
||||
uint16_t days = d;
|
||||
for (uint8_t i = 1; i < m; ++i)
|
||||
days += pgm_read_byte(daysInMonth + i - 1);
|
||||
if (m > 2 && y % 4 == 0)
|
||||
++days;
|
||||
return days + 365 * y + (y + 3) / 4 - 1;
|
||||
}
|
||||
|
||||
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
|
||||
return ((days * 24L + h) * 60 + m) * 60 + s;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DateTime implementation - ignores time zones and DST changes
|
||||
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
|
||||
|
||||
DateTime::DateTime (long t) {
|
||||
ss = t % 60;
|
||||
t /= 60;
|
||||
mm = t % 60;
|
||||
t /= 60;
|
||||
hh = t % 24;
|
||||
uint16_t days = t / 24;
|
||||
uint8_t leap;
|
||||
for (yOff = 0; ; ++yOff) {
|
||||
leap = yOff % 4 == 0;
|
||||
if (days < 365 + leap)
|
||||
break;
|
||||
days -= 365 + leap;
|
||||
}
|
||||
for (m = 1; ; ++m) {
|
||||
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
|
||||
if (leap && m == 2)
|
||||
++daysPerMonth;
|
||||
if (days < daysPerMonth)
|
||||
break;
|
||||
days -= daysPerMonth;
|
||||
}
|
||||
d = days + 1;
|
||||
}
|
||||
|
||||
DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
|
||||
if (year >= 2000)
|
||||
year -= 2000;
|
||||
yOff = year;
|
||||
m = month;
|
||||
d = day;
|
||||
hh = hour;
|
||||
mm = min;
|
||||
ss = sec;
|
||||
}
|
||||
|
||||
static uint8_t conv2d(const char* p) {
|
||||
uint8_t v = 0;
|
||||
if ('0' <= *p && *p <= '9')
|
||||
v = *p - '0';
|
||||
return 10 * v + *++p - '0';
|
||||
}
|
||||
|
||||
// A convenient constructor for using "the compiler's time":
|
||||
// DateTime now (__DATE__, __TIME__);
|
||||
// NOTE: using PSTR would further reduce the RAM footprint
|
||||
DateTime::DateTime (const char* date, const char* time) {
|
||||
// sample input: date = "Dec 26 2009", time = "12:34:56"
|
||||
yOff = conv2d(date + 9);
|
||||
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
|
||||
switch (date[0]) {
|
||||
case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
|
||||
case 'F': m = 2; break;
|
||||
case 'A': m = date[2] == 'r' ? 4 : 8; break;
|
||||
case 'M': m = date[2] == 'r' ? 3 : 5; break;
|
||||
case 'S': m = 9; break;
|
||||
case 'O': m = 10; break;
|
||||
case 'N': m = 11; break;
|
||||
case 'D': m = 12; break;
|
||||
}
|
||||
d = conv2d(date + 4);
|
||||
hh = conv2d(time);
|
||||
mm = conv2d(time + 3);
|
||||
ss = conv2d(time + 6);
|
||||
}
|
||||
|
||||
uint8_t DateTime::dayOfWeek() const {
|
||||
uint16_t day = get() / SECONDS_PER_DAY;
|
||||
return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
|
||||
}
|
||||
|
||||
long DateTime::get() const {
|
||||
uint16_t days = date2days(yOff, m, d);
|
||||
return time2long(days, hh, mm, ss);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RTC_DS1307 implementation
|
||||
|
||||
void RTC_DS1307::adjust(const DateTime& dt) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.write(bin2bcd(dt.second()));
|
||||
Wire.write(bin2bcd(dt.minute()));
|
||||
Wire.write(bin2bcd(dt.hour()));
|
||||
Wire.write(bin2bcd(0));
|
||||
Wire.write(bin2bcd(dt.day()));
|
||||
Wire.write(bin2bcd(dt.month()));
|
||||
Wire.write(bin2bcd(dt.year() - 2000));
|
||||
Wire.write((byte) 0);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
DateTime RTC_DS1307::now() {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 7);
|
||||
uint8_t ss = bcd2bin(Wire.read());
|
||||
uint8_t mm = bcd2bin(Wire.read());
|
||||
uint8_t hh = bcd2bin(Wire.read());
|
||||
Wire.read();
|
||||
uint8_t d = bcd2bin(Wire.read());
|
||||
uint8_t m = bcd2bin(Wire.read());
|
||||
uint16_t y = bcd2bin(Wire.read()) + 2000;
|
||||
|
||||
return DateTime (y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
void RTC_DS1307::setSqwOutLevel(uint8_t level) {
|
||||
uint8_t value = (level == LOW) ? 0x00 : (1 << RTC_DS1307__OUT);
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(DS1307_CONTROL_REGISTER);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void RTC_DS1307::setSqwOutSignal(Frequencies frequency) {
|
||||
uint8_t value = (1 << RTC_DS1307__SQWE);
|
||||
switch (frequency)
|
||||
{
|
||||
case Frequency_1Hz:
|
||||
// Nothing to do.
|
||||
break;
|
||||
case Frequency_4096Hz:
|
||||
value |= (1 << RTC_DS1307__RS0);
|
||||
break;
|
||||
case Frequency_8192Hz:
|
||||
value |= (1 << RTC_DS1307__RS1);
|
||||
break;
|
||||
case Frequency_32768Hz:
|
||||
default:
|
||||
value |= (1 << RTC_DS1307__RS1) | (1 << RTC_DS1307__RS0);
|
||||
break;
|
||||
}
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(DS1307_CONTROL_REGISTER);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t RTC_DS1307::readByteInRam(uint8_t address) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(address);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 1);
|
||||
uint8_t data = Wire.read();
|
||||
Wire.endTransmission();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void RTC_DS1307::readBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(address);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, (int)length);
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
p_data[i] = Wire.read();
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void RTC_DS1307::writeByteInRam(uint8_t address, uint8_t data) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(address);
|
||||
Wire.write(data);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
void RTC_DS1307::writeBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write(address);
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
Wire.write(p_data[i]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t RTC_DS1307::isrunning(void) {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 1);
|
||||
uint8_t ss = Wire.read();
|
||||
return !(ss>>7);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// DS 1388 implementation
|
||||
|
||||
void RTC_DS1388::adjust(const DateTime& dt) {
|
||||
Wire.beginTransmission(DS1388_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.write(bin2bcd(0)); // hundreds of seconds 0x00
|
||||
Wire.write(bin2bcd(dt.second())); // 0x01
|
||||
Wire.write(bin2bcd(dt.minute())); // 0x02
|
||||
Wire.write(bin2bcd(dt.hour())); // 0x03
|
||||
Wire.write(bin2bcd(0)); // 0x04
|
||||
Wire.write(bin2bcd(dt.day())); // 0x05
|
||||
Wire.write(bin2bcd(dt.month())); // 0x06
|
||||
Wire.write(bin2bcd(dt.year() - 2000)); // 0x07
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.beginTransmission(DS1388_ADDRESS);
|
||||
Wire.write((byte) 0x0b);
|
||||
Wire.write((byte) 0x00); //clear the 'time is invalid ' flag bit (OSF)
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
DateTime RTC_DS1388::now() {
|
||||
Wire.beginTransmission(DS1388_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1388_ADDRESS, 8);
|
||||
uint8_t hs = bcd2bin(Wire.read() & 0x7F); // hundreds of seconds
|
||||
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
|
||||
uint8_t mm = bcd2bin(Wire.read());
|
||||
uint8_t hh = bcd2bin(Wire.read());
|
||||
Wire.read();
|
||||
uint8_t d = bcd2bin(Wire.read());
|
||||
uint8_t m = bcd2bin(Wire.read());
|
||||
uint16_t y = bcd2bin(Wire.read()) + 2000;
|
||||
|
||||
return DateTime (y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
uint8_t RTC_DS1388::isrunning() {
|
||||
Wire.beginTransmission(DS1388_ADDRESS);
|
||||
Wire.write((byte)0x0b);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1388_ADDRESS, 1);
|
||||
uint8_t ss = Wire.read();
|
||||
return !(ss>>7); //OSF flag bit
|
||||
}
|
||||
|
||||
|
||||
void RTC_DS1388::EEPROMWrite(int pos, uint8_t c) {
|
||||
uint8_t rel_pos = pos % 256;
|
||||
if(pos > 255){
|
||||
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_1);
|
||||
} else {
|
||||
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_0);
|
||||
}
|
||||
// Set address
|
||||
Wire.write((byte)rel_pos);
|
||||
// Wite data
|
||||
Wire.write((byte)c);
|
||||
Wire.endTransmission();
|
||||
#if defined(__MSP430G2553__)
|
||||
delay(10); // Needed on MSP430 !!
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint8_t RTC_DS1388::EEPROMRead(int pos) {
|
||||
uint8_t rel_pos = pos % 256;
|
||||
if(pos > 255){
|
||||
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_1);
|
||||
} else {
|
||||
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_0);
|
||||
}
|
||||
// Set address
|
||||
Wire.write((byte)rel_pos);
|
||||
Wire.endTransmission(true); // Stay open
|
||||
// Request one byte
|
||||
if(pos > 255){
|
||||
Wire.requestFrom(DS1388_ADDRESS | DS1388_EEPROM_1, 1);
|
||||
} else {
|
||||
Wire.requestFrom(DS1388_ADDRESS | DS1388_EEPROM_0, 1);
|
||||
}
|
||||
uint8_t c = Wire.read();
|
||||
#if defined(__MSP430G2553__)
|
||||
delay(10); // Needed on MSP430 !!
|
||||
#endif
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RTC_PCF8563 implementation
|
||||
// contributed by @mariusster, see http://forum.jeelabs.net/comment/1902
|
||||
|
||||
void RTC_PCF8563::adjust(const DateTime& dt) {
|
||||
Wire.beginTransmission(PCF8563_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.write((byte) 0x0); // control/status1
|
||||
Wire.write((byte) 0x0); // control/status2
|
||||
Wire.write(bin2bcd(dt.second())); // set seconds
|
||||
Wire.write(bin2bcd(dt.minute())); // set minutes
|
||||
Wire.write(bin2bcd(dt.hour())); // set hour
|
||||
Wire.write(bin2bcd(dt.day())); // set day
|
||||
Wire.write((byte) 0x01); // set weekday
|
||||
Wire.write(bin2bcd(dt.month())); // set month, century to 1
|
||||
Wire.write(bin2bcd(dt.year() - 2000)); // set year to 00-99
|
||||
Wire.write((byte) 0x80); // minute alarm value reset to 00
|
||||
Wire.write((byte) 0x80); // hour alarm value reset to 00
|
||||
Wire.write((byte) 0x80); // day alarm value reset to 00
|
||||
Wire.write((byte) 0x80); // weekday alarm value reset to 00
|
||||
Wire.write((byte) 0x0); // set freqout 0= 32768khz, 1= 1hz
|
||||
Wire.write((byte) 0x0); // timer off
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
DateTime RTC_PCF8563::now() {
|
||||
Wire.beginTransmission(PCF8563_ADDRESS);
|
||||
Wire.write(PCF8563_SEC_ADDR);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(PCF8563_ADDRESS, 7);
|
||||
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
|
||||
uint8_t mm = bcd2bin(Wire.read() & 0x7F);
|
||||
uint8_t hh = bcd2bin(Wire.read() & 0x3F);
|
||||
uint8_t d = bcd2bin(Wire.read() & 0x3F);
|
||||
Wire.read();
|
||||
uint8_t m = bcd2bin(Wire.read()& 0x1F);
|
||||
uint16_t y = bcd2bin(Wire.read()) + 2000;
|
||||
|
||||
return DateTime (y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// RTC_BQ32000 implementation
|
||||
|
||||
void RTC_BQ32000::adjust(const DateTime& dt) {
|
||||
Wire.beginTransmission(BQ32000_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.write(bin2bcd(dt.second()));
|
||||
Wire.write(bin2bcd(dt.minute()));
|
||||
Wire.write(bin2bcd(dt.hour()));
|
||||
Wire.write(bin2bcd(0));
|
||||
Wire.write(bin2bcd(dt.day()));
|
||||
Wire.write(bin2bcd(dt.month()));
|
||||
Wire.write(bin2bcd(dt.year() - 2000));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
DateTime RTC_BQ32000::now() {
|
||||
Wire.beginTransmission(BQ32000_ADDRESS);
|
||||
Wire.write((byte) 0);
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(DS1307_ADDRESS, 7);
|
||||
uint8_t ss = bcd2bin(Wire.read());
|
||||
uint8_t mm = bcd2bin(Wire.read());
|
||||
uint8_t hh = bcd2bin(Wire.read());
|
||||
Wire.read();
|
||||
uint8_t d = bcd2bin(Wire.read());
|
||||
uint8_t m = bcd2bin(Wire.read());
|
||||
uint16_t y = bcd2bin(Wire.read()) + 2000;
|
||||
|
||||
return DateTime (y, m, d, hh, mm, ss);
|
||||
}
|
||||
|
||||
void RTC_BQ32000::setIRQ(uint8_t state) {
|
||||
/* Set IRQ square wave output state: 0=disabled, 1=1Hz, 2=512Hz.
|
||||
*/
|
||||
uint8_t reg, value;
|
||||
if (state) {
|
||||
// Setting the frequency is a bit complicated on the BQ32000:
|
||||
Wire.beginTransmission(BQ32000_ADDRESS);
|
||||
Wire.write(BQ32000_SFKEY1);
|
||||
Wire.write(BQ32000_SFKEY1_VAL);
|
||||
Wire.write(BQ32000_SFKEY2_VAL);
|
||||
Wire.write((state == 1) ? BQ32000_FTF_1HZ : BQ32000_FTF_512HZ);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
value = readRegister(BQ32000_CAL_CFG1);
|
||||
value = (!state) ? value & ~(1<<BQ32000__FT) : value | (1<<BQ32000__FT);
|
||||
writeRegister(BQ32000_CAL_CFG1, value);
|
||||
}
|
||||
|
||||
void RTC_BQ32000::setIRQLevel(uint8_t level) {
|
||||
/* Set IRQ output level when IRQ square wave output is disabled to
|
||||
* LOW or HIGH.
|
||||
*/
|
||||
uint8_t value;
|
||||
// The IRQ active level bit is in the same register as the calibration
|
||||
// settings, so we preserve its current state:
|
||||
value = readRegister(BQ32000_CAL_CFG1);
|
||||
value = (!level) ? value & ~(1<<BQ32000__OUT) : value | (1<<BQ32000__OUT);
|
||||
writeRegister(BQ32000_CAL_CFG1, value);
|
||||
}
|
||||
|
||||
void RTC_BQ32000::setCalibration(int8_t value) {
|
||||
/* Sets the calibration value to given value in the range -31 - 31, which
|
||||
* corresponds to -126ppm - +63ppm; see table 13 in th BQ32000 datasheet.
|
||||
*/
|
||||
uint8_t val;
|
||||
if (value > 31) value = 31;
|
||||
if (value < -31) value = -31;
|
||||
val = (uint8_t) (value < 0) ? -value | (1<<BQ32000__CAL_S) : value;
|
||||
val |= readRegister(BQ32000_CAL_CFG1) & ~0x3f;
|
||||
writeRegister(BQ32000_CAL_CFG1, val);
|
||||
}
|
||||
|
||||
void RTC_BQ32000::setCharger(int state) {
|
||||
/* If using a super capacitor instead of a battery for backup power, use this
|
||||
* method to set the state of the trickle charger: 0=disabled, 1=low-voltage
|
||||
* charge, 2=high-voltage charge. In low-voltage charge mode, the super cap is
|
||||
* charged through a diode with a voltage drop of about 0.5V, so it will charge
|
||||
* up to VCC-0.5V. In high-voltage charge mode the diode is bypassed and the super
|
||||
* cap will be charged up to VCC (make sure the charge voltage does not exceed your
|
||||
* super cap's voltage rating!!).
|
||||
*/
|
||||
// First disable charger regardless of state (prevents it from
|
||||
// possible starting up in the high voltage mode when the low
|
||||
// voltage mode is requested):
|
||||
uint8_t value;
|
||||
writeRegister(BQ32000_TCH2, 0);
|
||||
if (state <= 0 || state > 2) return;
|
||||
value = BQ32000_CHARGE_ENABLE;
|
||||
if (state == 2) {
|
||||
// High voltage charge enable:
|
||||
value |= (1 << BQ32000__TCFE);
|
||||
}
|
||||
writeRegister(BQ32000_CFG2, value);
|
||||
// Now enable charger:
|
||||
writeRegister(BQ32000_TCH2, 1 << BQ32000__TCH2_BIT);
|
||||
}
|
||||
|
||||
|
||||
uint8_t RTC_BQ32000::readRegister(uint8_t address) {
|
||||
/* Read and return the value in the register at the given address.
|
||||
*/
|
||||
Wire.beginTransmission(BQ32000_ADDRESS);
|
||||
Wire.write((byte) address);
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(DS1307_ADDRESS, 1);
|
||||
// Get register state:
|
||||
return Wire.read();
|
||||
}
|
||||
|
||||
uint8_t RTC_BQ32000::writeRegister(uint8_t address, uint8_t value) {
|
||||
/* Write the given value to the register at the given address.
|
||||
*/
|
||||
Wire.beginTransmission(BQ32000_ADDRESS);
|
||||
Wire.write(address);
|
||||
Wire.write(value);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t RTC_BQ32000::isrunning() {
|
||||
return !(readRegister(0x0)>>7);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// RTC_Millis implementation
|
||||
|
||||
long RTC_Millis::offset = 0;
|
||||
|
||||
void RTC_Millis::adjust(const DateTime& dt) {
|
||||
offset = dt.get() - millis() / 1000;
|
||||
}
|
||||
|
||||
DateTime RTC_Millis::now() {
|
||||
return offset + millis() / 1000;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,201 @@
|
|||
// A library for handling real-time clocks, dates, etc.
|
||||
// 2010-02-04 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
|
||||
// 2012-11-08 RAM methods - idreammicro.com
|
||||
// 2012-11-14 SQW/OUT methods - idreammicro.com
|
||||
// 2023-11-24 Return value for begin() to RTC presence check - NoWa
|
||||
|
||||
// DS1307
|
||||
#define DS1307_ADDRESS 0x68
|
||||
#define DS1307_CONTROL_REGISTER 0x07
|
||||
#define DS1307_RAM_REGISTER 0x08
|
||||
|
||||
// DS1307 Control register bits.
|
||||
#define RTC_DS1307__RS0 0x00
|
||||
#define RTC_DS1307__RS1 0x01
|
||||
#define RTC_DS1307__SQWE 0x04
|
||||
#define RTC_DS1307__OUT 0x07
|
||||
|
||||
// DS1388
|
||||
#define DS1388_ADDRESS 0x68
|
||||
|
||||
// DS1388 Control register bits
|
||||
#define DS1388_EEPROM_0 0x01
|
||||
#define DS1388_EEPROM_1 0x02
|
||||
|
||||
// PCF8563
|
||||
#define PCF8563_ADDRESS 0x51
|
||||
#define PCF8563_SEC_ADDR 0x02
|
||||
|
||||
// BQ32000
|
||||
#define BQ32000_ADDRESS 0x68
|
||||
// BQ32000 register addresses:
|
||||
#define BQ32000_CAL_CFG1 0x07
|
||||
#define BQ32000_TCH2 0x08
|
||||
#define BQ32000_CFG2 0x09
|
||||
#define BQ32000_SFKEY1 0x20
|
||||
#define BQ32000_SFKEY2 0x21
|
||||
#define BQ32000_SFR 0x22
|
||||
// BQ32000 config bits:
|
||||
#define BQ32000__OUT 0x07 // CAL_CFG1 - IRQ active state
|
||||
#define BQ32000__FT 0x06 // CAL_CFG1 - IRQ square wave enable
|
||||
#define BQ32000__CAL_S 0x05 // CAL_CFG1 - Calibration sign
|
||||
#define BQ32000__TCH2_BIT 0x05 // TCH2 - Trickle charger switch 2
|
||||
#define BQ32000__TCFE 0x06 // CFG2 - Trickle FET control
|
||||
// BQ32000 config values:
|
||||
#define BQ32000_CHARGE_ENABLE 0x05 // CFG2 - Trickle charger switch 1 enable
|
||||
#define BQ32000_SFKEY1_VAL 0x5E
|
||||
#define BQ32000_SFKEY2_VAL 0xC7
|
||||
#define BQ32000_FTF_1HZ 0x01
|
||||
#define BQ32000_FTF_512HZ 0x00
|
||||
|
||||
#define SECONDS_PER_DAY 86400L
|
||||
|
||||
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
|
||||
class DateTime {
|
||||
public:
|
||||
DateTime (long t =0);
|
||||
DateTime (uint16_t year, uint8_t month, uint8_t day,
|
||||
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
|
||||
DateTime (const char* date, const char* time);
|
||||
|
||||
uint16_t year() const { return 2000 + yOff; }
|
||||
uint8_t month() const { return m; }
|
||||
uint8_t day() const { return d; }
|
||||
uint8_t hour() const { return hh; }
|
||||
uint8_t minute() const { return mm; }
|
||||
uint8_t second() const { return ss; }
|
||||
uint8_t dayOfWeek() const;
|
||||
|
||||
// 32-bit times as seconds since 1/1/2000
|
||||
long get() const;
|
||||
|
||||
protected:
|
||||
uint8_t yOff, m, d, hh, mm, ss;
|
||||
};
|
||||
|
||||
// RTC based on the DS1307 chip connected via I2C and the Wire library
|
||||
class RTC_DS1307 {
|
||||
public:
|
||||
|
||||
// SQW/OUT frequencies.
|
||||
enum Frequencies
|
||||
{
|
||||
Frequency_1Hz,
|
||||
Frequency_4096Hz,
|
||||
Frequency_8192Hz,
|
||||
Frequency_32768Hz
|
||||
};
|
||||
|
||||
static bool begin() {
|
||||
Wire.beginTransmission(DS1307_ADDRESS);
|
||||
return (Wire.endTransmission() == 0);
|
||||
}
|
||||
static void adjust(const DateTime& dt);
|
||||
static DateTime now();
|
||||
static uint8_t isrunning();
|
||||
|
||||
// SQW/OUT functions.
|
||||
void setSqwOutLevel(uint8_t level);
|
||||
void setSqwOutSignal(Frequencies frequency);
|
||||
|
||||
// RAM registers read/write functions. Address locations 08h to 3Fh.
|
||||
// Max length = 56 bytes.
|
||||
static uint8_t readByteInRam(uint8_t address);
|
||||
static void readBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data);
|
||||
static void writeByteInRam(uint8_t address, uint8_t data);
|
||||
static void writeBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data);
|
||||
|
||||
// utility functions
|
||||
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
|
||||
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
|
||||
};
|
||||
|
||||
|
||||
// DS1388 version
|
||||
class RTC_DS1388 {
|
||||
public:
|
||||
static bool begin() {
|
||||
Wire.beginTransmission(DS1388_ADDRESS);
|
||||
return (Wire.endTransmission() == 0);
|
||||
};
|
||||
static void adjust(const DateTime& dt);
|
||||
static DateTime now();
|
||||
static uint8_t isrunning();
|
||||
|
||||
// EEPROM
|
||||
static void EEPROMWrite(int pos, uint8_t c);
|
||||
static uint8_t EEPROMRead(int pos);
|
||||
|
||||
// utility functions
|
||||
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
|
||||
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
// RTC based on the PCF8563 chip connected via I2C and the Wire library
|
||||
// contributed by @mariusster, see http://forum.jeelabs.net/comment/1902
|
||||
class RTC_PCF8563 {
|
||||
public:
|
||||
static bool begin() {
|
||||
Wire.beginTransmission(PCF8563_ADDRESS);
|
||||
return (Wire.endTransmission() == 0);
|
||||
}
|
||||
static void adjust(const DateTime& dt);
|
||||
static DateTime now();
|
||||
|
||||
// utility functions
|
||||
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
|
||||
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
|
||||
};
|
||||
|
||||
|
||||
// TI BQ32000 I2C RTC
|
||||
class RTC_BQ32000 {
|
||||
public:
|
||||
static bool begin() {
|
||||
Wire.beginTransmission(BQ32000_ADDRESS);
|
||||
return (Wire.endTransmission() == 0);
|
||||
}
|
||||
static void adjust(const DateTime& dt);
|
||||
static DateTime now();
|
||||
static uint8_t isrunning();
|
||||
|
||||
static void setIRQ(uint8_t state);
|
||||
/* Set IRQ output state: 0=disabled, 1=1Hz, 2=512Hz.
|
||||
*/
|
||||
static void setIRQLevel(uint8_t level);
|
||||
/* Set IRQ output active state to LOW or HIGH.
|
||||
*/
|
||||
static void setCalibration(int8_t value);
|
||||
/* Sets the calibration value to given value in the range -31 - 31, which
|
||||
* corresponds to -126ppm - +63ppm; see table 13 in th BQ32000 datasheet.
|
||||
*/
|
||||
static void setCharger(int state);
|
||||
/* If using a super capacitor instead of a battery for backup power, use this
|
||||
method to set the state of the trickle charger: 0=disabled, 1=low-voltage
|
||||
charge, 2=high-voltage charge. In low-voltage charge mode, the super cap is
|
||||
charged through a diode with a voltage drop of about 0.5V, so it will charge
|
||||
up to VCC-0.5V. In high-voltage charge mode the diode is bypassed and the super
|
||||
cap will be charged up to VCC (make sure the charge voltage does not exceed your
|
||||
super cap's voltage rating!!). */
|
||||
|
||||
// utility functions:
|
||||
static uint8_t readRegister(uint8_t address);
|
||||
static uint8_t writeRegister(uint8_t address, uint8_t value);
|
||||
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
|
||||
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
|
||||
};
|
||||
|
||||
|
||||
// RTC using the internal millis() clock, has to be initialized before use
|
||||
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
|
||||
class RTC_Millis {
|
||||
public:
|
||||
static void begin(const DateTime& dt) { adjust(dt); }
|
||||
static void adjust(const DateTime& dt);
|
||||
static DateTime now();
|
||||
|
||||
protected:
|
||||
static long offset;
|
||||
};
|
|
@ -32,47 +32,48 @@ int taskRunCounter = 0; // Task couter for loop section
|
|||
void OBP60Init(GwApi *api){
|
||||
api->getLogger()->logDebug(GwLog::LOG,"obp60init running");
|
||||
|
||||
// Extension port MCP23017
|
||||
// Check I2C devices MCP23017
|
||||
// Check I2C devices
|
||||
Wire.begin(OBP_I2C_SDA, OBP_I2C_SCL);
|
||||
Wire.beginTransmission(MCP23017_I2C_ADDR);
|
||||
Wire.beginTransmission(DS1388_I2C_ADDR);
|
||||
if (Wire.endTransmission() != 0) {
|
||||
api->getLogger()->logDebug(GwLog::ERROR,"MCP23017 not found, check wiring");
|
||||
api->getLogger()->logDebug(GwLog::ERROR,"DS1388 not found, check wiring");
|
||||
initComplete = false;
|
||||
}
|
||||
else{
|
||||
// Init extension port
|
||||
MCP23017Init();
|
||||
|
||||
// Settings for backlight
|
||||
String backlightMode = api->getConfig()->getConfigItem(api->getConfig()->backlight,true)->asString();
|
||||
api->getLogger()->logDebug(GwLog::DEBUG,"Backlight Mode is: %s", backlightMode);
|
||||
if(String(backlightMode) == "On"){
|
||||
setPortPin(OBP_BACKLIGHT_LED, true);
|
||||
}
|
||||
if(String(backlightMode) == "Off"){
|
||||
setPortPin(OBP_BACKLIGHT_LED, false);
|
||||
}
|
||||
if(String(backlightMode) == "Control by Key"){
|
||||
setPortPin(OBP_BACKLIGHT_LED, false);
|
||||
}
|
||||
|
||||
// Settings flash LED mode
|
||||
String ledMode = api->getConfig()->getConfigItem(api->getConfig()->flashLED,true)->asString();
|
||||
api->getLogger()->logDebug(GwLog::DEBUG,"Backlight Mode is: %s", ledMode);
|
||||
if(String(ledMode) == "Off"){
|
||||
setBlinkingLED(false);
|
||||
}
|
||||
|
||||
// Marker for init complete
|
||||
// Used in OBP60Task()
|
||||
initComplete = true;
|
||||
|
||||
// Buzzer tone for initialization finish
|
||||
setBuzzerPower(uint(api->getConfig()->getConfigItem(api->getConfig()->buzzerPower,true)->asInt()));
|
||||
buzzer(TONE4, 500);
|
||||
|
||||
else{
|
||||
// Init code for DS1388
|
||||
}
|
||||
|
||||
// Init hardware
|
||||
hardwareInit();
|
||||
|
||||
// Settings for backlight
|
||||
String backlightMode = api->getConfig()->getConfigItem(api->getConfig()->backlight,true)->asString();
|
||||
api->getLogger()->logDebug(GwLog::DEBUG,"Backlight Mode is: %s", backlightMode);
|
||||
if(String(backlightMode) == "On"){
|
||||
// setPortPin(OBP_BACKLIGHT_LED, true);
|
||||
}
|
||||
if(String(backlightMode) == "Off"){
|
||||
// setPortPin(OBP_BACKLIGHT_LED, false);
|
||||
}
|
||||
if(String(backlightMode) == "Control by Key"){
|
||||
// setPortPin(OBP_BACKLIGHT_LED, false);
|
||||
}
|
||||
|
||||
// Settings flash LED mode
|
||||
String ledMode = api->getConfig()->getConfigItem(api->getConfig()->flashLED,true)->asString();
|
||||
api->getLogger()->logDebug(GwLog::DEBUG,"Backlight Mode is: %s", ledMode);
|
||||
if(String(ledMode) == "Off"){
|
||||
setBlinkingLED(false);
|
||||
}
|
||||
|
||||
// Marker for init complete
|
||||
// Used in OBP60Task()
|
||||
initComplete = true;
|
||||
|
||||
// Buzzer tone for initialization finish
|
||||
setBuzzerPower(uint(api->getConfig()->getConfigItem(api->getConfig()->buzzerPower,true)->asInt()));
|
||||
buzzer(TONE4, 500);
|
||||
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
#ifdef BOARD_OBP60S3
|
||||
#define USBSerial Serial
|
||||
// CAN NMEA2000
|
||||
#define ESP32_CAN_TX_PIN GPIO_NUM_13
|
||||
#define ESP32_CAN_RX_PIN GPIO_NUM_12
|
||||
#define ESP32_CAN_TX_PIN 46
|
||||
#define ESP32_CAN_RX_PIN 3
|
||||
// Bus load in 50mA steps
|
||||
#define N2K_LOAD_LEVEL 5 // 5x50mA = 250mA max bus load with back light on
|
||||
// RS485 NMEA0183
|
||||
#define GWSERIAL_TX 26
|
||||
#define GWSERIAL_RX 14
|
||||
#define GWSERIAL_TX 17
|
||||
#define GWSERIAL_RX 8
|
||||
#define GWSERIAL_MODE "UNI"
|
||||
// Allowed to set a new password for access point
|
||||
#define FORCE_AP_PWCHANGE
|
||||
|
|
|
@ -33,4 +33,5 @@ build_flags=
|
|||
${env.build_flags}
|
||||
upload_port = /dev/ttyACM0
|
||||
upload_protocol = esptool
|
||||
upload_speed = 230400
|
||||
monitor_speed = 115200
|
Loading…
Reference in New Issue