SERIAL losses first few symbols during transmission WHEN interrupt initialized

When the modem receives a call then 2 things are happening:
a) on modem Pin 10 is LOW level which I catch by INT0
b) modem send to leonardo board the string "number data time etc." > leonardo send to PC

so I made this code for debug, and especial have used PORT writing since it 20x faster then digitalWrite, but anyway I loose first few symbols from serial transmit

//Serial modem > leonardo > PC

volatile byte flag = 0;

void setup(){
  pinMode(13, OUTPUT);
  pinMode(3, INPUT); //low level from modem for INT0
  while(!Serial); // for leonardo
  Serial.begin(115200);
  Serial1.begin(115200);
  attachInterrupt(0, blink, LOW);

  }

void loop(){
  // Копируем Serial1 --> Serial
  if(Serial1.available()) Serial.write(Serial1.read());
  // Копируем Serial --> Serial1
  if(Serial.available()) Serial1.write(Serial.read());

  if (flag) {
	  PORTC |= (1 << 7);
	  flag = 0;
  }

}

void blink() {
	flag = 1;
}

any idea? or how to make this code more faster to catch all symbols OR how to change the algorithm to catch all symbols. please help

I use

void fReceiveSerial_LIDAR( void * parameters  )
{
  bool BeginSentence = false;
  sSerial.reserve ( StringBufferSize300 );
  char OneChar;
  for ( ;; )
  {
    EventBits_t xbit = xEventGroupWaitBits (eg, evtReceiveSerial_LIDAR, pdTRUE, pdTRUE, portMAX_DELAY);
    if ( LIDARSerial.available() >= 1 )
    {
      while ( LIDARSerial.available() )
      {
        OneChar = LIDARSerial.read();
        if ( BeginSentence )
        {
          if ( OneChar == '>')
          {
            if ( xSemaphoreTake( sema_ParseLIDAR_ReceivedSerial, xSemaphoreTicksToWait10 ) == pdTRUE )
            {
              xQueueOverwrite( xQ_LIDAR_Display_INFO, ( void * ) &sSerial );
              xEventGroupSetBits( eg, evtParseLIDAR_ReceivedSerial );
            }
            BeginSentence = false;
            break;
          }
          sSerial.concat ( OneChar );
        }
        else
        {
          if ( OneChar == '<' )
          {
            sSerial = ""; // clear string buffer
            BeginSentence = true; // found begining of sentence
          }
        }
      } //  while ( LIDARSerial.available() )
    } //if ( LIDARSerial.available() >= 1 )
    xSemaphoreGive( sema_ReceiveSerial_LIDAR );

  }
  vTaskDelete( NULL );
} //void fParseSerial( void * parameters  )

This line "if ( LIDARSerial.available() >= 1 )" before entering the while loop since trying to receive serial on the Due, STM32, and ESP32. Using "if ( LIDARSerial.available() >0 )" caused receive data loss.

I also send sentence delimiters and discard the non complete sentences. In addition, once the sentence beginning has been received, I do not delete the receive buffer, even if the loop exits and reenters, until a new sentence descriptor is received. I am receiving around 255 words per sentence.

Idahowalker:
"if ( LIDARSerial.available() >= 1 )" before entering the while loop since trying to receive serial on the Due, STM32, and ESP32. Using "if ( LIDARSerial.available() >0 )" caused receive data loss.

I cant imagine this :slight_smile: why, should be some logical explain
BUT anyway, even if I make while instead of if, I think this is not applicable to my case because

a) if INT0 triggered doesnt matter what I have while/if
b) INT0 fired at the same time when serial.available>0. both things start at the same time

  pinMode(3, INPUT); //low level from modem for INT0
  attachInterrupt(0, blink, LOW);

If your modem is connected to pin 3, why do you hook the interrupt to pin 2?

Whandall:
If your modem is connected to pin 3, why do you hook the interrupt to pin 2?

@alexblade, there's already a mechanism for avoiding this careless mistake: digitalPinToInterrupt()
Why don't you use it?

Be careful of level-triggered interrupts. They will fire continuously as long as the condition is true. That can eat up a lot of processor time. Why do you need an interrupt to capture your "modem pin" going low? Why not use polling and the state change example from the IDE?

If you MUST use an interrupt, first choice would be edge-triggered (FALLING). If you MUST use a level-triggered interrupt, then disable the interrupt in the ISR and don't re-enable it in the main code until the input goes HIGH again.

Whandall:
If your modem is connected to pin 3, why do you hook the interrupt to pin 2?

because this is Leonardo board (its mentioned in post 1 :slight_smile:

gfvalvo, to honest say I want to like train low level understanding/coding... but in this particular case mentioned pin is not mistake. I can write digitalPinToInterrupt() and still losing characters

@Be careful of level-triggered interrupts. They will fire continuously as long as the condition is true.@
hm I dont know this thank you, but any way I'm usually using or millis or detach to avoid bounce

alexblade:
@Be careful of level-triggered interrupts. They will fire continuously as long as the condition is true.@
hm I dont know this thank you, but any way I'm usually using or millis or detach to avoid bounce

I don't know what that means and it's not what's shown in the code you posted. But, suit yourself.

gfvalvo,
detach means
ISR(){
detachInterrupt();
state=!state;
}

millis mean
ISR(){
static unsigned long millis_prev;
if(millis()-100 > millis_prev) state = !state; // меняем значение на противоположное
millis_prev = millis();
}

but i the code I posted led can blinking as long as want doesnt matter, blink is needed just to see if I caught the INT0

main idea in the code to show how I send data serial to PC. and problem in the post 1
have you any idea?

alexblade:
have you any idea?

Yes, I have some Ideas:

  • Post the ACTUAL code that's causing the problem you're talking about.

  • Post the COMPLETE code.

  • Post the code properly with CODE TAGS.

gfvalvo? this is ctrlC ctrlV complete code :slight_smile: with code tags . POST1

when modem send data (and in this time ISR fired) then first few 5-10 symbols is missing from transmit.
if comment interrupt (disable part of code) then I dont see led blink but see all data in serial port

Why do you need an interrupt to monitor Modem Pin 10?

this code like debug.
INT0 is needed to monitor state of modem pin 10
serial is needed to monitor state of modem pin 7

You aren't providing any answers that make sense. I'm done wasting my time. Good luck.

gfvalvo:
Why do you need an interrupt to monitor Modem Pin 10?

because low level is on pin 10 only 30ms when incoming call is.

I do not have other instruments check if it was LOW and if it was in generally sometime. if you know please advise

Things go so much better if you have clear requirements in you're head and then you can clearly communicate them to others. I still don't think that you need interrupts to catch a 30ms pulse. But, if you want to, I told you the answer back in Reply #5. Use an Edge-Triggered (FALLING) interrupt.

Your next problem is that once you set Bit 7 in PORTC, you never reset it. So, the LED is always on.

gfvalvo:
I still don't think that you need interrupts to catch a 30ms pulse.

May be. May be exist in the worl other solution. May be need other algorithm. But. with my current brain(knowledge)> If need to catch two events, and one of them only can catch by low level 30-edge=<25ms, so I can do this only in above mode. sorry for my newb questions.

I have changed to CHANGE/FALLING. no happy.

"Your next problem is that once you set Bit 7 in PORTC, you never reset it. So, the LED is always on."
I know. I can: PORTC^=bit7. or can: if (flag) printf; but this is not cause for "losing symbols"

BTW I changed IF in my code to WHILE and I have used cli(); and seems is working now... I will test more to be ensure. and let you know.

thank you for your help.