#include <Arduino.h>
#define N2k_SPI_CS_PIN 53 // If you use mcp_can and CS pin is not 53, uncomment this and modify definition to match your CS pin.
#define N2k_CAN_INT_PIN 21 // If you use mcp_can and interrupt pin is not 21, uncomment this and modify definition to match your interrupt pin.
#define USE_MCP_CAN_CLOCK_SET 8 // If you use mcp_can and your mcp_can shield has 8MHz chrystal, uncomment this.
#include <NMEA2000_CAN.h> // This will automatically choose right CAN library and create suitable NMEA2000 object
#include <N2kMessages.h>
const int ntcPin = A0; // For Main Cabin Temperature
const float Beta = 3950.0;
const float thermistorNominal = 10000.0;
const float temperatureNominal = 25.0;
const int referenceResistor = 10000;
const int ntc2Pin = A1; // For sea temperature
const float Beta1 = 3950.0;
const float thermistorNominal_1 = 10000.0;
const float temperatureNominal_1 = 25.0;
const int referenceResistor_1 = 10000;
const int ntc3Pin = A2; // For outside temperature
const float Beta2 = 3950.0;
const float thermistorNominal_2 = 10000.0;
const float temperatureNominal_2 = 25.0;
const int referenceResistor_2 = 10000;
volatile int flow_frequency_A; // Measures flow sensor A pulses
volatile int flow_frequency_B; // Measures flow sensor B pulses
float vol_A = 0.0, vol_B = 0.0, total_vol = 0.0;
float l_minute_A, l_minute_B, total_l_minute;
unsigned char flowsensor_A = 18; // Sensor A Input
unsigned char flowsensor_B = 3; // Sensor B Input
unsigned long currentTime;
unsigned long cloopTime;
// List here messages your device will transmit.
const unsigned long TransmitMessages[] PROGMEM={130310L,127489L,130316L,130312L,130311L,0};
static unsigned long N2kMsgSentCount=0;
static unsigned long N2kMsgFailCount=0;
tN2kSyncScheduler TemperatureScheduler(false,500,520);
tN2kSyncScheduler EnvironmentalScheduler(false,500,540);
tN2kSyncScheduler OutsideEnvironmentalScheduler(false,500,520);
void OnN2kOpen() {
// Start schedulers now.
TemperatureScheduler.UpdateNextTime();
EnvironmentalScheduler.UpdateNextTime();
OutsideEnvironmentalScheduler.UpdateNextTime();
}
// *****************************************************************************
void setup() {
Serial.begin(9600);
pinMode(flowsensor_A, INPUT);
pinMode(flowsensor_B, INPUT);
digitalWrite(flowsensor_A, HIGH); // Optional Internal Pull-Up
digitalWrite(flowsensor_B, HIGH); // Optional Internal Pull-Up
attachInterrupt(digitalPinToInterrupt(flowsensor_A), flow_A, RISING); // Setup Interrupt for sensor A
attachInterrupt(digitalPinToInterrupt(flowsensor_B), flow_B, RISING); // Setup Interrupt for sensor B
currentTime = millis();
cloopTime = currentTime;
// Set Product information
NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
100, // Manufacturer's product code
"Simple temp monitor", // Manufacturer's Model ID
"1.2.0.24 (2024-08-11)", // Manufacturer's Software version code
"1.1.0.0 (2024-08-11)" // Manufacturer's Model version
);
// Set device information
NMEA2000.SetDeviceInformation(112233, // Unique number. Use e.g. Serial number.
130, // Device function=Temperature. See codes on https://web.archive.org/web/20190531120557/https://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
75,
2040 // Just choosen free from code list on https://web.archive.org/web/20190529161431/http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
);
NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode,22);
NMEA2000.EnableForward(false); // Disable all msg forwarding to USB (=Serial)
NMEA2000.ExtendTransmitMessages(TransmitMessages);
NMEA2000.SetOnOpen(OnN2kOpen);
NMEA2000.Open();
}
// *****************************************************************************
void loop() {
int analogValue = analogRead(ntcPin);
float resistance = calculateResistance(analogValue);
float temperatureC = calculateTemperatureC(resistance);
float temperatureF = temperatureC * 9.0 / 5.0 + 32.0;
/*Serial.print("Analog Value: ");
Serial.print(analogValue);
Serial.print(" Resistance: ");
Serial.print(resistance);
Serial.print(" ohms Temperature: ");
Serial.print(temperatureC);
Serial.print(" °C / ");
Serial.print(temperatureF);
Serial.println(F(" °F"));*/
int analogValue_1 = analogRead(ntc2Pin);
float resistance_1 = calculateResistance_1(analogValue_1);
float temperatureC_1 = calculateTemperatureC_1(resistance_1);
float temperatureF_1 = temperatureC_1 * 9.0 / 5.0 + 32.0;
/*Serial.print("Analog Value_1: ");
Serial.print(analogValue_1);
Serial.print(" Resistance_1: ");
Serial.print(resistance_1);
Serial.print(" ohms Temperature_1: ");
Serial.print(temperatureC_1);
Serial.print(" °C / ");
Serial.print(temperatureF_1);
Serial.println(F(" °F"));*/
currentTime = millis();
if (currentTime >= (cloopTime + 1000))
{
cloopTime = currentTime;
// Calculate flow for sensor A
if (flow_frequency_A != 0)
{
l_minute_A = (flow_frequency_A / 7.5) / 60; // Calculate flow rate in L/min
vol_A += l_minute_A;
flow_frequency_A = 0;
}
else
{
l_minute_A = 0;
}
if (flow_frequency_B != 0)
{
l_minute_B = (flow_frequency_B / 7.5) / 60; // Calculate flow rate in L/min
vol_B += l_minute_B;
flow_frequency_B = 0;
}
else
{
l_minute_B = 0;
}
// Calculate total flow as FlowA - FlowB
total_l_minute = l_minute_A - l_minute_B;
total_vol = vol_A - vol_B;
// Print results
Serial.print("Flow A: ");
Serial.print(l_minute_A, DEC);
Serial.print(" L/min, Flow B: ");
Serial.print(l_minute_B, DEC);
Serial.print(" L/min, Total Flow: ");
Serial.print(total_l_minute, DEC);
Serial.println(" L/min");
}
//SendN2kTransmission();
SendOutsideEnvironmentalParameters();
//SendN2kTemperature();
NMEA2000.ParseMessages();
}
// *****************************************************************************
float calculateResistance(int analogValue) {
float voltage = analogValue * (5.0 / 1023.0);
return referenceResistor * (5.0 / voltage - 1.0);
}
float calculateTemperatureC(float resistance) {
float steinhart;
steinhart = resistance / thermistorNominal; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= Beta; // 1/B * ln(R/Ro)
steinhart += 1.0 / (temperatureNominal + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // Convert to Celsius
return steinhart;
}
float calculateResistance_1(int analogValue_1) {
float voltage = analogValue_1 * (5.0 / 1023.0);
return referenceResistor_1 * (5.0 / voltage - 1.0);
}
float calculateTemperatureC_1(float resistance_1) {
float steinhart;
steinhart = resistance_1 / thermistorNominal_1; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= Beta1; // 1/B * ln(R/Ro)
steinhart += 1.0 / (temperatureNominal_1 + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // Convert to Celsius
return steinhart;
}
float calculateResistance_2(int analogValue_2) {
float voltage = analogValue_2 * (5.0 / 1023.0);
return referenceResistor_2 * (5.0 / voltage - 1.0);
}
float calculateTemperatureC_2(float resistance_2) {
float steinhart;
steinhart = resistance_2 / thermistorNominal_2; // (R/Ro)
steinhart = log(steinhart); // ln(R/Ro)
steinhart /= Beta2; // 1/B * ln(R/Ro)
steinhart += 1.0 / (temperatureNominal_2 + 273.15); // + (1/To)
steinhart = 1.0 / steinhart; // Invert
steinhart -= 273.15; // Convert to Celsius
return steinhart;
}
double ReadCabinTemp() {
int analogValue = analogRead(ntcPin);
float resistance = calculateResistance(analogValue);
float temperatureC = calculateTemperatureC(resistance);
return CToKelvin(temperatureC); // Read here the true temperature e.g. from analog input
}
// *****************************************************************************
double ReadWaterTemp() {
int analogValue_1 = analogRead(ntc2Pin);
float resistance_1 = calculateResistance_1(analogValue_1);
float temperatureC_1 = calculateTemperatureC_1(resistance_1);
return CToKelvin(temperatureC_1); // Read here the true temperature e.g. from analog input
}
// *****************************************************************************
double ReadinsideTemp() {
int analogValue_2 = analogRead(ntc3Pin);
float resistance_2 = calculateResistance_1(analogValue_2);
float temperatureC_2 = calculateTemperatureC_1(resistance_2);
return CToKelvin(temperatureC_2); // Read here the true temperature e.g. from analog input
}
//*********************************************************************************
void SendN2kMsg(const tN2kMsg &N2kMsg) {
if ( NMEA2000.SendMsg(N2kMsg) ) {
N2kMsgSentCount++;
} else {
N2kMsgFailCount++;
}
}
// *****************************************************************************
/*void SendN2kTemperature() {
tN2kMsg N2kMsg;
SetN2kOutsideEnvironmentalParameters(N2kMsg, 1, ReadWaterTemp(), ReadCabinTemp());
NMEA2000.SendMsg(N2kMsg);
}*/
//******************************************************************************************
/*void SendN2kTemperature() {
tN2kMsg N2kMsg;
SetN2kTemperature(N2kMsg, 1, 2, N2kts_MainCabinTemperature, ReadinsideTemp());
SendN2kMsg(N2kMsg);
}*/
//***********************************************************************************
void SendOutsideEnvironmentalParameters() {
tN2kMsg N2kMsg;
SetN2kOutsideEnvironmentalParameters(N2kMsg, 1, ReadWaterTemp(),ReadCabinTemp());
SendN2kMsg(N2kMsg);
}
//**********************************************************************************
void SendN2kTemperatureExt() {
tN2kMsg N2kMsg;
SetN2kTemperatureExt(N2kMsg, 0xff,11,N2kts_InsideTemperature, ReadinsideTemp(),CToKelvin(21.6));
SendN2kMsg(N2kMsg);
}
// *****************************************************************************
void SendN2kEngineDynamicParam() {
tN2kMsg N2kMsg;
tN2kEngineDiscreteStatus1 Status1;
Status1.Bits.LowOilLevel=1;
Status1.Bits.OverTemperature=1;
SetN2kEngineDynamicParam(N2kMsg,1,656000,CToKelvin(86.3),CToKelvin(82.1),14.21,9.0 ,hToSeconds(2137.55),N2kDoubleNA,N2kDoubleNA,N2kInt8NA,N2kInt8NA,Status1);
SendN2kMsg(N2kMsg);
}
//***************************************************************
void flow_A() // Interrupt function for sensor A
{
flow_frequency_A++;
}
//***************************************************************
void flow_B() // Interrupt function for sensor B
{
flow_frequency_B++;
}
[/quote]
here is the code which i used to send data on bus is attached, environmental outside temperature and air ambient temperature which is PGN 130310 , shows on GARMIN 720s,but PGN 130312, and even 130316 is unable to show on Garmin.