Hi all. I have an issue that I struggle to solve. I used servo motors to pull strings on my first Pedal Steel Guitar. I am building my second Steel guitar. I use Hall-effect sensors on the pedal-bar, sent via esp-WiFi to the servo controller. If I operate the servo using- Example1, it works fine but the servo does not stop exactly on the same string pitch every time due to small variables from the pedal-bar.
I then used example2
Example1
// === SERVO 5 ===
if (myData2.pedalA > 50) {
int angle8 = map(myData2.pedalA, 50, 3600, 90, 99);
angle8 = constrain(angle8, 50, 180);
pwm.setPWM(5, 0, angleToPulse(angle8));
} else if (myData2.pedalC > 50) {
int angle9 = map(myData2.pedalC, 0, 2200, 90, 99);
angle9 = constrain(angle9, 0, 180);
pwm.setPWM(5, 0, angleToPulse(angle9));
} else if (myData2.pedalD > 10) {
int angle10 = map(myData2.pedalD, 0, 3500, 90, 83);
angle10 = constrain(angle10, 0, 180);
pwm.setPWM(5, 0, angleToPulse(angle10));
} else {
pwm.setPWM(5, 0, angleToPulse(90));
}
Example2
// === SERVO 4 ===
if (myData2.pedalC > 100 && myData2.pedalC <= 2260) {
int angle4 = map(myData2.pedalC, 0, 2260, 90, 106);
angle4 = constrain(angle4, 90, 106);
pwm.setPWM(4, 0, angleToPulse(angle4));
} else if (myData2.pedalC > 2260) {
pwm.setPWM(4, 0, angleToPulse(106));
} else {
pwm.setPWM(4, 0, angleToPulse(90));
}
} else {
// Control via LL
if (myData3.LL > 9700 && myData3.LL <= 11000) {
int angle5 = map(myData3.LL, 9700, 11000, 90, 111);
angle5 = constrain(angle5, 90, 111);
pwm.setPWM(4, 0, angleToPulse(angle5));
} else if (myData3.LL > 11000) {
pwm.setPWM(4, 0, angleToPulse(111));
} else {
pwm.setPWM(4, 0, angleToPulse(90));
}
}
In this code when the value go over the 2260 it jumps back to 90.
Please assist
@jdebruyn
If you want help, you're going to need to show us the whole sketch for Example 2. The segment you show is not even showing the complete if statement.
Anything seems possible when you don't know what you're talking about.
Attach the complete sketch. Servo 4 is my main issue. When I run pedalC alone it work as expected, but when I add LL section LL start to jitter and run backwards. I need help urgently please.
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <WiFi.h>
#include <esp_now.h>
// Define PCA9685
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// Constants for Servo
#define SERVO_MIN 102 // Approx pulse for 0 degrees
#define SERVO_MAX 512 // Approx pulse for 180 degrees
typedef struct {
float Slider1;
float Slider2;
int Value_SelectC;
int Value_SelectCsharp;
int Value_SelectA;
int Value_SelectB;
int Value_SelectBb;
int Value_SelectD;
int Value_SelectFb;
int Value_SelectE;
int Value_SelectFsharp;
int Value_SelectG;
float Slider_LUP;
float Slider_LL;
float Slider_LR;
float Slider_RR;
float Slider_RL;
int Value_AutoAdjust;
int Value_StringUP;
int Value_StringDOWN;
int Value_String1;
int Value_String2;
int Value_String3;
int Value_String4;
int Value_String5;
int Value_String6;
int Value_String7;
int Value_String8;
int Value_String9;
int Value_String10;
int Value_String11;
int Value_String12;
int E9;
int C6;
} struct_message;
typedef struct {
float pedalA;
float pedalB;
float pedalC;
float pedalD;
float pedalE;
} PotentiometerData;
typedef struct {
float LL;
float LR;
float RR;
float RL;
float V;
} kneelever;
typedef struct {
float freq;
float peak;
float volume;
} struct_freq_message;
struct_freq_message myData4;
// Global data
struct_message myData1;
PotentiometerData myData2;
kneelever myData3;
// Define sender MACs (replace with your actual MAC addresses)
uint8_t sender1[] = {0xd8, 0x3b, 0xda, 0x85, 0x38, 0x5c}; // tOUCH
uint8_t sender2[] = {0xe0, 0x5a, 0x1b, 0x6c, 0x8f, 0xf4}; // ABCD
//uint8_t sender3[] = {0x24, 0x6F, 0x28, 0x65, 0x43, 0x21}; // Sender 3
uint8_t sender4[] = {0xf4, 0x65, 0x0b, 0xe9, 0x4e, 0x60}; // freq counter
//f4:65:0b:56:71:3c this esp
//e0:5a:1b:6c:8f:f4 ABCD ADD
static int lastAngle5 = 90;
static int lastAngle6 = 90;
/*
int lastServo1 = 90;
int lastServo2 = 90;
int lastServo3 = 90;
int lastServo4 = 90;
int lastServo5 = 90;
int lastServo6 = 90;
int lastServo7 = 90;
int lastServo8 = 90;
int lastServo9 = 90;
int lastServo10 = 90;
int lastServo11 = 90;
int lastServo12 = 90;*/
int angleToPulse(int angle) {
return map(angle, 0, 180, 102, 512); // Adjust if your servo pulse range differs
}
void OnDataRecv(const esp_now_recv_info_t *info, const uint8_t *incomingData, int len) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
info->src_addr[0], info->src_addr[1], info->src_addr[2],
info->src_addr[3], info->src_addr[4], info->src_addr[5]);
//Serial.print("Received from: ");
// Serial.println(macStr);
// Compare sender MAC and copy appropriate data
if (memcmp(info->src_addr, sender1, 6) == 0) {
memcpy(&myData1, incomingData, sizeof(myData1));
//Serial.println("Sender 1 data:");
//Serial.print("E9 = "); Serial.println(myData1.E9);
// Serial.print("C6 = "); Serial.println(myData1.C6);
}
else if (memcmp(info->src_addr, sender2, 6) == 0) {
memcpy(&myData2, incomingData, sizeof(myData2));
// Serial.println("Sender 2 data:");
Serial.println(" A : ");
Serial.print(myData2.pedalA);
Serial.print(" B : ");
Serial.print(myData2.pedalB);
Serial.print(" C : ");
Serial.print(myData2.pedalC);
Serial.print(" D : ");
Serial.print(myData2.pedalD);
Serial.print(" E : ");
Serial.print(myData2.pedalE);
// Serial.print(" E9 : ");
// Serial.println(myData1.E9);
//Serial.print(" C6 : ");
// Serial.println(myData1.C6);
}
else if (memcmp(info->src_addr, sender4, 6) == 0) {
memcpy(&myData4, incomingData, sizeof(myData4));
//Serial.println("Sender 3 data:");
// Serial.print("freq = ");
// Serial.println(myData4.freq);
// Serial.print("peak = ");
// Serial.println(myData4.peak);
// Serial.print("Volume = ");
// Serial.println(myData4.volume);
} else {
Serial.println("Unknown sender");
}
}
int angleToPulse(int angle);
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());
pwm.begin();
pwm.setPWMFreq(50); // Standard servo frequency
// Initialize all servos to home position
for (int i = 0; i < 12; i++) {
pwm.setPWM(i, 0, angleToPulse(90));
}
WiFi.mode(WIFI_STA);
if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
{
int numReadings = 200;
int sum1 = 0;
int sum2 = 0;
int sum3 = 0;
int sum4 = 0;
int sum5 = 0;
for (int i = 0; i < numReadings; i++) {
sum1 += analogRead(33);
}
for (int i = 0; i < numReadings; i++) {
sum2 += analogRead(32);
}
for (int i = 0; i < numReadings; i++) {
sum3 += analogRead(35);
}
for (int i = 0; i < numReadings; i++) {
sum4 += analogRead(34);
}
for (int i = 0; i < numReadings; i++) {
sum5 += analogRead(25);
}
myData3.LL = (sum1 / numReadings) * 4 ;
myData3.LR = (sum2 / numReadings) * 4 ;
myData3.RL = (sum3 / numReadings) * 4 ;
myData3.RR = (sum4 / numReadings) * 4 ;
myData3.V = (sum5 / numReadings) * 4 ;
Serial.print(" LL : ");
Serial.print(myData3.LL);
Serial.print(" LR : ");
Serial.print(myData3.LR);
Serial.print(" RL : ");
Serial.print(myData3.RL);
Serial.print(" RR : ");
Serial.print(myData3.RR);
//Serial.print(" freq : ");
//Serial.print(myData4.freq);
// Serial.print("Peak: ");
// Serial.print(myData4.peak);
}
if (myData1.C6 == 0) {
// === SERVO 1 ===
if (myData3.RL > 5600 && myData3.RL <= 6800) {
int angle1 = map(myData3.RL, 5600, 6800, 90, 111);
angle1 = constrain(angle1, 90, 111);
pwm.setPWM(1, 0, angleToPulse(angle1));
} else if (myData3.RL > 6800) {
pwm.setPWM(1, 0, angleToPulse(111)); // Hold at max angle
} else {
pwm.setPWM(1, 0, angleToPulse(90)); // Stay at base angle
}
// === SERVO 2 ===
if (myData2.pedalE > 100 && myData2.pedalE <= 3300) {
int angle2 = map(myData2.pedalE, 4, 3300, 90, 98);
angle2 = constrain(angle2, 90, 98);
pwm.setPWM(2, 0, angleToPulse(angle2));
} else if (myData2.pedalE > 3300) {
pwm.setPWM(2, 0, angleToPulse(98)); // Hold at max angle
} else {
pwm.setPWM(2, 0, angleToPulse(90)); // Stay at base angle
}
/////////////////////////////////////////
// === SERVO 3 ===
if (myData2.pedalB > 100 && myData2.pedalB <= 3000) {
int angle3 = map(myData2.pedalB, 100, 3000, 90, 102);
angle3 = constrain(angle3, 90, 102);
pwm.setPWM(3, 0, angleToPulse(angle3));
} else if (myData2.pedalB > 3000) {
pwm.setPWM(3, 0, angleToPulse(102));
} else {
pwm.setPWM(3, 0, angleToPulse(90));
}
// === SERVO 4 ===
if (myData2.pedalC > 100 && myData2.pedalC <= 2260) {
int angle4 = map(myData2.pedalC, 0, 2260, 90, 106);
angle4 = constrain(angle4, 90, 106);
pwm.setPWM(4, 0, angleToPulse(angle4));
} else if (myData2.pedalC > 2260) {
pwm.setPWM(4, 0, angleToPulse(106));
} else {
pwm.setPWM(4, 0, angleToPulse(90));
}
} else {
// Control via LL
if (myData3.LL > 9700 && myData3.LL <= 11000) {
int angle5 = map(myData3.LL, 9700, 11000, 90, 111);
angle5 = constrain(angle5, 90, 111);
pwm.setPWM(4, 0, angleToPulse(angle5));
} else if (myData3.LL > 11000) {
pwm.setPWM(4, 0, angleToPulse(111));
} else {
pwm.setPWM(4, 0, angleToPulse(90));
}
}
// === SERVO 5 ===
if (myData2.pedalA > 100 && myData2.pedalA <= 4000) {
int angle5 = map(myData2.pedalA, 0, 4000, 90, 99);
angle5 = constrain(angle5, 90, 99);
pwm.setPWM(5, 0, angleToPulse(angle5));
} else if (myData2.pedalA > 4000) {
pwm.setPWM(5, 0, angleToPulse(99));
} else {
pwm.setPWM(5, 0, angleToPulse(90));
}
// === SERVO 6 ===
if (myData2.pedalB > 100 && myData2.pedalB <= 3000) {
int angle6 = map(myData2.pedalB, 0, 3000, 90, 94);
angle6 = constrain(angle6, 90, 94);
pwm.setPWM(6, 0, angleToPulse(angle6));
} else if (myData2.pedalB > 3000) {
pwm.setPWM(6, 0, angleToPulse(94));
} else {
pwm.setPWM(6, 0, angleToPulse(90));
}
// === SERVO 7 ===
if (myData2.pedalE > 100 && myData2.pedalE <= 3300) {
int angle7 = map(myData2.pedalE, 0, 3300, 90, 98);
angle7 = constrain(angle7, 90, 98);
pwm.setPWM(7, 0, angleToPulse(angle7));
} else if (myData2.pedalE > 3300) {
pwm.setPWM(7, 0, angleToPulse(98));
} else {
pwm.setPWM(7, 0, angleToPulse(90));
}
// === SERVO 8 ===
if (myData3.LL >= 9000 && myData3.LL <=11000) {
int angle8 = map(myData3.LL, 9000, 11000, 80, 90);
angle8 = constrain(angle8, 80, 90);
pwm.setPWM(8, 0, angleToPulse(angle8));
} else if (myData3.LR > 9000 && myData3.LR <= 9600) {
pwm.setPWM(8, 0, angleToPulse(90)); // fixed angle
} else {
pwm.setPWM(8, 0, angleToPulse(90));
}
// === SERVO 9 ===
if (myData3.RR > 5000 && myData3.RR <=6300) {
int angle9 = map(myData3.RR, 80, 4097, 90, 90);
angle9 = constrain(angle9, 90, 90); // constant angle, just for structure
pwm.setPWM(9, 0, angleToPulse(angle9));
} else {
pwm.setPWM(9, 0, angleToPulse(90));
}
// === SERVO 10 ===
if (myData2.pedalA > 100 && myData2.pedalA <= 4000) {
int angle10 = map(myData2.pedalA, 80, 4000, 90, 79);
angle10 = constrain(angle10, 79, 90);
pwm.setPWM(10, 0, angleToPulse(angle10));
} else if (myData2.pedalD > 100 && myData2.pedalD <= 4000) {
int angle10b = map(myData2.pedalD, 80, 4095, 90, 99);
angle10b = constrain(angle10b, 90, 99);
pwm.setPWM(10, 0, angleToPulse(angle10b));
} else {
pwm.setPWM(10, 0, angleToPulse(90));
}
// === SERVO 11 ===
if (myData2.pedalE > 80 && myData2.pedalE <= 4200) {
int angle11 = map(myData2.pedalE, 80, 4200, 90, 85);
angle11 = constrain(angle11, 85, 90);
pwm.setPWM(11, 0, angleToPulse(angle11));
} else {
pwm.setPWM(11, 0, angleToPulse(90));
}
// === SERVO 12 ===
if (myData2.pedalE > 80 && myData2.pedalE <= 4097) {
int angle12 = map(myData2.pedalE, 80, 4097, 90, 80);
angle12 = constrain(angle12, 80, 90);
pwm.setPWM(12, 0, angleToPulse(angle12));
} else {
pwm.setPWM(12, 0, angleToPulse(90));
}
How are you getting those large values of the digital counts ie up to 11000 ie data3.LL?
The esp32 only has a 12 bit analog to digital converter so the max would be 4096.
Unless I am totally reading this incorrectly.
You seem to be executing the command
pwm.setPWM(4, 0, angleToPulse(90))
which I assume is what you meant by "In this code when the value go over the 2260 it jumps back to 90" in two different places (lines 262 and 273).
These are differentiated by the test "if (myData1.C6 == 0) {" in line 221. If this condition is true, then line 262 may be executed; otherwise line 273 may be executed.
You do not supply sufficient information to determine which of these conditions is causing the reset to 90 degrees. You should put in some sample print statements to determine the state of the values used and find which of these two statements is being executed.
Anything seems possible when you don't know what you're talking about.
So I added a photo of my project. This is my second and it will have a lot of features, most of what I have to figure out how to. One of the issues is wat's above in the code.
On the question where I get such large numbers 11000, is as follow.
All the controllers I use on the guitar are ESP32-NOW communication between them. Servo controller, motor controller for strings 1 to 6, motor controller 7 to 12 and a frequency reader. The servo controller handles the strings, if I press the foot of knee levers it tightens or slacken the strings to change pitch. The motor controllers handle the tuning of the guitar, and the frequency reader handle the LED lights and freq that are used by the motor controllers to tune the guitar in 3 different ways. Manual tuning, semi auto tuning and full auto tuning where the strings get vibrated by a coil and the motor controllers tune according to freq one string after the other.
So the large numbers are from the Hall effect sensors to read pedals and knee levers.
I have two issues here. The first issue is if I only use.
if (myData2.pedalC > 100 );
int angle = map(myData2.pedalC, 0, 2200, 90, 106);
it works fine except the string does not stop exactly at the same spot every time. (With sound I need it super accurate). So, I used the below, all data from pedal4 section.
I now have a range where I can control the start and end of the servo movements. But it does not work as I thought it would be. What happen, the servo starts moving and follow pedalC up to value 2260 and then returns to 90 which is the neutral position of the servo motor. I need the servo to remain at the 2260 position until the pedalC value go lower than 2260. That is the section I struggle with.
if (myData2.pedalC > 100 && myData2.pedalC <= 2260) {
int angle4 = map(myData2.pedalC, 0, 2260, 90, 106);
The second part I struggle with is servo4. When I use the "
if (myData2.pedalC > 100 );
int angle = map(myData2.pedalC, 0, 2200, 90, 106);" as is I can run pedalC and LL independently but when I use the setup "if (myData2.pedac < 100 && myData2.pedalC <= 2260);
and if (myData1.LL > 9700 && myData1.LL >= 11000); together as in the sketch then one of them pedalC would not work and LL run backwards.
While I'm at it I also need an accurate frequence reader code
frequency meter.
Thanks for the info, I fixed the large numbers as it came from my smoothing calculations. The values are now close to 0 - 4095. However, I changed the circuit by removing the"myData2.pedalC<=2260" which caused the issue but now when pressing pedalC the top values are not super stable. It fluctuates a little which is not ideal in the guitar world. I still need to fix it somehow.
if (myData2.pedalC > 100 && myData2.pedalC <= 2260) {