(SOLUCIONADO) Conflicto entre GPS y Servo

Hola a todos!!

Estoy realizando un programa en el cual requiero controlar un servo, según los valores que me indique el GPS (GPS Neo 6M), utilizo la librería <TinyGPS.h> para el GPS, pero el motor no toma el valor del GPS y se descontrola. Es un servo SM-s4303r de rotación continua.

El GPS hace la comunicación serial y arroja los datos correctos, pero al intentar mover el servo con esos datos se descontrola, cuando se quita la parte de la comunicación entre el GPS y el arduino (estoy usando Arduino UNO) ///ss.begin(9600);/// el arduino recibe unos datos predeterminados y el servo funciona de manera estable.

No se, si será un problema de librerías, entre SoftwareSerial.h y Servo.h, o un error en el código, les agradezco que me ayuden por favor, gracias.

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


TinyGPS gps;
SoftwareSerial ss(4, 3);
Servo myservo;

static void smartdelay(unsigned long ms);    


void setup()
{
  Serial.begin(9600);
  ss.begin(9600);//////////////Esta es la parte que creo me genera conflicto 
  myservo.attach(9);
}

void loop()
{
  float lat, lon, pos;  // variables GPS, pos -> es la posicion a la que quiero mover el servo
  gps.f_get_position(&lat, &lon);  //obtiene latitud y longitud

  pos=formula; // es un formula para hallar la posición hacia donde debe ir el servo

  Serial.println(lat,6);
  Serial.println(lon,6);
Serial.println(pos,6);


 if (brújula < (pos+2))  //brújula es el control externo para saber la posición del servo
{ 
     myservo.write(80);              
    delay(500);
    }
  else if (brújula> (pos-2))  {
     myservo.write(100);              
    delay(500);
    }                     
   else myservo.write(90);            
    delay(500);

smartdelay(1000);

}


static void smartdelay(unsigned long ms)
{
  unsigned long start = millis();
  do 
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

Antes de responderte, te voy a pedir que leas las normas del foro y luego edites la forma en que has posteado el código.
Debes usar tags. Este es el tag para códigos </>

Gracias, me disculpo por no leer las normas. Quedo corregido, agradezco la ayuda, por favor.

Y todo lo alimentas con el arduino? Aca dice SM-S4303 JR que consume 100mA.

Y es posible que el NEO este de acuerdo a lo que he visto en unos 67 mA Aunque la suma es factible, yo creo que estas en problemas asi que te sugiero que evalúes usar una fuente externa de 5V que alimente el servo. Mantén el gnd de esta fuente unida al GND del Arduino y obviamente el control del servo.

Sí claro, no especifiqué eso. Pero si, yo le conecto una batería al servo y están puenteadas a tierra (gnd). Porque el servo lo puedo controlar, pero cuando utilizo la comunicación serial, pierde el control, pero no se la razón.

No entiendo el código o precisamente la rutina smartdelay. No tiene sentido para mi. La rutina no es llamada en ningún momento. La defines al comienzo y luego? no usas nunca smartdelay(ms) No digo que sea el problema pero no tiene mucha lógica.

deberías leer el estado del gps en algun momento.

Hola amigo , veo que estas usando el GPS en el Serial por software , personalmente preferiría mandar el GPS al Serial por Hardware , ya que el GPS continuamente esta mandando datos y posiblemente estés capturando basura por que el dato pudo haber sido enviado antes de que tu leas la cadena o se quedo a medias , si usas por serial acuérdate que existe un buffer de anillo que cada que llega un dato se va acumulando por interrupción y cuando necesitas al final solo tienes que preguntar por el Serial available y sacas todo lo almacenado :slight_smile:

Cambia el Serial SW para tu output y usa algún cable usb-serial ttl , o desconecta el pin de recepcion de el GPS , para que cuando envíes te llegue al PC.

Saludos :slight_smile:

EricSanchezB: Hola amigo , veo que estas usando el GPS en el Serial por software , personalmente preferiría mandar el GPS al Serial por Hardware , ya que el GPS continuamente esta mandando datos y posiblemente estés capturando basura por que el dato pudo haber sido enviado antes de que tu leas la cadena o se quedo a medias , si usas por serial acuérdate que existe un buffer de anillo que cada que llega un dato se va acumulando por interrupción y cuando necesitas al final solo tienes que preguntar por el Serial available y sacas todo lo almacenado :)

Cambia el Serial SW para tu output y usa algún cable usb-serial ttl , o desconecta el pin de recepcion de el GPS , para que cuando envíes te llegue al PC.

El por razaones que no nos interesan a menos que así lo pida, esta leyendo el gps con el Arduino, de modo que debemos responder sus consultas tal como lo plantea, ahora si le da otro enfoque entonces claro, tu sugerencia es válida. Pero entonces si no usa Arduino no sería pregunta para este foro no te parece? Acá solo hablamos de arduino. Y si no, es OFF TOPIC. Lo que veo es que no estas leyendo el gps porque no usas la rutina smartdelay que contiene ss.read() responsable de leer los datos provenientes del gps.

surbyte:
No entiendo el código o precisamente la rutina smartdelay. No tiene sentido para mi.
La rutina no es llamada en ningún momento.
La defines al comienzo y luego?
no usas nunca smartdelay(ms)
No digo que sea el problema pero no tiene mucha lógica.

deberías leer el estado del gps en algun momento.

Graciias, error mio de nuevo. No coloque esa parte en el código del post, ya lo corregí. El smartdelay se utiliza en un ejemplo de la libreria <TinyGPS.h>. Y es el que me da el tiempo en que imprime o me da los datos, sin ese smart lo he probado y no funciona, o no se como hacer que funcione sin eso, pero si va un smartdelay(1000) en la parte final del codigo.

Entonces ahora si funciona no ?

surbyte: Entonces ahora si funciona no ?

No, osea en el programa lo tenia asi, con el smartdelay, pero aqui no lo puse completo. Aún no sirve :\

Porque no empiezas verificando que tu GPS se esta comunicando con el Arduino
Usa esta parte

static void smartdelay(unsigned long ms) {
  unsigned long start = millis();
  do   {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);

de este modo

void loop() 
  float lat, lon, pos;  // variables GPS, pos -> es la posicion a la que quiero mover el servo
  gps.f_get_position(&lat, &lon);  //obtiene latitud y longitud

  pos = formula; // es un formula para hallar la posición hacia donde debe ir el servo

  Serial.println(lat,6);
  Serial.println(lon,6);
  Serial.println(pos,6);

    while (ss.available())
        gps.encode(ss.read());

Si no funciona cambia esto

SoftwareSerial ss(3, 4);

Solo 3 x 4

Gracias, pero sigue sin funcionar. El programa yo lo he hecho por partes, primero comprobando los valores del GPS, son correctos, pero el motor se vuelve loco. Cuando no envío los datos del GPS, el motor responde correctamente. Estuve leyendo, que puede ser un conflicto en las librerias del servo.h y el serialsoftware.h ya que usan el mismo timer o tienen algun problema con las interrupciones, pero no he visto alguna solucion.

Y porque no lo comentaste antes!! Aunque ese problema ocurría antes hoy SoftwareSerial no usa timer peroooo para no perder datos usa una interrupción asociada con el pin en uso. Eso debe estar haciendo que pierdas la posibilidad de que servo o SoftwareSerial. trabajen bien. puedes bajar los baud ratos del GPS? como para disminuir las interrupciones. A ver si mejora las cosas.

Me temo que entonces lo que propuso EricSanchezB sea la única opción plausible. Me parece que Softwareserial y Servo juntos utilizan demasiados recursos de arduino. Si tu arduino es un mega o un leonardo, la solución será sencilla. Si es un uno, vas a tener que hacer equilibrios durante el desarrollo.

Gracias por su ayuda. Después de buscar y buscar encontré un post, donde hacen una modificación a la librería y funciona con el UNO, probé y efectivamente se solucionó el error. Este es el link http://forum.arduino.cc/index.php?topic=251764