Code runs every other serial read?

I'm supposed to get a TTL Pulse every time I send an "x" on the serial port, but it happens every other time, I can't figure out if I'm not clearing the variable correctly or if I declared it wrong.

char incomingByte = 0;
int ppsin = 8;
const uint32_t c = 1;
int CTB = 9;
void setup() {
  Serial.begin(9600);
}

void loop() {

  if (Serial.available() > 0) {
    incomingByte = Serial.read();
  }
  if(incomingByte == 'x')
  {
    for (uint32_t i=c; i>0; i--)
      pulseIn(ppsin,HIGH);
    delayMicroseconds(1895);
    digitalWrite(CTB, HIGH);
    delay(1);
    digitalWrite(CTB, LOW);
    incomingByte = 0;
  }
}

Arduino atmega328P

Does the RX LED flash each time you send an x? What is sending the x? You could add Serial.print() statements to see when data is available, and what data was read.

What is connected to the ppsin pin?

const uint32_t c = 1;


    for (uint32_t i=c; i>0; i--)
      pulseIn(ppsin,HIGH);

How many times is this loop going to execute?

I have a 50us pulse coming in every 2 ms on ppsin pin.

CTB pin is my output pulse which is triggered on the incoming x from a Laptop serial.

The whole idea is to be able to output a pulse on CTB pin in sync to the pulses coming in ever 2ms triggered by the x. Everything works great, but it only works on every other x I get. I'm using a quality oscilloscope to check timings and I see the x is coming in every time but not my output pulse on CTB. Nothing is connected to CTB at the moment.

Is it a constant stream of characters? I ask because I think if you add the delays up, they are greater than the amount of time to get a single character at 9600 baud.

I still want to know several things.

How many times is that loop going to be executed? In other words, why are you creating a loop that executes exactly once?

The pulseIn function returns a time. Shouldn't that time play into the length on time to delay?

Why does the detection of the input pulse and generation of the output pulse depend on serial data of the right kind arriving?

Thank you for your interest, I will give you some background on my project.

This unit is going to be integrated into a seismic boat mapping oil pockets. Seismic boats work based on creating a sound wave and recording the bounce from the bottom of the ocean, like a sonogram. On the past the crew would use cables with hydrophones that extended for miles that would record the sound waves bounce and therefore create a map. This new boat we are trying to work on uses floating devices that are not connected, instead of recording when a sound wave came in like the wired, this devices record constantly at 2ms intervals, they are sync with GPS PPS. So in order for me to trigger the sound wave, I have to be able to fit the sound on a specific time slot.

The prototype I'm building takes a 10 PPS pulse and based of it, I generates 2ms pulses on one Arduino, that are off only by 20 us at worst case which is acceptable. I have a second Arduino that receives a command to shot(the one I'm working on now), the "x" over serial. When it receives the "x" it will count a certain amount of pulses before outputting a pulse, exactly at one of the 2m pulses I'm generation from Arduino Chip 1.

To answer your question, I have it set to wait for one pulse so I could fit it on the oscilloscope and compare, the value will be closer to 220 pulses or 450 ms from receiving the "x" and outputting a pulse. This will happen every 5-10 second. It all works fine except for the Arduino only pulsing every other "x". I don't need to use the time generated by pulse in, but I use pulse in to count the pulses "or time slots" before outputting my pulse.

I included a screenshot of my picoscope. The Yellow is the rs232 "x" coming in, the Red is the 50us every 2 ms pulses and the Green one is the pulse I'm trying to generate on the time slot, which as you can see it right on it. The time increments or scope of that image is 1ms.

I can see nothing wrong with your code, but sometimes with simple code it's just as easy to re write, which is what I've done below.

volatile int ppsin_count = -1;
int CTB = 9;



void setup() {
  Serial.begin(9600);
  attachInterrupt (0, isr_ppsin, RISING);
}

void loop() {

  if (Serial.available() > 0) {
    if('x' == Serial.read()) {
       noInterrupts();
       pps_count = 1;
       interrupts();
    
        while (pps_count != 0) {}; // Wait for Nth pps pulse, do this to
                               // make latencies more determanistic
        
       
        delayMicroseconds(1895);
        digitalWrite(CTB, HIGH);
        delay(1);
        digitalWrite(CTB, LOW);
        pps_count = -1;

     }
   }

}
  
  
void isr_ppsin () {

    if (pps_count > 0)
          pps_count--;
    
}

Totally untested of course, just trying to show a different method.


Rob

I believe I have found my problem.

I tried what PaulS suggested and added a Serial.Println here

  if (Serial.available() > 0) {
    incomingByte = Serial.read();
    Serial.println(incomingByte);
  }

To my surprise, it started working with this debugging code added. Now I started to think, maybe it is too much time to wait @ 9600 for the full character to come in and and compare, so maybe that's why only on the second run of the loop is when it reads it, so I figure I try a higher baud rate, 115200, and it started to work very well. Does this make sense?

Graynomad,

As always thanks for the suggested approach, could you explain to me why the while works better with the timing? I'm interested as I will be working a lot more with timing in the near future.

My currently working code

char incomingByte = 0;
int ppsin = 8;
const uint32_t c = 1;
int CTB = 9;
void setup() {
  Serial.begin(115200);
}

void loop() {

  if (Serial.available() > 0) {
    incomingByte = Serial.read();
  }
  if(incomingByte == 'x')
  {
    for (uint32_t i=c; i>0; i--)
      pulseIn(ppsin,HIGH);
    delayMicroseconds(1895);
    digitalWrite(CTB, HIGH);
    delay(5);
    digitalWrite(CTB, LOW);
    incomingByte = 0;
  }
}

I'll still be working on this for some time until the project starts so I will update as it goes.

could you explain to me why the while works better with the timing?

I understood that you want the time from the pps interrupt to producing your first pulse to be, as far as possible, always the same delay.

If the code was allowed to do the full loop while waiting for the interrupt to set pps_count to 0
the latency would vary more, so I figured to put it in a very tight loop so there wouldn't be much variation.

Another way to do it would be

 if (Serial.available() > 0) {
    if ('x' == Serial.read()) {
       noInterrupts();
       pps_count = 1;
       interrupts();
    }
    if (pps_count == 0) {
        delayMicroseconds(1895);
        digitalWrite(CTB, HIGH);
        delay(1);
        digitalWrite(CTB, LOW);
        pps_count = -1;

     }
   }

pps_count can become 0 at any time and with this code there are two if statements in the loop so there's a larger variable in the amount of time between pps_count being set to 0 by the ISR and the pulse actually starting.

To be honest your approach of using the pulseIn call is possibly more determanistic, but at the time that wasn't working so I was playing with other ideas.


Rob