Need help with Arduino code for servo direction, please

I'm trying to get servos to point 0, 90, and 180 degrees with MIT app inventor.
So the MIT app connects with to my Adafruit ESP32 V2 feather which has the 8 channel PWM servo wing, and they move.
As a newbie, I'm trying to adapt the example code for just 2 of the 8 servos but since I don't fully understand, they are not pointing correctly.
I need help with the Arduino code to receive the MIT text like B01, N01, and F01. So B will turn the servo fully clockwise, N would turn 90 and F would turn it fully counterclockwise. 00 to 07 would be the servos.
This is a copy of my Arduino code. Note that it currently receives number 1 to 6 but it will need to use my B01 (or I could use 1 for 0, 2 for 90, and 3 for 180. So 204 would turn servo number 5 to 90 degrees) if that technique makes it easier.
I'm just so frustrated, again.

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <BluetoothSerial.h>

BluetoothSerial SerialBT;

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();

#define SERVOMIN  150
#define SERVOMAX  600
#define USMIN  600
#define USMAX  2400
#define SERVO_FREQ 50

uint8_t servonum = 0;

void setup() {
  SerialBT.begin("Esp32-BT");
  pwm.begin();
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);
  delay(10);
}

void setServoPulse(uint8_t n, double pulse) {
  double pulselength;
  pulselength = 1000000;
  pulselength /= SERVO_FREQ;
  Serial.print(pulselength); Serial.println(" us per period"); 
  pulselength /= 4096;
  Serial.print(pulselength); Serial.println(" us per bit"); 
  pulse *= 1000000;
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() {
  if(SerialBT.available()){
    char c = SerialBT.read();
    Serial.println(servonum);
    if(c == '1'){
      pwm.setPWM(0, 0, 150);
    }
    if (c == '2'){
      pwm.setPWM(0, 0, 475);
    }
    if (c == '3'){
      pwm.setPWM(0, 0, 600);
    }
    if(c == '4'){
      pwm.setPWM(1, 0, 150);
    }
    if (c == '5'){
      pwm.setPWM(1, 0, 475);
    }
    if (c == '6'){
      pwm.setPWM(1, 0, 600);
      }

    delay(500);
  }
}

(``` added for indents - ABG)

You might look here

Your question is really an Arduino question and can be answered on the Arduino forums probably.

To receive multicharacter messages, you will need the readuntil command.

Search this board for 'readuntil' for threads discussing it.

This should work ( I don't have the pwm so I have commented that part ).
The commands ( N01, F01... ) should be terminated with a '\n' or a '\r'

blue01.ino (2.1 KB)
bt01.aia (2.0 KB)

Dear @Eric_Michalek,
please forgive me, I don't want to "teach" :upside_down_face: you Arduino, but:

first of all, if 150 is = 0° and 600 is = 180°, 90° shouldn't it be 375 => (600-150)/2 +150 ? Or there is something different with respect to the pure mathematical average ?

Then, where is called, in the code, the function:
void setServoPulse(uint8_t n, double pulse) ?

Because you have only 8 PWM channels, there is no need to transmit 00 to 07 but only 0 to 7, therefore the commands can be just "B0" to B7" , and "N0" to "N7" and "F0" to "F7"

Now, supposing you use the @davidefa's Arduino code, you'll receive into "cmd" the string containing the command from AI2 (but reduced to two characters, as just said above), so to extract from that string the degrees to which the servo shall go and the PWM channel to be driven (any of 8 channels) , you could do something like:
At initialization:
string S_deg = "";
string S_channel = "";
int channel = 0;
int servo_deg = 0;

In the loop:
S_deg = cmd.substring(1,1); //1st left character
S_channel = cmd.substring(2,2); //1st right (or 2nd left) character
channel = S_channel.toInt(); // channel converted into a number 0<n<7

if (S_deg == "B") servo_deg = 600
else if (S_deg == "N") servo_deg = 375
else if (S_deg == "F") servo_deg = 150
else {}; // do some stuff in case of error

and your pwm.set should become:
pwm.setPWM(channel, 0, servo_deg); // supposing that the pwm library requires pwm.set (int,int,int);

Best wishes

Thanks for responding, and PLEASE, by all means, teach away.
As I hope I stated, I'm new to Arduino. Ask me to create a Microsoft Access database, I'm your guy. But Arduino, I'm just learning the basics.

Problem is, at this moment, I have a specific purpose for this project. So even thou I want to learn Arduino, and eventually know enough to do other things with that knowledge...
I fully admit I'm looking for a shortcut just to get it working. Just the basic code that controls 1 servo so I can add the other 7 on my own.

As for the code I have shown, I started with the Adafruit sample code and (blindly) made changes so I'm not even sure what is/was needed.

As for your response:

150 to 600, yes, I was using 375 at some point but it wasn't working so I was trying numbers in the range. Probably something with other parts of the code but I got frustrated and that is why you see the different number vice 375.

void setServoPulse(uint8_t n, double pulse) ? This is where I have no clue what I'm doing. At this point, I'm just going with it to get it working and will hopefully learn/understand later.

00 to 07 but only 0 to 7. I started with an Arduino Uno that has a 16 servo hat and added an HC-05 module, so I thought a 2 place message would allow for servos 10 to 15 as it controlls 16 servos vice 8.

For the @davidefa's Arduino code, I'm not sure at the moment because I can't get it to work. I used both the App and loaded the code, but no response from servos.

But I definitely can say I don't know how to use the other suggestions at this time.

If anyone has the same components, and is willing to share a stripped down version , I'd be extremely grateful.

(I realize and apologize for asking someone to clean up and fix my code but I've become so frustrated because I already 3d printed and assembled the parts not realizing the code would be so hard for me.)

Again, I thank you for helping a newbie

Eric

Dear @Eric_Michalek,
never give up !
Sooner or later your project will work (thanks to the huge community).
So, let me tell you some hints.
Be sure that both BT and Geolocalization permissions are granted on your Android system (phone or tablet), and that your ESP32 is paired to your phone,
Second step, you shall be sure of what the app is "really" sending to the ESP. To this purpose you could echo on the Serial Monitor of the PC the data being received from the BT.
Please be sure to use the "classic BT" feature of the ESP and not the BLE (avoid the BLE as the hell !) so to allow you to use the standard BluetoothClient blocks.

Next step is to separate the troubles: in other words, make the servo control to work as you expect in a standalone environment, without any app connected. You can simulate the input from the app by simply using the Serial Monitor input (i.e. sending commands from the PC keyboard). This will remove any doubts regarding the values to be sent by the app so to reach the wanted servo position.
(As a side comment, I've read somewhere on the web, that just by removing the command is not stopping the servo movement, therefore some trick could be necessary to achieve that feature. Other Power Users, deeper than me in the servo driving, might suggest something on this matter).

Once you'll be confident that each section (app vs ESP) is working separately as intended, you can glue them together.

Last hint is: to make it the simplest, just send from your app the characters "B" , "N", "F" by means of 3 buttons, and move then only servo 1 to 180° (600), 90° (375) and 0° (150) and see what happens.

If nothing else works, you can try to have a look at the many other threads on the topic

I admit that these are just "theoretical" hints but before trying a "bing bang" solution, it's better to go on step-by-step (my sons are always complaining about this "old fashioned" phylosophy.. :rofl: :rofl: :rofl:)
Best wishes.

In the code I posted I commented the part relative to the 8 servo board ( that I don't have ).
The attached code has this part re-enabled.

P.S.
In the arduino serial monitor you should see the commands received and commands executed.

blue01.ino (2.2 KB)

Without check your code I know these values are usually not correct. They are just somewhere in the middle of the average good values. If you use the Adafruit code, you should know there is a calibration process that gives you the correct values for minimum and maximum. 0 degree is somewhere between 100-200, and that does not mean it is 150. The 180 degree could be somewhere between 500-700. I do not remember correclty. Read the calibration process on Adafruit page to get the correct values for your servo.

1 Like