[SOLVED] Master and Slave freeze when receiving bytes on Serial (IBUS)

EDIT: See post #16 for solution and how daft I am.

Problem:
I'm in the middle of an arduino flight controller project and I use a receiver that communicates using a serial protocol at 115200 bps. I can intercept and read the data fine but I also want to send it to a slave arduino pro micro (the master is the arduino nano which reads serial). Reason for this is because the master will handle several devices in the future and the slave arduino needs to control ESCs. Hence this is a time critical project.

However, as soon as I connect the two arduinos in I2C and start writing (20) bytes, the system hangs and the slave doesn't receive anything. BUT, the moment I turn the radio off (such that the receiver stops sending bytes) the slave suddenly receives the last buffered bytes. Strange behaviour because I used software serial to debug and ensure that reading "ibus" (protocol of the receiver) is correct and my subroutine works great.

In short:
Receiver (to Serial) -> Nano (to I2C) -> Pro Micro (to Serial PC) -> Serial Monitor

Software
I will link the code to my google drive.

Hardware setup:
I2C:
Arduino nano 328P = master
Pro micro 32U4 = slave, address 8
both connected directly, no pull ups. Reason is when i add 2.2k pull ups the whole i2c network freezes both arduinos, can't even upload anything.

Serial:
Radio receiver's output --> RX pin on Nano

Power:
USB power -> Pro micro
Vcc on pro micro -> Nano's 5V
Vcc on pro micro -> receiver
GND all common

LED on nano is the breakout one (PIN13, but i prefer using ports as seen in the code)

Maybe some of you more experienced folk here can help me figure this out?

Thanks in advance

Just post your .ino files here as it will be much easier to access them.

...R

MASTER CODE - NANO

// I2C MASTER - NANO

#include <Wire.h>

//  ###########################################################################
//  ######################## IBUS declarations ################################
//  ###########################################################################
 // Max iBus packet size (2 byte header, 14 channels x 2 bytes, 2 byte checksum)
static uint16_t rcValue[14];
static uint8_t ibusIndex = 0;
static uint8_t ibus[32] = {0};	
static uint8_t safeibus[20] = {0};		//ibus safe to send via i2c (checksum successful)
static boolean rxFrameDone;
unsigned long timeoutIBUS = 0;			//so we aren't stuck in an infinite loop if we disconnected the receiver, etc...
unsigned long timeoutLength = 20000;		//timeout length in microseconds. 
//prototype
void readibus();

void setup()
{	

	Wire.begin();			//Master
	Serial.begin(115200);		//bit rate of ibus
	DDRB |= 1<<PINB5;     //output LEDPIN
	PORTB &= ~(1<<PINB5);      //set low initially
}

void loop()
{	

	if (rxFrameDone == false )		//make sure we have filled the ibus buffer
	{
		Wire.beginTransmission(8);		//start talking to slave 8
		Wire.write(safeibus,20);			//upon acknowledgment, send 20 bytes 
		Wire.endTransmission();
		rxFrameDone = true;			//reset for next buffer
		delay(50);					//delay is only for debugging
	}
	PORTB |= (1<<PINB5);		//led high
	readibus();					
	delay(50);					//delay is only for debugging
	PORTB &= ~(1<<PINB5);		//led  low

}


void readibus()		//Has to be called from time to time, to check if at least 32 bytes arrived
{	
	uint16_t chksum,rxsum;
	uint8_t packet1, packet2;		//we don't care about first 2 packets, so they can be temporary
	unsigned long currenttime = 0;
	//rxFrameDone = true;		//to start reading ibus bytes



	/*
	this check needs to be done frequently ~ at the rate of ibus packets (NOT rate of serial).
	Wait until we have 32 bytes waiting for us, remember this subroutine is ran continuously. The chip has 64 bytes buffer so we are set 
	even if we miss a whole ibus packet. 
	*/
	if (Serial.available() >= 32)
	{
		timeoutIBUS = micros();			//Note timer start (avoids infinite loop)
		packet2 = Serial.read();		//read the first packet, but put it in 2nd variable for when the loop starts
		while (rxFrameDone == true)		//keep looking for 0x2040, if we never find it, then we need a time out
		{
			packet1 = packet2;				//shift previous packet here
			packet2 = Serial.read();		//find next packet
			//ibus packets start with 0x2040
			if (packet1 == 0x20 && packet2 == 0x40)		//check if we found the start of ibus packets
			{
				//read ibus and perform checksum
				ibus[0] = packet1;			//we dont need to copy ibus[0 and 1] but for good measure we will
				ibus[1] = packet2;
				for(int i=2;i<32;i++)		//copy rest of available bytes into the ibus array
				{
					ibus[i] = Serial.read();

				}
				//perform checksum on data.
				chksum= 0xFFFF;		
				for (int i = 0; i < 30; i++)
				{
					chksum -= ibus[i];
				}

				rxsum = ibus[30] | (ibus[31] << 8);		//copy the checksum from ibus, contained in the last 2 bytes
				if (chksum == rxsum)	//make sure chksum matches with what we received
				{
					for(int i = 0; i<20; i++)		//copy 10 channels (10 x 2 bytes = 20) into our i2c array,
					{
						safeibus[i] = ibus[i+2];		//ibus data packets start on the third packet, 0, 1, > 2 <
					}
				}
				else
				{
					//checksum FAILED for some reason, could be a bad connection, best not to copy data
				}
				rxFrameDone = false;		//exit out of loop
			}
			else
			{
				currenttime = micros();
				//Checking for timeout, in case we are stuck in an infinite loop, receiver disconnected etc...
				if (currenttime - timeoutIBUS > timeoutLength)
				{
					rxFrameDone = false;		//exit the loop: however this means we will copy the PREVIOUS channel data to i2c. This might not be a good failsafe.
					//return;	
				}

			}

		}

	}
		
	


}

SLAVE CODE

// I2C SLAVE - PRO MICRO - 32U4

#include <Wire.h>
uint16_t ch[10] = {0};		//holds 10 channels, 16 bit values
int x;

void setup()
{
	Wire.begin(8);                // join i2c bus with address 8
	Wire.onReceive(receiveEvent);			//initiate a receive event
	Serial.begin(115200);			//initiate serial bus > this will talk with the computer so we can debug.
	x=0;
}

void loop()
{

	//Serial.print(ch[x]); Serial.print("\t");
	x++;
	if (x > 9) 
	{
		x=0;
	//	Serial.print("\n");
	}
		
}

void receiveEvent(int howMany)			//interrupt service routine for i2c
{
	
	int i=0;
	uint8_t lowbyte, highbyte;		//low and high bytes of channel values
	while(Wire.available())
	{
		lowbyte = Wire.read();		//read lower byte first
		highbyte = Wire.read();
		ch[i] = (highbyte << 8) | lowbyte;		//left shift the high byte to form a channel value
		Serial.print(ch[i]);	Serial.print("\t");			//display the data output on serial monitor.
		i++;
	}
	Serial.print("\n");			//new line for next receive event

}

So this is what happens. Radio is on, RX led on nano flashes. I switch the radio off (receiver stops sending bytes), then I get output from the arduino pro micro on serial. Here is the data:

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
1523 1610 1073 1502 1578 1575 1000 1000 1000 1000 
1523 1610 1073 1502 1578 1575 1000 1000 1000 1000 
1523 1610 1073 1502 1578 1575 1000 1000 1000 1000 
1523 1610 1073 1502 1578 1575 1000 1000 1000 1000 
1523 1610 1073 1502 1578 1575 1000 1000 1000 1000 
1523 1610 1073 1502 1578 1575 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000

What does this mean?
Safeibus is originally 0, as set when initializing the array. Then the receiver starts sending bytes, this gives us the different values for each channel. After the radio is switched off, receiver goes into failsafe mode and sends 1000 for each channel, this is what we receive via i2c.

IF i switch the radio back on, either nano stops sending or the micro stops receiving. Both of which causes nothing to be shown on serial monitor.

I'm completely confused by your connection arrangements.

Is the Nano connected to the Micro by both wireless and by wired serial?

I am very suspicious of your use of WHILE in a few places because that is a blocking loop and nothing else gets a look in before it is finished. Have a look at how serial data is received without blocking in the 2nd and 3rd examples in Serial Input Basics. The technique is widely applicable.

...R

The nano and micro are connected together by i2c only. The only wireless device is the radio receiver which is connected to the serial port of the nano's RX pin. Micro has USB serial so I can read what it's seeing on the serial monitor.

Have I got this right?

PC ---> USB cable ---> Micro(Serial) ---> I2C --->Nano ----->(Serial) --> WirelessDevice ----> ?

What is the wireless device?
What is it talking to?
Is the wireless communication 1-way or 2-way?

...R

You got it right, but the arrows should point in the opposite direction. The wireless device is a radio receiver, model FS-IA6B. Communication is one way, the receiver sends serial data to the RX pin on Nano.

KalBEN.10:
You got it right, but the arrows should point in the opposite direction. The wireless device is a radio receiver, model FS-IA6B. Communication is one way, the receiver sends serial data to the RX pin on Nano.

Please post a link to the datasheet for the wireless device and also tell us what it is receiving the data from.

Please provide some examples of the messages that are received and tell us what is the interval between messages.

Have you studied the link I gave you in Reply #4?

...R

  1. Data sheet is not publically available because it is a chinese manufacturer. However, the ibus protocol has been reverse engineered by people in rcgroups.com forums.
    I found a program on github that converts ibus to ppm using an arduino so I investigated how ibus is read, and worked from there to create my own subroutine. Link to github: ibus2ppm

As you can see from his code, it is ran constantly in a loop without delays. I could not use this approach because my arduino will need to (not yet) communicate with several devices on i2c (mpu-9250 and a bmp-280) as well as an ultrasonic sensor possibly in the future.
I thought that if I place a check to see if at least 32 bytes are in buffer, that means a whole ibus packet arrived.

  1. The messages I receive from i2c (only when i switch off the radio) are shown in post #3.

To debug (and make sure i can read ibus) I plugged the arduino nano to my computer, and used SoftwareSerial library to read ibus.
Here are the results:

channels 1-10, I move the sticks around and flip some switches.

Connected
0 0 0 0 0 0 0 0 0 0 
1523 1613 1069 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1069 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1069 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1069 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1069 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1075 1515 1010 1010 1000 1000 1000 1000 
1523 1610 1180 1538 1010 1010 1000 1000 1000 1000 
1530 1611 1264 1567 1010 1010 1000 1000 1000 1000 
1623 1636 1370 1622 1010 1010 1000 1000 1000 1000 
1697 1687 1424 1701 1010 1010 1000 1000 1000 1000 
1753 1730 1544 1715 1010 1010 1000 1000 1000 1000 
1787 1757 1686 1718 1010 1010 1000 1000 1000 1000 
1834 1805 1827 1726 1010 1010 1000 1000 1000 1000 
1904 1870 1936 1794 1010 1010 1000 1000 1000 1000 
2000 1957 1998 1865 1010 1010 1000 1000 1000 1000 
2000 2000 2000 1974 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 2000 1010 1010 1000 1000 1000 1000 
2000 2000 2000 1999 1010 1010 1000 1000 1000 1000 
1903 1912 1999 1915 1010 1010 1000 1000 1000 1000 
1795 1792 1988 1661 1010 1010 1000 1000 1000 1000 
1643 1639 1816 1557 1010 1010 1000 1000 1000 1000 
1567 1583 1613 1502 1010 1010 1000 1000 1000 1000 
1522 1443 1352 1502 1010 1010 1000 1000 1000 1000 
1467 1310 1096 1494 1010 1010 1000 1000 1000 1000 
1374 1142 1066 1294 1010 1010 1000 1000 1000 1000 
1341 1119 1066 1152 1010 1010 1000 1000 1000 1000 
1309 1119 1066 1084 1010 1010 1000 1000 1000 1000 
1296 1119 1065 1026 1010 1010 1000 1000 1000 1000 
1233 1119 1063 1012 1010 1010 1000 1000 1000 1000 
1177 1119 1060 1011 1010 1010 1000 1000 1000 1000 
1130 1119 1060 1011 1010 1010 1000 1000 1000 1000 
1062 1119 1060 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1059 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1060 1010 1010 1010 1000 1000 1000 1000 
1033 1119 1060 1010 1010 1010 1000 1000 1000 1000 
1035 1119 1063 1011 1010 1010 1000 1000 1000 1000 
1086 1119 1065 1012 1010 1010 1000 1000 1000 1000 
1194 1214 1066 1052 1010 1010 1000 1000 1000 1000 
1359 1364 1067 1193 1010 1010 1000 1000 1000 1000 
1477 1479 1074 1296 1010 1010 1000 1000 1000 1000 
1523 1537 1085 1402 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1560 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1500 2000 
1523 1610 1096 1502 1010 1010 2000 1000 1500 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 2000 2000 
1523 1610 1096 1502 1010 1010 2000 1000 1500 2000 
1523 1610 1096 1502 1010 1010 1000 1000 1500 2000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 2000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 2000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 2000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 2000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000 
1523 1610 1096 1502 1010 1010 1000 1000 1000 1000
  1. I have looked at the link you gave and it is very useful, bookmarked it. However I don't think it applies to my case because I have no direct control over what is sent to me. IBUS doesn't send end markers, its just a stream of bytes and it's arduino's job to find the start of the packets and process the data. With that being said, I am looking to rewrite readibus().

I found something interesting. When I use a wire.begintransmission command, the program locks up until the radio is turned off, i know this because the LED is not flashing. But if I don't call any wire commands the program works fine because LED flashes. Is it possible that this is a wire library limitation? If so, are there any better libraries that I can use?

Responding to Reply #9 ...

Sorry. Maybe my brain is on holiday at the moment but I feel even more confused.

You say you have a receiver that communicates with your Nano using Serial. Presumably that receiver is sending ascii characters to the Nano (or maybe bytes)?

Where does IBUS come into this? I presume, if I redrew the diagram in Reply #6 with the arrows pointing the other way that IBUS would be further to the right?

And if you have data in IBUS format why on earth would you make things more complicated and less precise by converting to PPM?

But even if I put that to one side how is the PPM data getting converted into Serial data.? Surely you need PPM to IBUS (or to something) rather than IBUS to PPM?

Why is the radio device a secret? Even if you don't have an English language datasheet surely you can tell us what the radio device is and what it does?

...R

IBUS is a serial communication protocol, it sends bytes of information in a continous stream, every couple ms (it is unknown to me how often). To put it another way. I have a radio, this one: Flysky fs-i6 2.4g 6ch afhds rc radio transmitter with fs-ia6 receiver for fpv rc drone engineering vehicle boat robot Sale - Banggood.com-arrival notice-arrival notice

and it comes with a radio receiver:

By connecting the receiver FS-IA6B to my arduino Nano on the RX pin, I can receive bytes of data in the format of IBUS. This is not a problem, see post #9 to view my intercepted data.

PC <-- Serial <-- Micro <-- I2C <-- Nano <----(Serial - IBUS) <-- Receiver <--- Radio Transmitter

Robin2:
And if you have data in IBUS format why on earth would you make things more complicated and less precise by converting to PPM?

Exactly, I don't want to use PPM, my receiver is perfectly capable of producing PPM, PWM and IBUS, best of which is IBUS. I used the code from github to figure out how to read IBUS. That's all. PPM doesn't come into this at all.

Robin2:
Why is the radio device a secret? Even if you don't have an English language datasheet surely you can tell us what the radio device is and what it does?

The device is not a secret, it's simply lacking documentation. I tried looking for a datasheet but found nothing. People in various forums had to reverse engineer ibus to read its data.

PS.
I am building a quadcopter drone using 2 arduinos as flight controller. The master will be responsible for collecting data from all the connected devices and then output to slave micro which controls the ESCs and motors.

OK. I think things are a little clearer now. Is this correct ...

  • The nano receives IBUS data via Serial
  • It sends that data unchanged via I2C to the Micro
  • The Micro uses the data (for something)
  • The Micro sends debug messages to the PC over its USB cable.

You say the IBUS data comes at intervals and you have not said that it includes any terminating character that the Nano could use to detect the end of a message (or a starting character which could be similarly used). If there are end- and/or start-characters that will make things very much easier - that is how the examples in my tutorial work.

If there are no start- or-end-characters then the practical way to identify the end of a message is to measure the time between characters. When the time is longer than the normal inter-character gap you will know you are in the interval between messages.

If you don't have a system to identify the end of a message you run the risk of reading the end of one message and the start of another which would cause havoc.

Do you have a program that just receives the IBUS data and shows it on the Serial Monitor?

...R

You are correct.

Here is my code for debugging ibus:

#include <SoftwareSerial.h>
SoftwareSerial IBUS(2,3);		//RX TX


//IBUS
// Max iBus packet size (2 byte header, 14 channels x 2 bytes, 2 byte checksum)
static uint16_t rcValue[14];
static uint8_t ibusIndex = 0;
static uint8_t ibus[32] = {0};	
static uint8_t safeibus[20] = {0};		//ibus safe to send via i2c (checksum successful)
static boolean rxFrameDone;
unsigned long timeoutIBUS = 0;			//so we aren't stuck in an infinite loop if we disconnected the receiver, etc...
unsigned long timeoutLength = 20000;		//timeout length in microseconds. 
//prototype
void readibus();

///OTHER
int count=0;

//prototype
void readibus();



void setup()
{
	Serial.begin(115200);			//hardware serial for us to communicate with PC
	while(!Serial){}		//wait for HW serial to connect
	Serial.println("Connected");
	IBUS.begin(115200);			//Connect to our software serial
	IBUS.listen();			//set IBUS as our active soft serial. Might not be necessary but whatever
	
	DDRB |= 1<<PINB5;     //output LEDPIN
	PORTB &= ~(1<<PINB5);      //set low initially
}



void loop()
{
	//print ibus collected data.
	
	PORTB |= (1<<PINB5);
	readibus();
	Serial.print(rcValue[count]); Serial.print("\t");
	count ++;
	if (count >= 10) 
	{
		count = 0;
		Serial.print("\n");
		delay(50);
	}
	PORTB &= ~(1<<PINB5);
	


}

// reading ibus
void readibus()		//Has to be called from time to time, to check if at least 32 bytes arrived
{	
	uint16_t chksum,rxsum;
	uint8_t packet1, packet2;		//we don't care about first 2 packets, so they can be temporary
	unsigned long currenttime = 0;
	/*
	this check needs to be done frequently ~ at the rate of ibus (NOT rate of serial)
	//wait until we have 32 bytes waiting for us, remember this subroutine is ran continuously. The chip has 64 bytes buffer so we are set 
	even if we miss a whole ibus packet. Lucky us.
	*/
	rxFrameDone = true;
	if (IBUS.available() >= 32)
	{
		timeoutIBUS = micros();			//Save the timer
		packet2 = IBUS.read();		//read the first packet, but put it in 2nd variable for when the loop starts
		while (rxFrameDone == true)		//keep looking for 0x2040, if we never find it, then we need a time out
		{
			packet1 = packet2;		//shift previous packet here
			packet2 = IBUS.read();		//find next packet

			if (packet1 == 0x20 && packet2 == 0x40)		//check if we found the start of ibus packets
			{
				//read ibus and perform checksum
				ibus[0] = packet1;			//we dont need to copy ibus[0 and 1] but for good measure we will
				ibus[1] = packet2;
				for(int i=2;i<32;i++)		//copy all bytes into ibus array
				{
					ibus[i] = IBUS.read();

				}
				chksum= 0xFFFF;		//perform checksum on data.
				for (int i = 0; i < 30; i++)
				{
					chksum -= ibus[i];
				}

				rxsum = ibus[30] | (ibus[31] << 8);		//copy the checksum from ibus' last 2 packets
				if (chksum == rxsum)	//make sure chksum matches checksum we received (rxsum)
				{
					/*for(int i = 0; i<20; i++)		//copy 10 channels (10 x 2 bytes = 20) into i2c-ready array,
					{
						safeibus[i] = ibus[i+2];		
					}*/
					rcValue[0] = (ibus[ 3] << 8) | ibus[ 2];
					rcValue[1] = (ibus[ 5] << 8) | ibus[ 4];
					rcValue[2] = (ibus[ 7] << 8) | ibus[ 6];
					rcValue[3] = (ibus[ 9] << 8) | ibus[ 8];
					rcValue[4] = (ibus[11] << 8) | ibus[10];
					rcValue[5] = (ibus[13] << 8) | ibus[12];
					rcValue[6] = (ibus[15] << 8) | ibus[14];
					rcValue[7] = (ibus[17] << 8) | ibus[16];
					rcValue[8] = (ibus[19] << 8) | ibus[18];
					rcValue[9] = (ibus[21] << 8) | ibus[20];
					//for(int x=0;x<10;x++)
					//{
					//	Serial.print(rcValue[x]);	Serial.print("\t");
					//
					//}
					//Serial.println("");
				}
				else
				{
					//checksum FAILED for some reason, could be a bad connection, best not to copy data
				}
				rxFrameDone = false;
			}
			else
			{
				currenttime = micros();
				//Checking for timeout, in case we are stuck in an infinite loop, receiver disconnected etc...
				if (currenttime - timeoutIBUS > timeoutLength)
				{
					rxFrameDone = false;		//exit the loop: however this means we will copy the last channel data to i2c. This might not be a good failsafe.
					//return;		//exit the loop asap
				}

			}

		}

	}

}

While I don't have any indicators for end of a message, ibus does in fact send a 2 byte header, to indicate the start of the packet, it is 0x20 followed by 0x40. Therefore I do know when the packet starts so there is no need to measure the time interval.

I am obviously not able to test your program but I think it can suffer from the problem of not capturing the correct collection of bytes so as to have a complete message. Just because you have 32 bytes in the buffer does not mean you have the correct 32 bytes.

I would separate the collection of a complete message from the subsequent analysis to see if the checksum is correct.

You say the start values are 0x20 followed by 0x40. I assume that combination cannot occur within the data. Do you know if it is possible for a lone 0x20 or a lone 0x40 to appear in the data - if not then the parsing could be very simple, by treating that byte as an end-marker. It would mean you would lose the very first message, but you would get all the rest.

If it is essential to detect the pair then I would write code that checks regularly for 0x20 and sets a flag when it gets it. (I would not wait for any specific number of bytes). Then if the flag is set and if the next byte is 0x40 it sets another flag and starts saving the data. If that second byte is not 0x40 it would clear the first flag and go back to checking for 0x20. If the messages are a fixed length then you just need to read the next N bytes after finding the 0x40 and then go back to checking for 0x20

The purpose of all of this is to write code that can run asynchronously alongside other stuff in your larger program by picking up pieces of the incoming message as they are available rather than trying to treat it as a single chunk.

...R

Robin2:
I am obviously not able to test your program but I think it can suffer from the problem of not capturing the correct collection of bytes so as to have a complete message. Just because you have 32 bytes in the buffer does not mean you have the correct 32 bytes.

I would separate the collection of a complete message from the subsequent analysis to see if the checksum is correct.

You say the start values are 0x20 followed by 0x40. I assume that combination cannot occur within the data. Do you know if it is possible for a lone 0x20 or a lone 0x40 to appear in the data - if not then the parsing could be very simple, by treating that byte as an end-marker. It would mean you would lose the very first message, but you would get all the rest.

If it is essential to detect the pair then I would write code that checks regularly for 0x20 and sets a flag when it gets it. (I would not wait for any specific number of bytes). Then if the flag is set and if the next byte is 0x40 it sets another flag and starts saving the data. If that second byte is not 0x40 it would clear the first flag and go back to checking for 0x20. If the messages are a fixed length then you just need to read the next N bytes after finding the 0x40 and then go back to checking for 0x20

The purpose of all of this is to write code that can run asynchronously alongside other stuff in your larger program by picking up pieces of the incoming message as they are available rather than trying to treat it as a single chunk.

...R

IT WORKS

oh god

** AFTER MANY HOURS **

I checked my hardware setup because I was reading about i2c pullups, frequency, capacitance etc and this time I tried something different. INSTEAD of powering both the nano and ia6b receiver off the VCC pin on the micro, I decided to plug seperate USB cables to the nano and micro, with the nano powering the receiver from its 5v pin. I flashed the very same code I wrote and BOOM! it works. I can read all of the data from the micro flawlessly and the latency is minimal. I'm so happy. Is it possible that the receiver was drawing too much power and the potential difference was too little on the i2c bus such that the line was floating? Im worried this might be the case in the future as my quadcopter will run off a 5v 1A regulator. Maybe I'll add another one.

~

I do want to ask, which would be optimal/faster: whilst waiting for a full packet to arrive do something and then process the data, or copy the bytes as they go until I have a full packet and then process it?

I did a quick benchmark using the micros() function to check how long it takes until i have all 10channels using my code versus the ibus2ppm lib. It takes on average 150us with a maximum of 600us using my function and the ibus2ppm lib takes 5500us on average which sort of makes sense because it has to wait for all the packets to arrive and then process.

I must thank you for your help with the serial library. I will probably rewrite it to run asynchrounously since I will have many more devices hooked up on the i2c and pwm pins. Maybe even gps using software serial.

Additionally, would you recommend doing the checksum again on the micro (just in case I get odd data) or a simple failsafe will do (validate that data is between 1000-2000) ?

Thank you for sharing your knowledge and time.

KalBEN.10:
Additionally, would you recommend doing the checksum again on the micro (just in case I get odd data) or a simple failsafe will do (validate that data is between 1000-2000) ?

I have no idea what the risk of a data error is so I can't advise beyond guessing that a simple validation would be sufficient.

Maybe you could check to see if the next value is consistent with the previous value - for example 1100 might not normally follow immediately after 1900 with nothing in between.

I don't think you have explained why you are not receiving the data directly into the Micro so that the Nano would not be needed?

...R

Robin2:
I don't think you have explained why you are not receiving the data directly into the Micro so that the Nano would not be needed?

...R

There are various reasons. The main being that the micro is not fast enough on its own to process all of the information and poll all of the devices. I could for instance use interrupts but that would induce another problem and that is when writing PWM to ESCs. When an interrupt occurs during a pulse, the pulse is going to be a little too long and will cause "jerkiness" when flying the quadcopter. By offloading the control of ESCs to another arduino I don't need to worry about that. Also I can have many more serial ports and I do plan on adding a GPS unit. I will also have more program space and time to filter out IMU data.
I'm aware there are better processors out there that can do all of this better on their own. For now though, this is going to be a fun challenge for me which is the main reason why I'm doing this. Perhaps in the future I will replace everything with a single ARM cortex but If im not mistaken they don't support the arduino interface.