Code is conflicting

This is super long, but bear with me. So I made buzzers for my HiQ team and am finding some very puzzling things. So lets say p1 is blue and p2 is green. The led lights up with the color that wins. The buzzers are hit almost simultaneously. The led shows that green won, the serial monitor shows that p1(blue) buzzed in .203 seconds after it hit zero and p2(green) buzzed in .259 seconds after it hit zero(so according to that blue should've won), and the lcd says that p1(blue) buzzed in 1.35 seconds after it hit zero and p2(green) buzzed in .436 seconds after it hit zero(order is consistent with led, but the buzzers were almost hit at the same time). These results seemingly don’t have a pattern because sometimes the serial monitor makes sense, and sometimes the lcd makes sense, and there doesn't seem to be a numerical pattern. I have no way to check the validity of the led. This is all almost splitting hairs because when pressed noticeably at different times the results are correct (the numerical validity is not known but the lcd and serial monitor always show different values.) I am posting my code wondering if anyone has ANY clue why these results are so different. I believe the print statements are almost identical.

#include <SoftwareSerial.h> //include the needed libraries
#include <LiquidCrystal.h>

// initialize the lcd library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
/*
HiQ buzzer practice program
written By Alex Rodgers

 ----------------------------------------------------------------------------
I wrote this due to the HiQ team I am part of needing practice buzzers.
    ***********************************
    *                                 *
    *       LCD D14 pin------D2       *
    *       LCD D13 pin------D3       *
    *       LCD D12 pin------D4       *
    *       LCD D11 pin------D5       *
    *       P1's button------D6       *
    *       P2's button------D7       *
    *       Blue led(rgb)----D9       *
    *       Green led(rgb)---D10      *
    *       LCD enable pin---D11      *
    *       LCD RS pin-------D12      *
    *       7 seg RX pin-----D13      *
    *                                 *
    ***********************************
*/

int timeansw=16;//how long to count down from

const int softwareTx = 13; //define what pin to use for tx to 7 seg display


SoftwareSerial s7s(0, softwareTx); //define what pins to use for 7 seg display serial
const int p1=6; //define all needed variables
const int p2=7; 
const int led1=9;
const int led2=10;
int p1answ=1;
int p2answ=1;
int reading1;
int previous1=HIGH;
int reading2;
int previous2=HIGH;
long p1time=0;
long p2time=0;
long debounce=200;

int led1read=LOW;
int led2read=LOW;
int p1timex=0;
int p2timex=0;
//button 2

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;        // will store last time LED was updated

// constants won't change :
const long interval = 1000;           // interval at which to blink (milliseconds)

void setup() {
  pinMode(p1, INPUT_PULLUP); //buttons configured as inputs but with a pullup
  pinMode(p2, INPUT_PULLUP);
  pinMode(led1, OUTPUT); //leds configured as outputs
  pinMode(led2, OUTPUT);
  digitalWrite(led1, LOW); //make sure leds are off
  digitalWrite(led2, LOW);
  timeansw=(timeansw+1);
  
  s7s.begin(9600); //begin communication with display
  Serial.begin(9600); //begin serial communication
  lcd.begin(16, 2); //define how many characters are on the lcd

s7s.write(0x76); //clear display
s7s.write(0x7A); //
s7s.write((byte) 40);
  s7s.print("-HI-");  //print hi on display
   lcd.setCursor(0, 0);
 lcd.print("HiQ buzzers"); //print to lcd
 lcd.setCursor(0, 1); 
 lcd.print("Written: Alex R");
 Serial.println(""); //now we are printing to serial
 Serial.println("HiQ buzzer practice program");
 Serial.println("Written by Alex Rodgers March, 2016");
 delay(2000); //delay so the message can be read
 s7s.write(0x76); //clear 7 seg display
 lcd.clear(); //clear lcd

}

void loop() {
  reading1=digitalRead(p1); //check pin modes
  reading2=digitalRead(p2);
  led1read=digitalRead(led1);
  led2read=digitalRead(led2);
  if (reading1 == LOW && previous1 == HIGH && p1answ == 1){
    lcd.setCursor(0,0);
    p1answ=2;
    if (timeansw==0){
      p1timex=(millis()-previousMillis);
      if(led2read==LOW){
        digitalWrite(led1, HIGH);
      }
   
   lcd.print("p1 ");
   lcd.print(p1timex/1000);
   lcd.print(".");
   lcd.print(p1timex%1000);
   lcd.println("s late");
   Serial.print("p1 is ");
   Serial.print(p1timex/1000);
   Serial.print(".");
   Serial.print(p1timex%1000, 4);
   Serial.println(" seconds late");
    } else{
      p1timex=((millis()-previousMillis)+((timeansw-1))*1000);
         lcd.print("p1 ");
   lcd.print(p1timex/1000);
   lcd.print(".");
   lcd.print(p1timex%1000);
   lcd.println("s early");
   Serial.print("p1 is ");
   Serial.print("p1 is ");
   Serial.print(p1timex/1000);
   Serial.print(".");
   Serial.print(p1timex%1000, 4);
   Serial.println(" seconds early");
    }
    }
     if (reading2 == LOW && previous2 == HIGH && p2answ == 1){
    p2answ=2;
    if (timeansw==0){
      p2timex=(millis()-previousMillis);
      if(led1read==LOW){
        digitalWrite(led2, HIGH);
      }
      lcd.setCursor(0,1);
   lcd.print("p2 ");
   lcd.print(p2timex/1000);
   lcd.print(".");
   lcd.print(p2timex%1000);
   lcd.print("s late");
   Serial.print("p2 is ");
   Serial.print(p2timex/1000);
   Serial.print(".");
   Serial.print(p2timex%1000, 4);
   Serial.println(" seconds late");
    } else{
      p2timex=((millis()-previousMillis)+((timeansw-1))*1000);
      lcd.setCursor(0,1);
   lcd.print("p2 ");
   lcd.print(p2timex/1000);
   lcd.print(".");
   lcd.print(p2timex%1000);
   lcd.print("s early");
   Serial.print("p2 is ");
   Serial.print(p2timex/1000);
   Serial.print(".");
   Serial.print(p2timex%1000, 4);
   Serial.println(" seconds early");
    }
    }
    
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval && timeansw>0) {
     
        if (timeansw>0){
  timeansw = timeansw-1;
    }
    
    previousMillis = currentMillis;// save the last time you blinked the LED
    
    s7s.write(0x76); //clear display
    s7s.write(0x79); //set cursor
    s7s.write(0x2); //cursor position
    s7s.write(timeansw/10); //write the tens place of time
    if (timeansw >= 10){ //check if time left is more than 10
    s7s.write(0x79); //set cursor
    s7s.write(0x3); //cursor position
    s7s.write(timeansw - 10); //write the one's place of time
    } else{ //if time left is less than 10
    s7s.write(0x79); //set cursor
    s7s.write(0x3); //cursor position
    s7s.write(timeansw); //set time
    }


  }
}

If you are only interested in which button is pressed first, I would give up on the polling method you are using and use interrupts instead. Nick Gammon has a great intro to interrupts if you are not familiar with them. It can be found here

econjack:
I would give up on the polling method you are using and use interrupts instead.

Most cases on this forum seem to be able to get away with polling but yep this seems like one where interrupts are required.

It could happen that button A was pressed just after you looked at it, but before button B was pressed, although the next one you looked at in the polling cycle was the newly pressed button B which was then declared winner.

Interrupt-on-change seems the cool thing to do. At the very least, reading both inputs simultaneously from the port register would eliminate the appearance of favoritism. :slight_smile: (In practice, it would not likely make a perceptible difference.)

But about the times being wrong: The thing that stands out to me is that the millis() calls are all over the place, and are separated by numerous calls to Serial.print() and lcd.print(), each of which is printing multiple characters. And at 9600 baud, each one of those characters eats about a millisecond, and so each of those if/else code blocks eats about 50ms. Ouch! Short of rewriting everything, I'd suggest at least factoring the time calculations out of the printing code. Get the buzzer checks done immediately, figure out who won and by how much time, and THEN tell the world. Having those things interleaved as they are currently is certainly a big part of the accuracy issue.

SoftwareSerial s7s(0, softwareTx);

It is a very bad idea to use pin 0 as the software serial pin and the hardware serial pin at the same time. Use -1 to indicate that you are not interested in receiving.