Servo.write(Serial.read())

Тема в разделе "Arduino & Shields", создана пользователем JIukaviy, 22 апр 2013.

  1. JIukaviy

    JIukaviy Нерд

    Здравствуйте люди добрые! К вас я с такой проблемой. Имеется у меня проект на юнити. И имеется Arduino. С компа я передаю на Arduino число (а точнее 6 чисел). Которое представляет собой угол, в который надо установить сервомотор. Так вот, все вроде бы не плохо работает. Но после того как число превышает 127 (я использую тип char, число передается одним байтом.) Серво встает в 0 градусов. Я решил что это из за того что число 128 Arduino воспринимает как -128. (то есть signed char, 127 это 0111 1111, а 128: 1000 0000. Первый бит отвечает за знак числа) пробовал следующим образом:
    Servo.write((unsigned int)Serial.read()).
    не помогает. Пробовал сравнивать полученное число с нулем. и если оно меньше нуля, то прибавлять к нему 255:
    Код (Text):
    int GetAngel(){
        unsigned int angel = Serial.read();
        if(angel < 0)  angel += 255;
        return angel;
    }
    не помогло. Я С++ толком не знаю. Может кто подскажет?
     
  2. roggedhorse

    roggedhorse Гик

    Метод read в классе Serial определен так:
    Код (Text):

    int read(void);
     
    Метод write() в классе Servo так:
    Код (Text):

    // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds
    void write(int value);       
     
    Комментарий означает следующее: если угол меньше 200 градусов, он трактуется как угол. Иначе - как ширина импульса в микросекундах


    Однако в вашем коде есть пара проблем:

    Результат Serial.read() приводится к unsigned int
    Соответственно условие (angel < 0) всегда ложно

    Рекомендую вам понять, что приходит от передающей стороны. Например так:

    Код (Text):
    int GetAngel(){
        int angel = Serial.read();
        Serial.println(angel, DEC);
        if(angel < 0)  angel += 255;
        return angel;
    }
     
  3. JIukaviy

    JIukaviy Нерд

    О как. Всегда думал что servo.write(). Принимает угол.
    Syntax

    servo.write(angle)
    Parameters

    servo: a variable of type Servo
    angle: the value to write to the servo, from 0 to 180

    Код (Text):
    void Servo::write(int value)
    {
      if(value < MIN_PULSE_WIDTH)
      {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
        if(value < 0) value = 0;
        if(value > 180) value = 180;
        value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX()); 
      }
      this->writeMicroseconds(value);
    }
    То есть если значение больше чем 544, то значение трактуется как ширина импульса в микросекундах. Если меньше, то как угол. По идее, все должно быть правильно.

    Кстати да.

    Код (Text):
    int GetAngel(){
        unsigned int angel = Serial.read();
        if(angel < 0)  angel += 255;
        return angel;
    }
    unsigned int по началу не было. Я добавил его потом, от отчаяния.
    С чтением данных от Arduino могут возникнуть проблемы. Если посылать с терминала. То как послать нужную цифру, Alt+цифра? Вроде бы так. Число 127 интерпретируется как 63, 128 интерпретируется как 192. 129 как 193.
     
  4. roggedhorse

    roggedhorse Гик

    Давайте определимся с терминами.
    127 - число
    1, 2 и 7 - цифры.

    Если введете в консоли терминала число 127 и нажмете Enter, то будут отправлены как минимум 3 байта:
    - со значением 49 (цифра 1)
    - со значением 50 (цифра 2)
    - со значением 55 (цифра 7)

    Чтобы передать однобайтовое число в Ардуино и принять его там как однобайтовое без знака, вам нужно послать символ с кодом, равным этому числу. Например, отправленный в сторону Ардуино символ с кодом 176 прилетит в Ардуино и функция Serial.read() вернет вам 176

    Чтобы передать число в human-readable формате, вам нужно на стороне Ардуино написать парсер.
    Отправляете строку "176", на стороне Ардуино парсите полученную строку байт функцией scanf
     
  5. JIukaviy

    JIukaviy Нерд

    Alt+число не подойдет? по идее оно пишет символ у которого код равен введенному числу.
     
  6. roggedhorse

    roggedhorse Гик

    в теории
     
  7. Megakoteyka

    Megakoteyka Оракул Модератор

    Подойдет, но некоторые символы (например, с кодом 0) отображаться не будут.
    Для отображаемых символов точно работает.
     
  8. JIukaviy

    JIukaviy Нерд

    Фух, косяк я обнаружил. Был он не в Arduino, а в Unity. А точнее в моем коде. Делал я следующим образом:
    Код (Text):
    string OutputData = "";
     
    OutputData += (char)LegAngels.BaseLeft1;
    OutputData += (char)LegAngels.ShoulderLeft1;
    OutputData += (char)LegAngels.KneeLeft1;
           
    OutputData += (char)LegAngels.BaseRight1;
    OutputData += (char)LegAngels.ShoulderRight1;
    OutputData += (char)LegAngels.KneeRight1;
     
    sp.Write(OutputData);
    Потом поправил на это:
    Код (Text):
    byte[] OutputData = new byte[18];
     
    OutputData[0] = (byte)LegAngels.BaseRight2;
    OutputData[1] = (byte)LegAngels.ShoulderRight2;
    OutputData[2] = (byte)LegAngels.KneeRight2;
     
    OutputData[3] = (byte)LegAngels.BaseRight3;
    OutputData[4] = (byte)LegAngels.ShoulderRight3;
    OutputData[5] = (byte)LegAngels.KneeRight3;
     
    sp.Write(OutputData, 0, 6);
     
    И все заработало. Ништяк) Спасибо за помощь!
     
    roggedhorse нравится это.
  9. Unixon

    Unixon Оракул Модератор

    Никогда не видел так много Ангелов в таком маленьком кусочке кода... :D робот, видимо, будет с крыльями.
     
    Mitrandir, JIukaviy и Megakoteyka нравится это.