Я завтра возвращаюсь домой и смогу приступить к колибровке и смогу точно сказать линейную зависимость.
А по поводу ШИМ сигнала я его буду усиливаливать с помощью полевого транзистора мне дали схему и я ее уже спаял на 4 канала. А вход как раз реагиреюует на ШИМ.
остатки от машинки, на которой опробовал ДУ на модулях LORA. Управлялась джойстиком с кнопкой. Только PiPico была без ВиФи.
#include <Wire.h>
#define motorAspeedPIN 6 // motorA MOSFET
#define AreversPIN 13 //revers relay A
#define motorBspeedPIN 7 // motorB MOSFET
#define BreversPIN 12 //revers relay B
#define motorCspeedPIN 8 // motorC MOSFET
#define CreversPIN 11 //revers relay C
#define motorDspeedPIN 9 // motorD MOSFET
#define DreversPIN 10 //revers relay D
byte Xval=126; // нач.значение с оси Х джстк от ДУмодуля
byte Yval=127 ; //начальное значение с оси У джстк от ДУмодуля
bool Zval; // нач.значение кнопки дж -переключение скорости от ДУмодуля
byte diffSpeed = 0; // не понадобилось
byte speedValP = 0;
byte speedValPpoworot = 0;
byte speedValL = 0;
byte speedValLpoworot = 0;
byte ValP = 0;// угол поворота джойстика вправо от оси Х
byte ValL = 0;// угол поворота джойстика влево от оси Х
byte maxSpeed;//
bool reversARelay = 0;
bool reversBRelay = 0;
bool reversCRelay = 0;
bool reversDRelay = 0;
void setup() {
Serial.begin(9600);
pinMode(AreversPIN, OUTPUT);
pinMode(BreversPIN, OUTPUT);
pinMode(CreversPIN, OUTPUT);
pinMode(DreversPIN, OUTPUT);
pinMode(motorAspeedPIN, OUTPUT);
pinMode(motorBspeedPIN, OUTPUT);
pinMode(motorCspeedPIN, OUTPUT);
pinMode(motorDspeedPIN, OUTPUT);
digitalWrite(motorAspeedPIN, LOW);
digitalWrite(motorBspeedPIN, LOW);
digitalWrite(motorCspeedPIN, LOW);
digitalWrite(motorDspeedPIN, LOW);
analogWriteResolution(8);
analogWriteFreq(5000);
Wire.setSDA(0);
Wire.setSCL(1);
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
// Serial.begin(9600); // start serial for output
}
void loop() {
if (Zval == 0) {
maxSpeed=90;
// speedValP = 0;
// speedValL = 0;
} else {
maxSpeed=255;
}
if (Xval > 125) {
if (Yval > 125 && Yval < 128) {
speedValP = map(Xval, 125, 255, 0, maxSpeed);
speedValL = map(Xval, 125, 255, 0, maxSpeed);
ValL = 0;
ValP = 0;
} else if (Yval > 128) {
ValL = map(Yval, 125, 255, 0, 90);//значение с джст переводим в градусы отклонения
speedValLpoworot = map(Xval, 125, 255, 0, maxSpeed);
speedValL = speedValLpoworot * cos(ValL);
speedValP = map(Xval, 125, 255, 0, maxSpeed);
ValP = 0;
} else if (Yval < 125) {
ValP = map(Yval, 125, 0, 0, 90);
speedValPpoworot = map(Xval, 125, 255, 0, maxSpeed);
speedValP = speedValPpoworot * cos(ValP);
speedValL = map(Xval, 125, 255, 0, maxSpeed);
ValL = 0;
}
reversARelay = 0;
reversBRelay = 0;
reversCRelay = 0;
reversDRelay = 0;
} else if (Xval < 125) {
if (Yval > 125 && Yval < 128) {
speedValP = map(Xval, 125, 0, 0, maxSpeed);
speedValL = map(Xval, 125, 0, 0,maxSpeed);
ValL = 0;
ValP = 0;
} else if (Yval > 128) {
ValL = map(Yval, 125, 255, 0, 90);
speedValLpoworot = map(Xval, 125, 0, 0, maxSpeed);
speedValL = speedValLpoworot * cos(ValL);
speedValP = map(Xval, 125, 0, 0, maxSpeed);
ValP = 0;
} else if (Yval < 125) {
ValP = map(Yval, 125, 0, 0, 90);
speedValPpoworot = map(Xval, 125, 0, 0, maxSpeed);
speedValP = speedValPpoworot * cos(ValP);
speedValL = map(Xval, 125, 0, 0, maxSpeed);
ValL = 0;
}
reversARelay = 1;
reversBRelay = 1;
reversCRelay = 1;
reversDRelay = 1;
}
else {
if (Yval > 125 && Yval < 129) {
speedValP = 0;
speedValL = 0;
reversARelay = 0;
reversBRelay = 0;
reversCRelay = 0;
reversDRelay = 0;
} else if (Yval > 125) {
speedValP = map(Yval, 125, 255, 0, maxSpeed);
speedValL = map(Yval, 125, 255, 0, maxSpeed);
reversARelay = 0;
reversBRelay = 1;
reversCRelay = 1;
reversDRelay = 0;
} else if (Yval < 125) {
speedValP = map(Yval, 127, 0, 0, maxSpeed);
speedValL = map(Yval, 127, 0, 0, maxSpeed);
reversARelay = 1;
reversBRelay = 0;
reversCRelay = 0;
reversDRelay = 1;
}
// }
//speedValP = Xval;
//speedValL = Xval;
}
Amotor(speedValP, reversARelay);
Bmotor(speedValL, reversBRelay);
Cmotor(speedValP, reversCRelay);
Dmotor(speedValL, reversDRelay);
Serial.print("Xval=");
Serial.print(Xval);
Serial.print(",Yval=");
Serial.println(Yval);
}
void Amotor(byte speed, bool revers) {
analogWrite(motorAspeedPIN, speed);
digitalWrite(AreversPIN, revers);
}
void Bmotor(byte speed, bool revers) {
analogWrite(motorBspeedPIN, speed);
digitalWrite(BreversPIN, revers);
}
void Cmotor(byte speed, bool revers) {
analogWrite(motorCspeedPIN, speed);
digitalWrite(CreversPIN, revers);
}
void Dmotor(byte speed, bool revers) {
analogWrite(motorDspeedPIN, speed);
digitalWrite(DreversPIN, revers);
}
void receiveEvent(int howMany) {
while (1 < Wire.available()) // loop through all but the last
{
byte c = Wire.read();
Yval = c;
byte a = Wire.read();
Xval = a;
bool x = Wire.read(); // receive byte as an integer
Zval = x;
}
}
Бегала очень быстро . Поэтому использовалась кнопка для выбора скорости. Все делалось через MAP функцию и через ИФы с ELSE. Для тестирования ДУ и такой говнокод прокатил.Моторчики управлялись мосфетами и реле (для реверсирования моторчика).
Для четырех соленоидов еще проще. Вперед - 2 соленоида , назад -2 других. И ШИМ.
Это неверная последовательность.
Сначала - мультиметр.
Потом - алгоритм.
И только в самом конце - код.
Да конечно, я наверное так и хотел сказать примерно. Сначала околибровать измерить что-то примерно построить. Ну а потом ставить на трактор. Возможно опять снимать. И ещё настраивать. Если не получится ноутбук настроить.
Спасибо.
Я думаю на основе ваших и предыдущих советав, что нибудь сделаю. Но все равно придется спрашивать.
Ведь это мой первый блин. ![]()
Даже не знаю как сообщения исправлять. Отправишь потом ёлки палки.
Советов
ну вы опять прямо на вопрос ответить не хотите, догадываться приходится (( ШИМ знаете, разный бывает. Частота, период, минимальная и максимальная длина импульса там всякие… А у вас, получается, клапан на 5 вольт начинает открываться, а на 24 вольтах открыт полностью, да? И это на транзисторе. То есть если я догадался правильно, то вы просто analogWrite можете делать на затвор транзистора и оно будет работать как надо.
Штош. Насчет таблиц, вот смотрите. Если нормализуете показания датчиков холла, например, в диапазон 0…255 (analogWrite как раз такие и принимает) и введете вычисление значений каждой полуоси, то есть у вас будет четыре полуоси джойстика:
вперед = 0…255
назад = 0…255
влево = 0…255
вправо = 0…255
ВАЖНО У вас одновременно будут ненулевые максимум два значения (одно из вперед/назад и одно из влево/вправо). Ваш алгоритм без таблиц нахреналиард значений будет следующим:
если (вперед > 0) {
левыйПереднийКлапан = вперед > влево ? вперед - влево : 0
правыйПереднийКлапан = вперед > вправо ? вперед - вправо : 0
левыйЗаднийКлапан = 0
правыйЗаднийКлапан = 0
} иначе если (назад > 0) {
левыйПереднийКлапан = 0
правыйПереднийКлапан = 0
левыйЗаднийКлапан = назад > влево ? назад - влево : 0
правыйЗаднийКлапан = назад > вправо ? назад - вправо : 0
} иначе {
// если оси вперед и назад обе равны нулю то тогда ща будет прикольно:
левыйПереднийКлапан = вправо
правыйПереднийКлапан = влево
левыйЗаднийКлапан = влево
правыйЗаднийКлапан = вправо
// помните, да, что у вас только одно из влево и вправо может быть НЕ равно нулю?
// вот вам и танковый разворот без доп. оси джойстика
}
у вас при любом раскладе будет определено состояние каждого клапана, и одновременно открыты будут не более одного на каждой стороне. Это если вы хотите замедлять одну сторону для поворота. Я по-прежнему считаю что это неправильно и что машине нужна обратная связь от моторов…
Если что записи вида “вперед > влево ? вперед - влево : 0” называются инлайн-условиями, читается как “условие ? если да : если нет” это для сокращения записи
кстати насчет полного привода. Я бы переднее и заднее колесо на каждой стороне соединил цепью или ремнем
а смысл, они и так соединены общим гидравлическим потоком, жидкости жеж не сжимаемы
насколько понял у него пока монопривод, думает на вторую ось тоже моторы ставить и гидромагистраль тянуть. Тоже неплохо. Только во-первых это +4 мотора, и во вторых если цепь/ремень оборвется доехать можно, а если магистраль вытечет то только эвакуатор)) я бы предпочел минимизировть прокат гидравлики
у него 4-ре мотора, борта включены последовательно
а я так понял что по 2 мотора на каждом колесе: 1 по часовой стрелке вращает и 1 против, таким образом вперед/назад открытием 1 из 2х клапанов реализовано
блин, понял, гидрораспределитель хитрая штука походу. Получается трубка выхода одного мотора вставлена во вход второго мотора, а гидроуселитель по этой цепи жижу либо в 1 либо в другую сторону гоняет, и это управляется двумя соленоидами. Вполне изящное решения, рассинхрониться им не даст сцепление с дорогой ещё.
ссорян. Ну алгоритм выше это никак не меняет))
обратная связь не нужна она и так там есть (связаны гидравлическим потоком, обороты строго пропорциональны расходу)
нужна, и ее там нет. Контроллеру же плевать, что трактор едет 20 км/ч вперед - дерни ручку назад до упора, потому что пчела укусила руку, и он клапана в реверс на полную откроет… Потому что контроллер не знает текущую скорость и направление движения трактора. Или я чего-то не понимаю?
Опять же открытие клапанов на 100% же не значит, что трактор сразу на максимальную скорость выйдет, а лишь то, что на моторах максимальный крутящий момент появится. Скорость ему еще нужно набрать, под действием силы, приложенной к массе трактора
а как он едет? скорость равна текущему значению расходов, на кранах (где гидравлика) стиком управляется и вот управление самая сложная операция
тоесть когда краны открываются на полную он моментально набирает максималку? Ускорение в этот момент равно бесконечности?
Добавлю: максималка в горку равна максималке по прямой?
в пределах производительности насоса, она тоже регулируется, на стадии настройки гидросистемы (типа ограничение максимального тока) еще и двигатель обороты сбросит от нагрузки
Пытать надо ТС на предмет даташита регулятора, что там и как, 150 штук это же не за просто так берут
А по мне стик для управления это блажь, но я ни разу не лётчик, но даже для моделей авто используется руль и педаль газа, хотя стик проще - FS-GT3C к примеру
Да, согласен. Там и обратка со стравливающим клапаном где-нибудь может быть.
Но. Давление в системе зависит от производительности насоса на моторе. Клапана на распредах контролируют поток. Когда клапан открывается, давление начинает давить на крыльчатку пневмомоторов, т.е. прикладывая силу. Чем больше открыт клапан - тем больше сила. На оси появляется момент, который может вращать колесо. А может и не вращать, если колесо ломом заблокировано. Под действием такой силы, приложенной к массе трактора, при условии достаточного сцепления с дорогой, трактору будет придано ускорение и он начнет разгоняться. Это как в машине, даже если у вас всего одна передача, скорость не равна положению педали газа, верно?
И вот поскольку это не игрушка а полноразмерный трактор, в котором будет сидеть живой человек, я бы предпочел чтобы контроллер знал текущие угловые скорости моторов и они были учтены в расчетах
это уже вкусовщина… пусть хоть 2 потенциометра использует, с щелчком в центре. Суть задачи не меняется))
это безопасность
