NMEA2000
NMEA2000 copied to clipboard
Two Nodes on one Network
Hello Together,
I have a Simrad GO7 XSR Chart Plotter..... and I have two nodes created by my own on an ESP8266....
1st is sending a Heading Signal 2nd is sending Humanity and Teperaturs
Strange is that the GO7 is not showing both on the correct way if both nodes are connected to the bus (see pictures) Name of Node is most like --------- and both nodes are shown together ....
Code1:
#include <Arduino.h>
#include <EEPROM.h>
#define USE_MCP_CAN_CLOCK_SET 8
#define N2k_SPI_CS_PIN 15
#include <NMEA2000_CAN.h>
#include <N2kMessages.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#define ONE_WIRE_BUS 2
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "DFRobot_SHT20.h"
DFRobot_SHT20 sht20;
#ifndef STASSID
#define STASSID "ssid"
#define STAPSK "password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
const int SPI_CS_PIN = 15;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
#define RapidDataUpdatePeriod 2000 //167 // Some strange periot to cause Slow and rapid to run unsync.
// List here messages your device will transmit.
const unsigned long TemperatureTransmitMessages[] PROGMEM={130316L,0};
const unsigned long HumidityTransmitMessages[] PROGMEM={130313L,0};
#define DEV_TEMP 0
#define DEV_HUMI 1
void setup() {
Serial.begin(115200);
EEPROM.begin(512);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int count;
EEPROM.get(0 ,count);
Serial.print("Boot Counter: ");
Serial.println(count);
while (WiFi.waitForConnectResult() != WL_CONNECTED && count <= 10) {
Serial.println("Connection Failed! Rebooting...");
count++;
EEPROM.put(0, count);
EEPROM.commit();
delay(5000);
ESP.restart();
}
EEPROM.put(0, 0);
EEPROM.commit();
sht20.initSHT20();
delay(100);
sht20.checkSHT20();
// Port defaults to 8266
// ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname("SB Environmental");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
ArduinoOTA.setPasswordHash("hash");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// Reserve enough buffer for sending all messages. This does not work on small memory devices like Uno or Mega
NMEA2000.SetN2kCANSendFrameBufSize(450);
// Set Product information
NMEA2000.SetDeviceCount(2); // Enable multi device support for 2 devices
NMEA2000.SetProductInformation("00000002", // Manufacturer's Model serial code
102, // Manufacturer's product code
"SB_Temperatur", // Manufacturer's Model ID
"V1.0", // Manufacturer's Software version code
"V1.0", // Manufacturer's Model version
0xff, // load equivalency - use default
0xffff, // NMEA 2000 version - use default
0xff, // Sertification level - use default
DEV_TEMP
);
NMEA2000.SetProductInformation("00000003", // Manufacturer's Model serial code
103, // Manufacturer's product code
"SB_Humidity", // Manufacturer's Model ID
"V1.0", // Manufacturer's Software version code
"V1.0", // Manufacturer's Model version
0xff, // load equivalency - use default
0xffff, // NMEA 2000 version - use default
0xff, // Sertification level - use default
DEV_HUMI
);
// Set device information
NMEA2000.SetDeviceInformation(00000002, // Unique number. Use e.g. Serial number.
130, // Device function=Analog to NMEA 2000 Gateway. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
75, // Device class=Inter/Intranetwork Device. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
1857, // Just choosen free from code list on http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
4, // Marine
DEV_TEMP
);
NMEA2000.SetDeviceInformation(00000003, // Unique number. Use e.g. Serial number.
170, // Device function=Analog to NMEA 2000 Gateway. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
75, // Device class=Inter/Intranetwork Device. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
1857, // Just choosen free from code list on http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
4, // Marine
DEV_HUMI
);
// Uncomment 3 rows below to see, what device will send to bus
//NMEA2000.SetForwardStream(&Serial); // PC output on due programming port
// NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show in clear text. Leave uncommented for default Actisense format.
// NMEA2000.SetForwardOwnMessages();
// If you also want to see all traffic on the bus use N2km_ListenAndNode instead of N2km_NodeOnly below
NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly,22);
//NMEA2000.SetDebugMode(tNMEA2000::dm_ClearText); // Uncomment this, so you can test code without CAN bus chips on Arduino Mega
NMEA2000.EnableForward(false); // Disable all msg forwarding to USB (=Serial)
NMEA2000.Open();
sensors.begin();
}
bool IsTimeToUpdate(unsigned long NextUpdate) {
return (NextUpdate<millis());
}
unsigned long InitNextUpdate(unsigned long Period, unsigned long Offset=0) {
return millis()+Period+Offset;
}
void SetNextUpdate(unsigned long &NextUpdate, unsigned long Period) {
while ( NextUpdate<millis() ) NextUpdate+=Period;
}
void loop() {
ArduinoOTA.handle();
SendN2kRapidData();
NMEA2000.ParseMessages();
}
void SendN2kRapidData() {
static unsigned long RapidDataUpdated=InitNextUpdate(RapidDataUpdatePeriod);
tN2kMsg N2kMsg;
if ( IsTimeToUpdate(RapidDataUpdated) ) {
SetNextUpdate(RapidDataUpdated,RapidDataUpdatePeriod);
sensors.requestTemperatures();
float EngineTemp = sensors.getTempCByIndex(0);
float OutsideHumd = sht20.readHumidity();
float OutsideTemp = sht20.readTemperature();
// Temperature
// Temperatures should be in Kelvins
// Input:
// - SID Sequence ID.
// - TempInstance This should be unic at least on one device. May be best to have it unic over all devices sending this PGN.
// - TempSource see tN2kTempSource
// - ActualTemperature Temperature in °K. Use function CToKelvin, if you want to use °C.
// - SetTemperature Set temperature in °K. Use function CToKelvin, if you want to use °C. This is meaningfull for temperatures,
// which can be controlled like cabin, freezer, refridgeration temperature. God can use value for this for
// outside and sea temperature values.
SetN2kTemperatureExt(N2kMsg, 1, 0, N2kts_OutsideTemperature, CToKelvin(OutsideTemp), 0.0);
NMEA2000.SendMsg(N2kMsg, DEV_TEMP);
SetN2kTemperatureExt(N2kMsg, 1, 0, N2kts_EngineRoomTemperature, CToKelvin(EngineTemp), 0.0);
NMEA2000.SendMsg(N2kMsg, DEV_TEMP);
//*****************************************************************************
// Humidity
// Humidity should be a percent
// Input:
// - SID Sequence ID.
// - HumidityInstance This should be unic at least on one device. May be best to have it unic over all devices sending this PGN.
// - HumiditySource see tN2kHumiditySource
// - Humidity Humidity in percent
SetN2kHumidity(N2kMsg, 1, 0, N2khs_OutsideHumidity, OutsideHumd);
NMEA2000.SendMsg(N2kMsg, DEV_HUMI);
}
}
Code2:
#include <Arduino.h>
#include <EEPROM.h>
#define USE_MCP_CAN_CLOCK_SET 8
#define N2k_SPI_CS_PIN 15
#include <NMEA2000_CAN.h>
#include <N2kMessages.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include <QMC5883LCompass.h>
#ifndef STASSID
#define STASSID "ssid"
#define STAPSK "password"
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
QMC5883LCompass compass;
float azimuth;
#define RapidDataUpdatePeriod 500
void setup() {
Serial.begin(115200);
EEPROM.begin(512);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
int count;
EEPROM.get(0 ,count);
Serial.print("Boot Counter: ");
Serial.println(count);
while (WiFi.waitForConnectResult() != WL_CONNECTED && count <= 10) {
Serial.println("Connection Failed! Rebooting...");
count++;
EEPROM.put(0, count);
EEPROM.commit();
delay(5000);
ESP.restart();
}
EEPROM.put(0, 0);
EEPROM.commit();
// Port defaults to 8266
// ArduinoOTA.setPort(8266);
// Hostname defaults to esp8266-[ChipID]
ArduinoOTA.setHostname("SB Kompass");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
ArduinoOTA.setPasswordHash("hash");
ArduinoOTA.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH) {
type = "sketch";
} else { // U_FS
type = "filesystem";
}
// NOTE: if updating FS this would be the place to unmount FS using FS.end()
Serial.println("Start updating " + type);
});
ArduinoOTA.onEnd([]() {
Serial.println("\nEnd");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) {
Serial.println("Auth Failed");
} else if (error == OTA_BEGIN_ERROR) {
Serial.println("Begin Failed");
} else if (error == OTA_CONNECT_ERROR) {
Serial.println("Connect Failed");
} else if (error == OTA_RECEIVE_ERROR) {
Serial.println("Receive Failed");
} else if (error == OTA_END_ERROR) {
Serial.println("End Failed");
}
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// INIT Kompass Modul
compass.init();
compass.setMode(0x01, 0x0C, 0x00, 0x40);
compass.setSmoothing(4,true);
// Reserve enough buffer for sending all messages. This does not work on small memory devices like Uno or Mega
NMEA2000.SetN2kCANSendFrameBufSize(250);
// Set Product information
NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
1, // Manufacturer's product code
"SB_Kompass", // Manufacturer's Model ID
"V1.0", // Manufacturer's Software version code
"V1.0" // Manufacturer's Model version
);
// Set device information
NMEA2000.SetDeviceInformation(1, // Unique number. Use e.g. Serial number.
140, // Device function=Analog to NMEA 2000 Gateway. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
60, // Device class=Inter/Intranetwork Device. See codes on http://www.nmea.org/Assets/20120726%20nmea%202000%20class%20&%20function%20codes%20v%202.00.pdf
1857 // Just choosen free from code list on http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
);
// Uncomment 3 rows below to see, what device will send to bus
//NMEA2000.SetForwardStream(&Serial); // PC output on due programming port
// NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show in clear text. Leave uncommented for default Actisense format.
// NMEA2000.SetForwardOwnMessages();
// If you also want to see all traffic on the bus use N2km_ListenAndNode instead of N2km_NodeOnly below
NMEA2000.SetMode(tNMEA2000::N2km_NodeOnly,22);
//NMEA2000.SetDebugMode(tNMEA2000::dm_ClearText); // Uncomment this, so you can test code without CAN bus chips on Arduino Mega
NMEA2000.EnableForward(false); // Disable all msg forwarding to USB (=Serial)
NMEA2000.Open();
}
bool IsTimeToUpdate(unsigned long NextUpdate) {
return (NextUpdate<millis());
}
unsigned long InitNextUpdate(unsigned long Period, unsigned long Offset=0) {
return millis()+Period+Offset;
}
void SetNextUpdate(unsigned long &NextUpdate, unsigned long Period) {
while ( NextUpdate<millis() ) NextUpdate+=Period;
}
void loop() {
ArduinoOTA.handle();
// Read compass values
compass.read();
azimuth = compass.getAzimuth();
SendN2kRapidData();
NMEA2000.ParseMessages();
}
void SendN2kRapidData() {
static unsigned long RapidDataUpdated=InitNextUpdate(RapidDataUpdatePeriod);
tN2kMsg N2kMsg;
if ( IsTimeToUpdate(RapidDataUpdated) ) {
SetNextUpdate(RapidDataUpdated,RapidDataUpdatePeriod);
// Kompasswert Magnetische Abweichung, Ablenkung im Boot
SetN2kMagneticHeading(N2kMsg, 0, DegToRad(azimuth), DegToRad(2.6), DegToRad(0.0));
NMEA2000.SendMsg(N2kMsg);
//Heading+=0.1; if (Heading>=360.0 ) Heading-=360.0;
}
}
The nodes are sending the periodic data on the right way .... checked with CanOE.... they are also running stable... but only this identyfing makes trouble.
Pictures: http://dl2ksb.de/1.jpg http://dl2ksb.de/2.jpg http://dl2ksb.de/3.jpg
someone a soulution?
Each PGN has its defined period. On NMEA2000.cpp, where PGNs has been listed there is mentioned default period, which you should use. So use 2000 for temp and humidity as you have. For naming RapidData is not, good, since in NMEA2000 point rapid is <200 ms period. Magnetic heading you should send with 100 ms period.
Then one problem is OneWire temperature. As default it does it by blocking, which means 700 ms stop for your code. During that period some messages may not be served and may cause problems. If you use async mode with OneWire, you get stops down to 10 ms, which is OK, but still not good. With ESP32 it is possible to run OneWire on other core, but then you need to do something with ArduinoOTA, since that runs other core. Other solution would be to put NMEA2000.ParseMessages to own task to other core. If you use other core or tasking you should prevent data concurrent access with mutexes.
Also you should check how compass reading stops tasking. If there is any delays, it poisons the loop.
Try first to comment all device access - sensors, sht20 and compass - and just set fixed values to them. Then check does devices appear on bus as they should.
Hi Timo,
thanks for your great project, and your support.
I tryed to comment everything out, without no result. In my opinion the OTA Stuff is interupting /slowing down the loop. My problem is that I sealed the nodes with epoxy .... if I remove the OTA Stuff, I will not be able to reupload the software. So I need to build a new test node first, to check if the OTA code is the problem.
btw: offtopic do you have a dbc file for the NMEA2k messages?!
What do you meant with dbc file? I do not have any more information than available on network.
dbc is a format which is used for CAN busses, to describe the messages, the signals and there values...
So I did some more tests today .... I commented out all the communication with sensors, with no result. I also change the time value .... with no results. strange is that if the device is displayed on the poltter the Node Adress and the manufacturer are shown correct, rest is -------
I also tested with an Arduino Mega ... same code (without OTA), same heading sensor.... works fine. But when I put a second node (one of the above) to the network, also the Arduino Mega is shown as ---- ---- and data of both is showed togeter under one device ....
I think I solved the problem....
I found in your code following...
NMEA2000.SendProductInformation(); NMEA2000.SendIsoAddressClaim();
When I send them periodically it seems to work fine.
So TNAKS again for this great libary and your support!!!
That may be cure, but does not solve actual problem. ISO address claim and product information should be sent on request and library does that automatically, if you just poll ParseMessages. You do not seem to have interrupt enabled for mcp_can. You should wire interrupt line to 8266 and add also #define N2k_CAN_INT_PIN xx
If interrupt handling has not been enabled you may loose those requests, which will cause them to disappear. Check also that you do not have any delay(xx) calls anywhere on your code. Like I mentioned you should change one wire to async mode. Below is snap from my old code, where I used sensors with single line. With that code you have max about 10 ms delays, which is not bad, if you have interrupt receiving and sending. Now I normally add a DS2482-100 bus master to system.
In CanBoat and SignalK they have description file for messages. That has been designed on on big structure and does not compile on small Arduinos. That DB also does not include all important information. That is why I originally made it with functions. In my own systems I use a bit different method and have each PGN described on separated structure. In this way program takes memory only for selected PGNs. Then I also use class method, where each PGN has own class. Unfortunately it eats a bit more flash. For the beginners the function way is the easiest to understant - I think.
// *****************************************************************************
#define DataInstanceStart 0
#define InvalidInstance 0xff
tTemperatureSensorData SensorsData[] = {
{DataInstanceStart+0,N2kts_FreezerTemperature,{0x28,0x50,0x0A,0xA1,0x07,0x00,0x00,0xD1,0x00},N2kDoubleNA,0.05,0},
{DataInstanceStart+1,N2kts_RefridgerationTemperature, {0x28,0xBA,0x22,0xA0,0x07,0x00,0x00,0x7E,0x00},N2kDoubleNA,-0.77,0},
{DataInstanceStart+2,N2kts_HeatingSystemTemperature, {0x28,0x75,0xED,0x9F,0x07,0x00,0x00,0x5A,0x00},N2kDoubleNA,-0.87,0},
{DataInstanceStart+3,N2kts_EngineRoomTemperature, {0x28,0x7B,0xDF,0x9F,0x07,0x00,0x00,0x4E,0x00},N2kDoubleNA,0.05,0},
{InvalidInstance,N2kts_MainCabinTemperature,{},N2kDoubleNA,0,0}
};
void CheckTemperatures() {
static unsigned long lastTempRequest = 0;
static int resolution = 12;
static unsigned long delayInMillis = 0;
static int LastSensorIndex = 0;
double Temperature;
if ( SensorsData[LastSensorIndex].Instance==InvalidInstance ) {
LastSensorIndex=0;
lastTempRequest=0;
Serial.println("");
}
if ( lastTempRequest == 0 ) { // Initialization
sensors.begin();
sensors.setWaitForConversion(false);
sensors.requestTemperatures();
delayInMillis = 750 / (1 << (12 - resolution));
lastTempRequest = millis();
}
if (millis() - lastTempRequest >= delayInMillis) // waited long enough??
{
Temperature = sensors.getTempC(SensorsData[LastSensorIndex].OneWireAddress);
if (Temperature>-120) {
SensorsData[LastSensorIndex].Temperature=CToKelvin(Temperature+SensorsData[LastSensorIndex].Offset);
SensorsData[LastSensorIndex].FailCount=0;
Serial.print(" Temperature ("); Serial.print(SensorsData[LastSensorIndex].Instance); Serial.print("):");
Serial.println(KelvinToC(SensorsData[LastSensorIndex].Temperature), resolution - 8);
} else {
SensorsData[LastSensorIndex].FailCount++;
if (SensorsData[LastSensorIndex].FailCount++ > MaxSensorFailCount ) {
SensorsData[LastSensorIndex].Temperature=N2kDoubleNA;
}
}
LastSensorIndex++;
// immediately after fetching the temperature we request a new sample in the async modus
sensors.requestTemperatures();
delayInMillis = 750 / (1 << (12 - resolution));
lastTempRequest = millis();
}
}
Timo & TyphoonSB, sorry to chip in,
I also had issues with my v.long code taking something like 3.5sec to run a full loop and maretron DSM250 display timing out and flashing the values in-out... Following some testing I managed to drop that down to 800-1000ms but not down to 100 needed for some PGNs. So using Teensy and P. Stoffregen OneWire lib (there's a fork specifically for ESP chips btw) I managed to get the times down to 100ms easily.
code extract:
//temp sensor includes
#include <OneWire.h> // using teensy Paul Stoffregen lib
#include <DallasTemperature.h> // split requestTemperaturesByIndex() to getTempCByIndex() to avoid 750ms delay
// Gearbox oil Temp sensor (DS18B20) includes
// Setup a oneWire instance to communicate with any OneWire devices
const unsigned char GBoxOilTemp = A18;
OneWire gboiltemp(GBoxOilTemp);
// Pass our oneWire reference to Dallas Temperature
DallasTemperature gboilsensor(&gboiltemp);
float TransOilTemp;
float TransOilTempB;
setup:
gboilsensor.begin();
and on the loop:
gboilsensor.requestTemperaturesByIndex(0);
TransOilTemp = gboilsensor.getTempCByIndex(0);
Serial.println("Transmission Oil Temp: " + String(TransOilTemp));
considering it really works, anything fundamentally wrong with this Timo?
cheers
V.
Something...
For 1-wire temperature sensors you need to request conversion and then wait for 750 ms (for 12 bit sensors) before you can read temperatures. The OneWire and DallasTemperature will as default do it in blocking way. Like you would have: RequestTemperature(); delay(750); ReadTemperature(); So your code will not do much during delay. In ESP it may do task switching, but not on Teensy or Arduinos. DallasTemperature also offers "async" way as I used in my code example. The idea is just send request and do other things until 750 ms has been spent and you can read data. With that method code will be blocked only about 10 ms at time, which is acceptable in simple temperature sender. In complex system I used the chip I mentioned. I also rewrote its handling with i2c_t3c, which gives interrupt, when transfer is ready. In this way code spends some us with 1-wire.
So read the code above carefully and modify it for your system so you will get much better performance.
some short update from my site ....
in my test all cummunication is commented out .... no no interuption from these (till now)
Timo, the definition of interupt pin was a good topic.... so I defined it .... and then the uC runs into an error....
ISR not in IRAM!
User exception (panic/abort/assert)
Abort called
>>>stack>>>
ctx: cont
sp: 3ffffe60 end: 3fffffc0 offset: 0000
3ffffe60: 3ffee5bc afbdfa76 00000000 00000000
3ffffe70: 000000fe 00000000 00000000 00000000
3ffffe80: 00000000 00000000 00000000 00ff0000
3ffffe90: 5ffffe00 5ffffe00 3ffee82c 00000000
3ffffea0: 00000002 00000003 3ffef574 4020c8de
3ffffeb0: 401005ce 0000001f 3ffee5bc 4020c8f4
3ffffec0: 00989680 00000001 3ffef574 4020cdf9
3ffffed0: 00000000 0000001f 3ffef5e0 40206d17
3ffffee0: 0000000f 00000001 3ffee5bc 00000000
3ffffef0: 3ffee5c4 3ffef5e0 3ffef574 4020cea8
3fffff00: 3ffee5c4 3ffef5e0 3ffef574 40207ce9
3fffff10: 00000000 00000000 00000010 00000001
3fffff20: 00000000 3fff0c4c 3ffef574 40204bba
3fffff30: 3fff06bc 00000000 00000000 00000000
3fffff40: 00000098 00000001 3ffef574 00000000
3fffff50: 3ffee5c5 3ffee5e0 3ffee5a0 402015c5
3fffff60: 00000000 0000ffff 000000ff 00000000
3fffff70: 40213a80 00000000 40201188 4020108c
3fffff80: 00000002 feefeffe feefeffe feefeffe
3fffff90: feefeffe feefeffe feefeffe 3ffee7cc
3fffffa0: 3fffdad0 00000000 3ffee78c 4020c4d0
3fffffb0: feefeffe feefeffe 3ffe8500 40100ed9
<<<stack<<<
so I changed in NMEA2000_mcp.cpp
void Can1Interrupt() {
pNMEA2000_mcp1->InterruptHandler();
}
to
ICACHE_RAM_ATTR void Can1Interrupt() {
pNMEA2000_mcp1->InterruptHandler();
}
now it´s not running into an overflow.... but need to test it on the Boat, to say if my problem is solved now
I could add that as define for ESP8266, so default library will compile.
that would be fine .... but let me check if it´s work on the NMEA network on the Boat. I will check that later today.
Please test with:
...
#if defined(ESP8266)
ICACHE_RAM_ATTR void Can1Interrupt();
#else
void Can1Interrupt();
#endif
...
//*****************************************************************************
#if defined(ESP8266)
ICACHE_RAM_ATTR void Can1Interrupt() {
#else
void Can1Interrupt() {
#endif
pNMEA2000_mcp1->InterruptHandler();
}
Something...
For 1-wire temperature sensors you need to request conversion and then wait for 750 ms (for 12 bit sensors) before you can read temperatures. The OneWire and DallasTemperature will as default do it in blocking way. Like you would have: RequestTemperature(); delay(750); ReadTemperature(); So your code will not do much during delay. In ESP it may do task switching, but not on Teensy or Arduinos. DallasTemperature also offers "async" way as I used in my code example. The idea is just send request and do other things until 750 ms has been spent and you can read data. With that method code will be blocked only about 10 ms at time, which is acceptable in simple temperature sender. In complex system I used the chip I mentioned. I also rewrote its handling with i2c_t3c, which gives interrupt, when transfer is ready. In this way code spends some us with 1-wire.
So read the code above carefully and modify it for your system so you will get much better performance.
thanks Timo, looks v.similar to the WaitForConversion2 asynchronous example that comes with DallasTemperature library. Will convert my code this way.
V.
Hi Timo,
I tryed it out, and it seems to work now. Interupts are triggered, and the node is show as it should.
I created already a pullrequest aginst your mcp lib.
Thanks for solving this problem!
Did you remove periodic? NMEA2000.SendProductInformation(); NMEA2000.SendIsoAddressClaim();
Yes I did!