Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!
Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.
Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!
I am trying to program a 4DOF robotic arm (using 4 servo motors). I would like to move the servos using an Android app, by means of bluetooth (HC-05). I developed the app, in whose interface there are 7 buttons (Up, Down, Left, Rght, Forward, Backward, Save) and a field in which you can type using the keyboard.
So far, I tried to manage only Up button (which sens 'U' via bluetooth to arduino) and Down (which sens 'D'), which would move the servo intended for vertical arm movements. That code works quite good, although the app crashes sometimes, but I still can't figure the reason out. Using the .prinln() function I can see that Arduino read in the bluetooth input the character '⸮ ' , what does it mean? I use a baud of 9600.
Then, what I would like to do is: once I have moved the servo and reached a particular position, I'd like to save the position of the motor into an array. In order to allow multiple positions saving, after Save button is pressed, I want Arduino to wait for another input from the bluetooth (so that, it would wait for another button to be clicked from the app or for something typed into the dedicated bar from keyboard) that defines the position within the array, in which I save the servo position (eg: I type '2' into the dedicated app bar and Arduino, which is waiting for an input, receiving it, saves the last servo position into the array servo01pos[2]). I wrote the "case ('S')" code that is quite long and inefficient but, at least, it works.
Thanks in advance to anyone who will help me.
Giammarco
Here the full code:
#include
SoftwareSerial bluetooth(10, 11); //BlueTooth RX ,TX
#include // servo library
unsigned long timestampSend = 0; // BT Write wait period
String readString;
Servo servo01; // servo name
byte pos01 = 90;
#define ANGLE_STEP 10 // 10 degree steps
int servo01pos[50];
char data;
char button;
int x = 1;
void setup() {
Serial.begin(9600);
bluetooth.begin(9600);
delay(1000);
Serial.println("Ready ...");
Serial.println("\n");
servo01.attach(12);
servo01.write(pos01);
}
void loop() {
do {
if (bluetooth.available() > 0) {
Serial.println(data);
do {
delay(500);
data = bluetooth.read();
Serial.println(data);
} while (bluetooth.available() > 0);
if (data == 'U' || data == 'D' || data == 'L' || data == 'R' || data == 'F' || data == 'B' || data == 'S' || data == 'X') {
Serial.print("Received value: ");
Serial.println(data);
switch (data) {
case ('S'): //SAVE
Serial.println("Enter the button you desire to set...");
do {
data = 254;
bluetooth.listen();
button = bluetooth.read();
if (button == '0' || button == '1' || button == '2') {
data = 'S';
}
} while (data != 'S');
Serial.println("SAVING POSITIONS ...");
if (button == '0') {
servo01pos[0] = pos01;
} else if (button == '1') {
servo01pos[1] = pos01;
} else if (button == '2') {
servo01pos[2] = pos01;
}
servo01.write(pos01);
Serial.println(button);
Serial.println(pos01);
Serial.println(servo01pos[1]);
Serial.println(servo01pos[2]);
Serial.println(servo01pos[0]);
//}
break;
case ('U'):
Serial.println("UP");
if (pos01 <= 180 - ANGLE_STEP) {
pos01 = pos01 + ANGLE_STEP;
servo01.write(pos01);
Serial.println(pos01);
delay(20);
Serial.println(data);
}
break;
case ('X'):
Serial.println("EXIT");
x = 0;
break;
}
}
}
} while (x != 0);
}
This character basically is an indication that the character your Arduino receives doesn't arrive correctly. The can be caused by several things. The serial port could be an issue, but you set the speed to 9600 baud and I assume you've set the output window to 9600 baud as well.
Another reason can be the character set that is being used by the app that is sending the characters over Bluetooth. This can be a little bit of a headache at times, for example when your Arduino expects 8 bit code, but receives for example unicode characters (which can be 1 or more bytes). Since I don't know much about what you used to develop the app, I'd start by looking there. As a test you could try sending numbers instead of letters, maybe this makes a difference.
Serial.print(data, DEC); // outputs data as decimal numbers "78" Serial.print(data, HEX); // gives "4E"
Here "D" (capital D") results in "44" (hex) or "68" (dec). I suspect you may see not only something different, but maybe even 2 instead 1 number.
Personally, I'd first make a simple sketch, without any motor support, just to test the Bluetooth part of things, so you are 100% sure the code receives the right characters,. Once that works you can start adding the motor functions. Too many wildcards can make it hard to debug.
As for you switch-case statement: nothing wrong with that. 👍 I do however tend to break things up a functions, so my code becomes a little more manageable. This also helps you put pieces of code together for a specific task, which can be tested extensively. In the end you'd have function that works 100% and you would not have to worry too much about it when working on the rest of the code.
Just as an example, make a function for saving the position, eg:
void SavePosition() { Serial.println("Enter the button you desire to set...");
do {
data = 254;
bluetooth.listen();
button = bluetooth.read();
if (button == '0' || button == '1' || button == '2') {
data = 'S';
}
} while (data != 'S');
Serial.println("SAVING POSITIONS ...");
if (button == '0') {
servo01pos[0] = pos01;
} else if (button == '1') {
servo01pos[1] = pos01;
} else if (button == '2') {
servo01pos[2] = pos01;
}
servo01.write(pos01);
Serial.println(button);
Serial.println(pos01);
Serial.println(servo01pos[1]);
Serial.println(servo01pos[2]);
Serial.println(servo01pos[0]); }
And modify the switch-case to:
switch (data) {
case ('S'): //SAVE
SavePosition;
break;
case ('U'):
Serial.println("UP");
if (pos01 <= 180 - ANGLE_STEP) {
pos01 = pos01 + ANGLE_STEP;
servo01.write(pos01);
Serial.println(pos01);
delay(20);
Serial.println(data);
}
break;
case ('X'):
Serial.println("EXIT");
x = 0;
break;
}
}
As you can see; the code has become much more readable. But in the end this is just a personal preference - your code is just fine as well.
I know this doesn't give you a cookie-cut fix for the issue, but I do think it will help get the issue resolved .. or at least point you in the right direction 😊
@hans Thank you very much for your comprehensive reply, very gracious of you. I'll try to explain some steps a bit deeper. I used 9600 baud in both window and code. I made some trials with different apps, I used someone just downloaded from PlayStore and I found same problems (after 2 or 3 'U' messages sent to Arduino, it stops to communicate to the mobile App and it print the reversed question mark). I also tried the catlog of Android Studio (by which I developped the app), no errors were found.
I know this doesn't give you a cookie-cut fix for the issue, but I do think it will help get the issue resolved .. or at least point you in the right direction
A reason could be how you read the data from the BT module. I see you use the read command, without checking if there is data:
data = bluetooth.read();
For example, it is quite common with serial communication (though I recall you're using the standard SoftwareSerial library) to do something like this:
if(bluetooth.available()){ c = bluetooth.read(); Serial.print(c); }
Not sure if this is applicable for the library you're using though. Basically saying: while characters are available: read a character and print it. (more info in these examples)
One other thing that came to mind, but may not be relevant, with the weird characters is the data length, parity bits and stop bits settings. Back in the day (good old modems) this could cause garbage output, if not set right, as well. Not sure if this can be set with Bluetooth, or is even relevant, since I do not have such a module, but back in the data 8 data bits, 1 stop bit and no parity (0) used to be quite common.
if(bluetooth.available()){ c = bluetooth.read(); Serial.print(c); }
Thank you again for the patience and your help. I tried a very short code to verify if that error could occour anyway. With that one I had not the same problem, until I add motors and functions to move the servomotors. Here the working code:
#include <SoftwareSerial.h> // Bluetooth library SoftwareSerial bluetooth(10, 11); // BlueTooth RX ,TX
#include <Servo.h> // Servo library Servo servo01; // servo name byte pos01 = 90; int servo01pos[5]; char button;
void setup(){ // Bluetooth setup Serial.begin(9600); bluetooth.begin(9600); Serial.println("The bluetooth gates are open.\n Connect to HC-05 from any other bluetooth device with 1234 as pairing key!.\nReady ...\n"); delay(1000);
// Read the new value from bluetooth // e' una funzione di nome readBT che prende in input un intero (keyType, che deve essere 1 o 2) e restituisce un carattere (in questo caso quello ricevuto dal BT) char readBT(int keyType){
I think I solved the problem using a power supply. It seems that the reversed question mark occurred when there was a power outage. Now it seems to work properly. Thank you very much again for your help! Giammarco
SpeedTest.net Test the speed of your Internet connection (requires Flash!!!)
Leapfrog 3D printers Manufacturer of the great Creatr and Xeed 3D printers - Stunning customer service!!
MalwareBytes Probably one of the best tools to prevent and remove all kinds of malware and viruses on Windows and MacOS X.
Media Player Classic My favorite media player for Windows - light weight and supports all common video formats.
AlternativeTo Great resource when you're looking for alternatives for an application that you'd like to use, but might not be available on your platform or the application you have is just not doing it right.
Robots.txt Analyzer Very simple and effective tool for online checking of your robots.txt file without having to use Google Webmaster Tools.
Links Page These and more of our favorite links can be found on the Links Page.
New Downloads
ConnectMeNow4-v4.0.18-macOS-x86-64.dmgDate: 2024-04-24 - Size: 3.5 MBVersion 4 of ConnectMeNow - A tool for more convenient mounting of network shares under macOS. This is the Intel version which works on Intel and Apple Silicon Macs.
ConnectMeNow4-v4.0.18-macOS-arm64.dmgDate: 2024-04-24 - Size: 3 MBVersion 4 of ConnectMeNow - A tool for more convenient mounting of network shares under macOS. This is the Apple Silicon version (not suitable for Intel).
MiniWOL2 MacOS (64 bits Apple Silicon)Date: 2023-08-01 - Size: 1.2 MBminiWol is a simple, but effective application to send Wake On LAN to network devices. This is the signed 64 bit MacOS ARM (Apple Silicon) version.
MovieScanner2-2.2.3-Windows-32bit-setup.exeDate: 2023-04-12 - Size: 18.6 MBA small application that uses FFProbe to scan your video files and logs these details in a small database. This is the 32 bit Windows version.
MovieScanner2-2.2.2-Linux-GTK-64bits.tar.gzDate: 2023-04-11 - Size: 29.2 MBA small application that uses FFProbe to scan your video files and logs these details in a small database. This is the 64 bit Linux version for GTK.
MovieScanner2-2.2.2-Linux-QT5-64bits.tar.gzDate: 2023-04-11 - Size: 29.1 MBA small application that uses FFProbe to scan your video files and logs these details in a small database. This is the 64 bit Linux version for QT5.
Downloads Page Find these and more Downloads on the Downloads Page, where you will also find articles references, operating system requirements and categories.
Amazon Ads
Support us by doing your shopping at Amazon.com, either click the link, or click one of the links below …
You can also sponsor us through these Amazon offerings:
Please consider disabling your ad blocker for our website.We rely on these ads to be able to run our website.You can of course support us in other ways (see Support Us on the left).