GPS and SD card problem

Hello everyone!
I'm using Mega 2560 with all 4 hardware Serial ( Serial1, Serial2, Serial3, SDA/SCL) and 1 software Serial for data transfer, and here are my code:

#include <TinyGPS++.h>
#include <stdlib.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <JY901.h>
#include <SPI.h>
#include <SD.h>

File myfile;

float angle1,angle2;

byte buffer1[5],buffer2[5];

unsigned int t0,t1,velocity,velocitykmhr,location1,location2;

float ax1,ay1,az1,vx1,vy1,vz1,vx11,vy11,vz11,v,v_final,t;

int x=0,y=0;

unsigned int FS,RS,FRS,RRS,FS1,FS2,FS3,FS4,RS1,RS2,RS3,RS4,FRS1,FRS2,RRS1,RRS2;

SoftwareSerial ss(11,10);////Tx:51,Rx:50

TinyGPSPlus gps;

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);//JY901
  Serial2.begin(9600);//CAR1
  Serial3.begin(9600);//CAR2
  JY901.StartIIC();
  ss.begin(9600);
  pinMode(53,OUTPUT); 
  
  if (SD.begin()) {
    Serial.println("initialization done!");
    }
  else{
  Serial.println("initialization failed.");
  return;
  }
}

void loop() {
t0=millis();

while(Serial3.available()>0 or Serial2.available()>0 or Serial1.available()>0 or ss.available()>0 ){
Serial.println(ss.read());
///////GPS/////
  if(gps.encode(ss.read())){
  velocity=gps.speed.mps();///m per s
  velocitykmhr=gps.speed.kmph();///km per hr
  location1=gps.location.lat();
  location2=gps.location.lng();
    Serial.println("==========================");
    Serial.println(location1); 
    Serial.println(location2); 
  }
 
Serial2.readBytes(buffer2,5);
Serial3.readBytes(buffer1,5);


if(buffer1[0]==0xEE and buffer2[0]==0xEE){

Serial.println("CAR2 Refspeed:");   
Serial.print(buffer1[1], HEX);
Serial.println(buffer1[2], HEX);
RRS1=buffer1[1]<<8;
RRS2=buffer1[2]&0xFF;
RRS=RRS1+RRS2;
         
Serial.println("CAR2 Speed:");   
Serial.print(buffer1[3], HEX);
Serial.println(buffer1[4], HEX);
RS1=buffer1[3]<<8;
RS2=buffer1[4]&0xFF;
RS=RS1+RS2;

Serial.println("CAR1 Refspeed:");   
Serial.print(buffer2[1], HEX);
Serial.println(buffer2[2], HEX);
FRS1=buffer2[1]<<8;
FRS2=buffer2[2]&0xFF;
FRS=FRS1+FRS2;

Serial.println("CAR1 Speed:");   
Serial.print(buffer2[3], HEX);
Serial.println(buffer2[4], HEX);
FS1=buffer2[3]<<8;
FS2=buffer2[4]&0xFF;
FS=FS1+FS2;  


/////JY901 (SDA-SCL)/////(for angle1)  
  JY901.GetAcc();
  JY901.GetGyro();
  JY901.GetAngle();
  angle1=JY901.stcGyro.w[2];///z axis = yaw = steering angle
  angle1=angle1/32768*2000;
  if(angle1<0)
  angle1=-angle1;
  

/////JY901/////(for angle2)
  JY901.CopeSerialData(Serial1.read());
  angle2=JY901.stcAngle.Angle[1];/// y axis = roll = camber angle
  angle2=angle2/32768*180;
  if(angle2<0)
  angle2=-angle2;
  

}
else{
if(x<7;x++)
{
buffer1[x] = 0;
}
if(y<7;y++)
{
buffer2[y] = 0;
}
}
  
  

  myfile = SD.open("test.txt", FILE_WRITE);

  myfile.print(location1);
  myfile.print(",");
  myfile.print(location2);
  myfile.print(",");
  
  myfile.print(RS);
  myfile.print(",");
  myfile.print(RRS);
  myfile.print(",");

  myfile.print(FRS);
  myfile.print(",");
  myfile.print(FS);
  myfile.print(",");

  myfile.print(velocitykmhr);
  myfile.print(",");
  
  myfile.print(angle1);
  myfile.print(",");
  myfile.print(angle2);

}
 
  myfile.close();
}

But there are 2 problems I've met:
1.The GPS data is transfer by the software serial which is connect on pin 10, 11, but it cannot be read on the Serial monitor.
Serial.println(ss.read());
do read values like 47 86 22 but the encode is not working.
But if I changed the code (the one beneath), it will just be fine. Why?

#include <TinyGPS++.h>
#include <SoftwareSerial.h>

// Choose two Arduino pins to use for software serial
int RXPin = 11;
int TXPin = 10;

int GPSBaud = 9600;

// Create a TinyGPS++ object
TinyGPSPlus gps;

// Create a software serial port called "gpsSerial"
SoftwareSerial gpsSerial(RXPin, TXPin);

void setup()
{
  // Start the Arduino hardware serial port at 9600 baud
  Serial.begin(9600);

  // Start the software serial port at the GPS's default baud
  gpsSerial.begin(GPSBaud);
}

void loop()
{
  // This sketch displays information every time a new sentence is correctly encoded.
  while (gpsSerial.available() > 0 )
  if (gps.encode(gpsSerial.read()))
    
      displayInfo();
  // If 5000 milliseconds pass and there are no characters coming in
  // over the software serial port, show a "No GPS detected" error
  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println("No GPS detected");
    while(true);
  }
}

void displayInfo()
{
   // Raw speed in 100ths of a knot (i32)
      Serial.print("Raw speed in 100ths/knot = ");
      Serial.println(gps.speed.value()); 
      // Speed in knots (double)
      Serial.print("Speed in knots/h = ");
      Serial.println(gps.speed.knots()); 
      // Speed in miles per hour (double)
      Serial.print("Speed in miles/h = ");
      Serial.println(gps.speed.mph()); 
      // Speed in meters per second (double)
      Serial.print("Speed in m/s = ");
      Serial.println(gps.speed.mps()); 
      // Speed in kilometers per hour (double)
      Serial.print("Speed in km/h = "); 
      Serial.println(gps.speed.kmph()); 
 Serial.print("Number os satellites in use = "); 
      Serial.println(gps.satellites.value()); 


    Serial.print("Latitude: ");
    Serial.println(gps.location.lat(), 6);
    Serial.print("Longitude: ");
    Serial.println(gps.location.lng(), 6);
    Serial.print("Altitude: ");
    Serial.println(gps.altitude.meters());
  
  
  Serial.print("Date: ");
  if (gps.date.isValid())
  {
    Serial.print(gps.date.month());
    Serial.print("/");
    Serial.print(gps.date.day());
    Serial.print("/");
    Serial.println(gps.date.year());
  }
  else
  {
    Serial.println("Not Available");
  }

  Serial.print("Time: ");
  if (gps.time.isValid())
  {
    if (gps.time.hour() < 10) Serial.print(F("0"));
    Serial.print(gps.time.hour());
    Serial.print(":");
    if (gps.time.minute() < 10) Serial.print(F("0"));
    Serial.print(gps.time.minute());
    Serial.print(":");
    if (gps.time.second() < 10) Serial.print(F("0"));
    Serial.print(gps.time.second());
    Serial.print(".");
    if (gps.time.centisecond() < 10) Serial.print(F("0"));
    Serial.println(gps.time.centisecond());
  }
  else
  {
    Serial.println("Not Available");
  }

  Serial.println();
  Serial.println();
  delay(1);
}
  1. The SD card writing is not stable, it drop data a lot of times or even didn't write anything inside although it goes "initialization done!". Are there anything I've coded wrong? Or is there any other way to stable the data storage?

Thanks for your help!!

Did you mean

Serial.println((char)ss.read());

Yes.

But
Serial.println(location1);
Serial.println(location2);
still can't read any value, and that is the core problem.

Thanks for your reply!

That logic is incorrect. You could have data waiting on Serial2 which makes the while statement true so then you attempt to read ss. And then you proceed to read it again inside gsp.encode.

So should it be like this?

if(Serial3.available()>0 and Serial2.available()>0 and Serial1.available()>0 and ss.available()>0){
 Serial.println(ss.read());
 while(gps.encode(ss.read()){
.
.
.

Thanks for your reply!!

You only know for certain that you have one character to read, yet you read two?

What about the cast we discussed earlier?

Sorry I didn't notice that, so it should be:

Serial.println((char)ss.read());
 while(gps.encode((char)ss.read()){

or not?

Thanks for your reply!!

But you're still reading two characters, when you're only certain there's one to read.
Did you mean to store the character, and use the stored character for the print and the encode?

Serial.println((char)ss.read()); is to make sure that gps's wiring is correct (otherwise it will return -1).
while (gps.encode((char)ss.read()){...} is for encoding the gps's data.
I'm not sure if this is what you're asking :sweat_smile:

Thank you for your reply!!

You do realise that once you've read a character, that character is lost, so you can't send it to the encode function.

1 Like

I'll try it later, thank you a lot!!!

There is a Serial.peek() function if you want to print the character without removing it from the buffer.

Incidentally, the cast to (char) is needed because Serial.read() returns a signed integer, not a character. The reason for this is so read() can return a value of -1 to indicate that the buffer is empty.

I've tried but failed again, which makes me wonder if it's possible that some problems happened when software serial and hardware serial transfer at the same time?
Cause since I've change the code to the one with only GPS', it's just be fine.
The value of

    Serial.println(location1); 
    Serial.println(location2); 

are all 0, but the value of

    Serial.print("Latitude: ");
    Serial.println(gps.location.lat(), 6);
    Serial.print("Longitude: ");
    Serial.println(gps.location.lng(), 6);
    Serial.print("Altitude: ");
    Serial.println(gps.altitude.meters());

are 24.345135 and 120.354315.

And the SD card didn't save anything at all, why?

Thanks for your reply!!

If you've changed your code, post it
All of it

#include <TinyGPS++.h>
#include <stdlib.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <JY901.h>
#include <SPI.h>
#include <SD.h>

File myfile;

float angle1,angle2;

byte buffer1[5],buffer2[5];

unsigned int t0,t1,velocity,velocitykmhr,location1,location2;

float ax1,ay1,az1,vx1,vy1,vz1,vx11,vy11,vz11,v,v_final,t;

int x=0,y=0;

unsigned int FS,RS,FRS,RRS,FS1,FS2,FS3,FS4,RS1,RS2,RS3,RS4,FRS1,FRS2,RRS1,RRS2;

SoftwareSerial ss(11,10);////Tx:51,Rx:50

TinyGPSPlus gps;

void setup() {
  Serial.begin(9600);
  Serial1.begin(9600);//JY901
  Serial2.begin(9600);//CAR1
  Serial3.begin(9600);//CAR2
  JY901.StartIIC();
  ss.begin(9600);
  pinMode(53,OUTPUT); 
  
  if (SD.begin()) {
    Serial.println("initialization done!");
    }
  else{
  Serial.println("initialization failed.");
  return;
  }
}

void loop() {
t0=millis();

if(Serial3.available()>0 or Serial2.available()>0 or Serial1.available()>0 or ss.available()>0 ){
//Serial.println(ss.read());
///////GPS/////
  if(gps.encode(char)ss.read()){
  velocity=gps.speed.mps();///m per s
  velocitykmhr=gps.speed.kmph();///km per hr
  location1=gps.location.lat();
  location2=gps.location.lng();
    Serial.println("==========================");
    Serial.println(location1); 
    Serial.println(location2); 
  }
 
Serial2.readBytes(buffer2,5);
Serial3.readBytes(buffer1,5);


if(buffer1[0]==0xEE and buffer2[0]==0xEE){

Serial.println("CAR2 Refspeed:");   
Serial.print(buffer1[1], HEX);
Serial.println(buffer1[2], HEX);
RRS1=buffer1[1]<<8;
RRS2=buffer1[2]&0xFF;
RRS=RRS1+RRS2;
         
Serial.println("CAR2 Speed:");   
Serial.print(buffer1[3], HEX);
Serial.println(buffer1[4], HEX);
RS1=buffer1[3]<<8;
RS2=buffer1[4]&0xFF;
RS=RS1+RS2;

Serial.println("CAR1 Refspeed:");   
Serial.print(buffer2[1], HEX);
Serial.println(buffer2[2], HEX);
FRS1=buffer2[1]<<8;
FRS2=buffer2[2]&0xFF;
FRS=FRS1+FRS2;

Serial.println("CAR1 Speed:");   
Serial.print(buffer2[3], HEX);
Serial.println(buffer2[4], HEX);
FS1=buffer2[3]<<8;
FS2=buffer2[4]&0xFF;
FS=FS1+FS2;  


/////JY901 (SDA-SCL)/////(for angle1)  
  JY901.GetAcc();
  JY901.GetGyro();
  JY901.GetAngle();
  angle1=JY901.stcGyro.w[2];///z axis = yaw = steering angle
  angle1=angle1/32768*2000;
  if(angle1<0)
  angle1=-angle1;
  

/////JY901/////(for angle2)
  JY901.CopeSerialData(Serial1.read());
  angle2=JY901.stcAngle.Angle[1];/// y axis = roll = camber angle
  angle2=angle2/32768*180;
  if(angle2<0)
  angle2=-angle2;
  

}
else{
if(x<7;x++)
{
buffer1[x] = 0;
}
if(y<7;y++)
{
buffer2[y] = 0;
}
}
  
  

  myfile = SD.open("test.txt", FILE_WRITE);

  myfile.print(location1);
  myfile.print(",");
  myfile.print(location2);
  myfile.print(",");
  
  myfile.print(RS);
  myfile.print(",");
  myfile.print(RRS);
  myfile.print(",");

  myfile.print(FRS);
  myfile.print(",");
  myfile.print(FS);
  myfile.print(",");

  myfile.print(velocitykmhr);
  myfile.print(",");
  
  myfile.print(angle1);
  myfile.print(",");
  myfile.print(angle2);

}
 
  myfile.close();
}

Thanks for your reply!!

I've never seen this construct before
What does it do?

It just count the receive buffer from microchip and clear it if some data are lost in that cycle.

Does this return an integer or a float?

Float, I suppose.