Delay timing issue

Hey there! I have been working on a laser free space optical communication system. The system is working great, but then randomly breaks down. I ran tests, and found there to be a 0-2 additional ms delay between actions. overtime this throws off the synergy of both receiver and sender. If the distance between a where I am reading a input and the change from a high to a low power is 100, it takes around 60 bits before the breakdown which matches a 1-2 error. Any issues on how to fix this? ( I think im using the code tags correctly)


String inputStr = "";  // Binary output string
String outputStr = ""; // ASCII output string
int inputPin = A0;
int delayTime = 200; // Variable for delay duration
int THRESHOLD = 0; // Threshold value for HIGH/LOW distinction

bool lightDetected = false; // Tracks first detection

void setup() {
  Serial.begin(9600);
  delay(500);
  pinMode(inputPin, INPUT);
}

void loop() {
  while (!lightDetected) {
    Serial.println("Waiting for light detection...");
    int power = analogRead(inputPin);
    if (power <= 0) {
      lightDetected = true;
      Serial.println("Light detected! Initializing delay before data collection...");
      delay(1.25 * delayTime);
    } else {
      return;
    }
  }

  // Main data collection
  int power1 = analogRead(inputPin);
  delay(delayTime);
  int power2 = analogRead(inputPin);
  delay(delayTime);
  int power3 = analogRead(inputPin);
  delay(delayTime);
  int power4 = analogRead(inputPin);
  delay(delayTime);

  bool p1 = (power1 > THRESHOLD);
  bool p2 = (power2 > THRESHOLD);
  bool p3 = (power3 > THRESHOLD);
  bool p4 = (power4 > THRESHOLD);

  if (p1 && !p2 && !p3 && p4) {
    inputStr += "01";
    Serial.println(inputStr);
  } else if (p1 && !p2 && p3 && !p4) {
    inputStr += "11";
    Serial.println(inputStr);
  } else if (!p1 && p2 && p3 && !p4) {
    inputStr += "10";
    Serial.println(inputStr);
  } else if (!p1 && p2 && !p3 && p4) {
    inputStr += "00";
    Serial.println(inputStr);
  } else if (p1 && p2 && p3 && p4) {
    Serial.print("Binary string is: ");
    Serial.println(inputStr);
    Serial.println(inputStr.length());
    //processBinaryMessage(inputStr);

    Serial.println("Would you like to restart? (y/n)");
    while (true) {
      if (Serial.available()) {
        char nORy = Serial.read();
        if (nORy == 'y' || nORy == 'Y') {
          inputStr = "";
          outputStr = "";
          lightDetected = false;
          break;
        } else if (nORy == 'n' || nORy == 'N') {
          Serial.println("Halting program.");
          while (true); // Halt
        }
      }
    }
  }
}

// Function to convert binary string to decimal
int processBinaryMessage(String binaryStr) {
  
 for (int x = 0; x < inputStr.length()/8; x += 8) {
  for (int i = 8; i >= 0; i--) {
    int decimalValue = 0;
    char ConvertedChar = "";

   
   if (binaryStr[8-i] == '1') {
      int power = i-1;
      int changeValue = pow(2, power);  // Compute power of 2 for each bit
      //While testing, if over 2, the value of change value would be off by one. I tested and checked everything and do not know why
      if (power>1){
        changeValue += 1;
      }

      decimalValue +=changeValue;
      
    }
     ConvertedChar = char(decimalValue);
     outputStr = outputStr + ConvertedChar;
     Serial.println(outputStr);


  }
  }

  
}

What?

It is not entirely clear what you are doing, but I can make a couple of comments.

The argument to delay() is integer milliseconds, so this float calculation is not appropriate

     delay(1.25 * delayTime)

Depending on which Arduino you are using, analogRead() takes a significant fraction of a millisecond.

  delay(delayTime);
  int power3 = analogRead(inputPin);

For more accurate delays, use delayMicroseconds();

understood. I have a phototransitor that reads 0 when a laser is pointed at it, and some number when not. I turn some string into bits and use manchester encoding to transmit them via laser. this is the reciver code

Ill bet that the transmitter code looks quite a bit different. Either end could have a timing problem.

They both do. Im trying to fix this one first though.

If you have errors in both transmitter and receiver, wouldn't it be better to tackle the transmitter first?

A clever approach is to write code that has exactly the same timing for both transmitter and receiver.

If you receive what arrives as it does and interpret intervals with a little +/- tolerance, you get a more stable transmission. Mitsubishi posted a White Paper about led to led serial transmission between handheld PDA's and like where short pulses up to 4 intervals are 0 and long pulse 7 to 10 intervals are 1.... at 55KHz intervals to get a low baud rate but the detector is the same led used to signal!

They allowed a lot of slop but the read window is 10 intervals per bit transmitted, room for slop.

Model the imperfect and code for that should make a robust system.

Your equipment is not precision.
Your measurement equipment is not precision.
Your total precision is the first imprecision times the second imprecision.

This topic is the same as another (two, now one) topic where the last OP post was the surprise rollout of the code (not formatted) in this topic's Post #1.

Does this work?
Many inputs will not read an exact 0... negative is also not to be expected...

If this is meant to keep repeating the while loop, you can simply remove it.
Else it will bring you to invisible main (basically starting at setup() again.

Could you explain what you are trying to achieve?
It seams this vould be done much easier...

No, it will not. It will exit the loop() function which will return you to main() which will then again call the loop() function, not setup().

1 Like