Hey guys,
I have a tricky problem on my hands and have run out of ideas. Here's the situation:
I am connecting the Electron to another device via the Serial1 port, running at 57600bps. The serial port is free-running, and is constantly outputting messages of variable payload size (17 bytes up to 360 bytes) as defined in its protocol ICD. I have about 20 different message types all running at different frequencies, ranging from 1Hz up to 50Hz.
When I am triggering the function to collect the received packets, stuff them in my UDP buffer, and send them out, I start to lose serial data.
I have tried two approaches so far:
-
In my application loop, have a loop that reads the serial data into a circular buffer, and when enough messages have been read to generate a UDP packet of under 1024 bytes, shoot it out. This did not work because whenever the UDP packing function was being called, a bunch of serial messages were being dropped. I diagnosed this by comparing a message counter in my read loop with the UDP function being called, and one without. The counter without the UDP function call was incrementing at much faster rate (approximately 4-fold, meaning 3 out of 4 packets were being dropped).
-
In my application loop, run only the function that packs the UDP packets to send them out, and reading the serial only via the serialEvent1() function. Less packets were being dropped this way, but still enough to break the protocol handshake/heartbeat.
This is what serialEvent1() looks like:
void serialEvent1(void){
uint8_t temp;
mavlink_message_t message;
mavlink_status_t status;
bool new_message = false;
while(Serial1.available() > 0){
temp = Serial1.read();
// -- Check for a complete message if(mavlink_parse_char(MAVLINK_COMM_0, temp, &message, &status)){ // -- Got full message, copy it for processing later! memcpy((uint8_t *) &message_buffer[message_buffer_next], (uint8_t *) &message, sizeof(mavlink_message_t));
if(message_buffer_next == BUFFER_SIZE - 1){ message_buffer_next = 0; } else { message_buffer_next++; }
}
}
}
This is what the process_udp function looks like:
uint8_t udp_buffer[1024];
uint16_t buffer_offset;
void process_udp(){
if(message_buffer_next != message_buffer_index){
// -- if message will blow buffer, send it. if(message_buffer[message_buffer_index].length + buffer_offset > 1024){ IPAddress ip(x, x, x, x); udp.sendPacket((uint8_t *) &udp_buffer, buffer_offset, ip, 5000); buffer_offset = 0; } // -- copy new message onto buffer memcpy((uint8_t *) &udp_buffer[buffer_offset], (uint8_t *) &message_buffer[message_buffer_index], message_buffer[message_buffer_index].length); buffer_offset += message_buffer[message_buffer_index].length; if(message_buffer_index == BUFFER_SIZE - 1){ message_buffer_index = 0; } else { message_buffer_index++; }
}
}
And in my mainloop, I am simply calling process_udp(). From my understanding, calling it like this will execute the function only when there is spare CPU time, and interrupt on the serial port when new data available. This should not result into any dropped data, unless there is something I'm missing? Isn't the serialEvent1() function the result of a hardware interrupt?
I have noticed also, that the small I pack my UDP packets, the more data I'm dropping, which hints at some blocking process in the sendto function.
Any ideas?