I2C GPS with 7 segment displays.

Hi, I've just got this GPS module:

http://www.amazon.co.uk/gp/product/B00H28RUSS?psc=1&redirect=true&ref_=oh_aui_detailpage_o01_s00

I'm using TinyGPSPlus to communicate with it. This works fine, the test programmes run well.

However, I'm making a GPS speedometer/accelerometer/compass thing for my car with it, displaying things on 4 7 segment displays. I can drive the display happily and I can read data from the GPS module, so long as I display it through serial monitor. I can't run both at the same time!

It's quite impossible to describe or explain what's happening with the display, so I'll upload a video. The way I drive the display is I load the first digit into the LED driver's shift register (these drivers sink current btw), then I enable the outputs of the driver at the same time as supplying power to the first 7 segment display. Then I switch to the second display, etc. All I can deduce from what happens is that the programme is periodically halted, and I know it's due to the communication with the GPS module.

This is my code. I apologise in advance, I'm not a programmer :stuck_out_tongue:

#include <math.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const byte RXPin = 0, TXPin = 1;
static const int GPSBaud = 9600;

// The TinyGPS++ object
TinyGPSPlus gps;

// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);

// Outputs
byte sdi = 8;
byte clk = 9;
byte oe = 7;
byte digits[4] = {4,5,2,3};

// Inputs
byte but = 6;

byte index = 0;
byte index2 = 0;
byte mode = 0;
String modes[5] = {"SPEd", "ACEL", "ALt", "InCL", "dIr"};
byte butpressed = 0;
byte dec = -1;
byte segments[8] = {0,0,0,0,0,0,0,0};

float numbers[50];// 50
float number = 0.0;
char vals[10];

String str = "0000";

// the setup routine runs once when you press reset:
void setup() {
  
  ss.begin(GPSBaud);
  
  analogReference(EXTERNAL);
  
  pinMode(clk, OUTPUT);     
  pinMode(sdi, OUTPUT); 
  pinMode(oe, OUTPUT); 
  
  pinMode(digits[0], OUTPUT);
  pinMode(digits[1], OUTPUT);
  pinMode(digits[2], OUTPUT);
  pinMode(digits[3], OUTPUT);
  
  pinMode(but, INPUT);
}

// the loop routine runs over and over again forever:
void loop() {   
  
  index++;
  index2++;
  
  digitalWrite(digits[index], LOW);
  digitalWrite(digits[(index+1)%4], HIGH);
  
  numbers[index2] = valuek();
 
  number = mean();

  smartDelay(0);
  
  getStr();
  
  if (dec != -1 && index >= dec) {
    displayFigure(str[index+1]);
  }
  else {
    displayFigure(str[index]);
  }
  
  if (index == 3) {
    index = -1;
    dec = -1;
  }
  
  if (index2 == 49) { //49
    index2 = -1;
  }
}

float mean() {
  float sum = 0;
  for (byte x = 0; x < 50; x++) {
    sum += numbers[x];
  }
  return sum/50.0;
}

String splitString(String txt) {
  byte i = txt.indexOf('.');
  if (i == -1 or i > 3) {
    dec = -1;
    return txt;
  }
  else {
    dec = i;
    return txt;
  }
}

void buttonTest() {
  if (digitalRead(but) == LOW) {    
    if (butpressed == 0) {
      mode++;
    }
    
    if (mode == 5) {
      mode = 0;
    }
    
    str = modes[mode];
    butpressed = 1;
  }
  else {
    butpressed = 0;
  }
}

void getStr() {
  
    switch (mode) {
    case 0:
      dtostrf(number, 4, 2, vals);
      str = vals;
      buttonTest();
      str = splitString(str);
      break;
    case 1:
      dtostrf(number, 4, 1, vals);
      str = vals;
      buttonTest();
      str = splitString(str);
      break;
    case 2:
      dtostrf(number, 4, 2, vals);
      str = vals;
      buttonTest();
      str = splitString(str);
      break;
    case 3:
      dtostrf(number, 4, 0, vals);
      str = vals;
      buttonTest();
      str = splitString(str);
      break;
    case 4:
      dtostrf(number, 4, 2, vals);
      str = vals;
      buttonTest();
      str = splitString(str);
      break;
  } 
}

float valuek() {
  float x = ((((analogRead(A0)*3.29)/1024.0)-1.64)/0.333333)*9.80665;
  float y = ((((analogRead(A1)*3.29)/1024.0)-1.62)/0.3326)*9.80665;
  float z = ((((analogRead(A2)*3.29)/1024.0)-1.64)/0.351)*9.80665;
  
  switch (mode) {
    case 0:
      return gps.speed.mph();
      break;
    case 1:
      return sqrt(sq(x) + sq(y));
      break;
    case 2:
      return gps.altitude.meters();
      break;
    case 3:
      if (z <= 9.80665) {
        return acos(z/9.80665)*180/M_PI;
      }
      else {
        return 0;
      }
      break;
    case 4:
      return 0.0;
      break;
  } 
}

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

void displayFigure(char fig) {  
  switch (fig) {
    case '0':
      segments[1] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[5] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case '1':
      segments[1] = 1;
      segments[7] = 1;
    break;
    case '2':
      segments[0] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case '3':
      segments[0] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[5] = 1;
      segments[6] = 1;
    break;
    case '4':
      segments[0] = 1;
      segments[1] = 1;
      segments[3] = 1;
      segments[5] = 1;
    break;
    case '5':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[5] = 1;
      segments[6] = 1;
    break;
    case '6':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[5] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case '7':
      segments[2] = 1;
      segments[3] = 1;
      segments[5] = 1;
    break;
    case '8':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[5] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case '9':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[5] = 1;
      segments[6] = 1;
    break;
    case 'S':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[5] = 1;
      segments[6] = 1;
    break;
    case 'P':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[7] = 1;
    break;
    case 'E':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case 'd':
      segments[0] = 1;
      segments[3] = 1;
      segments[5] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case 'A':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[3] = 1;
      segments[5] = 1;
      segments[7] = 1;
    break;
    case 'C':
      segments[1] = 1;
      segments[2] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case 'L':
      segments[1] = 1;
      segments[6] = 1;
      segments[7] = 1;
    break;
    case 'I':
      segments[1] = 1;
      segments[7] = 1;
    break;
    case 't':
      segments[0] = 1;
      segments[1] = 1;
      segments[7] = 1;
    break;
    case 'n':
      segments[0] = 1;
      segments[5] = 1;
      segments[7] = 1;
    break;
    case 'r':
      segments[0] = 1;
      segments[7] = 1;
    break;
    case '-':
      segments[0] = 1;
    break;
    case 'o':
      segments[0] = 1;
      segments[1] = 1;
      segments[2] = 1;
      segments[3] = 1;
    break;
  }
  
if (index == dec-1){
    segments[4] = 1;
  }
  
  digitalWrite(oe, HIGH);
  
  for (byte x = 0;x < 8; x++){
    digitalWrite(sdi, segments[x]);
    segments[x] = 0;
    digitalWrite(clk, HIGH);
    digitalWrite(clk, LOW);
  }
  
  digitalWrite(oe, LOW);
}

I was wondering if my problem has anything to do with the smartDelay() function. I just copied it from the TinyGPS example code because it made it work, but I don't really understand what it's doing.

Thank you very much in advance for any help you can give me :slight_smile:

(The video is to come)