Есть несколько вопросов по коду.

NikitosZs
NikitosZs аватар
Offline
Зарегистрирован: 26.09.2013

Здравствуйте! Хочу сделать робота, объезжающего препятствия исходя из покааний двух фиксированных УЗ дальномеров + возможность управления с джойстика. Привожу далее код целиком, затем выделю отдельно куски с вопросами.

Полный:

#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); // задаём значение ШИМ вывода для правого двигателя

 

tsostik
Offline
Зарегистрирован: 28.02.2013

NikitosZs пишет:

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);

Правда, примера, где разница окажется важной, я навскидку не придумал.

NikitosZs пишет:

3) Можно ли вообще писать такое сложное условие? 

while(ldist<15 && rdist<15 && ldist>5 && rdist>5 && (ldist<rdist)) // если по обоим датчикам от 5 до 15, при этом справа больше

Можно, но с целью минимизации возможных ошибок все скобки лучше расставить явно, дабы в случае чего не оказалось, что у компилятора и у программиста разные представления о приоритете вычесления конкретного выражения.

NikitosZs пишет:

4)Обращение к ножкам arduino uno. К аналоговым я обращаюсь как A1(например), к цифровым как 3 или, скажем 5.

int Um1 = A3; // задаём пин измерения напряжения
analogWrite(3, RMpwm); // задаём значение ШИМ вывода для правого двигателя

Форма обозначения пина A1 - это не более, чем дефайн, определенный в arduino.h (точнее в платвормозависимых файлах, подклучаемых из нее). Так что так обращаться можно, хотя опять же создает поле для ошибок. Как по мне, так лучше все пины указывать цифрами в начале скетча в виде

#define motorPin 3
#define sensorPin 15

...
analogWrite(motorPin, motorValue);
sensorValue=analogRead(sensorPin);

(цифра "15" взята "от балды", если что)

NikitosZs
NikitosZs аватар
Offline
Зарегистрирован: 26.09.2013

Спасибо!

Это первая моя программа, да и ардуина ещё не пришла, поэтому и вопросы на уровне будет ли работать, т.к проверить не могу.