diff --git a/bbn_m5atomS3_lite_resistance_Ohm/NmeaChecksum.h b/bbn_m5atomS3_lite_resistance_Ohm/NmeaChecksum.h new file mode 100644 index 0000000..6db8331 --- /dev/null +++ b/bbn_m5atomS3_lite_resistance_Ohm/NmeaChecksum.h @@ -0,0 +1,23 @@ +#ifndef NmeaChecksum_h +#define NmeaChecksum_h + +#define NMEA_END_CHAR_1 '\r' + +/* + NMEA-0183 checksum + */ + +uint8_t nmea0183_checksum(const char *sentence); + +uint8_t nmea0183_checksum(const char *sentence) { + const char *n = sentence + 1; + uint8_t chk = 0; + /* While current char isn't '*' or sentence ending (newline) */ + while ('*' != *n && NMEA_END_CHAR_1 != *n && '\0' != *n) { + chk ^= (uint8_t) *n; + n++; + } + return chk; +} + +#endif diff --git a/bbn_m5atomS3_lite_resistance_Ohm/NmeaXDR.h b/bbn_m5atomS3_lite_resistance_Ohm/NmeaXDR.h new file mode 100644 index 0000000..aa2a0f6 --- /dev/null +++ b/bbn_m5atomS3_lite_resistance_Ohm/NmeaXDR.h @@ -0,0 +1,76 @@ +#ifndef NmeaXDR_h +#define NmeaXDR_h + +/* + XDR - Transducer Measurement + https://gpsd.gitlab.io/gpsd/NMEA.html#_xdr_transducer_measurement + https://www.eye4software.com/hydromagic/documentation/articles-and-howtos/handling-nmea0183-xdr/ + + Format: $--XDR,a,x.x,a,c--c, ..... *hh + Example: + + $HCXDR,A,171,D,PITCH,A,-37,D,ROLL,G,367,,MAGX,G,2420,,MAGY,G,-8984,,MAGZ*41 + $SDXDR,C,23.15,C,WTHI*70 + + Transducer Types: + A - Angular displacement + C - Temperature + D - Depth + F - Frequency + H - Humidity + N - Force + P - Pressure + R - Flow + B - Absolute humidity + G - Generic + I - Current + L - Salinity + S - Switch, valve + T - Tachometer + U - Voltage + V - Volume + could be more + + Unit of measurement + "" - could be empty! + A - Amperes + B - Bars | Binary + C - Celsius + D - Degrees + H - Hertz + I - liters/second + K - Kelvin | Density, kg/m3 kilogram per cubic metre + M - Meters | Cubic Meters (m3) + N - Newton + P - Percent of full range | Pascal + R - RPM + S - Parts per thousand + V - Volts + could be more +*/ + +/* + Bareboat Necessities Sensors NMEA-0183 XDR Sentences: + + NMEA-0183 Sender + BB + + Resistance Sensor: + + $BBXDR,G,137.2,O,Ohms_esp32*6E + $BBXDR,G,137.4,O,Ohms_esp32*68 + $BBXDR,G,139.7,O,Ohms_esp32*65 + $BBXDR,G,137.9,O,Ohms_esp32*65 + +*/ + +#include "NmeaChecksum.h" + +void gen_nmea0183_xdr(const char *nmea_fmt, float value) { + char nmea_part[82]; + snprintf(nmea_part, 76, nmea_fmt, value); + int checksum = nmea0183_checksum(nmea_part); + Serial.printf("%s*%02X\r\n", nmea_part, checksum); +} + +#endif diff --git a/bbn_m5atomS3_lite_resistance_Ohm/bbn_m5atomS3_lite_resistance_Ohm.ino b/bbn_m5atomS3_lite_resistance_Ohm/bbn_m5atomS3_lite_resistance_Ohm.ino new file mode 100644 index 0000000..4943ebf --- /dev/null +++ b/bbn_m5atomS3_lite_resistance_Ohm/bbn_m5atomS3_lite_resistance_Ohm.ino @@ -0,0 +1,56 @@ +#include +#include "NmeaXDR.h" + +// readVoltage is used to improve the linearity of the ESP32 ADC +// see: https://github.com/G6EJD/ESP32-ADC-Accuracy-Improvement-function +double readVoltage(byte pin) { + double reading = analogRead(pin); // Reference voltage is 3v3 so maximum reading is 3v3 = 4095 in range 0 to 4095 + if (reading < 1 || reading > 4095) return 0; + // return -0.000000000009824 * pow(reading,3) + 0.000000016557283 * pow(reading,2) + 0.000854596860691 * reading + 0.065440348345433; + return (-0.000000000000016 * pow(reading, 4) + 0.000000000118171 * pow(reading, 3) - 0.000000301211691 * pow(reading, 2) + 0.001109019271794 * reading + 0.034143524634089) * 1000; +} // Added an improved polynomial, use either, comment out as required + +enum ResistanceConfiguration { + UPSTREAM, + DOWNSTREAM, +}; + +unsigned long timeout = 0; +int adc_voltage_pin = G8; + +ResistanceConfiguration voltage_divider_type = DOWNSTREAM; +float reference_voltage = 3.3; // in volts +float reference_resistance = 100; // in Ohms + +void setup() { + auto cfg = M5.config(); + AtomS3.begin(cfg); + pinMode(adc_voltage_pin, INPUT); + Serial.begin(4800); +} + +void loop() { + if (timeout < millis()) { + float volt = readVoltage(adc_voltage_pin) * reference_voltage / 4095; + float measured_resistance = 0.0; + switch (voltage_divider_type) { + case UPSTREAM: + if (volt == 0.0f) { + measured_resistance = NAN; + } else { + measured_resistance = (reference_voltage - volt) / volt; + } + break; + case DOWNSTREAM: + if (volt == reference_voltage) { + measured_resistance = NAN; + } else { + measured_resistance = volt / (reference_voltage - volt); + } + break; + } + measured_resistance *= reference_resistance; + gen_nmea0183_xdr("$BBXDR,G,%.1f,O,Ohms_esp32", measured_resistance); + timeout = millis() + 1000; + } +}