I'm currently working on a robot which can operate in auto mode and which can be controlled in manual mode. For this demo I made arduino code and my ai2 project (both are in the appendix). Within my app I use the switch to switch between the modes and use the button to start, I can't seem to make it work so maybe i made my block even worse, but i just am not able to get the correct information.
I start with if a state switch or my run button is pushed, to send the number 200 to arduino, then in arduino i programmed it that when i receive 200 it know what index it needs to start for receiving my data (for a better vieuw check my receive3Bytes function), when i switch into manual mode i send bytes based on the position of my joystick (first send 255 to let it know which index my reading needs to start, again check the function to understand it better).
Now i hope i've sketched my problem, this is the first time sending bytes from ai2 to arduino so it's all new to me, but what am I doing wrong? i'm getting my run at -1 which can't even be because I send either 1 or 0 and my autostatus is constantly 0 which is strange because it should be 1 based on what i programmed right?
ps. i actually made this mess because i can't send and receive at the same time, so just to have a good transition from one another I thought it would be helpfull to have multiple clock components but maybe im wrong.
Well, what am I doing wrong with the receiving on my arduino code then, because I can't find it. Also I see you get a constant 255 even in auto mode, that's not what I wanted so I need to change my blocks eitherway.
But with my function what did you change to make it work, what's the difference between your and my way?
Dear Brum,
as @Patryk_F says your Arduino code has something "strange":
void receive3Bytes(void)
{
const byte aantal = 2; // what this is used for ?
if (Bluetooth.available() > 0)
{
incoming = Bluetooth.read();
if (incoming == 200)
{
i = 0;
for (i; i <= 1; i++)
{
incoming = Bluetooth.read();
data[i] = incoming;
i++; // why this increment ? the for loop already does it.
}
}
else if (incoming == 255)
{
i = 2;
for (i; i <= 3; i++)
{
incoming = Bluetooth.read();
data[i] = incoming;
i++; // why this increment ? the for loop already does it.
}
}
Run = data[0];
Auto = data[1];
X_as = data[2];
Y_as = data[3];
}
}
Then I would preferably write
byte n;
if (incoming == 200)
{
for (i= 0; i <= 1; i++)
{
for (n=0; n<= 10; n++) delayMicroseconds(100); // allows time to receive next char :thinking:
incoming = Bluetooth.read();
data[i] = incoming;
}
Run = data[0];
Auto = data[1];
}
else if (incoming == 255)
{
for (i=2; i <= 3; i++)
{
for (n=0; n<= 10; n++) delayMicroseconds(100); // allows time to receive next char :thinking:
incoming = Bluetooth.read();
data[i] = incoming;
}
X_as = data[2];
Y_as = data[3];
}
I haven't changed anything in your blocks. I only compiled to APK and installed it on my phone. I connected via BT to the terminal and read what exactly is sending your app.
Aantal is the amount of bytes, I don't want to read the bytes Run and Auto all the time, only if 200 is send and then the next 2 bytes are those, so basicly 1 byte to set the position (0 for run and 1 for auto/ 2 for joystickX and 3 for joystickY) combined with the byte for the placement, it's 3 bytes. based on that i wanted to set my bytes to the right variables if you understand.
I see you have delays in the function, I actually wanted to avoid those. It needs to be a const read of my positioning of the joystick so it can run and stop within a couple ms.
I think I read the data incorrect yesterday, the block output seems indeed fine it was a little late for me. But what was the difference between my receiving code and yours. Because as i mentioned i got -1 for my run byte, which can't be possible because I made it send either 1 or 0. So what did i do wrong?
I believe that aantal in your intention is a the number of bytes but, apart its declaration is not used anywhere else in the code
The delays I suggest are not done with the delay() function which blocks any operation, but with delayMicroseconds() which on the contrary allows interrupts to occur.
And you can trim at microsecond resolution the time to wait for a new character.
In my experience it's better if you allow some time between each character: if the characters are not available when you check with the read() function, you exit your loop without waiting for them.
If you lose characters you wil lose also the synchronization between the receiving operation and thesending sequence of AI2.
Last, t's still not pretty clear to me why you use a "for" loop when you skip the characters received by using a second i++. If it is just to empty the receiver buffer you better just have to receive and read() into a dummy variable.
The for loop is there to read 3 bytes, not more and not less. If I send my data to arduino it reads 255 and based on that I know I need to set my index to begin with 2 to read my x-as, then the i++ is there to set the index to 3 to read my y-as and then the for loop should break. I want to set a specific number of bytes to read to avoid breaking out in index 1 for example and the next byte to receive is my x-as and stores that value inside my run, that would break the code and that's why I want to read specificly 3 bytes at the time.
Maybe it's all inefficiënt and it's better to read those 4 at once but as mentioned before it's my first time doing this so I know I probably made a lot of mistakes, and to add to it it's still a demo.
But thanks for the advice, I'll take a look at it.
Dear @Brum_A,
for sure if you force the "i" index to reach the ending value before its natural last value, the "for" loop ends suddenly. You can exit a for even by using a break command when you encounter a wanted situation.
Anyway, let's accept that .
It remains alive my other hint: allow a while between subsequent characters, if you try to read() faster than the sender does send the characters, you will de-synchronize your receiving loop.
Honestly I didn't check your code on a real piece of HW, but normally it works like that
I'm keeping crossed mi fingers for you.
Cheers, Ugo.
I've made some other code where I sort of use the delay...
`if (Bluetooth.available() > 0)
{
incoming = Bluetooth.read();
while (incoming == 200)
{
for (i = 0; i <= 1; i++)
{
while (Bluetooth.available() == 0)
{
}
value = Bluetooth.read();
if (value == 200 || value == 255)
{
break;
}
data[i] = value;
i++;
}
Run = data[0];
Auto = data[1];
break;
}
while (incoming == 255)
{
for (i = 2; i <= 3; i++)
{
while (Bluetooth.available() == 0)
{
}
value = Bluetooth.read();
if (value == 200 || value == 255)
{
break;
}
data[i] = value;
i++;
}
X_as = data[2];
Y_as = data[3];
break;
}
}
incoming = 0;
}`
with this code i'm setting the 200 and 255 to the correct index. Then within the for loop i'm waiting in the index with the while available == 0, then if a byte is received it loops out of it setting the byte to value and then to the correct position in the char.
So for example if I start my program it should receive and set incoming to 200, then the for loop starts and waits until it receives a byte then comes out of the loop and sets run to the value. Then the for loop increases and it again waits for the next byte and sets auto to the value.
Auto still always gets to 0 and I don't understand why that's done... I'm literally waiting for the next byte to come before moving on so what is wrong with this?
Dear @Brum_A,
but in my understanding of your code you have put a break after the comparison of
if (value == 200 || value == 255)
{
break;
}
This means that you exit suddenly the for loop or, in other words you will never do
data[i] = value;
i++;
nor the
X_as = data[2];
Y_as = data[3];
break;
because the execution will skip to the very next instruction after the closing braket } of the for loop.
Another problem that I see is this neverending loop here below
while (Bluetooth.available() == 0)
{
}
if no characters are never available, the Arduino code will stay there forever !!!
In this case it would be better to allow a timeout. Something like:
int timeout = 0;
while (Bluetooth.available() == 0)
{
delayMicrosecond(10);
if(++timeout == LIMIT) break; // exits the while loop without having received any charcater
}
if(timeout < LIMIT) value = Bluetooth.read();
else
{ // place where to do something else when the timeout elapses...
}
Hoping this can be one step beyond.
Have a great development.
Cheers, Ugo.
But the break is already after the 200/255 selection. So thats only if a sudden random 255 comes to it and if there isn't one it shouldn't come to that break. I can set the run status but the auto just doesn't want to go
Sorry, but without putting the code on a piece of hardware it becomes hard for me to help you more.
The unique hint that remains for me is to avoid the possible neverending loop if no characters arrive while your code is doing the wait for a new character. I mean the following:
void receive5Bytes(void)
{
if (Bluetooth.available() > 0) // bytes are available
{
incoming = Bluetooth.read(); // if incoming is not 250 for some reason it doesn't come inside the loop
while (incoming == 250) // check if 250 has been send, then the lineup to my variables are ok.
{
for (i = 0; i <= 3; i++) // set the index to 0 and start counting
{
delayMicroseconds(10);
value = Bluetooth.read();
data[i] = value; // store inside data with index the value
i++; // up the value
}
Run = data[0]; // set the variables based on the index they were put
Auto = data[1];
X_as = data[2];
Y_as = data[3];
break; // end the loop and therefore the function
}
}
}
I still get wrong data.
Sometimes my run becomes -1 for some reason or 255 which is impressive because i haven't implemented 255 in my blocks only 250 and the joystick doesn't reach 255, so that's also strange.
auto isn't affected it stays at 0 for the whole program.
I need to say i now changed to timeralways to fire instead of a timerinterval of 25, but i can't believe that's the problem. I'll put my programs with it maybe you can see some other things i'm doing wrong