Передача данных с помощью APC 220

vvadim
Offline
Зарегистрирован: 23.05.2012

Отправляю данные с потенциометра

int pot = A0;
int potVal;
byte LSB;
byte MSB;
void setup()
{ 
  pinMode(pot, INPUT);
  Serial.begin(57600);
}
void loop()
{  
  potVal = analogRead(pot);
  LSB = potVal & 0xff;
  MSB = (potVal >> 8) & 0xff;
  Serial.print("*");
  Serial.write(LSB);
  Serial.write(MSB);
  delay (2);
} 

Обрабатываю переданные значения и управляю сервой

#include <Servo.h>
Servo myservo;
int potVal;
byte LSB;
byte MSB;

void setup()
{
  Serial.begin(57600);
  myservo.attach(9);
}
void loop() 
{ 
  if(Serial.available()>2) {
    char ch=Serial.read();
    if(ch=='*'){
      LSB = Serial.read();
      MSB = Serial.read();
      potVal = word(MSB, LSB);
      if(potVal>10 & potVal<100){      
      myservo.writeMicroseconds(600);
      delay (30);
      }
     else if( potVal>110 & potVal<600){
     myservo.writeMicroseconds(1200);
     delay (80);
     }
     else if( potVal>700 & potVal<1000){
     myservo.writeMicroseconds(2000);
     delay (120);
     }
      Serial.println(potVal);
    }
  }
}






Наблюдаю следующее. Если в коде управления сервой нет delay() то в Serial с показаниями потенциометра всё нормально. В коде примера в Serial выскакивают большие цифры 31786, 10876. От чего это происходит и как с этим бороться. Нужно обеспечить вращение сервы с разной скоростью.

 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Что же вы все по одним и тем же граблям то ходите, уже третию тему с одной и той же проблемой заводите...

http://arduino.ru/forum/programmirovanie/opyat-vopros-po-serial

http://arduino.ru/forum/programmirovanie/peredacha-dannykh-s-pomoshchyu-apc-220

 

maksim
Offline
Зарегистрирован: 12.02.2012

У вас все по прежнему переполняется буфер. Вы отправляете данные каждые 2 миллисекунды, а читаете в лучшем случае каждые 30. Куда деваются остальные пакеты? Правильно в буфер. Но так буфер не резиновый - он переполняется и вы получаете свои непонятные числа.

И вообще зачем там задержки и как вы ими хотите изменить скорость серв?

vvadim
Offline
Зарегистрирован: 23.05.2012

А как изменить скорость поворота сервы без использования задержек? Я не знаю

maksim
Offline
Зарегистрирован: 12.02.2012

А как у вас в коде задержки влияют на скорость? Судя по коду никак.

vvadim
Offline
Зарегистрирован: 23.05.2012

Ну да, я буду использовать 

 

for(pos = 0; pos < 180; pos += 1)   
  {                                  
    myservo.write(pos);              
    delay(15); 
  }
Здесь уже скорость перевода в другое положение определяется величиной задержки. 
vvadim
Offline
Зарегистрирован: 23.05.2012

Может можно использовать millis как в примере мигать без delay?

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так передавайте позиции для сервы с нужной задержкой.

maksim
Offline
Зарегистрирован: 12.02.2012
#define pot A0

int pos = 1005;    
int step = 5;

void setup()
{ 
  Serial.begin(57600);
}

void loop()
{  
  pos += step;
  if(pos == 1000 || pos == 2000)  step = -step;
  byte LSB = pos & 0xff;
  byte MSB = (pos >> 8) & 0xff;
  Serial.print("*");
  Serial.write(LSB);
  Serial.write(MSB);
  int del = map(analogRead(pot), 0, 1023, 2, 200);
  delay(del);
} 

 

#include <Servo.h>
Servo myservo;

void setup()
{
  Serial.begin(57600);
  myservo.attach(9);
}

void loop() 
{ 
  if(Serial.available()) 
  {
    if(Serial.read() == '*')
    {
      byte LSB = Serial.read();
      byte MSB = Serial.read();
      int pos = word(MSB, LSB);     
      myservo.writeMicroseconds(pos);
      //Serial.println(pos);
    }
  }
}

 

vvadim
Offline
Зарегистрирован: 23.05.2012

Двигаюсь дальше. Вот базовый код. В дальнейшем буду его развивать, добавлять кнопки. Работает. Не показываю антидребезг.

void loop(){
  if(inputMode) {
    val = analogRead(potpin);           
    val = map(val, 0, 1023, 500, 2500);   
    myservo.writeMicroseconds(val3);                 
    delay(10);
  }  

  SPEED = analogRead(SPEEDpin);
  SPEED = map(SPEED, 0, 1023, 5, 50);

  /////////////  ПЕРЕХОДИМ В ПОЗ А  

  if(buttonAPin == HIGH ) {             
    inputMode=0;
    for(pos = val; pos < value; pos += 10)                   
    {                                                            
      myservo.writeMicroseconds(pos);                                      
      delay(SPEED);                                                
    } 
    for(pos = val; pos > value; pos -= 10)                      
    {                                
      myservo.writeMicroseconds(pos);                                       
      delay(SPEED);                                                
    }
  }
  /////////////  ВОЗВРАТ К УПРАВЛЕНИЮ ПОТЕНЦИОМЕТРОМ


  if(buttonPOSPin == HIGH) { 
    for(pos = value; pos < val; pos += 10) 
    {                                  
      myservo.writeMicroseconds(pos);              
      delay(SPEED);                       
    } 
    for(pos = value; pos > val; pos -= 10)    
    {                                
      myservo.writeMicroseconds(pos);             
      delay(SPEED);                       
    } 
    inputMode=1;
  } 
}

На его основе код передатчика

void loop(){
  SPEED = analogRead(SPEEDpin);
  SPEED = map(SPEED, 0, 1023, 1, 100);

  potVal = analogRead(potpin);
  potVal = map(potVal, 0, 1023, 550, 2500);
  
  if(ButtonAState == HIGH && ButtonPOSState == LOW) A = 1; 
  else if(ButtonPOSState == HIGH && ButtonAState == LOW) A = 2;

  /////////////  ОТПРАВЛЯЕМ

  LSB = potVal & 0xff;
  MSB = (potVal >> 8) & 0xff;
  LSBvalue = value & 0xff;
  MSBvalue = (value >> 8) & 0xff;
  Serial.print("*");
  Serial.write(A);
  Serial.write(LSB);
  Serial.write(MSB);
  Serial.write(LSBvalue);
  Serial.write(MSBvalue);
  Serial.write(SPEED);
  delay (20);
} 

Приёмник. Использую библиотеку VarSpeedServo. Можно изменять скорость отработки без задержек.

void loop() {
  if(inputMode) {
    MyServo.slowmove (potVal, 255);  
  }
  if(Serial.available()>6) {
    char ch=Serial.read();
    if(ch=='*'){
      A = Serial.read();
      LSB = Serial.read();
      MSB = Serial.read();
      LSBvalue = Serial.read();
      MSBvalue = Serial.read();
      SPEED = Serial.read();

      potVal = word(MSB, LSB);
      value = word(MSBvalue, LSBvalue);

      ///////////////  управление сервой

      if(A == 0) {
        inputMode = 1;  
      }
      ///////////////////////////////////////////////
      else if(A == 1) {
        inputMode = 0;
        for(pos = potVal; pos < value; pos += 10)                   
        {                                                            
          MyServo.slowmove (pos, SPEED);                                 
        } 
        for(pos = potVal; pos > value; pos -= 10)                      
        {                                
          MyServo.slowmove (pos, SPEED);                                
        } 
      } 
      //////////////////////////////////////////////////////
      else if(A == 2) {
        for(pos = value; pos < potVal; pos += 10) 
        {                                  
          MyServo.slowmove (pos, SPEED);       
        } 
        for(pos = value; pos > potVal; pos -= 10)    
        {                                
          MyServo.slowmove (pos, SPEED);        
        }
        inputMode = 1; 
      }

      /////////////////////////////////////////////////////////////////// 

      Serial.print(A);
      Serial.print("\t");
      Serial.print(potVal);
      Serial.print("\t");
      Serial.print(value);
      Serial.print("\t");
      Serial.println(SPEED);
    }
  }
}

При переводе в положение POS  серва игнорирует установленную скорость перевода и переходит на максимальной. В коде приёмника ничего придумать не могу. Пробовал в коде передатчика ввести таймер ( на примере мигаем без delay) и после отправления А=2 через 3 сек отправить А=0 - при нажатии кнопки POS сначала на долю секунды передаётся А=0, потом А=2 и через 3 сек снова А=0.

В базовом коде серва сначала медленно переходит в положение POS а потом управляется потенциометром. 

vvadim
Offline
Зарегистрирован: 23.05.2012

Кусок кода с передатчика

 

 if(ButtonAState == HIGH) A = 1; 
  if(ButtonPOSState == HIGH ) A = 2;
  if(A == 2)
  {
    static unsigned long previousMillis = 0;
    unsigned long currentMillis = millis();
 
    if(currentMillis - previousMillis > 3000) {
      previousMillis = currentMillis;
      A = 0;
    }
  }
 
При нажатии кнопки POS сначала  А=0 потом А=2  и через 3 сек А=0. Нужно при нажатии кнопки А=2 и через 3 сек А=0. Как это побороть? Монитр порта