How to get this code working without delay();

Hello all,
I am having a problem reading from the serial buffer without using
a delay.

I have an infrared LED transmitting to a infrared dectector
which is connected to the serial port Rx. Both are on the same
uno board.

loop() sends a string out via the IR Tx, then reads the serial Rx buffer
and prints out the string which was sent.

I have to add a delay in the while loop in order
for this loop to keep printing the strings out.

After searching the forum for this issue, the delay should not
be needed but without it the serial prints just get hung up.

#define nullchar '\0'
int stringSend(char*);
void sendByte(byte);
void  pinOn(void);
void  pinOff(void);
void timer2_init(void);
#define Bd   424   //2400baud = 424, 4800 is 212, 9600 is 106 micro-seconds 
char incomingByte;
char*  stringarray[] = {"Holy Cow Batman", "To be or not to be that is the question", "Get in here Watson"};



void setup() {
  Serial.begin(2400);
  while (!Serial);
  timer2_init();
}


/* sends three strings to the IR Tx, then reads H.W. Serial Rx buffer, and prints it out */
void loop() {
static int  x = 0;

  if (x > 2){
    x = 0;
  }
 
  stringSend(stringarray[x]);
  x++; 
  
  while( Serial.available() > 0) {
      incomingByte = Serial.read(); 
      Serial.print(incomingByte);
      delay(10);                 //serial print hangs up without this
  }
 
} //loop


/* sends a string a char at a time to sendByte */
int stringSend(char* thestring)
{
  char ch;
  int j = 0;

  if ( thestring == NULL)
    return 0;

  while ( *(thestring + j) !=  nullchar)  {
    ch = *(thestring + j);
    sendByte(ch);
    j++;
  }

  sendByte('\n'); //send a return
  return 1;

}


/* low level routine that sends the byte to the IR Tx */
void sendByte(byte mybyte) {

int i;

  //send start bit
  pinOn();     
  delayMicroseconds(Bd);
  
  for (i = 0; i < 8; i++) {

    if (mybyte & _BV(i)) {
      pinOff();
      delayMicroseconds(Bd);
    }
    else {
      pinOn();
      delayMicroseconds(Bd);
    }
  }
  
  //send stop bit
  pinOff();
  delayMicroseconds(Bd);

}

Please post a complete sketch so it can be tested locally with a wire loopback to emulate the IR path.

Here is all the code.

#define nullchar '\0'
int stringSend(char*);
void sendByte(byte);
void  pinOn(void);
void  pinOff(void);
void timer2_init(void);
#define Bd   424   //2400baud = 424, 4800 is 212, 9600 is 106 micro-seconds 
char incomingByte;
char*  stringarray[] = {"Holy Cow Batman", "To be or not to be that is the question", "Get in here Watson"};



void setup() {
  Serial.begin(2400);
  while (!Serial);
  timer2_init();
}


/* sends three strings to the IR Tx, then reads H.W. Serial Rx buffer, and prints it out */
void loop() {
static int  x = 0;

  if (x > 2){
    x = 0;
  }
 
  stringSend(stringarray[x]);
  x++; 
  
  while( Serial.available() > 0) {
      incomingByte = Serial.read(); 
      Serial.print(incomingByte);
      delay(10);                 //serial print hangs up without this
  }
 
} //loop


/* sends a string a char at a time to sendByte */
int stringSend(char* thestring)
{
  char ch;
  int j = 0;

  if ( thestring == NULL)
    return 0;

  while ( *(thestring + j) !=  nullchar)  {
    ch = *(thestring + j);
    sendByte(ch);
    j++;
  }

  sendByte('\n'); //send a return
  return 1;

}


/* low level routine that sends the byte to the IR Tx */
void sendByte(byte mybyte) {

int i;

  //send start bit
  pinOn();     
  delayMicroseconds(Bd);
  
  for (i = 0; i < 8; i++) {

    if (mybyte & _BV(i)) {
      pinOff();
      delayMicroseconds(Bd);
    }
    else {
      pinOn();
      delayMicroseconds(Bd);
    }
  }
  
  //send stop bit
  pinOff();
  delayMicroseconds(Bd);

}



//turns output pin 3 on
void  pinOn() {
  cli();
  TCCR2A |= _BV(COM2B1);
  sei();
}


//turns output pin 3 off
void  pinOff() {
  cli();
  TCCR2A &= ~(_BV(COM2B1));
  sei();
}

//timer2 setup for 38kHz carrier freq.
void timer2_init () {
  cli();
  //set up timer2 for 38kHz square wave, to turn output on COM2B1 COM2B0 = 1 0  clear on match, set when tc2 = 00
  TCCR2A = _BV(WGM20);             //mode 5
  TCCR2B = _BV(WGM22) | _BV(CS21); //prescaler /8
  OCR2B = 13;
  OCR2A = 26;

  pinMode(3, OUTPUT);
  sei();
}

Change the while to an if and remove the delay()

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data.

...R

I think to really simulate IR Tx, Rx I will have to use 2 uno’s. As the code is now I get a string each pass of the loop which in reality can’t happen since the loop time is so fast and the Tx so slow. Then checking the buffer for 1 character each time through the loop() should be fine.

noweare:
I think to really simulate IR Tx, Rx I will have to use 2 uno's.

Very sensible.

...R

Robin2:
Very sensible.

...R

:wink: yeah, thanks for that