Есть несколько вопросов по коду.
- Войдите на сайт для отправки комментариев
Здравствуйте! Хочу сделать робота, объезжающего препятствия исходя из покааний двух фиксированных УЗ дальномеров + возможность управления с джойстика. Привожу далее код целиком, затем выделю отдельно куски с вопросами.
Полный:
#define fwd {digitalWrite(7, 0); analogWrite(6, 255); digitalWrite(2, 0); analogWrite(3, 255);} // полный вперёд
#define fl {digitalWrite(7, 0); analogWrite(6, 127); digitalWrite(2, 0); analogWrite(3, 255);} // поворот налево
#define fr {digitalWrite(7, 0); analogWrite(6, 255); digitalWrite(2, 0); analogWrite(3, 127);} // поворот направо
#define rl {digitalWrite(7, 1); analogWrite(6, 127); digitalWrite(2, 0); analogWrite(3, 127);} // разворот налево
#define rr {digitalWrite(7, 0); analogWrite(6, 127); digitalWrite(2, 1); analogWrite(3, 127);} // разворот направо
#define stp {digitalWrite(7, 0); analogWrite(6, 0); digitalWrite(2, 0); analogWrite(3, 0);} // стоп
int Um1 = A3; // задаём пин измерения напряжения
int Um2 = A2; // задаём пин измерения напряжения
int ledPin = 10; //задаём пин со светодиодом
int LSpot = A0; // пин среднего отвода потенциометра левого стика
int RSpot = A1; // пин среднего отвода потенциометра правого стика
int LS; // переменная для хранения значения положения левого стика
int RS; // переменная для хранения значения положения правого стика
int LMpwm; // значение ШИМ для левого мотора(положительное заполнение для "вперёд")
int LMfwd; // значение определяющее обратное врещение(0=вперёд,1=реверс) левого мотора
int RMpwm; // значение ШИМ для правого мотора(положительное заполнение для "вперёд")
int RMfwd; // значение определяющее обратное врещение(0=вперёд,1=реверс) правого мотора
int Apilot = 4; // пин кнопки автопилот(замыкаем на землю и автопилот вкл)
const int ltrig = 12; // левый тригер
const int lecho = 11; // левое эхо
const int rtrig = 9; // правый тригер
const int recho = 8; // правое эхо
unsigned int ldist=0; // тут храним левую дистанцию в см
unsigned int rdist=0; // тут храним правую дистанцию в см
double mnog1; // делитель напряжения первой банки(после, заменить числом в расчёте)
double mnog2; // делитель напряжения второй банки(после, заменить числом в расчёте)
void setup()
{
pinMode(ltrig, OUTPUT); // указываем что является вводом, а что выводом сигналов
pinMode(lecho, INPUT);
pinMode(rtrig, OUTPUT);
pinMode(recho, INPUT);
pinMode(Apilot, INPUT);
digitalWrite(Apilot, HIGH); // включаем поддяжку кнопки автопилот
ldist=leftUS(); // первичный опрос УЗ дальномеров(левый)
rdist=rightUS(); // первичный опрос УЗ дальномеров(правый)
pinMode(ledPin, OUTPUT); // указываем режим работы пина светодиода-индикатора
}
void loop()
{
switch(digitalRead(Apilot)) // считываем положение кнопки автопилот и ветвим программу
{
case 1: // если кнопка автопилот выключена
LS = analogRead(LSpot); // считываем значение напряжения с левого стика
if(LS>591 || LS<431) // если левый стик вышел из dead-зоны
{
LMpwm = map(LS, 591, 1023, 50, 255); // если наклон вперёд, то присваиваем положительное заполнение ШИМ левого мотора
LMpwm = map(LS, 0, 431, 0, 205); // если наклон назад, то присваиваем отрицательное заполнение ШИМ левого мотора
LMfwd = map(LS, 0, 1023, 1, 0); // выставляем направление вращения левого мотора в зависимости от наклона л.стика
}
else{
LMpwm = 0; // иначе останавливаем
LMfwd = 0; // иначе останавливаем
}
RS = analogRead(RSpot); // считываем значение напряжения с правого стика
if(RS>591 || RS<431) // если правый стик вышел из dead-зоны
{
RMpwm = map(RS, 591, 1023, 50, 255); // если наклон вперёд, то присваиваем положительное заполнение ШИМ правого мотора
RMpwm = map(RS, 0, 431, 0, 205); // если наклон назад, то присваиваем отрицательное заполнение ШИМ правого мотора
RMfwd = map(RS, 0, 1023, 1, 0); // выставляем направление вращения левого мотора в зависимости от наклона п.стика
}
else{
RMpwm = 0; // иначе останавливаем
RMfwd = 0; // иначе останавливаем
}
analogWrite(6, LMpwm); // задаём значение ШИМ вывода для левого двигателя
digitalWrite(7, LMfwd); // задаём напрявление вращение для левого двигателя
analogWrite(3, RMpwm); // задаём значение ШИМ вывода для правого двигателя
digitalWrite(2, RMfwd); // задаём напрявление вращение для правого двигателя
voltage(); // обращаемся к функции, возвращающей минимальное напряжение акб
case 0: // если кнопка автопилот включена(на землю)
while(ldist>=15 && rdist >= 15) // если места впереди >15см по обоим дальномерам
{
fwd; // едем вперёд
ldist=leftUS(); // переспрашиваем датчик левый
rdist=rightUS(); // переспрашиваем датчик правый
}
while(ldist>=15 && rdist<15 && rdist >10) // если слева >15см, а справа от 10 до 15
{
fl; // уплываем влево
ldist=leftUS(); // переспрашиваем датчик левый
rdist=rightUS(); // переспрашиваем датчик правый
}
while(rdist>=15 && ldist<15 && ldist>10) // если справа >15см, а слева от 10 до 15
{
fr; // уплываем вправо
ldist=leftUS(); // переспрашиваем датчик левый
rdist=rightUS(); // переспрашиваем датчик правый
}
while(ldist<15 && rdist<15 && ldist>5 && rdist>5 && (ldist<rdist)) // если по обоим датчикам от 5 до 15, при этом справа больше
{
rr; // разворачиваемся на месте направо
ldist=leftUS(); // переспрашиваем датчик левый
rdist=rightUS(); // переспрашиваем датчик правый
}
while(ldist<15 && rdist<15 && ldist>5 && rdist>5 && (ldist>rdist)) // если по обоим датчикам от 5 до 15, при этом слева больше
{
rl; // разворачиваемся на месте налево
ldist=leftUS(); // переспрашиваем датчик левый
rdist=rightUS(); // переспрашиваем датчик правый
}
while(ldist<=5 || rdist<=5) // если оба дальномера показывают <=5см
{
stp; // стоим и ждём помощи
ldist=leftUS(); // переспрашиваем датчик левый
rdist=rightUS(); // переспрашиваем датчик правый
digitalWrite(ledPin, HIGH); // включаем сд
}
voltage(); // обращаемся к функции, возвращающей минимальное напряжение акб
}
}
int leftUS() // функция возвращающая дистанцию по левому дальномеру в см
{
unsigned int lechot; // тут храним время левого эхо
digitalWrite(ltrig, HIGH); // включаем левый тригер
delayMicroseconds(10); // ждём 10 микросекунд
digitalWrite(ltrig, LOW); // выключаем левый тригер
lechot=pulseIn(lecho, HIGH); // считаем время импульса по левому эхо
ldist=lechot/58; // получаем расстояние слева в см
return ldist; // возвращаем значение в см левого датчика
}
int rightUS() // функция возвращающая дистанцию по правому дальномеру в см
{
unsigned int rechot=0; // тут храним время правого эхо
digitalWrite(rtrig, HIGH); // включаем правый тригер
delayMicroseconds(10); // ждём 10 микросекунд
digitalWrite(rtrig, LOW); // выключаем правый тригер
rechot=pulseIn(recho, HIGH); // считаем время импульса по правому эхо
rdist=rechot/58; // получаем расстояние справа в см
return rdist; // возвращаем значение в см правого датчика
}
void voltage() // функция, возвращающая минимальное напряжение на акб
{
double U, U1, U2; // вводим локальные переменные напряжений
U1=analogRead(Um1)/mnog1; // вычисляем реальное значение напряжения первой банки
U2=analogRead(Um2)/mnog2-U1; // вычисляем реальное значение напряжения второй банки
U=min(U1,U2); // присваиваем минимальное значение
if(U<3.2) // если напряжение в нагрузке меньше 3.2 вольт на какую либо банку
{
digitalWrite(ledPin, HIGH); // включаем сд
if(U<3) // если напряжение в нагрузке меньше 3 вольт на какую либо банку
{
batterylow : // метка для зацикливания
digitalWrite(ledPin, LOW); // выключаем светодиод
stp; // останавливаем движки
delay(500); // ждём пол секунды
digitalWrite(ledPin, HIGH); // снова включаем сд
delay(500); // снова ждём
{
goto batterylow; // входим в бесконечный цикл
}
}
}
}
Вопросы и куски:
1) Возможно ли использовать такую форму записи и далее так обращаться к ней для исполнения? Определяю направление движения, робот управляется двумя моторчиками по два провода на каждый. Один провод под шим, другой под задание направления движения(Я понимаю, что при смене направления у меня будет инверсироваться ШИМ сигнал).
#define fwd {digitalWrite(7, 0); analogWrite(6, 255); digitalWrite(2, 0); analogWrite(3, 255);} // полный вперёд
fwd; // едем вперёд
2) Можно ли кидать несколько условий мапинга на одно значение, притом, что значение будет выходить за границы условия мапинга(ерунду написал какую-то..)
RMpwm = map(RS, 591, 1023, 50, 255); // если наклон вперёд, то присваиваем положительное заполнение ШИМ правого мотора
RMpwm = map(RS, 0, 431, 0, 205); // если наклон назад, то присваиваем отрицательное заполнение ШИМ правого мотора
RMfwd = map(RS, 0, 1023, 1, 0); // выставляем направление вращения левого мотора в зависимости от наклона п.стика
3) Можно ли вообще писать такое сложное условие?
while(ldist<15 && rdist<15 && ldist>5 && rdist>5 && (ldist<rdist)) // если по обоим датчикам от 5 до 15, при этом справа больше
4)Обращение к ножкам arduino uno. К аналоговым я обращаюсь как A1(например), к цифровым как 3 или, скажем 5.
int Um1 = A3; // задаём пин измерения напряжения analogWrite(3, RMpwm); // задаём значение ШИМ вывода для правого двигателя
1) Возможно ли использовать такую форму записи и далее так обращаться к ней для исполнения? Определяю направление движения, робот управляется двумя моторчиками по два провода на каждый. Один провод под шим, другой под задание направления движения(Я понимаю, что при смене направления у меня будет инверсироваться ШИМ сигнал).
#define fwd {digitalWrite(7, 0); analogWrite(6, 255); digitalWrite(2, 0); analogWrite(3, 255);} // полный вперёд fwd; // едем вперёдМожно, но вместо fwd лучше писат FWD (просто полезное соглашение, чтобы дефайны легко отличались на взгляд от недефайнов.)
Хотя вместо
#define action {something; something_else;}
Чаще встречатеся форма
#define action do{something; something_else;} while(0);
Правда, примера, где разница окажется важной, я навскидку не придумал.
3) Можно ли вообще писать такое сложное условие?
Можно, но с целью минимизации возможных ошибок все скобки лучше расставить явно, дабы в случае чего не оказалось, что у компилятора и у программиста разные представления о приоритете вычесления конкретного выражения.
4)Обращение к ножкам arduino uno. К аналоговым я обращаюсь как A1(например), к цифровым как 3 или, скажем 5.
Форма обозначения пина A1 - это не более, чем дефайн, определенный в arduino.h (точнее в платвормозависимых файлах, подклучаемых из нее). Так что так обращаться можно, хотя опять же создает поле для ошибок. Как по мне, так лучше все пины указывать цифрами в начале скетча в виде
(цифра "15" взята "от балды", если что)
Спасибо!
Это первая моя программа, да и ардуина ещё не пришла, поэтому и вопросы на уровне будет ли работать, т.к проверить не могу.