Крутим моторчиком на 90 градусов в заданные промежутки времени с концевиком

tyutrin
Offline
Зарегистрирован: 23.06.2020

Нашел скетч который крутит моторчиком с заданными задержками времени. Проверил, отлично работает. 

#define MOTO_PIN 12
#define TIME_ON_MOTO 10000
#define TIME_OFF_MOTO 10000
boolean state_moto = 0;
unsigned long new_millis_moto = millis();


void setup() {
  pinMode(MOTO_PIN, OUTPUT);
}

void loop() {

  if (millis() > new_millis_moto) {
    state_moto = !state_moto;
    
    digitalWrite(MOTO_PIN, state_moto);
    
    if (state_moto) {
      new_millis_moto = millis() + TIME_ON_MOTO;
    }
    else {
      new_millis_moto = millis() + TIME_OFF_MOTO;
    }
  }
}
Когда придет щелевой оптический датчик на нем планирую реализовать следующее. При повороте оси моторчика на 90 градусов щелевой датчик перекрывается диском и моторчик останавливается. Дальше дожидается когда истечет время TIME_ON_MOTO и снова поворачивается на 90 градусов пока щелевой датчик не откроется и ждет остаток времени TIME_OFF_MOTO. Т.е. "концевик" по изменению сигнала с щелевого датчика должен останавливать моторчик.
 
Сейчас пытаюсь использовать для этого кнопку. Куда пихать условие изменения состояния кнопки и как его грамотно написать не пойму. Нечего не выходит. Видел С++ последний раз в институте 15 лет назад. Пытаюсь разбираться. Спасите помогите.
b707
Offline
Зарегистрирован: 26.05.2017

tyutrin пишет:

Нашел скетч который крутит моторчиком с заданными задержками времени. Проверил, отлично работает.

вообще-то это код мигания светодиодом из стандартного примера "блинк без делей", только неграмотно скопированный.  В строчках 20 и 23 грубая ошибка работы с миллис.

Цитата:
Когда придет щелевой оптический датчик на нем планирую реализовать следующее. При повороте оси моторчика на 90 градусов щелевой датчик перекрывается диском и моторчик останавливается. Дальше дожидается когда истечет время TIME_ON_MOTO и снова поворачивается на 90 градусов пока щелевой датчик не откроется и ждет остаток времени TIME_OFF_MOTO. Т.е. "концевик" по изменению сигнала с щелевого датчика должен останавливать моторчик.
 
У вас принципиальная ошибка в логике. Один и тот же концевик (в вашем случае - щелевой датчик) - не может одновременно работать на оба положения и поворот 90 градусов между ними. Либо ставьте два датчики на обоих концах поворота - либо вообще откажитесь от датчиков и отсчитывайте поворот по времени, как у вас сделано сейчас.
 
 

 

tyutrin
Offline
Зарегистрирован: 23.06.2020

b707 пишет:

вообще-то это код мигания светодиодом из стандартного примера "блинк без делей", только неграмотно скопированный.  В строчках 20 и 23 грубая ошибка работы с миллис.

Код взял тут: http://arduino.ru/forum/programmirovanie/kak-vklyuchit-na-nekotoroe-vremya Читал про millis полдня, ошибку не вижу. Ткните носом пожалуйста.

b707 пишет:

У вас принципиальная ошибка в логике. Один и тот же концевик (в вашем случае - щелевой датчик) - не может одновременно работать на оба положения и поворот 90 градусов между ними. Либо ставьте два датчики на обоих концах поворота - либо вообще откажитесь от датчиков и отсчитывайте поворот по времени, как у вас сделано сейчас.

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

tyutrin
Offline
Зарегистрирован: 23.06.2020

удалил

b707
Offline
Зарегистрирован: 26.05.2017

tyutrin пишет:

Код взял тут: http://arduino.ru/forum/programmirovanie/kak-vklyuchit-na-nekotoroe-vremya Читал про millis полдня, ошибку не вижу. Ткните носом пожалуйста.

вот как раз в этой теме в сообщениях #19 и #22 обсуждается, почему так делать нельзя.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

tyutrin пишет:

Нашел скетч который крутит ...

... Куда пихать условие 

Так найдите скетч в который это условие уже запихано и проблема решится сама собой.

Гриша
Offline
Зарегистрирован: 27.04.2014

Задача очень простая и достаточно интересная, рекомендую не опускать руки, а попытаться разобраться в следующем

Мигаем светодиодом без delay() - будет вашим таймером

Функция digitalRead() - будете читать состояние концевика, на прерываниях не предлагаю, начните с простого. 

delay() - забыть как страшный сон, желательно еще и понять почему, но это уже на последок.

посетить эту страницу и вдумчиво изучить. 

Область видимости переменных - обязательно к пониманию в первом приближении. 

к сожалению тут на форуме нет конкретной информации про "флаги", такая информация полезна лишь новичкам...

по сути это некоторая переменная, дополнительное условие как вариант 

int prevstate = 1;  // установили флаг

if (digitalRead(2) == HIGH  && prevstate == HIGH) { // 
prevstate = LOW; // сняли флаг
....  /// что-то выполнили по условию
.....
}

 

думаю, что пока хватит. 

 

 

tyutrin
Offline
Зарегистрирован: 23.06.2020

Спасибо. Постараюсь решить.

tyutrin
Offline
Зарегистрирован: 23.06.2020

Гриша пишет:

Мигаем светодиодом без delay() - будет вашим таймером

По пунктам. Понял зачем вычислять разницу millis. Про dalay() забыл еще до первого поста. Но мне нужно два интервала чередующихся. Дописал еще одно условие. Как то так. Выглядит как то не по русски, но вроде работает.

 

const int ledPin =  13;        
int ledState = LOW;            
long previousMillis = 0;        
long interval;                  
long intervalOn = 10000;
long intervalOff = 5000;

void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();

  if (ledState == LOW)
    interval = intervalOff;
  else
    interval = intervalOn;

  if (currentMillis - previousMillis > interval) {                  

    previousMillis = currentMillis;                                 

    if (ledState == LOW)                                            
      ledState = HIGH;
    else
      ledState = LOW;

    digitalWrite(ledPin, ledState);                                 
  }
}
Гриша
Offline
Зарегистрирован: 27.04.2014

tyutrin пишет:

 У диска 4 сектора по 90 градусов, на двух секторах щель датчика будет открыта, на двух щель закрыта. Т.е. событие отследить можно по спаду или росту сигнала с датчика.

не совсем понимаю как выглядит ваша пластина, рисунок можно увидеть?

 

tyutrin
Offline
Зарегистрирован: 23.06.2020

Гриша пишет:

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

tyutrin
Offline
Зарегистрирован: 23.06.2020

Оптический концевик будет такой. 

tyutrin
Offline
Зарегистрирован: 23.06.2020

Если я правильно все понял, мне нужно с помощью флагов менять состояние входа "кнопка" при кратковременном нажатии с высокого на низкий или с низкого на высокий (программная кнопка с фиксацией) а дальше условием в момент когда моторчик крутится прерывать его движение сменой уровня входа "кнопка" или ничего не делать если моторчик стоит. Т.е. таким образом я кнопкой имитирую оптический щелевой датчик который будет делать все тоже самое но отмеряя нужный мне угол 90 градусов.

Гриша
Offline
Зарегистрирован: 27.04.2014
const int ledPin =  13;        
int ledState = HIGH;            
long previousMillis = 0;        
long interval;                  // это лишнее, зачем оно если есть игнтервалы ниже
long intervalOn = 100;
long intervalOff = 1000;

int button = 0;  // состояние кнопки, переменная.   
int flag = 0;  // флаг события


void setup() {
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();

 
  if (digitalRead(buttonpin) != button && flag == 0)
    {
	 button = !button; //
	 flag = 1; //
	 
	}
   if (flag == 1 && button == 1)
    {
	    digitalWrite(ledPin, LOW); //был вкл, мы его остановили
		
		if (currentMillis - previousMillis > intervalOff ) //тепрь ждем когда выйдет время 
		 {
		          // нужно сбросить флаг и запустить мотор 
		 }
		
	}
  
 // аналогично описываем когда кнопка разомкнута  
  // только в этом алгоритме ошибка - если в интервале времени кнопку не нажать - система повиснет. подумайте об этом
  // отсутствует подавление дребезга контактов, проверка достоверности нажатия, но это позже... 
  
  

  if (ledState == LOW)                        // лишнее
    interval = intervalOff;                   // лишнее
  else                                        //лишнее
    interval = intervalOn;                     //лишнее






}

это не код, а одно из направлений к решению задачи...

tyutrin
Offline
Зарегистрирован: 23.06.2020

Как сделать кнопку с флагами и без дребезга я уже прикинул в отдельном коде. Сейчас думаю над этим "только в этом алгоритме ошибка - если в интервале времени кнопку не нажать - система повиснет. подумайте об этом"