Quantcast
Channel: Álvaro López » Arduino
Viewing all articles
Browse latest Browse all 6

Telemetría y data logger with Arduino Part II

$
0
0


Para el proyecto, tal y como describí en la parte I del artículo, cuento con unas radios 433Mhz de 3DR que funcionan a la perfección. Adjuntan un programa de conexión muy interesante y cómo y además operan valores TTL, con lo que se conectan directamente al puerto serie de arduino.

Para comprobar la conexión utilicé el los programas y el LCD descritos en un post anterior

Llegado este punto, y siendo breve, dudé entre efectuar los calculos en tierra o en el rover, pero puesto que uno de los principales usos de mi sistema será el de logger para un posterior proceso, he decidido que los haré en el rover y los datos serán enviados procesados a la base, la cual solo mostrará los mismos, y en una versión futura, será capaz de enviar ordenes al rover.

Siguiendo con el proyecto, el GPS EM-411 (el mismo que el EM-406 pero cumpliendo RoHS y con los pines rx/tx traspuestos), también ha llegado. Me ha soprendido lo completo que es por su ridiculo coste ($24) y lo recomiendo siempre y cuando la cadencia (1Hz) sea suficiente. Gracias a que monta un chip SiRFIII es compatible con un programa de configuración que resulta extremadamente cómodo para configurar el mismo: SiRFDEMO.exe (buscarlo así en google)

sirfdemo.exe
Programa de configuración Sirfdemo

Tiene dos posibles configuraciones muy interesantes, admite programar los parámetros NMEA que necesitamos mostrar (hay algunos como la dilución o los numeros de los satélites que se están mostrando que no nos son necesarios) y la cadencia de los mismos, así como la posibilidad de activar el protocolo SiRF en lugar de NMEA el cual sin aún haberlo estudiado, a priori parece interesante.

Sirfdemo NMEA Config
Dialogo de configuración de los comandos NMEA que enviará el EM-411 así como la cadencia

Una vez configurado el gps con los parámetros básicos y necesarios (para comenzar con el comando GGA nos será suficiente)

Para las pruebas iniciales he querido simplificarlo todo, y el programa montado el Rover, que se puede ver en la foto compuesto por un arduino mega, un pack de baterías ni-mh, el gps y la radio, simplemente recogía los datos de gps y los enviaba por la radio. De hecho, si hubiese cableado el gps directamente a la radio el efecto hubiera sido el mismo, pero quería meter el arduino para posteriormente intercalar más datos como el sensor pitot y un termómetro unica y exclusivamente por que lo tengo en un cajón aburrido.

Rover y Base
Rover y Base

Como el unico objetivo era transmitir los datos desde el Rover a Base y testear el alcance de las antenas, el proceso lo he ejecutado en el Base.
He utilizado la librería TinyGPS que aparentemente funciona bastante bien, y los programas usados han sido los siguientes:


ROVER:

void setup(){
  Serial1.begin(4800);
  Serial2.begin(57600);
}

void loop(){
  while(Serial1.available()){
    Serial2.write(Serial1.read());
  }
}

Y para el Base, simplemente he usado un ejemplo que traia la librería, modificado ligeramente:

#include <TinyGPS.h>

/* This sample code demonstrates the normal use of a TinyGPS object.
   It requires the use of SoftwareSerial, and assumes that you have a
   4800-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/

TinyGPS gps;

static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);

void setup()
{
  Serial.begin(115200);
  Serial1.begin(57600);
  
  Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
  Serial.println();
  Serial.println("Sats HDOP Latitude Longitude Fix  Date       Time       Date Alt     Course Speed Card  Distance Course Card  Chars Sentences Checksum");
  Serial.println("          (deg)    (deg)     Age                        Age  (m)     --- from GPS ----  ---- to London  ----  RX    RX        Fail");
  Serial.println("--------------------------------------------------------------------------------------------------------------------------------------");
}

void loop()
{
  bool newdata = false;
  unsigned long start = millis();
  
  // Every second we print an update
  while (millis() - start < 1000)
  {
    if (feedgps())
      newdata = true;
  }
  
  gpsdump(gps);
}

static void gpsdump(TinyGPS &gps)
{
  float flat, flon;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  
  print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
  gps.f_get_position(&flat, &flon, &age);
  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5);
  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5);
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

  print_date(gps);

  print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2);
  print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
  print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
  print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
  print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
  print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);

  gps.stats(&chars, &sentences, &failed);
  print_int(chars, 0xFFFFFFFF, 6);
  print_int(sentences, 0xFFFFFFFF, 10);
  print_int(failed, 0xFFFFFFFF, 9);
  Serial.println();
}

static void print_int(unsigned long val, unsigned long invalid, int len)
{
  char sz[32];
  if (val == invalid)
    strcpy(sz, "*******");
  else
    sprintf(sz, "%ld", val);
  sz[len] = 0;
  for (int i=strlen(sz); i<len; ++i)
    sz[i] = ' ';
  if (len > 0) 
    sz[len-1] = ' ';
  Serial.print(sz);
  feedgps();
}

static void print_float(float val, float invalid, int len, int prec)
{
  char sz[32];
  if (val == invalid)
  {
    strcpy(sz, "*******");
    sz[len] = 0;
        if (len > 0) 
          sz[len-1] = ' ';
    for (int i=7; i<len; ++i)
        sz[i] = ' ';
    Serial.print(sz);
  }
  else
  {
    Serial.print(val, prec);
    int vi = abs((int)val);
    int flen = prec + (val < 0.0 ? 2 : 1);
    flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
    for (int i=flen; i<len; ++i)
      Serial.print(" ");
  }
  feedgps();
}

static void print_date(TinyGPS &gps)
{
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned long age;
  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
  if (age == TinyGPS::GPS_INVALID_AGE)
    Serial.print("*******    *******    ");
  else
  {
    char sz[32];
    sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d   ",
        month, day, year, hour, minute, second);
    Serial.print(sz);
  }
  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
  feedgps();
}

static void print_str(const char *str, int len)
{
  int slen = strlen(str);
  for (int i=0; i<len; ++i)
    Serial.print(i<slen ? str[i] : ' ');
  feedgps();
}

static bool feedgps()
{
  while (Serial1.available())
  {
    if (gps.encode(Serial1.read()))
      return true;
  }
  return false;
}

Y la salida generada por le puerto serie del Base ha sido la siguiente:


Testing TinyGPS library v. 12
by Mikal Hart
Sizeof(gpsobject) = 115

Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum
(deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail
--------------------------------------------------------------------------------------------------------------------------------------
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 136 0 0
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 490 0 0
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 608 0 0
**** **** ******* ******* **** ******* ******* **** ******* ****** ***** *** 0 0.00 *** 744 0 0
7 220 40.53405 -3.90062 557 09/18/2012 18:48:37 580 727.90 143.65 0.30 SE 1254 12.09 NNE 76308 444 1
7 220 40.53405 -3.90062 558 09/18/2012 18:48:38 594 727.80 144.91 0.22 SE 1254 12.09 NNE 76510 446 1
7 220 40.53405 -3.90062 558 09/18/2012 18:48:39 573 727.60 138.75 0.26 SE 1254 12.09 NNE 76712 448 1
7 220 40.53405 -3.90062 139 09/18/2012 18:48:40 143 727.50 138.09 0.28 SE 1254 12.09 NNE 77092 450 1
7 220 40.53405 -3.90062 596 09/18/2012 18:48:41 611 727.40 142.05 0.26 SE 1254 12.09 NNE 77294 452 1
7 220 40.53405 -3.90062 599 09/18/2012 18:48:42 613 727.20 146.51 0.26 SSE 1254 12.09 NNE 77496 454 1
7 220 40.53405 -3.90062 596 09/18/2012 18:48:43 642 727.10 140.14 0.28 SE 1254 12.09 NNE 77698 456 1
7 220 40.53405 -3.90062 620 09/18/2012 18:48:44 645 727.00 137.82 0.26 SE 1254 12.09 NNE 77900 458 1
7 220 40.53405 -3.90062 222 09/18/2012 18:48:45 255 726.90 141.64 0.26 SE 1254 12.09 NNE 78280 460 1
7 220 40.53405 -3.90061 640 09/18/2012 18:48:46 670 726.70 139.36 0.24 SE 1254 12.09 NNE 78482 462 1
7 220 40.53405 -3.90061 650 09/18/2012 18:48:47 683 726.60 140.66 0.24 SE 1254 12.09 NNE 78696 464 1
7 220 40.53405 -3.90061 661 09/18/2012 18:48:48 687 726.50 146.14 0.28 SE 1254 12.09 NNE 78887 466 1

Con esto he probado una librería capaz de procesar NMEA y la comunicación a una distancía de 2km de mi casa, suficiente ya que en el campo de vuelo 1km ya es suficiente como para no ver el avión.



Viewing all articles
Browse latest Browse all 6

Latest Images

Trending Articles





Latest Images