Sending Data to and from MIT app to Arduino via bluetooth (HC05)

Im working on creating a robotic arm that is controlled by buttons on a app, so far i have got all of that working, but, currently i am trying to implement a save feature that uses TinyDB to store servo positions and then send them to the arduino when a button is pressed. I am able to get the data to send, however, the some values are wrong once they reach the arduino (eg instead of 90 it becomes 14). I also have the problem of some data being received from the arduino going to the wrong variables in the app.

These are the two main blocks involved with sending and receiving data, under the clock block I cannot get the data being received from the arduino to not enter the global saved positions variable.

Below will be the code that intends to receive and store the data being sent from the application.

I am hoping to get some help solving these problems as i have not been able make any progress in the past couple of days.

if (dataIn == 255){
m = 40;
Serial.println(m);
memset(servo01SP, 0, sizeof(servo01SP)); // Clear the array data to 0
memset(servo02SP, 0, sizeof(servo02SP));
memset(servo03SP, 0, sizeof(servo03SP));
memset(servo04SP, 0, sizeof(servo04SP));
memset(servo05SP, 0, sizeof(servo05SP));
memset(servo06SP, 0, sizeof(servo06SP));

     while (m == 40) {

// if (Bluetooth.available() > 0) { // tell the code how many positions have been saved.
saves = Bluetooth.read();
Serial.print("Saves value: ");
Serial.println(saves);
if (saves > 0) {
hold = 1;
m = 0;
}
//Bluetooth.write(99);
index = 0;
}
if ( hold == 1) {
for (int i = 0; i <= saves; i++) {
index++;
Serial.println("New Loop");
if (i == 0) {
servo01SP[i] = start; // Set start positions.
servo02SP[i] = start;
servo03SP[i] = start;
servo04SP[i] = start;
servo05SP[i] = start;
servo06SP[i] = start;
}
while (servo01SP[i] <= 0) {
servo01SP[i] = Bluetooth.read(); // save position into the array
Serial.print("servo01");
Serial.println(servo01SP[i]);
delay(100);
}
Bluetooth.write(205);
while (servo02SP[i] <= 0) {
servo02SP[i] = Bluetooth.read();
Serial.print("servo02");
Serial.println(servo02SP[i]);
delay(100);
}
Bluetooth.write(205);
while (servo03SP[i] <= 0) {
servo03SP[i] = Bluetooth.read();
Serial.print("servo03");
Serial.println(servo03SP[i]);
delay(100);
}
Bluetooth.write(205);
while (servo04SP[i] <= 0) {
servo04SP[i] = Bluetooth.read();
Serial.print("servo04");
Serial.println(servo04SP[i]);
delay(100);
}
Bluetooth.write(205);
while (servo05SP[i] <= 0) {
servo05SP[i] = Bluetooth.read();
Serial.print("servo05");
Serial.println(servo05SP[i]);
delay(100);
}
Bluetooth.write(205);
while (servo06SP[i] <= 0) {
servo06SP[i] = Bluetooth.read();
Serial.print("servo06");
Serial.println(servo06SP[i]);
delay(100);
}
Bluetooth.write(205);
}
servo01SP[index] = start; // Set final positions.
servo02SP[index] = start;
servo03SP[index] = start;
servo04SP[index] = start;
servo05SP[index] = start;
servo06SP[index] = start;

                  for (int i = 0; i <= index; i++) {
                    Serial.println(index);
                    Serial.print("Servo 1: ");
                    Serial.println(servo01SP[i]);
                    Serial.print("Servo 2: ");
                    Serial.println(servo02SP[i]);
                    Serial.print("Servo 3: ");
                    Serial.println(servo03SP[i]);
                    Serial.print("Servo 4: ");
                    Serial.println(servo04SP[i]);
                    Serial.print("Servo 5: ");
                    Serial.println(servo05SP[i]);
                    Serial.print("Servo 6: ");
                    Serial.println(servo06SP[i]); 
                    Serial.println("Next index");                       
                  }

                Serial.println("entering runSteps");
                runSteps();
      }

}

currently, as it stands this is what is being printed by serial.print

Saves value: -1
Saves value: -1
Saves value: -1
Saves value: -1
Saves value: -1
Saves value: 3
New Loop
New Loop
servo0114
servo0290
servo03-1
servo03-1
servo03-1
servo03-1
servo03-1
servo03-1
servo03-1
servo03-1
servo03-1

I have been able to get all the data to print properly without this infinite loop but the values were still wrong and i think there is something ive done wrong in terms of my approach to the problem.

Happy to answer any questions or provide any more information as there is alot of other content, but, the stuff posted is what hasnt been working, everything else works fine.

Hello Ryley

Sounds like an exciting Project. You have put down some interesting code but sorry to say there are many errors in both your App Inventor code and the Arduino code - hence you do have some problems :upside_down_face:

I'm away from my desk now until the evening, UK time - another Power User may take up your cause. It would help if you upload the AI2 Project (.aia) and the Arduino Script.

Thanks for your reply Chris,

I've attached the files as recommended, as I'm sure u can definitely tell I'm new to the App inventor stuff.

Just for reference I'm in Australia and won't be back online after this for around 10 hours.

Eager to see what improvements I can make and get this all working smoothly!

Robot_Arm_Application_TinyDB.aia (509.0 KB)
Updated_robotic_arm_code_optimised_beforestore.ino (15.6 KB)

I dont believe i used the reply correctly previously, but, on the post i have attached the information requested :slight_smile:

Let's try to fix all the niggles. When I run the App on my phone:

  1. Define components in % rather than fixed pixel sizes.
    ProfessorCad: Tips & Tricks
  2. The 'Connected' Label should be used for any necessary messages and so make it stand-alone, width of the screen (98%)
  3. Do not use Arrangements as Spacers - they are 'smart components'. Always use Labels for this purpose (without margins)
  4. Use Image Buttons for Load Positions, Reset Saved Positions, Run Saved Positions
  5. To avoid the Screen becoming extra long, you could use a List Picker instead of a List View.
  6. 'Load Positions' doesn't mean a lot if the values are not displayed alongside the relative control, so you could ditch the ListView and instead have Labels.

It is very difficult to follow your code (I have helped others to code for robot arms)!

My understanding:

  1. The App controls the Robot Arm by sending values to change the positions (rotation angles?) of servo motors.
  2. You want to save up to 50 positions per servo, so that the entire movement of the arm can be recalled and repeated.

Given that the App sends the values to the Arduino, why send them back to the App - they could be recorded as they are sent.....?

I suspect that the Sketch originated from a Project that did not drive the Arm with an App?

This:

    if (dataIn == 0) {
      m = 0;
    }
    if (dataIn == 1) {
      m = 1;
    }
    if (dataIn == 2) {
      m = 2;
    }
    if (dataIn == 3) {
      m = 3;
    }
    if (dataIn == 4) {
      m = 4;
    }
    if (dataIn == 5) {
      m = 5;
    }
    if (dataIn == 6) {
      m = 6;
    }
    if (dataIn == 7) {
      m = 7;
    }
    if (dataIn == 8) {
      m = 8;
    }
    if (dataIn == 9) {
      m = 9;
    }
    if (dataIn == 10) {
      m = 10;
    }
    if (dataIn == 11) {
      m = 11;
    }
    if (dataIn == 12) {
      m = 12;
    }
    if (dataIn == 14) {
      m = 14;
    }
    if (dataIn == 16) {
      m = 16;
    }
    if (dataIn == 17) {
      m = 17;
    }
    if (dataIn == 18) {
      m = 18;
    }
    if (dataIn == 19) {
      m = 19;
    }
    if (dataIn == 20) {
      m = 20;
    }
    if (dataIn == 21) {
      m = 21;
    }
    if (dataIn == 22) {
      m = 22;
    }
    if (dataIn == 23) {
      m = 23;
    }
    if (dataIn == 24) {
      m = 24;
    }
    if (dataIn == 25) {
      m = 25;
    }
    if (dataIn == 26) {
      m = 26;
    }
    if (dataIn == 27) {
      m = 27;
    }

Could simply be: m = dataIn;

You might like to take a look at this:

To answer your questions:
1 - the app sends a 1-byte number to the Arduino while one of the movement arrows is being held down, once the button is released 0 is sent to the Arduino as seen in the pasted picture.

image

For the Arduino code it looks like this:

while (m == 16) {
if (Bluetooth.available() > 0) {
m = Bluetooth.read();
}
servo01.write(servo1PPos);
servo1PPos++;
delay(speedDelay);
}
// Move servo 1 in the negative direction
while (m == 17) {
if (Bluetooth.available() > 0) {
m = Bluetooth.read();
}
servo01.write(servo1PPos);
servo1PPos--;
delay(speedDelay);
}

this is what is used to control one servo motor, while the button is still being held down the servo motor moves in increments of 1 with a delay, depending on which arrow you press it will move in the positive or negative direction. Therefore the app does not send the positions to the code, but, instead tells the code to slowly increment the position, this is why the code has to send the positions back, this part has been working well.

  1. 50 positions is the maximum amount I've allowed to save but typically it won't exceed 10. In the code i have already made it capable of saving positions and repeating them in the same session you created them. Now I am trying to use Tinydb to save the desired positions (movement sequence) so you can simply open the app and run the positions you saved during your last session. As mentioned in the original post this is where im having problems trying to send multiple numbers to the arduino and reliably receive and order them.

I appreciate the helpful information on fixing some of the formatting and optimising things, I will definitely come back to do that once I get the entire program working!

In terms of the sending multiple 1-byte number problem, do you have any advice on how to approach the task? Would it be better to somehow convert the list into a string and send just one string that can be decoded in the Arduino code?

Also when I'm sending data to the app, I cannot filter the information incoming so it only goes to certain variables (see pasted image)

no matter what I tried, the logic statements just do not work in the clock and numbers greater than 95 still get stored in the global Saved_Positions list.

Would there be an easier way to contact you such as an audio call so everything can be explained clearly on both ends? There is a lot of information in terms of trying to understand the entire app and code and if that is what you need to do before being able to help with the data sending and receiving issues it will be hard to convey like this.

My point was, you send the position increments to the board, so you don't need the board to send them back, the App already 'knows' what they are.

The way the servo motors are controlled is different to the example you sent earlier, the app does not know what position is being sent to the servo motors. The app only sends a signal (a fixed 1 byte number) to the code which will then increase or decrease the servo positions in increments of 1 with a set delay speed in the code. Refer to the first section of my previous reply to see the blocks and code I am talking about.

Nevertheless Ryley

  1. You want to store the Arm movement start-to-finish, correct?
  2. The App sends the data to the board to make that happen, correct?
  1. Yes, I have the code and app blocks to do that without any issues. All the positions saved are stored in a list which is then stored in Tinydb (each save has 6 servo positions for reference).

  2. In terms of saving positions,the app sends a signal to the arduino, the arduino then sends the servo positions to the app, the app then stores those sent positions to a list.

The answers are simply yes or no - I take your answers as yes.

  1. You are storing the data so that it can be recalled and replayed?
  1. Yes
  1. The App, having recalled the data, sends it to the board to be replayed.
  1. No

That is what I want to do but I cannot get that to work properly

So 4 is a yes!

With respect to what I want the app to do then

  1. Yes

Exactly so.

That is why you need to store what the App sends, so it can re-send to the board and the board receives the data in the same way as it would if the data was input manually - now do you get it?

Okay, I understand what you mean in suggesting that, but, in order to do that I would need to re-do almost everything as currently, the app does not have any positional data until it's received from the Arduino due to how its coded.

In saying that, what I have for receiving the positions from the Arduino works well and I accurately get the data and store it into the app which puts me in the same position using both methods. I have the position data, but, the problem is now sending it to the board from here.