// пин светодиода
const uint8_t Led = 13;
// пины осей джойстика
const uint8_t pin_joyX = A0; // пин оси Х джойстика
const uint8_t pin_joyY = A1; // пин оси Y джойстика
const uint8_t pin_joyZ = A2; // пин оси Z джойстика
// пины клапанов
const uint8_t pin_valweFL = 9; // пин электромагнита A (вперед левая)
const uint8_t pin_valweFR = 10; // пин электромагнита B (вперед правая)
const uint8_t pin_valweBL = 11; // пин электромагнита C (назад левая)
const uint8_t pin_valweBR = 12; // пин электромагнита D (назад правая)
// это калибровки джойстика (минимум, центр, максимум), они для каждой оси могут быть разные
// можете замерить 1 раз и вписать в программу, можете потом всетаки реализоввать калибровку, как я очень советую
// ВАЖНО пишем реальное значение "до упора"
// Если "до упора вперед" это 600, а "до упора назад" это 200 то так и пишем, по возрастанию не сортируем!
int16_t joyX_F_max = 390; // X до упора вперед
int16_t joyX_mid = 510; // X центр
int16_t joyX_B_max = 630; // X до упора назад
int16_t joyY_L_max = 340; // Y до упора влево
int16_t joyY_mid = 500; // Y центр
int16_t joyY_R_max = 611; // Y до упора вправо
int16_t joyZ_CW_max = 340; // Z до упора по часовой
int16_t joyZ_mid = 500; // Z центр
int16_t joyZ_CCW_max = 611; // Z до упора против часовой
// это отклонения джойстика от центра, которые будут игнорироваться (называется death zone - мертвая зона)
// нужно чтобы избегать нежелательные срабатывания когда сенсоры джойстика немного "поплывут"
// от разницы температуры или изменения окружающего магнитного поля
const uint8_t joy_dz = 10;
// вычисляем начало интервалов для каждой оси, с учетом калибровки центров и мертвой зоны
// эта часть вычислит правильно независимо от того, в цифрах joyX_F_max больше или меньше чем joyX_B_max (и так же для остальных осей)
int16_t joyX_F_min = joyX_F_max > joyX_mid ? joyX_mid + joy_dz : joyX_mid - joy_dz;
int16_t joyX_B_min = joyX_B_max > joyX_mid ? joyX_mid + joy_dz : joyX_mid - joy_dz;
int16_t joyY_L_min = joyY_L_max > joyY_mid ? joyY_mid + joy_dz : joyY_mid - joy_dz;
int16_t joyY_R_min = joyY_R_max > joyY_mid ? joyY_mid + joy_dz : joyY_mid - joy_dz;
int16_t joyZ_CW_min = joyZ_CW_max > joyZ_mid ? joyZ_mid + joy_dz : joyZ_mid - joy_dz;
int16_t joyZ_CCW_min = joyZ_CCW_max > joyZ_mid ? joyZ_mid + joy_dz : joyZ_mid - joy_dz;
void setup() {
pinMode(Led, OUTPUT);
pinMode(pin_valweFL, OUTPUT);
pinMode(pin_valweFR, OUTPUT);
pinMode(pin_valweBL, OUTPUT);
pinMode(pin_valweBR, OUTPUT);
Serial.begin(9600);
}
void loop() {
// это мы получаем "сырые" показания с датчиков холла (оси джойстика) как есть
int16_t joy_X = analogRead(pin_joyX);
int16_t joy_Y = analogRead(pin_joyY);
int16_t joy_Z = analogRead(pin_joyZ);
// нормализуем значения
// функция map() нам пропорционально приведет занчение с холла из интервала joyX_F_min..joyX_F_max к интервалу 0..255
// но эта функция позволяет выходить за рамки интервала, если joy_X не лежит в пределах joyX_F_min..joyX_F_max
// и получится значение за пределами интервала 0..255
// поэтому используем функцию constrain(), которая обрежет результат выполнения map() до нужных 0..255
int16_t forward = constrain(map(joy_X, joyX_F_min, joyX_F_max, 0, 255), 0, 255); // полуось джойстика "вперед"
int16_t backward = constrain(map(joy_X, joyX_B_min, joyX_B_max, 0, 255), 0, 255); // полуось джойстика "назад"
int16_t left = constrain(map(joy_Y, joyY_L_min, joyY_L_max, 0, 255), 0, 255); // полуось джойстика "влево"
int16_t right = constrain(map(joy_Y, joyY_R_min, joyY_R_max, 0, 255), 0, 255); // полуось джойстика "вправо"
int16_t clockwise = constrain(map(joy_Z, joyZ_CW_min, joyZ_CW_max, 0, 255), 0, 255); // полуось джойстика "по часовой"
int16_t counterclockwise = constrain(map(joy_Z, joyZ_CCW_min, joyZ_CCW_max, 0, 255), 0, 255); // полуось джойстика "против часовой"
// /* для отладки выведем в порт значения
Serial.println("forward: " + String(forward) +
", backward: " + String(backward) +
", left: " + String(left) +
", right: " + String(right) +
", clockwise: " + String(clockwise) +
", counterclockwise: " + String(counterclockwise));/**/
// теперь у вас нормализованные значения 0..255, на их основе можно вычислить степень открытости клапанов
// причем по одной оси только одно значение сможет быть больше нуля, если джойстик вообще был отклонен
// значения для клапанов
int16_t valweFL = 0; // электромагнит A (вперед левая)
int16_t valweFR = 0; // электромагнит B (вперед правая)
int16_t valweBL = 0; // электромагнит C (назад левая)
int16_t valweBR = 0; // электромагнит D (назад правая)
if (forward > 0 || backward > 0) {
// есть движение вперед или назад, повороты замедлением одной стороны
valweFL = constrain( forward - left, 0, 255);
valweFR = constrain( forward - right, 0, 255);
valweBL = constrain(backward - left, 0, 255);
valweBR = constrain(backward - right, 0, 255);
} else {
// нет движения вперед или назад, делаем разворот
valweFL = clockwise;
valweFR = counterclockwise;
valweBL = counterclockwise;
valweBR = clockwise;
}
// выводим ШИМ
analogWrite(pin_valweFL, valweFL);
analogWrite(pin_valweFR, valweFR);
analogWrite(pin_valweBL, valweBL);
analogWrite(pin_valweBR, valweBR);
// /* для отладки выведем в порт значения
Serial.println("valweFL: " + String(valweFL) +
", valweFR: " + String(valweFR) +
", valweBL: " + String(valweBL) +
", valweBR: " + String(valweBR));/**/
}