Cruisers Forum
 


Reply
  This discussion is proudly sponsored by:
Please support our sponsors and let them know you heard about their products on Cruisers Forums. Advertise Here
 
Thread Tools Search this Thread Rate Thread Display Modes
Old 29-03-2018, 13:43   #1
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Arduino ESP8266 stream wifi

Hi, I hope this is the right forum and someone has already done something similar. I want to use an ESP8266 and BMP280 to broadcast barometric pressure and temperature data (formatted as NMEA 0183 sentences) over the ship's wifi network to OpenCPN. I understand OpenCPN reads $IIXDR NMEA 0183 sentences. My problem is coding the Arduino/ESP8266 wifi server.

I have the ESP8266 figured out and can load/run examples. In the Arduino code setup, I connect to the wifi network,
// start connecting with our wifi network
WiFi.begin(ssid, password);
// loop as long we are not connected
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
This gives the ESP8266 a wifi address. There are examples of a simple web-server, responding to HTTP requests. These examples work OK. I don't really want a server, waiting for requests. Instead, I want to broadcast the BMP280 NMEA data.

I thought I could code UDP write data inside the loop. I don't really understand how OpenCPN "listens" for serial data over wifi UDP or TCP port.

// broadcast udp package
udp.beginPacket(broadcastIp, 5005);
udp.write("$IIMDA,30,I,1.02,B,10.1,C,,C,,,,C, 158.69,T,,M,3.89,N,2,M*09\n");
udp.endPacket();
delay(1000);

Any coding help or examples would be most appreciated.
Thanks
Don
Capt.Don is offline   Reply With Quote
Old 29-03-2018, 14:06   #2
Registered User
 
rgleason's Avatar

Join Date: Mar 2012
Location: Boston, MA
Boat: 1981 Bristol 32 Sloop
Posts: 17,625
Images: 2
Re: Arduino ESP8266 stream wifi

Capt Don, hope you'll continue discussion here, but I think you should take a look at King Tides Blog websitee
https://kingtidesailing.blogspot.com/

And also at our Supplementary Hardware Book, (Opencpn Wiki has 4 books) there should be some examples. Sorry I don't have a direct example but those are the two resources that might be helpful.
rgleason is offline   Reply With Quote
Old 29-03-2018, 14:41   #3
Registered User

Join Date: Nov 2012
Location: Orust Sweden
Boat: Najad 34
Posts: 4,139
Re: Arduino ESP8266 stream wifi

Don


First you've to calculate the checksum correct. Your sentence would read: $IIMDA,30,I,1.02,B,10.1,C,,C,,,,C.69,T,,M,3.89,N,2 ,M*39
After the checksum you need \r\n.
It's normal to use port 10110 for NMEA although this has nothing to do with the function as such. And UDP would be fine for OCPN.
Attached is simple c++ code I once used to read a serial and send to UDP_IP. Maybe u can use some on your Arduino as well






Attached Files
File Type: doc GGAtoTTM.doc (11.7 KB, 126 views)
Hakan is offline   Reply With Quote
Old 29-03-2018, 15:22   #4
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Re: Arduino ESP8266 stream wifi

I guess where I'm confused is whether this should be (1) UDP server, (2) UPD client or (3) direct socket write. I'm leaning towards socket write.

What I'm trying to do is identical to those folks using Raspberry Pi and streaming serial data, though with a $3.00 ESP8266!

I'll look at the examples provided. Thanks
Don
Capt.Don is offline   Reply With Quote
Old 29-03-2018, 15:46   #5
cruiser

Join Date: Nov 2007
Location: Probably in an anchorage or a boatyard..
Boat: Ebbtide 33' steel cutter
Posts: 5,030
Re: Arduino ESP8266 stream wifi

Udp.Write needs to be sending a char array, just text won't work. I've had it working but on the move so not sure I can find the code,
Ive code somewhere to calc the checksum as well..
conachair is offline   Reply With Quote
Old 29-03-2018, 17:01   #6
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Re: Arduino ESP8266 stream wifi

I think I have a working prototype. The trick seems to be to setup a UDP client and server. The server listens for a client connection(s) and then sends the NMEA sentence to all clients. This was based off the ESP8266 WiFiTelnetToSerial - Example Transparent UART to Telnet Server for esp8266 example. I removed all the telnet send code and was left with a very simple server listen for connects and client send NMEA. Here's the prototype code,


#include <ESP8266WiFi.h>

#define MAX_SRV_CLIENTS 3
const char* ssid = ".....";
const char* password = "....";

WiFiServer server(8080); // Wifi server port
WiFiClient serverClients[MAX_SRV_CLIENTS]; // Array of clients

// Setup
void setup() {

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED)
delay(500);

server.begin();
server.setNoDelay(true);
}

// Loop
void loop() {
uint8_t i;
if (server.hasClient()){
for(i = 0; i < MAX_SRV_CLIENTS; i++){
if (!serverClients[i] || !serverClients[i].connected()) {
if(serverClients[i]) serverClients[i].stop();
serverClients[i] = server.available();
continue;
}
}
//no free spot
WiFiClient serverClient = server.available();
serverClient.stop();
}

// Insert pressure/temp here
char cbuf[100];
strncpy(cbuf,"$IIMDA,30,I,1.02,B,10.1,C,,C,,,,C.69 ,T,,M,3.89,N,2,M*39\r\n",100);

//Broadcast to all clients
for(i = 0; i < MAX_SRV_CLIENTS; i++){
if (serverClients[i] && serverClients[i].connected()) {
serverClients[i].write(cbuf,100);
}
}
delay(1000);
}



Next steps (1) refine this code (bit messy), (2) add the BMP280 barometer/temperature, (3) compute NMEA checksum.
Thank for your help,
Don
Attached Thumbnails
Click image for larger version

Name:	2018-03-29_170301.jpg
Views:	506
Size:	162.9 KB
ID:	167361  
Capt.Don is offline   Reply With Quote
Old 29-03-2018, 19:17   #7
cruiser

Join Date: Nov 2007
Location: Probably in an anchorage or a boatyard..
Boat: Ebbtide 33' steel cutter
Posts: 5,030
Re: Arduino ESP8266 stream wifi

Checksum calc routines -





String parseNmea(String nmeaBad)
{
//Serial.print(nmeaBad);
nmeaGood=nmeaBad.substring(1, nmeaBad.indexOf("*")); //cut of the leading "$" and the bad checksum

int CheckSum=(checkSum(nmeaGood)); //create a good checksum
nmeaGood="$"+nmeaGood+ "*" + String(CheckSum, HEX) + "\r\n"; // make the good nmea string

// Serial.println(nmeaGood);
return nmeaGood;
}


//---create a nmea checksum
char checkSum(String theseChars) {
char check = 0;
// iterate over the string, XOR each byte with the total sum:
for (int c = 0; c < theseChars.length(); c++) {
check = char(check ^ theseChars.charAt(c));
}
// return the result
return check;
}
conachair is offline   Reply With Quote
Old 29-03-2018, 20:42   #8
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Re: Arduino ESP8266 stream wifi

Digging deeper, it looks like OpenCPN prefers NMEA 0183 XDR sentences. For example, using XDR to combine temperature and pressure,

"$IIXDR,C,70.2,F,TempAir,P,1.03,B,Barometer*"

It is interesting that OpenCPN accepts temperature as Fahrenheit (F) and Celsius (C) and displays properly in the dashboard. This may be a lack of validation, but works OK!

However, it seems OpenCPN only accepts pressure units of 'B' as mBar. Is there a way to set to InHg? (My onboard antique barometer shows InHg!).

Thanks in advance -- I won't have a chance to look at this till next week. Having fun!

Don
Capt.Don is offline   Reply With Quote
Old 30-03-2018, 00:55   #9
cruiser

Join Date: Nov 2007
Location: Probably in an anchorage or a boatyard..
Boat: Ebbtide 33' steel cutter
Posts: 5,030
Re: Arduino ESP8266 stream wifi

Can't remember the dashboard reading xdr, roll on the day when it's signalk!
conachair is offline   Reply With Quote
Old 30-03-2018, 16:14   #10
Registered User
 
rgleason's Avatar

Join Date: Mar 2012
Location: Boston, MA
Boat: 1981 Bristol 32 Sloop
Posts: 17,625
Images: 2
Re: Arduino ESP8266 stream wifi

Don't know if this will help, but nmeaconverter_pi has recently been updated and released by Dirk. It now accepts wildcards too. The nmeaconverter_pi manual has some good examples where units are converted. I am sure you could enter the necessary conversion formulas and nmeaconverter will do the job.

https://opencpn.org/wiki/dokuwiki/do...nmea_converter
rgleason is offline   Reply With Quote
Old 04-04-2018, 07:38   #11
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Re: Arduino ESP8266 stream wifi

Shifting to the OpenCPN, Dashboard, Barometric History graph display,

1) The graph appears to show about 8 hours time - is there a setting for the time display duration? Is 8 hours sufficient for seeing trends is change in barometric pressure? I would think a longer duration, say 24 hours, would be preferred.

2) What causes the vertical lines at what appears to be random points in time? It would be nice if the x-axis, time, would display legend every hour / half-hour instead of arbitrary times (23:10, 00:20, 00:55...).

3) OpenCPN appears to poll for NMEA data stream every 10 seconds. What is the best interval for the Arduino/ESP8266 to broadcast the NMEA data? Temperature and barometer readings every 10 seconds is a bit extreme! I would think every few minutes would be fine.

The concept of streaming data to OpenCPN is great! I will publish my Arduino code shortly!

Thanks
Don
Attached Thumbnails
Click image for larger version

Name:	hPa-history.jpg
Views:	116
Size:	176.4 KB
ID:	167631  
Capt.Don is offline   Reply With Quote
Old 04-04-2018, 08:21   #12
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Re: Arduino ESP8266 stream wifi

And the code -- enjoy!
/*
Intuition's temperature and barometer NMEA over wifi

Usage:
Connect client to gateway IP, with x.x.x.255

Connections:

ESP-12-E BMP280 FTDI Other
-------- ------ ---- ----------
TX RXI
RX TXD
GPIO5 SCL
GPIO4 SDA
GPIO0 . . . . . . . . . . .SPDT ->GND Program, ->VCC Flash
GPIO2
GPIO15 . . . . . . . . . . GND
GND . . . .GND . . .GND . .GND

RST . . . . . . . . . . . .SPST ->GND Reset (don't need)
ACD
EN . . . . . . . . . . . . VCC
GPIO16
GPIO14
GPIO12
GPIO13
VCC . . . .VCC . . . . . . VCC

Flash logic,
Pins Normal Flash
----- ------ -----
GPIO0 VCC GND
GPIO2 VCC VCC
GPI015 GND GND

*/

#include <ESP8266WiFi.h> // ESP8266 library, http://arduino.esp8266.com/stable/pa...com_index.json
#include <BMP280.h> // BMP280 library, https://github.com/mahfuz195/BMP280-Arduino-Library

//************************************************** ******
// Global variables
//************************************************** ******
#define MAX_CLIENTS 3 // Number of simultaneous broadcast clients
#define DELAY_MS 1000 // MS to wait
#define DELAY_COUNT 5 // Counter of DELAY_MS to wait, 3600 is 1 hour
#define SSID "..." // Boat wifi network
#define PASS "..." // Boat wifi password
#define PORT 8080 // Port to connect
#define MYIP 254 // Fixed IP 3rd Octet
#define LED 2 // Built-in LED, on when broadcast

//--------------------------------------------------------
// ESP8266 WiFi variables
//--------------------------------------------------------
WiFiServer server(PORT); // Server/port
WiFiClient clients[MAX_CLIENTS]; // Array of clients

//--------------------------------------------------------
// BMP280 variables
//--------------------------------------------------------
BMP280 bmp; // BMP280 I2C
byte BMP280 = 1; // Is the BMP280 wired? 0=no, 1=yes

//************************************************** ******
// Support functions
//************************************************** ******

//--------------------------------------------------------
// nmea_checksum - create NMEA checksum
// Expecting NMEA string that begins with '$' and ends with '*'
// $IIMDA,30.1,I,1.02,B,20.1,C,,C,,,,,,,,,,,,M*
// $IIXDR,C,70.2,F,TempAir,P,1.03,B,Barometer*
//--------------------------------------------------------
String nmea_checksum(String s) {
char checksum = 0;

if( s[0]=='$' && s[s.length()-1]== '*') {
for(int i=1; i<s.length()-1;i++) {
checksum = checksum xor s[i];
}
}
return String(checksum,HEX);
}

//--------------------------------------------------------
// make_nmea_xdr - create NMEA XDR Sentence (OpenCPN recognizes)
// $IIXDR,C,70.2,F,TempAir,P,1.03,B,Barometer*
//--------------------------------------------------------
String make_nmea_xdr(float temp_c, float pres_mb) {
String xdr;
xdr = "$IIXDR,C," + String(temp_c,1) + ",F,TempAir,P," + String(pres_mb,6) + ",B,Barometer*";
xdr += nmea_checksum(xdr);
xdr += "\r\n";
return xdr;
}

//--------------------------------------------------------
// Convert pressure routines
//--------------------------------------------------------
float cvt_pres_inHg(float pres_mb) {
return pres_mb / 33.8639;
}
float cvt_pres_mbar(float pres_mb) {
return pres_mb / 100.0;
}

//--------------------------------------------------------
// Convert temperature C to F
//--------------------------------------------------------
float cvt_temp_f(float temp_c) {
return temp_c * 9.0 / 5.0 + 32.0;
}

//************************************************** ******
// Setup
//************************************************** ******
void setup() {

pinMode(LED, OUTPUT); // Initialize the LED pin as an output

// Check if valid BMP280 sensor
if (!bmp.begin()) {
BMP280 = 0;
}

bmp.setOversampling(4);


// Initialize WiFi ethenet library and network settings
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

// Change the 3rd Octet to known value so clients can connect
IPAddress local_ip = WiFi.localIP();
local_ip[3] = MYIP; // 254
WiFi.config(local_ip, WiFi.gatewayIP(), WiFi.subnetMask());

// Create server and listen for connections
server.begin();
server.setNoDelay(true); // disable sending small packets

}

//************************************************** ******
// Loop
//************************************************** ******
void loop() {

double temp_c;
double pres_mb;

String xdr;
char cbuf[82];
uint8_t i;

// If we don't have BMP280, no reason to run
if(!BMP280) exit(0);

// Broadcast pressure/temperature to connected clients
if (server.hasClient()) {
for(i = 0; i < MAX_CLIENTS; i++) {

// DM ** added check for clients[i].status==0 to reuse connections
if ( !(clients[i] && clients[i].connected() ) || clients[i].status()==0 ) {
if(clients[i]) {
clients[i].stop(); // make room for new connection
}
clients[i] = server.available();
continue;
}
}

// No free spot or exceeded MAX_CLENTS so reject incoming connection
server.available().stop();
}

// Read BMP280 temperature, pressure
char result = bmp.startMeasurment();
if(result != 0){
delay(result);
result = bmp.getTemperatureAndPressure(temp_c,pres_mb);
}

// Make NMEA XDR sentence with temperature and pressure
// OpenCPN expects hPa, e.g. 1.0128
xdr = make_nmea_xdr(cvt_temp_f(temp_c), pres_mb / 1000.0);
xdr.toCharArray(cbuf,xdr.length() + 1);

// Broadcast NMEA sentence to all clients
digitalWrite(LED, LOW);
for(i = 0; i < MAX_CLIENTS; i++) {
if (clients[i] && clients[i].connected()) {
clients[i].write(cbuf,xdr.length());
}
}

digitalWrite(LED, HIGH);

// Wait for next reading
for(int c=0; c < DELAY_COUNT; c++) {
delay(DELAY_MS);
}
}
Capt.Don is offline   Reply With Quote
Old 04-04-2018, 08:28   #13
Registered User

Join Date: Nov 2012
Location: Orust Sweden
Boat: Najad 34
Posts: 4,139
Re: Arduino ESP8266 stream wifi

Don..


re: OpenCPN appears to poll for NMEA data stream every 10 seconds.

>> Well, O is certainly not that slow. Less than a second is a better approximation,


re:What is the best interval for the Arduino/ESP8266 to broadcast the NMEA data?
>> Whatever suits your data. There are timeouts for certain important data like position, heading, speed, depth etc. Others will in Dashboard show latest until new data is received.
Hakan is offline   Reply With Quote
Old 04-04-2018, 09:49   #14
cruiser

Join Date: Nov 2007
Location: Probably in an anchorage or a boatyard..
Boat: Ebbtide 33' steel cutter
Posts: 5,030
Re: Arduino ESP8266 stream wifi

Quote:
Originally Posted by Capt.Don View Post
Shifting to the OpenCPN, Dashboard, Barometric History graph display,

1) The graph appears to show about 8 hours time - is there a setting for the time display duration? Is 8 hours sufficient for seeing trends is change in barometric pressure? I would think a longer duration, say 24 hours, would be preferred.
For graphing node red is streets ahead, it will, run happily in the background, easy to save everything to a database as well. On a Raspberry Pi it's cheap and SI, please to add voltage, temperature sensors as well, probably mean buying a USB i2c/1wire board. But we'll worth thinking about since you've started. Pressure is useful boat graphed engine temperature and battery voltage is just great

Here's a similar project to yours..

https://sdfjkl.org/blog/2017-08-09-nanobaro/
conachair is offline   Reply With Quote
Old 04-04-2018, 09:59   #15
Registered User
 
Capt.Don's Avatar

Join Date: Aug 2010
Posts: 961
Images: 1
Re: Arduino ESP8266 stream wifi

Node red looks interesting. I like the idea of connecting the various streams in a central database, and possibly moving out from OpenCPN.
Capt.Don is offline   Reply With Quote
Reply

Tags
wifi

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Arduino based Alternator Regulator Project wayne.b Electrical: Batteries, Generators & Solar 11 11-03-2021 10:16
Want to set up a boat WiFi system that connects through marina's wifi MV Wanderlust Marine Electronics 25 06-12-2016 12:45
Arduino software for navigation/boats vtomanov Navigation 2 11-09-2016 11:43
A DIY barograph based on an Arduino shield PauloOnArbutus Marine Electronics 5 23-01-2016 04:58

Advertise Here


All times are GMT -7. The time now is 22:37.


Google+
Powered by vBulletin® Version 3.8.8 Beta 1
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Social Knowledge Networks
Powered by vBulletin® Version 3.8.8 Beta 1
Copyright ©2000 - 2024, vBulletin Solutions, Inc.

ShowCase vBulletin Plugins by Drive Thru Online, Inc.