// 3.4 One character from the phone becomes the motor's duty cycle.
// The HC-05 adds no command of its own: what arrives from the air leaves
// the module on two wires. So this sketch only ever reads a UART - the
// same call a sketch printing to the serial monitor already uses.
const int PIN_RX = 16; // ESP32 RX2 <- module TX, direct
const int PIN_TX = 17; // ESP32 TX2 -> module RX, 1k / 2k divider
const int PIN_MOTOR = 25;
const long BAUD = 9600;
const int N_BITS = 10; // 8N1: start + 8 data + stop
const int PWM_FREQ = 1000;
const int PWM_BITS = 8;
const int PWM_MAX = (1 << PWM_BITS) - 1;
const float T_SLOT_MS = 0.625; // one Bluetooth slot, from 3.3
void setup() {
Serial.begin(115200); // to the computer
Serial2.begin(BAUD, SERIAL_8N1, PIN_RX, PIN_TX); // to the module
if (!ledcAttach(PIN_MOTOR, PWM_FREQ, PWM_BITS)) {
Serial.println("ledcAttach failed - no free timer");
}
ledcWrite(PIN_MOTOR, 0);
}
void loop() {
// No delay and no readString: the character may land at any moment and
// the receive FIFO is small, so the loop must stay free to drain it.
while (Serial2.available()) {
char c = Serial2.read();
if (c < '0' || c > '9') continue; // the module passes anything through
int duty = (int)((c - '0') / 9.0 * PWM_MAX + 0.5);
ledcWrite(PIN_MOTOR, duty);
float t_char = 1000.0 * N_BITS / BAUD; // ms, one character
Serial2.printf("OK %c %d\n", c, duty); // back to the phone
Serial.printf("cmd=%c duty=%d/%d Tchar=%.3f ms lat=%.3f ms\n",
c, duty, PWM_MAX, t_char, t_char + T_SLOT_MS);
}
}