Assistance with Teensy 3.2 and Adafruit Ultimate GPS Data Logger

Status
Not open for further replies.

BristolGarry

New member
Hi Folks - My son and I are planning on launching a High Altitude Balloon for the upcoming eclipse on the 21st. I just today received a Teensy 3.2 (we discovered that the sketch we are using is too big for an Arduino Pro Trinket), and I am now having some troubles compiling. To begin with, I am now getting a "'Serial1' does not name a type" error, which causes cascading errors. I know that there are differences between Arduino and Teensyduino, but am stumped as to where exactly I need to make changes. The code I am currently using is included below, and I am sure is full of other errors. Right now I want to fix the Serial1 error, and will gladly take any help I can get. :)

<code>

#include <Arduino.h>
#include <TinyGPS.h>
#include <SD.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2591.h>
#include <Adafruit_MCP9808.h>
#include <stdio.h>

#define GPS_RX 8
#define GPS_TX 7
#define LED_PIN 13
#define CHIP_SELECT 10
#define DEBUG
#define SD_MISSING_ERR 2
#define FILE_CREATION_ERR 3
#define MAX_BUFFER_SIZE 320 //120 for gps, 5 for light sensor (+ comma), 4 for temp
#define HWSERIAL Serial1

TinyGPS gps;
const byte max_light_buffer_size = sizeof(uint32_t) * 4 + 1;
const byte max_temp_buffer_size = 17;

char dataBuffer [121 + max_light_buffer_size + max_temp_buffer_size];

HWSERIAL mySerial = Serial1 (GPS_RX, GPS_TX);
TinyGPS GPS (&mySerial);
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();

File logfile;

void initGPS();
void initTSL2591();
void initMCP9808();

//Light sensor functions
void tsl2591UnifiedRead(boolean);

//Read light sensor using raw values rather than unified sensor
void tsl2591SimpleRead();
void tsl2591AdvancedRead();

//Specification of light sensor
void tsl2591GetSensorSpecs();

void mcp9808Read(boolean);

void error();


void setup() {
//define init parameters

pinMode( LED_PIN, OUTPUT );
pinMode( 10, OUTPUT );

//Serial.println(F("Starting...."));
HWSERIAL.begin(9600);

if ( !SD.begin( CHIP_SELECT ) ) {
//Serial.println( F( "Card init. failed!" ) );
error( SD_MISSING_ERR );
}

char filename[15]; //15 bytes
strcpy(filename, "GPSLOG00.txt");
for (uint8_t i = 0; i < 100; i++) {
filename[6] = '0' + i/10;
filename[7] = '0' + i%10;
// create if does not exist, do not open existing, write, sync after write
if (! SD.exists(filename)) {
break;
}
}

logfile = SD.open(filename, FILE_WRITE);
if (!logfile) {
//Serial.print(F("couldn't create "));
//Serial.println(filename);
error(FILE_CREATION_ERR);
}
//Serial.print(F("Writing to "));
//Serial.println(filename);

initGPS();
initTSL2591();
initMCP9808();
}

void loop() {
const unsigned short waitTime = 0;

if (GPS.newNMEAreceived()) {
char *stringptr = GPS.lastNMEA();

if (!GPS.parse(stringptr)) return;

/*
int reading = analogRead(sensorPin);
word voltage = reading * aref_voltage;
word millivolts = (voltage/1024.0) *1000.0;

// now print out the temperature
float temperatureC = ((millivolts - 424) / 6.25L) ; //converting from 6.25 mv per degree with 424 mV offset
//to degrees ((voltage - 424mV) times 100)
*/

strcpy(stringptr, dataBuffer);

tsl2591UnifiedRead(true);
mcp9808Read(true);

// Rad. lets log it!
//Serial.println(F("Logging"));

uint8_t stringsize = strlen(dataBuffer); //4 bytes
//if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)) error(4);
//if (strstr(stringptr, "RMC") || strstr(stringptr, "GGA")) logfile.flush();
logfile.println(dataBuffer);
strcpy(dataBuffer, "");
}
delay(waitTime);
}

void error( uint8_t errno ) {
while (1) {
uint8_t i;
for ( i=0;i < errno;i++ ) {
digitalWrite( LED_PIN, HIGH );
delay( 100 );
digitalWrite( LED_PIN, LOW );
delay( 100 );
}
for ( i=errno; i<10; i++ ) {
delay( 200 );
}
}
}

void initGPS() {

GPS.begin( 9600 );
GPS.sendCommand( PMTK_SET_NMEA_OUTPUT_RMCGGA );
GPS.sendCommand( PMTK_SET_NMEA_UPDATE_5HZ );
GPS.sendCommand( PGCMD_NOANTENNA );
}

void initTSL2591() {
//Serial.println(F("Starting Adafruit TSL2591"));

if (tsl.begin()) {
//Serial.println(F("Found a TSL2591 sensor"));
}
else {
//Serial.println(F("No sensor found ... check your wiring?"));
while(1);
}


// You can change the gain on the fly, to adapt to brighter/dimmer light situations
//tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
// tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain

// Changing the integration time gives you a longer time over which to sense light
// longer timelines are slower, but are good in very low light situtations!
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)

tsl2591Gain_t gain = tsl.getGain();
switch(gain)
{
case TSL2591_GAIN_LOW:
//Serial.println(F("1x (Low)"));
break;
case TSL2591_GAIN_MED:
//Serial.println(F("25x (Medium)"));
break;
case TSL2591_GAIN_HIGH:
//Serial.println(F("428x (High)"));
break;
case TSL2591_GAIN_MAX:
//Serial.println(F("9876x (Max)"));
break;
}

}

void initMCP9808() {
//Serial.println(F("MCP9808 demo"));

if (!tempsensor.begin()) {
//Serial.println(F("Couldn't find MCP9808"));
while (1);
}
}

//recommended reader for tsl2591
void tsl2591UnifiedRead(boolean log) {
sensors_event_t event;
tsl.getEvent( &event );
if ((event.light == 0) |
(event.light > 4294966000.0) |
(event.light <-4294966000.0))
{
/* If event.light = 0 lux the sensor is probably saturated */
/* and no reliable data could be generated! */
/* if event.light is +/- 4294967040 there was a float over/underflow */
// Serial.println("Invalid data (adjust gain or timing)");
}
else
{
//Serial.print(event.light); Serial.println(" lux");
}

if (log) {
int error = sprintf(dataBuffer, "%u %c", event.light, ',');
//if (error < 0) Serial.println(F("buffer error"));
}
}

void tsl2591SimpleRead() {
// Simple data read example. Just read the infrared, fullspecrtrum diode
// or 'visible' (difference between the two) channels.
// This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
//uint16_t x = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
//uint16_t x = tsl.getLuminosity(TSL2591_INFRARED);

/*Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
Serial.print(F("Luminosity: "));
Serial.println(x, DEC);
*/
}

void tsl2591AdvancedRead() {
uint32_t lum = tsl.getFullLuminosity();
uint16_t ir, full;
ir = lum >> 16;
full = lum & 0xFFFF;
/* Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
Serial.print("IR: "); Serial.print(ir); Serial.print(" ");
Serial.print("Full: "); Serial.print(full); Serial.print(" ");
Serial.print("Visible: "); Serial.print(full - ir); Serial.print(" ");
Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir)); */
}

void mcp9808Read(boolean log) {
float c = tempsensor.readTempC();

if (log) {
int error = sprintf(dataBuffer, "%.3f %c", c, "C");
// if (error < 0) Serial.println(F("buffer error"));
}

/*Serial.print("Temp: "); Serial.print(c); Serial.print("*C\t");
Serial.print(f); Serial.println("*F");*/
}

</code>

I am happy to post the error code(s) if needed.

Thanks!
 
It is likely one of the following:
  • I would imagine that you have not properly installed the Teensydunio IDE/libraries. It requires installation of software on top the Arduino base layer. https://www.pjrc.com/teensy/td_download.html.
  • Assuming you have installed things, you have not properly selected Teensy 3.2 from the drop down menu Tools -> Boards -> Teensy 3.1/3.2.
  • Serial1/2/3 do not take variable pins. Assuming you installed things correctly, and setup to run a Teensy 3.2, the use of Serial1 (a, b) is the problem, as Serial1 is a global class, not a type constructor. Instead they use fixed pins. Serial1 has RX1 = pin 0, TX1 = pin 1, Serial2 has RX2 = pin 9, TX2 = pin 10, Serial3 has RX3 = pin 7, TX3 = pin 8. There are alternate pins, but for now concentrate on using the standard pins. I would not use HWSERIAL, but instead use Serial1/2/3 directly.
  • When posting code, please use the '#' icon above the code to CODE and /CODE end markers. It makes it much easier to read. You used <code> and </code>. Instead replace the left angle with a left square bracket and the right angle with a right square bracket.
  • You don't need to use Serial.print (F("...")) on Teensy, you can just use Serial.print ("..."), but the uses I saw should still work.
 
Last edited:
Code:
HWSERIAL mySerial = Serial1 (GPS_RX, GPS_TX);

This is the problem line. The Teensy serial ports are tied to specific read/write pins (unless you use the "alternate pins" mechanism.)
Make sure you hook your GPS to pins 0 and 1, and then you don't need to declare HWSERIAL at all. Serial1 "just is" and will work after you call begin().
So, instead of using "mySerial," you want to use "Serial1" which is an actual object instance talking to serial port 1.
(You could also use Serial2 or Serial3, if those pins are more convenient for you.)

Instead, it becomes this:
Code:
// HWSERIAL mySerial = Serial1 (GPS_RX, GPS_TX);
TinyGPS GPS (&Serial1);
(note that HWSERIAL is commented out)

Separately, there's some other code here:
Code:
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591);
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();

Adafruit code does this a lot, initializing objects by constructing temporary objects, and trusting the compiler to sort it out and optimize it away.
Better, more idiomatic C++ use, would instead just declare the objects, and pass constructor arguments as needed:

Code:
Adafruit_TSL2591 tsl(2591);
Adafruit_MCP9808 tempsensor;

This is not a breaking problem, but I find their style counterproductive, and using that style was what made you run into this problem, so it's worth mentioning.
 
Hello Folks -

Thank you very much for the advice and suggestions. :) We made the changes as suggested, but are now getting the following error:


sketch_aug17:31: error: no matching function for call to 'TinyGPS::TinyGPS(HardwareSerial*)'
TinyGPS GPS( &Serial1 );

Here's the latest code that we have been working on (this is a collaborative effort between myself, my son and a young gentleman in another city.)

Code:
#include <TinyGPS.h>
#include <SdFat.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_TSL2591.h"
#include "Adafruit_MCP9808.h"
#include "HardwareSerial.h"
#include <Wire.h>
#include <stdio.h>

#define LED_PIN 13

//chip for sd io
#define CHIP_SELECT 10
#define SD_SPEED SD_SCK_MHZ(5)
#define DEBUG
#define SD_MISSING_ERR 2
#define FILE_CREATION_ERR 3

//All in one buffer for gps, light, and temp sensor. Large for safety.
#define BUFFER_SIZE 400

char buffer[BUFFER_SIZE];

/*
 * Since SoftwareSerial is not supported use HardwareSerial.
 * Default Serial pin is Serial1. For more info: https://www.pjrc.com/teensy/td_uart.html
 */
//  #define HW_SERIAL Serial1

TinyGPS GPS(&Serial1);
Adafruit_TSL2591 tsl(2591);
Adafruit_MCP9808 tempsensor;

SdFat sd;
File logfile;

void initGPS();
void initTSL2591();
void initMCP9808();

//Light sensor functions 
void tsl2591UnifiedRead(boolean);

//Read light sensor using raw values rather than unified sensor
void tsl2591SimpleRead();
void tsl2591AdvancedRead();

//Specification of light sensor
void tsl2591GetSensorSpecs();

void mcp9808Read(boolean);

void error();


void setup() {

  
  //define init parameters
  Serial.begin(9600);
  Serial.println("Adafruit GPS library basic test!");
  
  pinMode( LED_PIN, OUTPUT );
  pinMode( 10, OUTPUT );

  Serial.println(F("Starting...."));

  if (!sd.begin(CHIP_SELECT, SD_SPEED)) {
      if (sd.card()->errorCode()) {
      Serial.println(F("Error"));    
      return;
  }}

 char filename[15]; //15 bytes
 strcpy(filename, "GPSLOG00.txt");
 Serial.println(F("Creating text file."));
 for (uint8_t i = 0; i < 100; i++) {
  filename[6] = '0' + i/10;
  filename[7] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
  if (! sd.exists(filename)) {
     break;
  }
 }

 logfile = sd.open(filename, FILE_WRITE);
 if (!logfile) {
  Serial.print(F("couldn't create "));
  Serial.println(filename);
  error(FILE_CREATION_ERR);
 }
 Serial.print(F("Writing to "));
 Serial.println(filename);

 initGPS();
 initTSL2591();
 initMCP9808();
}

void loop() {
  
char c = GPS.read();
Serial.println(c);
  const unsigned short waitTime = 0;
  if (GPS.newNMEAreceived()) {
    Serial.println(F("Message recieved."));
    char *stringptr = GPS.lastNMEA();
   
    if (!GPS.parse(stringptr)) return;

/*
    int reading = analogRead(sensorPin);  
    word voltage = reading * aref_voltage;
    word millivolts = (voltage/1024.0) *1000.0; 
 
    // now print out the temperature
    float temperatureC = ((millivolts - 424) / 6.25L)  ;  //converting from 6.25 mv per degree with 424 mV offset
                                               //to degrees ((voltage - 424mV) times 100)
*/

    strncpy(stringptr, buffer, sizeof(buffer) - 1);

    tsl2591UnifiedRead(true);
    mcp9808Read(true);
    
    // Rad. lets log it!
    Serial.println(F("Logging"));

    //uint8_t stringsize = strlen(buffer); //4 bytes
    //if (stringsize != logfile.write((uint8_t *)stringptr, stringsize)) error(4);
    //if (strstr(stringptr, "RMC") || strstr(stringptr, "GGA")) logfile.flush();
    logfile.println(buffer);
    strcpy(buffer, "");
  }
  delay(waitTime);
}

void error( uint8_t errno ) {
  while (1) {
    uint8_t i;
    for ( i=0;i < errno;i++ ) {
      digitalWrite( LED_PIN, HIGH );  
      delay( 100 );
      digitalWrite( LED_PIN, LOW );
      delay( 100 );  
    }
    for ( i=errno; i<10; i++ ) {
      delay( 200 );  
    }
  }
}

void initGPS() {

  GPS.begin( 9600 );
  GPS.sendCommand( PMTK_SET_NMEA_OUTPUT_RMCGGA );
  GPS.sendCommand( PMTK_SET_NMEA_UPDATE_5HZ );
  GPS.sendCommand( PGCMD_NOANTENNA );
}

void initTSL2591() {
  Serial.println(F("Starting Adafruit TSL2591"));
  
  if (tsl.begin()) {
    Serial.println(F("Found a TSL2591 sensor"));
  }
  else {
    Serial.println(F("No sensor found ... check your wiring?"));
    while(1);
  }

  
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
  // tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain
  
  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)

  tsl2591Gain_t gain = tsl.getGain();
  switch(gain)
  {
    case TSL2591_GAIN_LOW:
      Serial.println(F("1x (Low)"));
      break;
    case TSL2591_GAIN_MED:
      Serial.println(F("25x (Medium)"));
      break;
    case TSL2591_GAIN_HIGH:
      Serial.println(F("428x (High)"));
      break;
    case TSL2591_GAIN_MAX:
      Serial.println(F("9876x (Max)"));
      break;
  }

}

void initMCP9808() {
  Serial.println(F("Looking for MCP9808 temperature sensor."));
  if (tempsensor.begin()) {
    Serial.println(F("Found a MCP9808 temperature sensor."));
  }
    else{
      Serial.println(F("No sensor found.... check your wiring?"));
    }
  }


//recommended reader for tsl2591
void tsl2591UnifiedRead(boolean log) {
  Serial.println("Reading from TSL2591.");
  sensors_event_t event;
  tsl.getEvent( &event );
  if ((event.light == 0) |
      (event.light > 4294966000.0) | 
      (event.light <-4294966000.0))
  {
    /* If event.light = 0 lux the sensor is probably saturated */
    /* and no reliable data could be generated! */
    /* if event.light is +/- 4294967040 there was a float over/underflow */
   Serial.println("Invalid data (adjust gain or timing)");
  }
  else
  {
    Serial.print(event.light); Serial.println(" lux");  
  }

  if (log) {
    int error = sprintf(buffer + strlen(buffer), "%f %c", event.light, ',');
    if (error < 0) Serial.println(F("buffer error"));
  }
}

void tsl2591SimpleRead() {
  // Simple data read example. Just read the infrared, fullspecrtrum diode 
  // or 'visible' (difference between the two) channels.
  // This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
  uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
  //uint16_t x = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
  //uint16_t x = tsl.getLuminosity(TSL2591_INFRARED);

  Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
  Serial.print(F("Luminosity: "));
  Serial.println(x, DEC);
  
}

void tsl2591AdvancedRead() {
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
 Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
  Serial.print("IR: "); Serial.print(ir);  Serial.print("  ");
  Serial.print("Full: "); Serial.print(full); Serial.print("  ");
  Serial.print("Visible: "); Serial.print(full - ir); Serial.print("  ");
  Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir)); 
}

void mcp9808Read(boolean log) {
  float c = tempsensor.readTempC();
  float f = c * 9.0 / 5.0 + 32;
  if (log) {
    int error = sprintf(buffer + strlen(buffer), "%.3f %c", c, "C");

   // if (error < 0) Serial.println(F("buffer error"));
  }
   
  Serial.print("Temp: "); Serial.print(c); Serial.print("*C\t"); 
  Serial.print(f); Serial.println("*F");
}

Thank you!

BristolGarry
 
That's not how TinyGPS works. You don't give it a serial port. You need to write code which reads the incoming data from the serial port and feeds it into TinyGPS.

From the TinyGPS "test_with_gps_device" example:

Code:
    while (ss.available())
      gps.encode(ss.read());
 
Status
Not open for further replies.
Back
Top