Считывание положения сервопривода

Ramzay
Offline
Зарегистрирован: 16.05.2013

Простой вопрос, код корявый поэтому проще сказать на словах. Есть серва которой периодически задаются углы поворота. Нужно чтобы при определенном угле поворота включался светодиод. К управлению сервы подключен только один кабель.

#include <Servo.h>
#define SRV 7
#define LED 2

Servo myservo;

int val=0;
void setup()
{
  myservo.attach(10);
  pinMode (SRV, OUTPUT);
  pinMode (LED,OUTPUT);
  pinMode (SRV,INPUT);
}

void loop() 
{
 digitalWrite(SRV,HIGH);
 myservo.write(90);
 myservo.read();
 val=myservo.read();
 delay(1000);
 myservo.write(0);
 delay(1000);
 myservo.write(180);
 delay(1000);
 digitalWrite(SRV,LOW);
 delay(8000);
 
 }
 
 
if(val==90)
 {
   digitalWrite(LED,HIGH);
 } else {
   digitalWrite(LED,LOW);
 }

После IF выдает ошибку. Как записать чтобы при повороте на 90гр подаалось питание на LED.

Ramzay
Offline
Зарегистрирован: 16.05.2013

О извините ,выделил строчки жирным и курсивом но он код не проглатил, а редактировать нельзя

Alexander
Offline
Зарегистрирован: 25.04.2010

Поправил

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

myservo.read(); не покажет вам в каком положении находится серва, так как эта функция всего лишь возвращает текущее значение сигнала подаваемого на серву. А вот если бы ввели в поиске по сайту "серво с обратной связью" ,то первая же найденная тема http://arduino.ru/forum/programmirovanie/vozmozhno-li-kak-realizovat-obratnuyu-svyaz-dlya-servoprivoda. А ругается у вас компилятор на то что вы условие вне функции написали.
Так нельзя:

void setup()
{
...
}

void loop() 
{
....
}

if(1 == 1)
{
}

а вот так можно:

void setup()
{
  if(1 == 1)
  {
  }
...
}

void loop() 
{
....
  if(1 == 1)
  {
  }
}

void zhopa()
{
  if(1 == 1)
  {
  }
...
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

Да зачем вам val вообще читать? Зачем IF? Вы же сами знаете куда серву повернули. Повернули, включили светикик, да и все.

void loop(){
  ....
  myservo.write(90);
  delay(1000); // даем серве время на поворот
  digitalWrite(LED,HIGH); 

  myservo.write(45);
  delay(1000); // даем время серве на поворот
  digitalWrite(LED,LOW); // гасим светик, так как угол уже не 90-то
  ....
}

 

Geronimo
Offline
Зарегистрирован: 06.05.2013

а вдруг злодей серву руками повернул?

или у сервы силенок нехватило?

leshak
Offline
Зарегистрирован: 29.09.2011

Geronimo пишет:

а вдруг злодей серву руками повернул?

А вдруг он ее молотком жахнул?

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

Если "силенок не хватило" - значит серва другая нужна. Нечего это в код загонять. Все равно она быстро сломается если не соотвествует задаче.

Ну а если хочется,в сетаки знать "где же она счас стоит", то доп. датчики нужны: энкодер  или переменник.

Переменник нужно либо снаружи монстрячить, либо расковыривать серву и подключатся к тому который у нее внутри.

Ramzay
Offline
Зарегистрирован: 16.05.2013

Да, вы правы. Я думал это будет просто, и решил в самообучающих целях написать. Тут конечно правильно включать светодиод после нужного угла, а затем выключать.
П.с. Никто не разбирается в советских бензиновых двигателях для авиамоделей?

leshak
Offline
Зарегистрирован: 29.09.2011

Ramzay пишет:
Да, вы правы. Я думал это будет просто, 

Ну так это и есть не сложно :) По крайней мере если не лезть в "кто-то снаружи повернул"

Ramzay пишет:
и решил в самообучающих целях написать.

А вот тут  не ошиблись. Это действительно довольно удачный пример для обучения (если смотреть на него как вы изначального его формулировали, без внешних воздействий).

Тот пример что я показал - можно еще улучшать/учится.

Я бы "дальше" его двигал в таком направление:

1. Вынес установку сервы в отдельную функцию. Что-то типа setServo(int newPos) написал, а уж в ней...
2. Включал/выключал светики в зависимсти от newPos (вначале через if, потом бы взял несколько светиков и конструкцию switch поизучал)
3. Сделал запоминание в какую-то глобальную переменную "текущего положения" (что-бы знать где серва стоит).
4. Исходя из прошлого пункта - можно будет время delay(НУЖНО_ДЛЯ_ПОВОРОТА) не жестко кодить, а вычислять (согласитесь что повернутся на 10 градусов, и на 130 - разное время занимает)
5. Делал-бы замену delay на использование millis()  - что-бы скетч не блокировался и можно было сделать какое-то подобие "одновременности".

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

Советские авиамодельные двигатели работали на эфире, а не бензине.

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

спирт, эфир, касторка 

Ramzay
Offline
Зарегистрирован: 16.05.2013

Давайте в отдельную тему, сегодня попробую с фотографиями после работы. Заодно посмотрю, может там маркировка есть.

Ramzay
Offline
Зарегистрирован: 16.05.2013
leshak
Offline
Зарегистрирован: 29.09.2011

leshak пишет:

Ramzay пишет:
Да, вы правы. Я думал это будет просто, 

Ну так это и есть не сложно :) По крайней мере если не лезть в "кто-то снаружи повернул"

Ramzay пишет:
и решил в самообучающих целях написать.

А вот тут  не ошиблись. Это действительно довольно удачный пример для обучения (если смотреть на него как вы изначального его формулировали, без внешних воздействий).

По этому поводу у меня случился приступ графомании

Леший в мире Ардуины: Умная Серва. Часть 1

Предупреждаю "многа букф" :)

Если лень продиратся через промежуточные результаты и смотреть "как мы к этому пришли", то вот сразу итого:

#include "Servo.h" // подключаем библиотеку сервы
 
#define LED_PIN 13  // используем встроенный светодиод
#define SERVO_PIN 9  // подключаем серву на 9-ты pin
#define DELAY_180 1200 // время, в миллисекундах, за которое серва поворачивается на 180 градусов
 
Servo myservo;
byte prevServoPos=0; // сюда будем запоминать, куда мы установили серву. изначально - стоит в нуле.
 
void setup(){
  pinMode(LED_PIN,OUTPUT); // настраиваем выход светика
  myservo.attach(SERVO_PIN); // подключаем серву
 
  init_servo();
   
  run_servo_logic();
   
}
 
void loop(){
}
 
void init_servo(){
  myservo.attach(SERVO_PIN); // подключаем серву
 
  // ставим серву в исходную позицию
  myservo.write(0);
  delay(DELAY_180); // ждем пока станет в 0
}
 
 
void run_servo_logic(){
  byte angles[]={90,45,135,90,180}; // углы в которые нужно ставить серву
  for(byte i=0;i<5;i++){
    setServo(angles[i]); // ставим серву в очередной угол
    toggleLed(); // переключаем состояние светика
  }
}
 
// переключает светик в противоположное состояние
void toggleLed(){
  digitalWrite(LED_PIN,!digitalRead(LED_PIN));
}
 
// Блокирующий аналог Servo.write()
// устанавливает myservo в позицию newPos 
// и делает задержку, минимально необходимую для выполнения команды
// для этого используют  глобальную prevServoPos - старое положение сервы
void setServo(byte newPos){
  // вычисляем нужную задержку
  int angleDiff=abs(newPos-prevServoPos);
  unsigned long servoDelay=(DELAY_180 /180)*angleDiff;
   
  // крутим серву
  myservo.write(newPos);
  delay(servoDelay); // применяем вычисленную задержку
   
  prevServoPos=newPos;// запомнили где теперь стоит серва
}

Надеюсь, что запала хватит и на  продолжение :) 

atas80
Offline
Зарегистрирован: 04.02.2017

Только что на SG90 ёто реализовал - ВСЕ РАБОТАЕТ !!!

https://habrahabr.ru/company/amperka/blog/127773/