Go Down

Topic: Code doesn't seem to run smoothly. (Read 142 times) previous topic - next topic

quattrodave

Apr 20, 2020, 08:30 pm Last Edit: Apr 20, 2020, 08:34 pm by quattrodave
Evening all,

I've been lurking around the forum for a good while now, but previously always found answers before needing to ask...

Last week I found a linksprite GPSV2-B board in my odds n sods draw so decided to action a project i've been mulling over for a while.  The end result I want to be able to monitor 2 marine diesel engines water temp & oil pressure then sound an alarm if the coolant gets too hot or oil pressure drops while the engine is running, engine running taken from a tach pulse. 

Seeing as found the GPS board i decided to add a GPS speedo and here is where my problem lies... Using the arduino i've never had to do any 'time sensative' porgraming and I think this is where the route of my problems lie. Having just the GPS data out put to the lcd screen works ok, however when i start to add the additional functionality it seems to struggle and either hang or display incorrect info.  I though i was being sensible and using 'While GPSSerial. Available' to run the GPS code and 'While GPSSerial Not Available' to run the other code but that hasn't seemed to work out.

Can anyone offer any advice how i might cure this or point me in the right direction please.

Using Arduino Uno R3, 16 x 2 LCD & TinyGPS ++.  Code is as follows:

Many Thanks

Dave

Code: [Select]

#include <LiquidCrystal.h>  // include display library code
#include <SoftwareSerial.h> // include sofrware serial port library code
#include <TinyGPS++.h>  // include GPS parsing library code

const int PORT_TEMP = 0;  // Analogue pin
const int STBD_TEMP = 1;  // Analogue pin
const int PORT_OIL = 2;   // Analogue pin
const int STBD_OIL = 3;   // Analogue pin
const int PORT_TACH = 5;  // Digital pin
const int STBD_TACH = 6;  // Digital pin
const int GPSrxPin = 2;   // Digital pin
const int GPStxPin = 3;   // Digital pin
const int buzzerPin = 7;  // Digital pin

int tim = 2000;  //the value of delay time
bool toggle = false;  //used to toggle between water temp & oil pressure

LiquidCrystal lcd(8, 9, 10, 11, 12, 13); // Initialize the library with the numbers of the interface pins
SoftwareSerial GPSSerial(GPSrxPin,GPStxPin); // Configure software serial port
TinyGPSPlus gps; // Iinitialize the TinyGPS++ object

void setup()
{
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.setCursor(0,0);
  lcd.print("Port  Knt   Stbd");
  lcd.setCursor(0,1);
  lcd.print(" 0     0      0 ");

  // define pin modes for tx, rx:
  pinMode(PORT_TEMP, INPUT);
  pinMode(STBD_TEMP, INPUT);
  pinMode(PORT_OIL, INPUT);
  pinMode(STBD_OIL, INPUT);
  pinMode(PORT_TACH, INPUT);
  pinMode(STBD_TACH, INPUT);
  pinMode(GPSrxPin, INPUT);
  pinMode(GPStxPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
 
  GPSSerial.begin(9600);  //Begin GPS comunications & set baud rate
  //Serial.begin(115200);  //Begin serial monitor comunications (output to PC screen) & set baud rate
}

void loop()
{
    while (GPSSerial.available() > 0){
      //Serial.write(GPSSerial.read());
      if (gps.encode(GPSSerial.read()))
        displayGPS();
    }
    while (GPSSerial.available() == 0){
      if (toggle == false){
        lcd.setCursor(0, 1);
        lcd.print("    ");
        lcd.setCursor(0, 1);
        lcd.print(analogRead(PORT_TEMP));
        lcd.print("c");
 
        lcd.setCursor(13, 1);
        lcd.print("    ");
        lcd.setCursor(13, 1);
        lcd.print(analogRead(STBD_TEMP));
        lcd.print("c");
        toggle = !toggle;
        }
      else{
        lcd.setCursor(0, 1);
        lcd.print("    ");
        lcd.setCursor(0, 1);
        lcd.print(analogRead(PORT_OIL));
        lcd.print("b");
 
        lcd.setCursor(13, 1);
        lcd.print("    ");
        lcd.setCursor(13, 1);
        lcd.print(analogRead(STBD_OIL));
        lcd.print("b");
        toggle = !toggle;
      }
      if(digitalRead(PORT_TACH) == HIGH){
        //Serial.println("Port Run");
        }
      else{
        //Serial.println("Port No Run");
        }
      if(digitalRead(STBD_TACH) == HIGH){
        //Serial.println("Stbd Run");
        }
      else{
        //Serial.println("Stbd No Run");
        }
     
      if(analogRead(PORT_TEMP) > 30 or analogRead(STBD_TEMP) > 30 or analogRead(PORT_OIL) > 30 or analogRead(STBD_OIL) > 30){
        tone(buzzerPin, 1000);
        }
      else{
        noTone(buzzerPin);
        }     
    delay(tim);
    }
}

void displayGPS() {
      // Display no of satellites on top row
      lcd.setCursor(9, 0);
      lcd.print(" ");
      lcd.setCursor(9, 0);
      lcd.print(gps.satellites.value());
      // Display speed in knots on bottom row
      lcd.setCursor(6, 1);
      lcd.print("   ");
      lcd.setCursor(6, 1);
      lcd.print(gps.speed.knots());     
}
/************************************************************/

Danois90

however when i start to add the additional functionality it seems to struggle and either hang or display incorrect info.
What other functionality? You have a 2 seconds delay which is not speeding up anything and the "tone()" function causes some sort of interference on some of the pins. You should also try to remove the "while" loops because they also blocks execution for some period of time.
Instead of mocking what's wrong, teach what's right! ;)
When you get help, remember to thank the helper and give some karma!
Please, do NOT send me any private messages!!

quattrodave

#2
Apr 20, 2020, 09:06 pm Last Edit: Apr 20, 2020, 10:10 pm by quattrodave
Hi,

Thanks for your reply.  The additional functionality would be
1 monitor and display port engine temp
2 monitor and display starboard engine temp
3 monitor and display port oil pressure
4 monitor and display starboard oil pressure
5 monitor port engine running or not
6 monitor starboard engine running or not
7 sound buzzer if port engine running and over temp or under pressure
8 sound buzzer if starboard  engine running and over temp or under pressure

What would you recommend in place of a while loop?

Danois90

#3
Apr 21, 2020, 01:11 pm Last Edit: Apr 21, 2020, 01:12 pm by Danois90
You could consider the following delay-free approach for your loop:

Code: [Select]
unsigned long last_millis = 0;

void loop()
{
  unsigned long cur_millis = millis();

  if ((GPSSerial.available() > 0) && gps.encode(GPSSerial.read()))
  {
    displayGPS();
    last_millis = cur_millis;
  }

  if (cur_millis - last_millis >= 2000)
  {
    int port_temp = analogRead(PORT_TEMP);
    int stbd_temp = analogRead(STBD_TEMP);
    int port_oil = analogRead(PORT_OIL);
    int stbd_oil = analogRead(STBD_OIL);

    if (toggle)
    {
      lcd.setCursor(0, 1);
      lcd.print("    ");
      lcd.setCursor(0, 1);
      lcd.print(port_temp);
      lcd.print("c");
 
      lcd.setCursor(13, 1);
      lcd.print("    ");
      lcd.setCursor(13, 1);
      lcd.print(stbd_temp);
      lcd.print("c");
    }
    else
    {
      lcd.setCursor(0, 1);
      lcd.print("    ");
      lcd.setCursor(0, 1);
      lcd.print(port_oil);
      lcd.print("b");
 
      lcd.setCursor(13, 1);
      lcd.print("    ");
      lcd.setCursor(13, 1);
      lcd.print(stbd_oil);
      lcd.print("b");
    }
    toggle ⁼ !toggle;

    if((port_temp > 30) or (stbd_temp > 30) or (port_oil > 30) or (stbd_oil > 30))
    {
      tone(buzzerPin, 1000);
    }
    else
    {
      noTone(buzzerPin);
    }     
  }
}


Some of the original code has been left out.
Instead of mocking what's wrong, teach what's right! ;)
When you get help, remember to thank the helper and give some karma!
Please, do NOT send me any private messages!!

Go Up