In my program I read wind speed and direction. I display the data on an LCD and I assign the data values to a new variable in a data structure which is then transmitted to a second Arduino Mega using a nRF24 radio link. On the LCD the wind speed and direction varies between the actual value and zero.
At the point in the code where the wind is read in from a software serial input the data is always correct but when it gets back to the point on the next iteration the data value has become zero before it is updated again. Here is that part of the code and sample data:
void Get_WIMWV()
{
const int print_MWV = 0;
j_MAX = 5; // number of Words in NEMA Sentence
Parse_Wind ();
//Serial.print("Checksum Status "); Serial.println(checksum_status);
if(checksum_status){ // if checksum is true process data
for(int j = 0; j<j_MAX; j++) // Since
{
data_MWV[j] = data_IN[j]; //see void Parse Sentence
}
// ************* PROCESS DATA **********************
Serial.print("wind Dir before update "); Serial.println(Wind_Dir,0);
string1 = data_MWV[1];
NEMA_TO_FLOAT(1); // this takes the char data that looks like the wind bearing and converts it to a floating point value
Wind_Dir = float3;
Serial.print("wind Dir after update in WIMWV "); Serial.println(Wind_Dir,0);
//ETdata.SD_course = course;
// data_MWV[2], R or T Relative or True
// data_MWV[3], Wind Speed
string1 = data_MWV[3];
NEMA_TO_FLOAT(1); // this takes the char data that looks like the wind speed and converts it to a floating point value
Wind_Speed = float3;
// data_MWV[4], Wind_Speed Units K/M/N N = knots
if(print_MWV) {PRINT_MWV();}
} // end if checksum_status true
//PRINT_MWV();
} //end of void WIMWV() case
Sample output:
wind Dir before update 0
wind Dir after update in WIMWV 119
wind Dir before update 0
wind Dir after update in WIMWV 122
wind Dir before update 0
wind Dir after update in WIMWV 129
I have fixed the problem by making a temporary data assignment but I do not understand why it fixes the problem.
I have looked for obvious causes like data being assigned a new value somewhere else in the code or code that is too big and causing overflow.
The code uses a data structure so that data can be transmitted and received between nRF24 radios and they will have the same structure so the data can be read directly. Here is the data structure which is 32 bytes. This structure is defined before the void setup().
struct RF_DATA
{
// total data per packet is 32 byte. int = 2, float = 4, + char text
char RFD_text[8];
int16_t RFD_int1;
int16_t RFD_int2;
int16_t RFD_int3;
int16_t RFD_int4;
int8_t RFD_int5;
int16_t RFD_int6;
int16_t RFD_int7;
int16_t RFD_int8;
int8_t RFD_int9;
int16_t RFD_int10;
int16_t RFD_int11;
int16_t RFD_int12;
int16_t RFD_int13;
}; // end RF_DATA1 structure
RF_DATA RFdata; //NAME THE DATA STRUCTURE
The Wind_Speed and Wind_Dir variables are type float. In the subroutine they are converted to int type and the assignments are made to the RFdata in the send data subroutine and here is that code.
/* RADIO RF24 */
// based on formatted data sketch
/*
Sending formatted data packet with nRF24L01.
Maximum size of data struct is 32 bytes.
contributted by iforce2d
The wire numbers listed are using a ribbon wire and a two row ribbon wire connector
1 - GND, wire 2
2 - VCC 3.3V !!! NOT 5V, wire 1
3 - CE to Arduino pin 9, wire 4
4 - CSN to Arduino pin 10, wire 3
5 - SCK to Arduino pin 13 for Uno, 52 on Mega, wire 6
6 - MOSI to Arduino pin 11 for Uno, 51 on Mega, wire 5
7 - MISO to Arduino pin 12 for Uno, 50 on Mega, wire 8
8 - UNUSED, wire 7
*/
void sendData1()
{
Active_waypoint.toCharArray(RFdata.RFD_text,8);
RFdata.RFD_int1 = int(heading);
RFdata.RFD_int2 = int(heading_to_steer);
RFdata.RFD_int3 = int(course);
RFdata.RFD_int4 = int(course_to_steer);
RFdata.RFD_int5 = byte(Steering_Mode);
RFdata.RFD_int6 = int(bearingrate);
RFdata.RFD_int7 = int(Waypoint_Bearing_From[WPT_index]); //BOD
RFdata.RFD_int8 = int(Bearing_to_destination_by_LatLon);
RFdata.RFD_int9 = byte(MSG);
RFdata.RFD_int10 = bnoCAL_status;
Serial.print("Wind A "); Serial.println(Wind_Dir);
RFdata.RFD_int11 = int(Wind_Dir);
Serial.print("Wind B "); Serial.println(Wind_Dir);
RFdata.RFD_int12 = int(Wind_Speed);
RFdata.RFD_int13 = int(XTE);
radio.stopListening(); // stop listening so we can send data
radio.powerUp();
delay(3);
radio.write(&RFdata, sizeof(RF_DATA));
radio.startListening(); // resume listening
}
Here is some typical output:
Wind A 124.50
Wind B 124.50
Wind A 124.50
Wind B 124.50
Wind A 0.00
Wind B 0.00
Wind A 137.00
Wind B 137.00
Wind A 137.00
Wind B 137.00
Wind A 137.00
Wind B 137.00
Wind A 0.00
Wind B 0.00
Wind A 110.50
Wind B 110.50
Wind A 110.50
Wind B 110.50
Wind A 110.50
Wind B 110.50
Wind A 0.00
Wind B 0.00
Wind A 123.50
Wind B 123.50
Wind A 123.50
Wind B 123.50
Wind A 123.50
Wind B 123.50
Wind A 137.50
Wind B 137.50
Wind A 137.50
Wind B 137.50
Wind A 0.00
Wind B 0.00
Wind A 0.00
Wind B 0.00
Wind B 0.00
Wind A 0.00
Wind B 0.00
Wind A 117.50
Wind B 117.50
Wind A 0.00
Now if I make the type int() conversions to temporary variables separately from the assignment to RFdata the code works correctly. Here is the revised code and output:
/* RADIO RF24 */
// based on formatted data sketch
/*
Sending formatted data packet with nRF24L01.
Maximum size of data struct is 32 bytes.
contributted by iforce2d
The wire numbers listed are using a ribbon wire and a two row ribbon wire connector
1 - GND, wire 2
2 - VCC 3.3V !!! NOT 5V, wire 1
3 - CE to Arduino pin 9, wire 4
4 - CSN to Arduino pin 10, wire 3
5 - SCK to Arduino pin 13 for Uno, 52 on Mega, wire 6
6 - MOSI to Arduino pin 11 for Uno, 51 on Mega, wire 5
7 - MISO to Arduino pin 12 for Uno, 50 on Mega, wire 8
8 - UNUSED, wire 7
*/
void sendData1()
{
int tmp1 = int(Wind_Dir);
int tmp2 = int(Wind_Speed);
Active_waypoint.toCharArray(RFdata.RFD_text,8);
RFdata.RFD_int1 = int(heading);
RFdata.RFD_int2 = int(heading_to_steer);
RFdata.RFD_int3 = int(course);
RFdata.RFD_int4 = int(course_to_steer);
RFdata.RFD_int5 = byte(Steering_Mode);
RFdata.RFD_int6 = int(bearingrate);
RFdata.RFD_int7 = int(Waypoint_Bearing_From[WPT_index]); //BOD
RFdata.RFD_int8 = int(Bearing_to_destination_by_LatLon);
RFdata.RFD_int9 = byte(MSG);
RFdata.RFD_int10 = bnoCAL_status;
Serial.print("Wind A "); Serial.println(Wind_Dir);
RFdata.RFD_int11 = tmp1; //int(Wind_Dir);
Serial.print("Wind B "); Serial.println(Wind_Dir);
RFdata.RFD_int12 = tmp2; //int(Wind_Speed);
RFdata.RFD_int13 = int(XTE);
radio.stopListening(); // stop listening so we can send data
radio.powerUp();
delay(3);
radio.write(&RFdata, sizeof(RF_DATA));
radio.startListening(); // resume listening
}
Typical output no longer has any zero values, here is typical output.
Wind B 106.00
Wind A 106.00
Wind B 106.00
Wind A 106.00
Wind B 106.00
Wind A 106.00
Wind B 106.00
Wind A 105.50
Wind B 105.50
Wind A 105.50
Wind B 105.50
Wind A 105.50
Wind B 105.50
Wind A 105.50
Wind B 105.50
Wind A 105.50
It is interesting to note that the int() type conversion and assignments for the first ten variables do not exhibit this error. This part works fine.
Active_waypoint.toCharArray(RFdata.RFD_text,8);
RFdata.RFD_int1 = int(heading);
RFdata.RFD_int2 = int(heading_to_steer);
// if(Steering_Mode == 4) RFdata.RFD_int2 = int(wind_to_steer);
RFdata.RFD_int3 = int(course);
RFdata.RFD_int4 = int(course_to_steer);
RFdata.RFD_int5 = byte(Steering_Mode);
RFdata.RFD_int6 = int(bearingrate);
RFdata.RFD_int7 = int(Waypoint_Bearing_From[WPT_index]); //BOD
RFdata.RFD_int8 = int(Bearing_to_destination_by_LatLon);
RFdata.RFD_int9 = byte(MSG);
RFdata.RFD_int10 = bnoCAL_status;
I am hoping someone can help me understand why the original code didn't work and why it works when the int() type conversion is done separately.