Serial1 - Atmega2560

Pessoal,

Estou com um problema muito estranho.
Eu fiz uma Classe para encapsular a biblioteca Adafruit_GPS (https://github.com/adafruit/Adafruit-GPS-Library/blob/master/Adafruit_GPS.cpp) a fim de abstrair outras partes do código para uma possível mudança de GPS.

Então, eu faço a chamada para classe, que cria o objeto da classe Adafruit_GPS utilizando a Serial1.
Até ai OK, funciona. O problema acontece quando eu desligo a placa completamente e volto a ligar.
O Código está considerando que a Serial1 é uma por SW e não HW. (Linha 252-269 da biblioteca deles.)

teste.ino

#include <GPSClass.h>
#include <Adafruit_GPS.h>

#include <SoftwareSerial.h>


GPSClass *gps;

void setup()  
{
  Serial.begin(9600);
  delay(200);
  Serial.println("Comecando!!!!");

  gps = new GPSClass(5,20);
  gps->on();
  gps->begin(&Serial1);
  gps->start();
}

void loop() {
  gps->getData();
  gps->show();
}

GPSClass.h

#ifndef _GPSCLASS_H
#define _GPSCLASS_H

#include <Adafruit_GPS.h>

#define MAXWAITSENTENCE 5

#include "Arduino.h"

class GPSClass {
  public:
    GPSClass(int , int);
    ~GPSClass();
    void start();
    void on();
    void off();
    
    void getData();
    
    void show();
    
    void begin(HardwareSerial *serIn);

   private:
    void readData();
    void parseData();
    int _gpsEnablePin;
    int _gpsFixPin;
    uint32_t timer;
    Adafruit_GPS *_gpsModule;
    HardwareSerial *_Serial;
};
#endif

GPSClass.cpp

#include "GPSClass.h"
#include <Adafruit_GPS.h>

#define GPSECHO  true

GPSClass::GPSClass(int gpsEnablePin, int gpsFixPin)  {
_Serial = NULL;

  timer = millis();
  _gpsEnablePin = gpsEnablePin;
  _gpsFixPin = gpsFixPin;
  
  
  pinMode(_gpsEnablePin, OUTPUT);
  pinMode(_gpsFixPin, INPUT);

};

GPSClass::~GPSClass() {
  delete _gpsModule;
};

void GPSClass::begin(HardwareSerial *serIn)
{
   _Serial = serIn;
   _Serial->begin(9600);
   _Serial->println("Ready to Rip!");
}

void GPSClass::start() {
  _gpsModule = new Adafruit_GPS(_Serial);
  
  _gpsModule->begin(9600);

  _gpsModule->sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);

  _gpsModule->sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);

  _gpsModule->sendCommand(PGCMD_ANTENNA);

  delay(1000);
}

void GPSClass::on() {
  digitalWrite(_gpsEnablePin, HIGH);
}

void GPSClass::off() {
  digitalWrite(_gpsEnablePin, LOW);
}



void GPSClass::getData() {
  this->readData();
  this->parseData();
}

void GPSClass::show() {
 // if millis() or timer wraps around, we'll just reset it
  if (timer > millis())  timer = millis();

  // approximately every 2 seconds or so, print out the current stats
  if (millis() - timer > 2000) { 
    timer = millis(); // reset the timer
    
//this->getLatitude();
//this->getLongitude();
    
    Serial.print("\nTime: ");
    Serial.print(_gpsModule->hour, DEC); Serial.print(':');
    Serial.print(_gpsModule->minute, DEC); Serial.print(':');
    Serial.print(_gpsModule->seconds, DEC); Serial.print('.');
    Serial.println(_gpsModule->milliseconds);
    Serial.print("Date: ");
    Serial.print(_gpsModule->day, DEC); Serial.print('/');
    Serial.print(_gpsModule->month, DEC); Serial.print("/20");
    Serial.println(_gpsModule->year, DEC);
    Serial.print("Fix: "); Serial.print((int)_gpsModule->fix);
    Serial.print(" quality: "); Serial.println((int)_gpsModule->fixquality); 
    if (_gpsModule->fix) {
      Serial.print("Location: ");
      Serial.print(_gpsModule->latitude, 4); Serial.print(_gpsModule->lat);
      Serial.print(", "); 
      Serial.print(_gpsModule->longitude, 4); Serial.println(_gpsModule->lon);
      
      Serial.print("Speed (knots): "); Serial.println(_gpsModule->speed);
      Serial.print("Angle: "); Serial.println(_gpsModule->angle);
      Serial.print("Altitude: "); Serial.println(_gpsModule->altitude);
      Serial.print("Satellites: "); Serial.println((int)_gpsModule->satellites);
    }
  }
}

void GPSClass::readData() {
  //char c = _gpsModule->read();
  // if you want to debug, this is a good time to do it!
  // if ((c) && (GPSECHO))
    // Serial.write(c); 
  
  _gpsModule->read();
}

void GPSClass::parseData() {
   // if a sentence is received, we can check the checksum, parse it...
  if (_gpsModule->newNMEAreceived()) {
    if (!_gpsModule->parse(_gpsModule->lastNMEA())) // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
  }
}

Eu dei uma enxugada no código, posso ter apagado uma funcção ou outra sem querer, se sentirem falta de algo, me avisem.

Mas como disse o problema está acontecendo quando desligo a placa e volto a religar. Nunca vi isso e não tenho achado muita ajuda na internet…

Agradeço quem puder ajudar.

Obrigado

O programa nao muda sozinho...

Porque e uqe adicionas o SoftwareSerial.h??

Que e que te esta a indicar que e uma software serial e nao hardware?

O teu post nao e claro acerca do que o software deixa de fazer quando desligas e voltas a ligar a placa. Tu referes um problema 2 vezes, mas nao dizes o que o problema e.

Tambem convinha dizeres o que fazes para que a placa e codigo volte a funcionar outra vez.
Ja pensaste que pode o GPS estar a adquirir a posicao logo apos teres desligado e voltado a ligar a placa? Nao me pareceu haver muito em termos de feedback para o operador se o GPS nao estiver [pronto.

Ja agora... o que pretendes atingir com isto:

 // if millis() or timer wraps around, we'll just reset it
  if (timer > millis())  timer = millis();

nao me parece que precises disto...

O metodo show e, no minimo, ridiculo... chamas um metodo que detecta se passou 2 segundos para ser executado? Nao ves um problema nisso???
Porque nao chamas esse metodo de 2 em 2 segundos?

Desculpe se não fui claro.

Respondendo aos seus questionamentos.

Porque e uqe adicionas o SoftwareSerial.h??

Chamo a SoftwareSerial.h pois é necessário para usar a biblioteca Adafruit_GPS, caso contrário não compila....

Que e que te esta a indicar que e uma software serial e nao hardware?

Serial1 não seria sempre HardwareSerial? Pode ser esse o problema. Sempre achei que quando referenciasse ela, seria HardwareSerial...

Quanto aos acontecimentos
1- Dou upload do programa
2- Funciona
3- Desligo todas as conexões de alimentação
4- Ligo novamente
5- Ele não funciona

Descobri que ele começa a considerar que é SoftwareSerial colocando vários Serial.print até achar onde ele tinha um comportamento diferente. (O endereço e o Valor de Serial1 são iguais tanto antes quanto depois de desligar)
Como disse, o comportamento acontece na biblioteca (linhas 252-269). Mas acredito que o problema seja na minha parte, caso contrário já teriam reclamado lá....

Para ser extremamente preciso, caso eu use o RESET, continua a funcionar.

Ja agora... o que pretendes atingir com isto:

Code:
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();

nao me parece que precises disto...

O metodo show e, no minimo, ridiculo... chamas um metodo que detecta se passou 2 segundos para ser executado? Nao ves um problema nisso???
Porque nao chamas esse metodo de 2 em 2 segundos?

Cada coisa tem sua razão, sim poderia chamá-lo a cada 2 segundos, mas a idéia era uma saída rápida de dados.
Na versão final esse método nem será chamado. A razão de 2 em 2 segundos é porque o GPS cospe os dados na Serial1, e eu preciso ficar fazendo o pooling dela para obter as atualizações. Se não colocasse o tempo, ficaria concorrendo o tempo e poderia nunca conseguir ler uma strip de dados completa.

Ok…

Ja viste o codigo dessa biblioteca da Adafruit?
Para ja ainda nao sabemos qual e o problema… o uqe e que deixa de funcionar e quais os sintomas de deixar de functionar. Assim e dificil de saber por onde pegar.

Como eu referi antes, meteste algum serial print a indicar o estado do GPS? O teu programa, se o GPS nao respondesse iria deixar de funcionar.

Explica-me este bocado de codigo:

void GPSClass::begin(HardwareSerial *serIn)
{
   _Serial = serIn;
   _Serial->begin(9600);
   _Serial->println("Ready to Rip!");
}

void GPSClass::start() {
  _gpsModule = new Adafruit_GPS(_Serial);
  
  _gpsModule->begin(9600);

Porque e que mandas Ready to Rip para o receptor de GPS?

Isso veio de uma das tentativas de resolver o problema.

Acabei copiando esse código sem verificar direito. Obrigado por avisar

Realmente não tem razão em mandar isso

Concordo contigo que não sabemos os sintomas que causam a falha. Esse é o grande problema para esse debug. Sugere o uso de alguma ferramenta para auxiliar?

Obrigado

fnoel:
Concordo contigo que não sabemos os sintomas que causam a falha. Esse é o grande problema para esse debug. Sugere o uso de alguma ferramenta para auxiliar?

Serial.print() ????

eu referi que pode ser um problema do GPS... custa assim tanto num dos if's do programa, colocar um else para te indicar que o programa parou ali?

Eu ainda nao vejo beneficio nenhum na tua classe... e grande parte disso e o facto de nao retornares nada para o utilizador. O teu sketch principal assume (erradamente) que tudo vai dar sempre certo... e como estas a ver agora, nao e bem assim.

A biblioteca da Adafruit tambem nao retorna nada? Enviares o resultado das funcoes da biblioteca da Adafruit para a porta serie pode ser a maneira mais simples e facil de ver onde esta o problema.