ttlappalainen / NMEA2000_esp32

Inherited object for use NMEA2000 with ESP32 boards
66 stars 40 forks source link

Sketches not compiling (FreeRTOS.h) Wemos D1 Mini #21

Closed merco closed 6 months ago

merco commented 6 months ago

In arduino ide 1.8.19 i get this error during compiling for Wemos D1 Mini

With this setting: #define USE_N2K_CAN 7

_Alternatives for freertos/FreeRTOS.h: [] ResolveLibrary(freertos/FreeRTOS.h) In file included from C:\Users\mercanti\Documents\Arduino\libraries\NMEA2000-master/NMEA2000_CAN.h:277, -> candidates: [] from C:\DAVIDE\nmea2000\testbrdge\testbrdge.ino:8: C:\Users\mercanti\Documents\Arduino\libraries\NMEA2000_esp32-master/NMEA2000esp32.h:39:10: fatal error: freertos/FreeRTOS.h: No such file or directory 39 | #include "freertos/FreeRTOS.h" | ^~~~~ compilation terminated.

Ideas?

ttlappalainen commented 6 months ago

Wemos D1 mini is ESP8266 not ESP32. With ESP8266 you can only use mcp_can driver (https://github.com/ttlappalainen/NMEA2000_mcp and https://github.com/ttlappalainen/CAN_BUS_Shield) and some MCP2515 based board.

merco commented 6 months ago

Ok I understand. My intent was only to use wemos to read the data from serial (using the simulator on the PC) and to send it to the network via tcp/ip or other, so no use of CAN directly. What example can I try to compile? Thank you

ttlappalainen commented 6 months ago

Then you do not use tNMEA2000 at all. You just use library module ActisenseReader and tActisenseReader class, set handler for it and forward message to stream you want. If you need to send it in different format, you need to parse messages with N2kMessages module functions or for SeaSmart format there is SeaSmart module.

#include <N2kMsg.h>
#include <ActisenseReader.h>

...
tActisenseReader ActisenseReader;
...

void setup() {
...
  ActisenseReader.SetMsgHandler(HandleStreamN2kMsg);
...
}

void HandleStreamN2kMsg(const tN2kMsg &N2kMsg) {
  NMEA2000.SendInActisenseFormat(FwdStream);
}

FwdStream can be e.g., UDPStream

merco commented 6 months ago

I'm trying to compile this...

#include <N2kMsg.h>
#include <NMEA2000.h>
#include <NMEA2000_CAN.h>
#include <ActisenseReader.h>

tActisenseReader ActisenseReader;

// Define READ_STREAM to port, where you write data from PC e.g. with NMEA Simulator.
#define READ_STREAM Serial       
// Define ForwardStream to port, what you listen on PC side. On Arduino Due you can use e.g. SerialUSB
#define FORWARD_STREAM Serial    

Stream *ReadStream=&READ_STREAM;
Stream *ForwardStream=&FORWARD_STREAM;

void setup() {
  // Define buffers big enough
  NMEA2000.SetN2kCANSendFrameBufSize(150);
  NMEA2000.SetN2kCANReceiveFrameBufSize(150);
  NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
                                 100, // Manufacturer's product code
                                 "Arduino Gateway",  // Manufacturer's Model ID
                                 "1.0.0.2 (2018-01-10)",  // Manufacturer's Software version code
                                 "1.0.0.0 (2017-01-06)" // Manufacturer's Model version
                                 );
  NMEA2000.SetDeviceInformation(1, // Unique number. Use e.g. Serial number.
                                130, // Device function=Analog to NMEA 2000 Gateway. 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
                                25, // Device class=Inter/Intranetwork Device. 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
                                2046 // Just choosen free from code list on https://web.archive.org/web/20190529161431/http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
                               );

  if (ReadStream!=ForwardStream) READ_STREAM.begin(115200);
  FORWARD_STREAM.begin(115200);
  NMEA2000.SetForwardStream(ForwardStream); 
  NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode);
   NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show bus data in clear text
  if (ReadStream==ForwardStream) NMEA2000.SetForwardOwnMessages(false); // If streams are same, do not echo own messages.

  // I originally had problem to use same Serial stream for reading and sending.
  // It worked for a while, but then stopped. Later it started to work.
  ActisenseReader.SetReadStream(ReadStream);
  ActisenseReader.SetDefaultSource(75);
  ActisenseReader.SetMsgHandler(HandleStreamN2kMsg); 

}
void HandleStreamN2kMsg(const tN2kMsg &N2kMsg) {
  NMEA2000.SendInActisenseFormat(ForwardStream);
}
void loop() {

  NMEA2000.ParseMessages();
  ActisenseReader.ParseMessages();
  //if ( Serial.available() ) { Serial.read(); } 
}

but i get this compile error

class tNMEA2000' has no member named 'SendInActisenseFormat' 51 | NMEA2000.SendInActisenseFormat(ForwardStream);

ttlappalainen commented 6 months ago

Sorry my mistake. Use N2kMsg.SendInActisenseFormat(FwdStream); and do not include #include or #include

merco commented 6 months ago

Thank you Timo now it compiles... but is I can't understand the usage. I've succesfully installed NMEASimulator and OpenSkipper. Now I would like to get data from NMEASimulator (\.\COMN2KIN) (com0com) \.\COM27 And get data via http web page (not with OpenSkipper) . I'm going to develop an android apk. I'm also using hub4com.exe --route=All:All \.\COM27 \.\COM4 (where COM4 is my USB/ESP8266 Wemos port)

With this sketch. (I Get always CAN Device Failed to Open)


// Demo: NMEA2000 library. Actisense NGT-1 compatible gateway. 
//   Sends all bus data to serial in Actisense format.
//   Send all data received from serial in Actisense format to the N2kBus, setting
//   data source to the gateway itself.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#include <Arduino.h>

#include <NMEA2000_CAN.h>  // This will automatically choose right CAN library and create suitable NMEA2000 object
#include <N2kMessages.h>
#include <ActisenseReader.h>
#include <Seasmart.h>
tActisenseReader ActisenseReader;

// Define READ_STREAM to port, where you write data from PC e.g. with NMEA Simulator.
#define READ_STREAM Serial       
// Define ForwardStream to port, what you listen on PC side. On Arduino Due you can use e.g. SerialUSB
#define FORWARD_STREAM Serial    

Stream *ReadStream=&READ_STREAM;
Stream *ForwardStream=&FORWARD_STREAM;

String HeaderPage = "<!DOCTYPE html><html><head><style> header { background: linear-gradient(to right, #1e5799 0%,#7db9e8 100%); color: #fff; padding:10px; text-align: center; vertical-align: middle; } body{ padding:15px; color: #5e5e5e; font-family: Helvetica,Arial,sans-serif; font-variant: small-caps; font-size:1em; text-align: center; } footer { background: linear-gradient(to left, #1e5799 0%,#7db9e8 100%); color: #fff; padding:10px; text-align: right; vertical-align: bottom; } h2 {  padding:10px; text-align: center; vertical-align: middle; font-size:2em; } </style></head><body><header>:: wemos ::</header>";
String FooterPage = "<footer>powerd by wemos</br>CC licence</footer></body></html>";
String rootPageBody = "<h2>Hello World</h2>";
String rootWebPage;
String datoLetto="";

ESP8266WebServer server(80);

const char *AP_ssid = "MyESP32";  // ESP32 as AP
const char *CL_ssid = "MyWLAN";   // ESP32 as client in network
const char *AP_password = "appassword";   // AP password. Must be longer than 7 characters
// Put IP address details here
IPAddress AP_local_ip(192, 168, 15, 1);  // Static address for AP
IPAddress AP_gateway(192, 168, 15, 1);
IPAddress AP_subnet(255, 255, 255, 0);

#define LED_BUILTINN D4

void setup() {
  // Define buffers big enough
  NMEA2000.SetN2kCANSendFrameBufSize(150);
  NMEA2000.SetN2kCANReceiveFrameBufSize(150);
  NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
                                 100, // Manufacturer's product code
                                 "Arduino Gateway",  // Manufacturer's Model ID
                                 "1.0.0.2 (2018-01-10)",  // Manufacturer's Software version code
                                 "1.0.0.0 (2017-01-06)" // Manufacturer's Model version
                                 );
  NMEA2000.SetDeviceInformation(1, // Unique number. Use e.g. Serial number.
                                130, // Device function=Analog to NMEA 2000 Gateway. 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
                                25, // Device class=Inter/Intranetwork Device. 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
                                2046 // Just choosen free from code list on https://web.archive.org/web/20190529161431/http://www.nmea.org/Assets/20121020%20nmea%202000%20registration%20list.pdf
                               );

  if (ReadStream!=ForwardStream) READ_STREAM.begin(115200);
  FORWARD_STREAM.begin(115200);
  NMEA2000.SetForwardStream(ForwardStream); 
  NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode);
  NMEA2000.SetForwardType(tNMEA2000::fwdt_Text); // Show bus data in clear text
  if (ReadStream==ForwardStream) NMEA2000.SetForwardOwnMessages(false); // If streams are same, do not echo own messages.

NMEA2000.SetMsgHandler(HandleStreamN2kMsg); // Also send all NMEA2000 messages in SeaSmart format

  // I originally had problem to use same Serial stream for reading and sending.
  // It worked for a while, but then stopped. Later it started to work.
  ActisenseReader.SetReadStream(ReadStream);
  ActisenseReader.SetDefaultSource(75);
  ActisenseReader.SetMsgHandler(HandleStreamN2kMsg); 

   pinMode(LED_BUILTINN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
    delay(1000);
     Serial.print("Hi, I'm Serial on standard TX RX pin! --> ");
  delay(1000);
      // Init wifi connection
    Serial.println("Start WLAN AP");         // WiFi Mode AP
    WiFi.mode(WIFI_AP);
    WiFi.softAP(AP_ssid, AP_password);
    delay(200);
    WiFi.softAPConfig(AP_local_ip, AP_gateway, AP_subnet);
    IPAddress IP = WiFi.softAPIP();
    Serial.println("");
    Serial.print("AP IP address: ");
    Serial.println(IP);

    startWebServer();
    digitalWrite(LED_BUILTINN, HIGH);

}

void handleRoot() { server.send(200, "text/html", rootWebPage); }

  void startWebServer() {
composeWebPage();
  server.on("/", handleRoot);
  server.begin();
  Serial.println("SERVER BEGIN!!");
}

void composeWebPage() {
  rootWebPage = HeaderPage;
  rootWebPage += rootPageBody+datoLetto;
  rootWebPage += FooterPage;
}  

#define MAX_NMEA2000_MESSAGE_SEASMART_SIZE 500 

void HandleStreamN2kMsg(const tN2kMsg &N2kMsg) {
 char buf[MAX_NMEA2000_MESSAGE_SEASMART_SIZE];
  if ( N2kToSeasmart(N2kMsg,millis(),buf,MAX_NMEA2000_MESSAGE_SEASMART_SIZE)==0 ) return;
  //SendBufToClients(buf);
String mystring(buf);
  datoLetto=mystring;
  composeWebPage();
//Serial.println("DATY");
  //Serial.println(buf);
}

void loop() {
  server.handleClient();
  NMEA2000.ParseMessages();
  ActisenseReader.ParseMessages();
  //if ( Serial.available() ) { Serial.read(); } 
}

I would expect to get some data in my root page with HandleStreamN2kMsg function that fill "datoLetto" variable. But the page remains the same.

ttlappalainen commented 6 months ago

If you plan to write Android app, where did you thought to parse data from messages? I also prefer to think to go to ESP32 (not S versions), which is more powerfull.

merco commented 6 months ago

Ok , now it works. I'm using websocket.

Another question: aobout time: how D2 44 51 10 become 07:36:16.149

273761490 (0x105144D2)

0: FF -- -- -- -- -- -- -- 11111111  SID=No linked PGNs
0: -- F0 -- -- -- -- -- -- ....0000  Source=GPS(0)
0: -- F0 -- -- -- -- -- -- 1111....  Reserved=1111
0: -- -- 70 4D -- -- -- -- ........  Date=2024-04-11
0: -- -- -- -- D2 44 51 10 ........  Time=07:36:16.149
ttlappalainen commented 6 months ago

It is longer story. Library has N2kMessages module, which has functions to parse most common messages. I prefer to use them or study from them how values will be constructed.

merco commented 6 months ago

Date is clear to me, bytes are inverted and days since 01-01-1970... But time? milliseconds?

ah ok

10 2^24 + 51 2^16 + 44 2^8 + D2 = xxxxxxxx
seconds= xxxxxx
0.0001