analog sensors to serial data

Suggestions for improving my code gathers data fro 2 analog sensors and sends via nmea 0183 on digital pin 00,01 with CRC checksum

the code is working but wondering if i should do some cleanup on it to make things more efficient
Using an Osepp Uno R3 Plus for ptototype
and pro mini for finished device

#include <SoftwareSerial.h>
SoftwareSerial NMEA(00, 01); // RX, TX 
/* Bring in analog values 0-5vdc from wind sensors and output nmea 0183 
*  Wind direction and speed sentence NMEA 0183
*  $WIMWV
*  $   String Start 
*  WI  Weather Instrument
*  MWV Wind Speed and Angle
       1 2 3 4 5
       | | | | |
$WIMWV,x.x,a,x.x,a*hh
1) Wind Angle, 0 to 360 degrees
2) Reference, R = Relative, T = True
3) Wind Speed
4) Wind Speed Units, K/M/N
5) Status, A = Data Valid
6) Checksum
*/
// the setup routine runs once when you press reset:
void setup() {
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
 NMEA.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
 int angleValue = analogRead(A0);                    // Reads Value from Analog pin 0 for wind angle
 int speedValue = analogRead(A1);                    // Reads Value from Analog pin 1 for wind speed
 int speed = map(speedValue, 0, 1023, 0, 83.3333);   // remaps speed value to 0 - 83.3333 Knots
 int angle = map(angleValue, 0, 1023, 350, 10);      // remaps angle value to 10 - 350 Degrees
//delay(1000);                                        // delay to make the output more readable
// build the nmea 0183 string for wind instrument and add checksum 
 String Wind = "WIMWV,";                               // WI = Weather instrument MWV wind data 
 String WindSpeedUnit = "N,";                          // unit for display N = Nautical Miles
 int WindAngle  = angle;
 int WindSpeed = speed;
 Wind = Wind + WindAngle + ",R," + WindSpeed + "," + WindSpeedUnit + "A"; // Builds string to send to serial port
 String data = Wind; 
 byte crc = 0;
for(int i=0;i<data.length();i++)                    // creates Checksum for string
 crc=crc^data[i];
Wind="$" + Wind + "*";                              // add line start and end
Serial.print(Wind);                                 // print to serial string
Serial.println(crc,HEX);                            // print checksum and line end
NMEA.print(Wind);                                 // print to serial string
NMEA.println(crc,HEX);                            // print checksum and line end
}

Wind_Sensor_calculation.ino (2.18 KB)

Suggestions for improving my code gathers data fro 2 analog sensors and sends via nmea 0183 on digital pin 00,01 with CRC checksum

the code is working but wondering if i should do some cleanup on it to make things more efficient

#include <SoftwareSerial.h>
SoftwareSerial NMEA(00, 01); // RX, TX 
/* Bring in analog values 0-5vdc from wind sensors and output nmea 0183 
*  Wind direction and speed sentence NMEA 0183
*  $WIMWV
*  $   String Start 
*  WI  Weather Instrument
*  MWV Wind Speed and Angle
       1 2 3 4 5
       | | | | |
$WIMWV,x.x,a,x.x,a*hh
1) Wind Angle, 0 to 360 degrees
2) Reference, R = Relative, T = True
3) Wind Speed
4) Wind Speed Units, K/M/N
5) Status, A = Data Valid
6) Checksum
*/
// the setup routine runs once when you press reset:
void setup() {
 // initialize serial communication at 9600 bits per second:
 Serial.begin(9600);
 NMEA.begin(9600);
}
// the loop routine runs over and over again forever:
void loop() {
 int angleValue = analogRead(A0);                    // Reads Value from Analog pin 0 for wind angle
 int speedValue = analogRead(A1);                    // Reads Value from Analog pin 1 for wind speed
 int speed = map(speedValue, 0, 1023, 0, 83.3333);   // remaps speed value to 0 - 83.3333 Knots
 int angle = map(angleValue, 0, 1023, 350, 10);      // remaps angle value to 10 - 350 Degrees
//delay(1000);                                        // delay to make the output more readable
// build the nmea 0183 string for wind instrument and add checksum 
 String Wind = "WIMWV,";                               // WI = Weather instrument MWV wind data 
 String WindSpeedUnit = "N,";                          // unit for display N = Nautical Miles
 int WindAngle  = angle;
 int WindSpeed = speed;
 Wind = Wind + WindAngle + ",R," + WindSpeed + "," + WindSpeedUnit + "A"; // Builds string to send to serial port
 String data = Wind; 
 byte crc = 0;
for(int i=0;i<data.length();i++)                    // creates Checksum for string
 crc=crc^data[i];
Wind="$" + Wind + "*";                              // add line start and end
Serial.print(Wind);                                 // print to serial string
Serial.println(crc,HEX);                            // print checksum and line end
NMEA.print(Wind);                                 // print to serial string
NMEA.println(crc,HEX);                            // print checksum and line end
}

Wind_Sensor_calculation.ino (2.18 KB)

What Arduino are you using? Most Arduino boards have hardware serial on pins 0 and 1. Software serial should use different pins.

The use of String objects can lead to memory fragmentation and hard to find bugs. Use strings (null terminated character arrays) instead.

Why have you not read the how to use this forum-please read stickies? If you post the code in code tags, the forum software won't mess the code up (italics).

Get rid of the String and use c style strings.

Cross posted here. Do not cross post. Cross posting wastes time.

thank you for the input, sorry about the cross post

SoftwareSerial NMEA(00, 01); // RX, TX

You should use regular serial if you're using pins 0 and 1.

Also note that leading zeroes on numbers has a special meaning. Don't do that unless you know. It means the compiler treats them as octal. For 0 and 1 it doesn't make any difference. But put in 08 or 09 and it's an error. Put in 010 and it equals 8.

Threads merged.

Delta_G:
Also note that leading zeroes on numbers has a special meaning. Don't do that unless you know. It means the compiler treats them as octal. For 0 and 1 it doesn't make any difference. But put in 08 or 09 and it's an error. Put in 010 and it equals 8.

Indeed! (+)

Serial.println(14, DEC);     //shows: 14 (decimal 14 appears in decimal base)
Serial.println(014, OCT);   //shows: 14 (octal 14 appears in octal base)
Serial.println(14, OCT);        //shows: 16 (decimal 14 appears in octal base)  
Serial.println(014, DEC);   //shows: 12 (octal 14 appears in decimal base)

Did you get this working? I am doing the same thing

// Bring in analog values 0-5vdc from wind sensors and output NMEA 0183
// Weather Instrument : Wind Speed and Angle  sentence


const byte WindAngleAIPin = A0;
const byte WindSpeedAIPin = A1;


// $ = Message Prefix
// WI = Talker Type: Weather Instrument
// MWV = Wind Speed and Angle
// %d.0 = Wind Angle in Degrees: 0.0 to 360.0
// R = Relative angle (T = True Heading)
// %d.0 = Wind Speed
// N = Knots (Statute Milews per Hour) (K = KPH, M=MPH)
// A = Valid Data
// * = Checksum Indicator
const char WIMWVFormat[] = "$WIMWV,%d.0,R,%d.0,N,A*";


// the setup routine runs once when you press reset:
void setup()
{
  // NMEA0183 standard uses 4800 baud RS-422
  Serial.begin(4800);
}


// the loop routine runs over and over again forever:
void loop()
{
  char buffer[sizeof WIMWVFormat + 10];
  int windAngle = map(analogRead(WindAngleAIPin), 0, 1023, 350, 10);      // remaps angle value to 350 - 10 Degrees
  int windSpeed = (analogRead(WindSpeedAIPin) * 83.3333) / 1024.0;        // remaps speed value to 0 - 83.3333 Knots


  // build the NMEA 0183 string for Weather Instrument : Wind Speed and Angle
  sprintf(buffer, WIMWVFormat, windAngle, windSpeed); // Builds string to send to serial port


  // The XOR checksum covers everything after the "$" to before the "*"
  byte checksum = 0;
  for (byte i = 1; i < (strlen(buffer) - 1); i++)           // creates Checksum for string
    checksum ^= buffer[i];


  Serial.print(buffer);                                 // print to serial string
  // Add a leading 0 if the checksum is less than two hex digits.
  if (checksum < 0x10)
    Serial.print('0');
  Serial.println(checksum, HEX);                           // print checksum and line end
}

johnwasser:
// Add a leading 0 if the checksum is less than two hex digits.

Add a leading 0 if the checksum is less than 0x10?

GolamMostafa:
Add a leading 0 if the checksum is less than 0x10?

Yes. Like I said: "Add a leading 0 if the checksum is less than two hex digits.". The value 0x10 is the lowest hex number that uses two hex digits. Therefore any value less than 0x10 will be expressed in one hex digit. The NMEA standard requires a two-hex-digit checksum.
Does that answer your question?

johnwasser:
Yes. Like I said: “Add a leading 0 if the checksum is less than two hex digits.”. The value 0x10 is the lowest hex number that uses two hex digits. Therefore any value less than 0x10 will be expressed in one hex digit. The NMEA standard requires a two-hex-digit checksum.
Does that answer your question?

An 8-bit checksum is stored in memory in the range: 00000000 - 11111111 (in hex: 00 - FF), which are 2-digit numbers. If we want to show them in the Serial Monitor, we will miss the leading 0s for the numbers: 0x00 - 0x0F which are less than 0x10, but they are not less than 2-digits. That’s why, it was my query if the comment would be like this – “Add a leading 0 if the checksum is less than 0x10.” which you have also implemented in your code:

  if (checksum < 0x10)
    Serial.print('0');
  Serial.println(checksum, HEX);

So I take it that you would have preferred if I had written:

  // Add a leading 0 if the checksum is less than 0x10.
  if (checksum < 0x10)
    Serial.print('0');

rather than what I wrote:

  // Add a leading 0 if the checksum is less than two hex digits.
  if (checksum < 0x10)
    Serial.print('0');

Your preference is noted.

johnwasser:
So I take it that you would have preferred if I had written:
// Add a leading 0 if the checksum is less than 0x10.
[...]
Your preference is noted.

Thank you with +.