Merging NeoSWSerial and TinyGps sketches in one. Scooter DRL+Oled-Speedometer+Em

Merging NeoSWSerial and TinyGps sketches in one. Scooter DRL+Oled-Speedometer+Emergency-braking-blinking.

Due to the success of the previous project with NeoSWSerial: https://forum.arduino.cc/index.php?topic=484371.0

…which I modified to add a Dummy Alarm LED, that was easy.
…I also modified to dim DRL’s at low speed as they get quite warm at still. Moving, the air cools down the DRL’s.

But I wanted to add a final function: OLED 1.3inch displaying speed mph with large digits.

I tried to adapt the next two previous existing projects but none of them worked for my screen (even choosing all different screen I2C options/drivers):

But I could make the oled work with TinyGPS library as shown in the picture:

Now the main question: How can I merge two different Sketches using two different libraries (NeoSWSerial and TinyGps) in one single sketch sharing one Neo 6M GPS module?. When I try to upload theres a conflict of incompatibility:

NMEAGPS gps;
TinyGPS gps;

Both can’t define a gps in the same sketch.

Both sketches to be merged are attached. (and yes the speedometer is not optimised, could be simplified)

And other newbie question: I have two GPS 6M modules and on both the real connection is one pin lower than declared by arduino. i.e:

SoftwareSerial mySerial(10, 11); // RX 10 arduino to TX device, TX 11 Arduino to RX device (Real physical connection is RX-9 TX-10)

NeoSWSerial gpsPort(10, 11); // Real connection RX to Arduino9, TX to Arduino10

What I’m I missing?

////////////////////////////////
Semi offtopic comment:
I really want to encourage riders to add DRL to your bikes. Is not only refreshing the image of your old motorbike, cold white(bluish) is incredibly beautiful.
But most important is, since I have them on, you catch the attention of other drivers and pedestrians, and since then I had less drivers cutting me off.
Really recommended for not “noisy” motorbikes.

GPS_OLED_MPH_attempt_1.ino (4.3 KB)

Honda_S-Wing_double_speed.ino (6.19 KB)

monkeyisland:
Now the main question: How can I merge two different Sketches using two different libraries (NeoSWSerial and TinyGps) in one single sketch sharing one Neo 6M GPS module?

You pick one library and adapt the other sketch to use the library you have chosen.

You pick one library and adapt the other sketch to use the library you have chosen.

+1

Here is the NeoGPS+NeoSWSerial sketch, updated with the OLED draw routine (copied from the TinyGPS+OLED sketch):

/* Arduino pin connection chart:
 *  pin  6: Mosfet Gate to control DRL (Daytime running lights) intensity.
 *  pin  8: Relay signal pin
 *  pin  9: RX GPS Neo 6M
 *  pin 10: TX GPS Neo 6M
 *  pin 11: Dummy (5v rated) LED positive leg
 *  pin A0: 2.2v braking signal in.
 */


#include <U8glib.h>

U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);


#include <NeoSWSerial.h>
#include <NMEAGPS.h>

NeoSWSerial gpsPort(10, 11); // Real connection RX to Arduino9,  TX to Arduino10
NMEAGPS     gps;
gps_fix     fix; //  this holds all the GPS pieces

const float FLASH_SPEED       = 30.0; // reached this speed would trigger 6 blinks NUM_BLINKS
const float FLASH_SPEED_2     = 40.0; // reached this speed would trigger 12 blinks NUM_BLINKS_2

const float DIM_DRL_LOW_SPEED = 5.0;  // Lower than this value the DRL dims to avoid overheating the side mirror case.
const uint8_t MIN_DRL_BRIGHTNESS = 100;
const uint8_t MAX_DRL_BRIGHTNESS = 255;

const float   SPEED_ACTIVATE_ALARM_LED = 5.0;
      // If remains below this mph for a while (LED_ALARM_TRIGGER_INTERVAL),
      //   activate dummy alarm LED
const unsigned long LED_ALARM_TRIGGER_INTERVAL = 300000;
      // Along with "SPEED_ACTIVATE_ALARM_LED", time without braking to
      //   activate dummy alarm LED

const int   STROBE_INTERVAL   = 50;    // 50ms is 20times per second
const int   PAUSE_STROBE      = 10000; // 10 seconds

const int   NUM_BLINKS        = 6;     // Pick an even number = 2*blinks
const int   NUM_BLINKS_2      = 12;
const int   BRAKE_PIN         = A0;    // select the input pin for the brake 5v(real 2.2v) signal
const int   MOSFET_PIN        = 6;
const int   ALARM_LED_PIN     = 11;    // Dummy Alarm led
const int   ALARM_LED_PERIOD  = 5000;  // Dummy Alarm led fading interval


const int   RELAY_PIN         = 8;

int  blinks = 0;
unsigned long changeTime; // the last time we toggled the relay
uint8_t lastSpeed = 255; // invalid speed forces the first draw



void setup()
{
  //Setup all the Arduino Pins
  pinMode( RELAY_PIN, OUTPUT );
  pinMode( BRAKE_PIN, INPUT  );

  //Turn OFF any power to the RELAY_PIN channels
  digitalWrite( RELAY_PIN, HIGH );

  Serial .begin( 9600 );
  gpsPort.begin( 9600 );
}


void loop()
{
  //  Check for new GPS data
  if (gps.available( gpsPort )) {

    fix = gps.read(); // Get the new data

    updateOLED( fix.speed_mph() );
    checkBraking();
    checkDRL();

    printDateTime(); // just testing?
  }

  blink();
  checkAlarm();

} // loop

//--------------------------------

void updateOLED( uint8_t speed )
{
  // Only redraw if the speed changes from last time.
  if (lastSpeed != speed) {
    lastSpeed = speed;

    u8g.firstPage();

    do {

      // graphic commands to redraw the complete screen should be placed here
      //SPEED:: Displays Speed and other related graphics
      u8g.setFont(u8g_font_lucasfont_alternater);
      u8g.setColorIndex(1);
      u8g.drawStr(0,10,"m");
      u8g.drawStr(0,18,"p");
      u8g.drawStr(0,28,"h");

      u8g.setFont(u8g_font_fub30n);
      u8g.setScale2x2();
      u8g.setPrintPos(12, 32); // for 2x2 (25,30)

      if (speed >= 10) {
        u8g.setColorIndex(0);
      }
      u8g.print( speed );

    } while(u8g.nextPage());

  }

} // updateOLED

//----------------------

void checkBraking()
{
  // Check for blinking the brake lights, but only if
  //    it is not blinking now *and* it has been
  //    long enough since the last blinking finished.
  bool braking = (analogRead( BRAKE_PIN ) > 100);

  if (braking && (blinks == 0) &&
      (millis() - changeTime > PAUSE_STROBE)) {

    if (fix.valid.speed && (fix.speed_mph() >= FLASH_SPEED_2)) {
      // we know we're going fast
      blinks = NUM_BLINKS_2;
    } else if (not fix.valid.speed || (fix.speed_mph() >= FLASH_SPEED)) {
      // we don't know our speed *or* we are not going fast
      blinks = NUM_BLINKS;
    }

    if (blinks > 0) {
      //  Start the blink "state machine"
      changeTime = millis();
      digitalWrite( RELAY_PIN, LOW );
    }
  }
} // checkBraking

//----------------------

void checkAlarm()
{
  int intensity;

  //  Check for fading the "alarm" LED
  if ((not fix.valid.speed || (fix.speed_mph() <= SPEED_ACTIVATE_ALARM_LED)) &&
      (millis() - changeTime >= LED_ALARM_TRIGGER_INTERVAL)){
    unsigned long time = millis();
    intensity = 90+90*cos(2*PI/ALARM_LED_PERIOD*time);
       // Original value 128+127 = 255. Don't need the LED too bright: using 90+90
  } else {
    intensity = 0;
  }
  analogWrite( ALARM_LED_PIN, intensity );

} // checkAlarm

//----------------------

uint8_t startDRL[] = {  7,  6,  5,  5,  4,  4,  4,  4,  5,  6,  6,  6 }; // hours
uint8_t stopDRL [] = { 16, 16, 16, 19, 20, 20, 20, 20, 19, 18, 18, 17 };

void checkDRL()
{
  //  Dim DRL at dusk/night month by month.
  //     This avoids DRL blinding other drivers at night.
  uint8_t brightness = MIN_DRL_BRIGHTNESS;

  if (fix.valid.speed && fix.valid.date && fix.valid.time &&
      (fix.speed_mph() >= DIM_DRL_LOW_SPEED)) {

    // Arrays start at zero, so subtract 1 for JANUARY
    uint8_t start = startDRL[ fix.dateTime.month-1 ];
    uint8_t stop  = stopDRL [ fix.dateTime.month-1 ];

    if ((start <= fix.dateTime.hours) && (fix.dateTime.hours <= stop)) {
      brightness = MAX_DRL_BRIGHTNESS;
    }
  }

  analogWrite( MOSFET_PIN, brightness );

} // checkDRL

//----------------------

void printDateTime()
{
  //for test:
  Serial.print(millis());
  Serial.print(' ');
  Serial.print(changeTime);
  Serial.print(' ');

  if (fix.valid.date && fix.valid.time && fix.valid.speed) {

    // Do something with fix.dateTime.month?
    Serial.print( fix.dateTime.month );
    Serial.print(' ');
    Serial.print( fix.dateTime.hours );
    Serial.print(':');
    if (fix.dateTime.minutes < 10)
      Serial.print('0');
    Serial.print( fix.dateTime.minutes );
    Serial.print(' ');
    Serial.print( fix.speed_mph() );
    Serial.print(' ');
    Serial.print( analogRead(BRAKE_PIN) );
    Serial.println(' ');

  }

} // printDateTime

//----------------------

void blink()
{
  //  Run the blink "state machine"
  if (blinks && (millis() - changeTime >= STROBE_INTERVAL)) {

    digitalWrite( RELAY_PIN, !digitalRead(RELAY_PIN) ); // toggle!
    changeTime = millis(); // remember when we toggled it
    blinks--;              // decrement the number of times we toggled it.
                           //   Blinking stops when we get to 0
  }
} // blink

There are a few other mods… indentation (very important), constant names are all uppercase, the loop routine was broken up into several smaller routines. This makes it much easier to read. Not tested. :slight_smile:

Notice that the “blinking” flags went away. Instead, the “blink” count is tested. If it is 0, that means blinking is false (all done). It starts at the required number of blinks (12 or 6) and decrements to 0.

Cheers,
/dev

Oh Dev, Double thanks again. First for optimising my sketch and secondly because you introduced new functions that turns out to be a learning tutorial for my future projects!

I'll mount it tomorrow or next day to see how everything works and I'll keep you updated.

THANKS