This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm whether you accept or reject these cookies being set.

A cookie will be stored in your browser regardless of choice to prevent you being asked this question again. You will be able to change your cookie settings at any time using the link in the footer.

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
MPU-9250 and BME280 to OpenPlotter
#1
I've been trying for a while to connect a MPU-9250 and a BME280 to a Raspberry pi 4 (4gb) running the last version of OpenPlotter. 

1) First I've been trying to have both sensor in parallel in I2C, the IMU is located next to the RPI, but the BME280 is outside and I need to run a 2m long cable, so it's hard to get consistent I2C data. I had to play a bit with cable type and tried several values of pull-up resistors. In the end I get a result that is near acceptable, but I still get data corruption after about 24hours generally. So this is not reliable enough for sailing and I cannot reduce the cable length of my setup. Are there reliable solutions to run several I2C sensors in parallels?

2) I tried another idea and connected the BME280 to an arduino outputting the I2C data in NMEA0183 XDR sentences via USB to OpenCPN (see code here https://forums.ybw.com/index.php?threads/nanobaro-nmea-usb-barometric-sensor-easy-diy-electronics-project.484828). It works well and I can get the NMEA XDR sentences to the RPI's OpenCPN, but I cannot get it to SignalK. I tried both adding the USB NMEA0183 connection with the OpenPlotter interface as well as in Signal K directly, setting NMEA0183 and baud rate 4800, similar setup as I have in OpenCPN, but the data doesn't get to the server. I'm not familiar with connection types and ports, is there a way to get NMEA data directly via USB to SignalK as I do in OpenCPN?

I'd appreciate some help, it seems like a setup a lot of people would have, and would be interesting to know how others do.
Reply
#2
1) You can run several I2C sensors without problems but only using the appropriate cable lenght

2) You should remove all your opencpn connections and use only tcp localhost 10110. This is the Signal K NMEA output. You should make all your USB connections in Signal K, use the openplotter-seria app to help creating signal k connections. The problem is that XDR sentences can not be parsed by Signal K due to its non standard format. Can this device generate Signal k data?
Reply
#3
I eventually did remove all other connections in OpenCPN and used OpenPlotter Serial app to create an interface for the arduino data. It is partly successful as the XDR sentence from the arduino is forwarded to other devices in NMEA, however as you said it is not parsed in SignalK.
I looked for ways to generate SignalK sentences (instead of NMEA) with the arduino but it seems complex and I found poor documentation.
Is there someone with experience with this? I think a good tutorial about generating code for SignalK data could benefit a lot.
Reply
#4
(2020-06-17, 09:04 AM)Barentsailor Wrote: Is there someone with experience with this? I think a good tutorial about generating code for SignalK data could benefit a lot.

You could try this :-
At the top paste this line >

Code:
#include "ArduinoJson.h"

then 
Code:
void sendSigK(String sigKey, float data)
{

   DynamicJsonBuffer jsonBuffer;
   String deltaText;

   //  build delta message
   JsonObject &delta = jsonBuffer.createObject();

   //updated array
   JsonArray &updatesArr = delta.createNestedArray("updates");
   JsonObject &thisUpdate = updatesArr.createNestedObject();   //Json Object nested inside delta [...
   JsonArray &values = thisUpdate.createNestedArray("values"); // Values array nested in delta[ values....
   JsonObject &thisValue = values.createNestedObject();
   thisValue["path"] = sigKey;
   thisValue["value"] = data;

   thisUpdate["Source"] = "ESP32";

   delta.printTo(Serial);
   Serial.println();
 
}
 Cut and paste above void loop() then in the main loop below 

'temp = pressure.readTemperature();

  press = pressure.readPressure();'

paste >

Code:
sendSigK("environment.outside.pressure", press);
sendSigK("environment.outside.temperature", temp );

Untested but might work first time, maybe.... Smile
Reply
#5
PaddyB, amazing, it worked on the first try! :-) Nearly, literally just had to downgrade to ArduinoJson.h V5 library instead of the V6 :-)

I also added a line to get the humidity reading for the BME280, and a correction to have the temperature in Kelvin. For BMP280 just remove this line and replace the library by the BMP one.
I didn't have time to go through the code that now is a mix between Nanobaro and PaddyB codes with some redundancy, but it runs very smooth as it is, SignalK is parsing all the data and exporting to all my devices.

It is a great solution for anyone having an I2C IMU and want to have a BME/BMP280 I2C on a good location running long cable length. Just run an USB cable to the arduino, it will act as power and serial data.

Here is the code if someone wanna use it as it is or try to make it more "pretty":

Code:
#include <Adafruit_BME280.h>
#include <Wire.h>
#include "ArduinoJson.h"

#define NMEA_TALKER_ID "WI" // Weather Instruments
#define NMEA_DELAY 1 // Send data every 1 seconds

// meters above mean sea level
#define ALTITUDE 1
// How many samples to take per iteration
#define PRESS_OVERSAMPLING 3

//create a new Adafruit_BME280 class object called pressure.
Adafruit_BME280 pressure;

const byte buff_len = 90;
char CRCbuffer[buff_len];

byte nmea_crc(String msg) {
 // NMEA CRC: XOR each byte with previous for all chars between '$' and '*'
 char c;
 int i;
 byte crc = 0;
 for (i = 0; i < buff_len; i++) {
   crc ^= msg.charAt(i); // XOR
 }
 return crc;
}

void setup() {
 // put your setup code here, to run once:

 Serial.begin(4800);

 if (!pressure.begin(0x76) ) {
   nmea_txt("BMP280 init fail");
   exit(1);
 }
 nmea_txt("Nanobaro ready.");

}

void nmea_send(String sentence, String params) {
 String msg = String(NMEA_TALKER_ID) + sentence + params;

 msg.toCharArray(CRCbuffer, sizeof(CRCbuffer)); // put complete string into CRCbuffer
 int crc = nmea_crc(CRCbuffer);

 if (crc < 16) msg += "0"; // pad with leading 0
 String hexcrc = String(crc, HEX);
 hexcrc.toUpperCase();
 Serial.println("$" + msg + "*" + hexcrc);
}

void nmea_txt(String text) {
 nmea_send("TXT", ",01,01,01," + text);
}

void sendSigK(String sigKey, float data)

{
  DynamicJsonBuffer jsonBuffer;
  String deltaText;

  //  build delta message
  JsonObject &delta = jsonBuffer.createObject();

  //updated array
  JsonArray &updatesArr = delta.createNestedArray("updates");
  JsonObject &thisUpdate = updatesArr.createNestedObject();   //Json Object nested inside delta [...
  JsonArray &values = thisUpdate.createNestedArray("values"); // Values array nested in delta[ values....
  JsonObject &thisValue = values.createNestedObject();
  thisValue["path"] = sigKey;
  thisValue["value"] = data;

  thisUpdate["Source"] = "ESP32";

  delta.printTo(Serial);
  Serial.println();
}

void loop() {
 
 float temp, press, hum;
   
 temp = pressure.readTemperature();
 press = pressure.readPressure();
 hum = pressure.readHumidity();
 
sendSigK("environment.outside.pressure", press);
sendSigK("environment.outside.temperature", temp + 273.5 );
sendSigK("environment.outside.humidity", hum/100 );

 delay(NMEA_DELAY * 1000);
}
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)