Sending Packets with XBee & Arduino

Hello!

In the previous post, I had figured out how to control the robot by sending commands through MATLAB.

The next step? Controlling the robot with a simulated neural network: I looked for MATLAB scripts with only a few neurons, and actually found a really nice one. Bonus: it’s customizable :).

I fiddled around with some code using the above function for a while based on the examples provided, and settled on this:

W = log(abs(randn(4)));
[spk NetParams V] = SimLIFNet(W,'simTime',35,'tstep',1e-2,...
'offsetCurrents',1.1*ones(length(W),1));
v = round(V, 3);
It generates a few variables, but I am taking advantage of V (from which I derive v), which is a matrix of about  4 x 4000 cells that represent neurons’ spiking (I chose to have 4 neurons). Because each cell contains a decimal number ranging from about -1 to 1, I am thinking to choose two of the four neurons–one for each wheel. Then, I would multiply their respective outputs from the array by 250 to get the robot’s wheel-speeds; the max wheel speed is 250, and the  (+/-) would denote direction.

Where the Title Comes In

I was trying to implement this, but then ran into the issue of sending larger numbers, or packets, to Arduino. I knew it was possible via XBee, but I wasn’t sure how to do it. 

My initial idea was the set ‘start’ and ‘stop’ characters that I could use to surround digits to identify them as a single number. A very-long-story-short, it took me more than a couple hours to figure out, but this is what I came up with:

//"sketch_jan16a"
void setup() {
 // initialize serial ports
 Serial.begin(9600); // USB serial port 0
 Serial.println("Starting up...");
 Serial3.begin(9600); // serial port 3
}
byte rx_byte = 0; // stores received byte
String str;

void loop() {
 if (Serial.available()) {
 rx_byte = Serial.read();
 Serial3.write(rx_byte);
 }
 if (Serial3.available()) {
 rx_byte = Serial3.read();
 if(rx_byte == '{')
 {
 Serial.println("start");
 str = "";
 }
 else if(rx_byte == '}')
 {
 Serial.println();
 Serial.println("end");
 Serial.println("final string: " + str);
 function(str);
 }
 else{
 Serial.write(rx_byte);
 char c = rx_byte;
 str = str + c;
 }
 }
}
void function(String str)
{
 double num = str.toFloat();
 Serial.print("String to Double: ");
 Serial.println(num);
}

A Video of It Working:

190116_Packet_viaXBee_vid

Here’s a Quick Rundown of How it Works:

  • I initialize the Serial ports: plain ‘Serial’ refers to the Arduino’s Serial Monitor, and ‘Serial3’ refers to the hardware serial pins that I’ve connected the robot-XBee to on the MEGA.
  • I initialize a string
  • After checking that both ‘serial’s are available, the program reads in the character sent to the robot-XBee as a byte
  • The program throw away all the bytes until I receive one representing ‘{‘; when it receives that, the Arduino’s Serial Monitor prints out “start” to let me know
  • Here’s the important part (that took me lots of trial and error to find):
    • The program clears the previously initialized string (this is to account for the ‘looping’ of ‘void loop’)
    • Order is important here: it reads in the next byte, first checking that it is not ‘}’, and then adds it to the string
    • It continues to add characters to the previously initialized string until it receives the ‘end’ character, ‘}’
  • It then prints out the final character on the Serial Monitor
  • You’ll note I then have it call a function, aptly named ‘function’ (lol):
    • This function converts the string to a Float (ie. a type of number). I had wanted to convert to a double… but more on that later
    • Then I basically have it print out the number as a number for good measure.

What I intend to have ‘function()’ do is multiply that number, ‘num’, by 250 and then call the ‘setSpeeds()’ function, etc, (detailed in previous posts)–> ta-da, we are controlling the wheels!

But: Also to Do Before I Test It on the Ground
I won’t be actively controlling the robot once I run the simulation for real–and in our tightly packed lab, I’m afraid it’ll wreck itself by running into things. Before I let it loose, I’d like to incorporate the old ‘Roomba’ code (modified and pared down) into this program.
I’ve looked into Arduino commands like attachInterrupt before, but never really got how to use them; the next thing would be to figure out how I might run ‘Roomba’ simultaneously/in the background of the simulation so the robot doesn’t crash into anything. 
What I intend to have ‘function()’ do is multiply that number, ‘num’, by 250 and then call the ‘setSpeeds()’ function, etc, (detailed in previous posts)–> ta-da, we are controlling the wheels!

Sending Packets with XBee & XTCU

Long story short, see here and here. 🙂

Other Useful Links:

I really found an ASCII table useful, even though you can use ‘Serial.print(rx_byte)’ to see the the DEC value of the character you send, and XTCU displays the HEX one right on-screen.

And I think I may have found this Arduino forum semi-helpful…?

Floats

I’ve always been sort of wary of floats, because I’ve heard they’re unnecessarily complicated to use: I’m an ‘int‘ type of person, lol.

In this particular instance, however, I couldn’t use ints because I was working with decimal numbers (which, for reference, is one of the reasons I stored the bytes as a string before converting to a type-of number). I had wanted to use a Double, and so I was pleased to find that Arduino’s String class has a command called ‘toDouble()‘.

It does not work. These people will corroborate.

What does work is ‘toFloat()’, and floats can support decimal numbers, so that’s what I’m using now. I got more wary, however, when I read in the float online API/reference that it sometimes didn’t do math (specifically: multiplication/division) correctly.

Floating point numbers are not exact, and may yield strange results when compared. For example 6.0 / 3.0 may not equal 2.0. You should instead check that the absolute value of the difference between the numbers is less than some small number.” –the API/reference

 Soo… I ran this:
void setup() {
 // put your setup code here, to run once:
float a = 6.0;
float b = 3.0;
float c = a/b;
Serial.begin(9600);

Serial.println(c);
}
void loop() {
 // put your main code here, to run repeatedly:
}
and it yielded ‘2.00’.
I’m a little weirded out by this… it seems to be working (and it’s important that it works properly in my code), but I still don’t understand why it might not work. I guess I’ll look further into it if something goes wrong? (yikes lol)
Until next time! 🙂

 

Leave a Reply

Your email address will not be published. Required fields are marked *