SoftwareSerial

Please do not post requests
Post Reply
User avatar
mrburnette
Posts: 2224
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

SoftwareSerial

Post by mrburnette » Mon Apr 27, 2015 1:50 pm

With 3 hardware serial ports on the Maple, it is unlikely that SoftwareSerial would be needed until one realizes that some Arduino libraries (Adafruit's GPS, for example) inherit from SoftwareSerial. If you are just out for a day's playing, modifying the GPS library may not be something you really wish to do.

Teensy3.1 had already faced this delima here: https://forum.pjrc.com/threads/17461-So ... 3-it-seems

I took Paul's changes and adapted it to the Maple STM32. This was a quick hack, but I can run the Adafruit GPS code on the Maple Mini without issues from SoftwareSerial. I have attached the .h and .cpp files that compile; additional modifications may be required for other 3rd party libraries.

The final bench project is here: http://www.hackster.io/rayburne/color-b ... time-clock


Ray
Attachments
SoftwareSerial.zip
(5 KiB) Downloaded 817 times

madias
Posts: 813
Joined: Mon Apr 27, 2015 11:26 am
Location: Vienna, Austria

Re: SoftwareSerial

Post by madias » Mon Apr 27, 2015 2:41 pm

Great job, Ray! :)
I'm currently found a mess on (arduino) sketches or libs including this "SW serial" and it was annoying to eliminate those lines from every sketch!
thank you!

User avatar
Rick Kimball
Posts: 1078
Joined: Tue Apr 28, 2015 1:26 am
Location: Eastern NC, US
Contact:

Re: SoftwareSerial

Post by Rick Kimball » Fri May 01, 2015 1:35 am

Neat stuff ...

One question. I noticed you are using .\ instead of ./ for your #includes ..

Code: Select all

... much deleted
-I/mnt/vbox/shared/Arduino_STM32_Sketch/hardware/Arduino_STM32/STM32F1/libraries/SPI/src -I/mnt/vbox/shared/Arduino_STM32_Sketch/hardware/Arduino_STM32/STM32F1/libraries/Wire /tmp/build2989123648752632366.tmp/Adafruit_GPS.cpp -o /tmp/build2989123648752632366.tmp/Adafruit_GPS.cpp.o 
/tmp/build2989123648752632366.tmp/Adafruit_GPS.cpp:6:28: fatal error: .\Adafruit_GPS.h: No such file or directory
 #include ".\Adafruit_GPS.h"
                            ^
compilation terminated.
Error compiling.
For us people on linux and OSX ./ works but .\ doesn't. On windows, you can do it either way, so you can use "./Adafruit_GPS.h"

-rick
-rick

User avatar
ahull
Posts: 1730
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: SoftwareSerial

Post by ahull » Fri May 01, 2015 9:32 am

I've spotted that problem a few times in the past, it usually simple to fix. It would be better however if the Linux version of the Arduino IDE handled this for you. Might be worth mentioning it on the Arduino IDE dev or bug pages.
- Andy Hull -

robtillaart
Posts: 2
Joined: Sun May 10, 2015 4:59 pm

Re: SoftwareSerial

Post by robtillaart » Sun May 10, 2015 5:21 pm

On the Arduino forum I did some investigations to replace the hard coded lookup tables with formulas.
Could also be useful for STM32 as you can do any baud rate then

See discussion - http://forum.arduino.cc/index.php?topic=138497.0 -

User avatar
RogerClark
Posts: 7691
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SoftwareSerial

Post by RogerClark » Mon May 11, 2015 12:57 am

I'm not sure how feasible this would be, but why not create a SoftwareSerial class that just calls the internal Hardware serial

I don't see any point in doing true software serial with the number of hardware ports on the board, apart from you can't specify the pins you want to use.

At least stuff would compile.

Ray, so you have an example of a class that inherits from SoftwareSerial that we could look at ?

User avatar
mrburnette
Posts: 2224
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: SoftwareSerial

Post by mrburnette » Mon May 11, 2015 2:00 am

RogerClark wrote:I'm not sure how feasible this would be, but why not create a SoftwareSerial class that just calls the internal Hardware serial

I don't see any point in doing true software serial with the number of hardware ports on the board, apart from you can't specify the pins you want to use.

At least stuff would compile.

Ray, so you have an example of a class that inherits from SoftwareSerial that we could look at ?
Ladyada's GPS lib

Code: Select all

// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS module
// using MTK33x9 chipset
//    ------> http://www.adafruit.com/products/746
// Pick one up today at the Adafruit electronics shop 
// and help support open source hardware & software! -ada

#include <Adafruit_GPS.h>

// This sketch is ONLY for the Arduino Due!
// You should make the following connections with the Due and GPS module:
// GPS power pin to Arduino Due 3.3V output.
// GPS ground pin to Arduino Due ground.
// For hardware serial 1 (recommended):
//   GPS TX to Arduino Due Serial1 RX pin 19
//   GPS RX to Arduino Due Serial1 TX pin 18
#define mySerial Serial1

Adafruit_GPS GPS(&mySerial);


// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences. 
#define GPSECHO  true

// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy

void setup()  
{
    
  // connect at 115200 so we can read the GPS fast enough and echo without dropping chars
  // also spit it out
  Serial.begin(115200);
  Serial.println("Adafruit GPS library basic test!");

  // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  mySerial.begin(9600);
  
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);   // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
  GPS.sendCommand(PGCMD_ANTENNA);

  // the nice thing about this code is you can have a timer0 interrupt go off
  // every 1 millisecond, and read data from the GPS for you. that makes the
  // loop code a heck of a lot easier!

#ifdef __arm__
  usingInterrupt = false;  //NOTE - we don't want to use interrupts on the Due
#else
  useInterrupt(true);
#endif

  delay(1000);
  // Ask for firmware version
  mySerial.println(PMTK_Q_RELEASE);
}

#ifdef __AVR__
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
#ifdef UDR0
  if (GPSECHO)
    if (c) UDR0 = c;  
    // writing direct to UDR0 is much much faster than Serial.print 
    // but only one character can be written at a time. 
#endif
}

void useInterrupt(boolean v) {
  if (v) {
    // Timer0 is already used for millis() - we'll just interrupt somewhere
    // in the middle and call the "Compare A" function above
    OCR0A = 0xAF;
    TIMSK0 |= _BV(OCIE0A);
    usingInterrupt = true;
  } else {
    // do not call the interrupt function COMPA anymore
    TIMSK0 &= ~_BV(OCIE0A);
    usingInterrupt = false;
  }
}
#endif //#ifdef__AVR__

uint32_t timer = millis();
void loop()                     // run over and over again
{
  // in case you are not using the interrupt above, you'll
  // need to 'hand query' the GPS, not suggested :(
  if (! usingInterrupt) {
    // read data from the GPS in the 'main loop'
    char c = GPS.read();
    // if you want to debug, this is a good time to do it!
    if (GPSECHO)
      if (c) Serial.print(c);
  }
  
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences! 
    // so be very wary if using OUTPUT_ALLDATA and trytng to print out data
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
  
    if (!GPS.parse(GPS.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
  }

  // 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
    
    Serial.print("\nTime: ");
    Serial.print(GPS.hour, DEC); Serial.print(':');
    Serial.print(GPS.minute, DEC); Serial.print(':');
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    Serial.println(GPS.milliseconds);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality); 
    if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", "); 
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
    }
  }
}


User avatar
RogerClark
Posts: 7691
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SoftwareSerial

Post by RogerClark » Mon May 11, 2015 9:25 am

Ray,

It looks like you are just passing a pointer to the Serial class, (actually a pointer to an instance of the HardwareSerial class), rather than using a library that inherits from Software Serial

What we have at the moment works fine for this, doesn't it ?

User avatar
mrburnette
Posts: 2224
Joined: Mon Apr 27, 2015 12:50 pm
Location: Greater Atlanta
Contact:

Re: SoftwareSerial

Post by mrburnette » Mon May 11, 2015 2:48 pm

RogerClark wrote:Ray,
It looks like you are just passing a pointer to the Serial class, (actually a pointer to an instance of the HardwareSerial class), rather than using a library that inherits from Software Serial

What we have at the moment works fine for this, doesn't it ?
Roger,
Yes, Hardware serial is actually utilized if the target platform is STM32:

Code: Select all

#if defined(__STM32F1__)
  HardwareSerial *port;
#endif

Code: Select all

#if defined(__STM32F1__)

// A dummy implementation of SoftwareSerial merely uses HardwareSerial.
// This allows libraries hard-coded to SoftwareSerial to compile and
// (hopefully) run properly.
//
SoftwareSerial::SoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic /* = false */)
{
	if (receivePin == 0 && transmitPin == 1) {
		port = &Serial3;
	} else if (receivePin == 8 && transmitPin == 9) {
		port = &Serial2;
	} else if (receivePin == 25 && transmitPin == 26) {
		port = &Serial1;
	} else {
		port = NULL;
	}
}
I took this approach as it is identical for what Paul did for Teensy3.1, ref:
https://forum.pjrc.com/threads/17461-So ... ensy-3-it-

Just smoke and mirrors but does keep from having to muck with renaming includes and such for newbies. I think I probably actually said more about it in the old forum and should have elaborated more when I posted here.


Ray

User avatar
RogerClark
Posts: 7691
Joined: Mon Apr 27, 2015 10:36 am
Location: Melbourne, Australia
Contact:

Re: SoftwareSerial

Post by RogerClark » Mon May 11, 2015 10:14 pm

Ray

That sounds like a good solution

I like the way it switches port based on pin selection.

Though you would need to know that's what it's doing, but at least it returns null if you specify a pin it can't use

Post Reply