скетч из псевдокода

kriss
Offline
Зарегистрирован: 24.01.2014

Имеем три контакта А,В и С.  Они  последовательно, в реальном времени, подают сигнал “1” на вход ардуины.  Если назвать три импульса подряд –пачкой, то нужно  вести счет  этих  пачек.    Догадываюсь , что это можно резко упростить    занявшись  счетом одного их них,  приняв его за базовый.   Но  последовательность   может   быть не выполнена и реверсироваться  В-А-С, А-С-В  или С-В-А   Повлияет ли это на правильный счет – я не допетриваю.   И  полез в дебри. И вот есть похожее на код,   на базе теории   конечных автоматов,  который   после доработок никак    не компилируется.  Но почему?

     Подскажите, где ошибка.  Я чайник - поэтому не нагружайте умными словами если что. 

int inA, inB, inC;         //   входы

int counter = 0;   // Счетчик

int newInState = 0;  текущее состояние  
int prevInState = 0; // пердыдущее Состояние  
int state1 = 0; // Состояние конечного автомата 1 (KA1)
int state2 = 0; // Состояние конечного автомата 2  (KA2)

void setup (); // здесь ли место??

// Сравниваем     текущее   состояние входов с предыдущим  . Если состояние

// изменилось, то переходим к другому КА.   Создаем   функции переходов

 void loop();       //  куда  ее  правильно вставить   ету  функцию loop() ???она в ошибке компиляции
void counter_super_func() {
  newInState = inA<<2 | inB<<1 | inC;
  if (newInState != prevInState) {
    func_1();
    func_2();  }
  prevInState = newInState;}

// КА для последовательност A-B-C
void func_1 () {
  switch (state1) {
  case 0:
    if (inA && !inB && !inC) {
      state1= 1;
    } else {
      state1=0;
    }
    break;
  case 1:
    if (!inA && inB && !inC) {
      state1= 2;
    } else {
      state1=0;
    }
    break;
  case 2:
    if (!inA && !inB && inC) {
      state1= 3;
    } else {
      state1=0;
    }
    break;
  case 3:
    if (!inA && !inB && !inC) {
      state1= 0;
      counter++;
    } else {
      state1=0;
    }
    break; }}

// КА для последовательност С-B-A
void func_2 () {
  switch (state2) {
  case 0:
    if (!inA && !inB && inC) {
      state2= 1;
    } else {
      state2= 0;
    }
    break;
  case 1:
    if (!inA && inB && !inC) {
      state2= 2;
    } else {
      state2= 0;
    }
    break;
  case 2:
    if (inA && !inB && !inC) {
      state2= 3;
    } else {
      state2=0;
    }
    break;
  case 3:
    if (!inA && !inB && !inC) {
      state2= 0;
      counter--;
    } else {
      state2=0;
    }
    break;  }}

toc
Offline
Зарегистрирован: 09.02.2013

1. откройте в примерах скетч Blink
2. запустите его
3. прочитайте каждую строку и постарайтесь понять

inspiritus
Offline
Зарегистрирован: 17.12.2012

Я бы сказал понять структуру программы.

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

если написать

setup(){}

Loop(){}

и поставить // перед "текущее состояние" ошибка пропадет но ничего происходить не будет

если совсем коротко то функцию loop не надо вставлять , вставляют в неё ;)

в рамках проектов программирования МК непонятно как Вы будете использовать результаты работы КА при отсутствии обращений к аппаратным средствам ( светодиоды, дисплей, испонительные механизмы)и как вводить исходную информацию для работы КА ( кнопки, датчики, сеть, связь с компьютером)  ? 

kriss
Offline
Зарегистрирован: 24.01.2014

Я  уже успел исправить синтаксис, но  появились другие ошибки. пытался декларировать функции перехода в   setup(), но.........

sketch_feb22b:18: error: 'func_1' was not declared in this scope

sketch_feb22b:19: error: 'func_2' was not declared in this scope

Я считал, что можно слепить скетч из отдельных кусков.  Ввод и вывод  для   мне понятны,  я уже натренировался  - работает  и на LCD 1602  и на семисегметном индикаторе.     но без счета.

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

 

 

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

...Перейти в сетап можно только ресетом аппаратным, или программным например так 

http://www.arduino.ru/forum/programmirovanie/programmnyi-reset

немного неестественно, но работает. Применимо, например для мультиварки: задали параметры, запустили и она варит попрограмме, закончила- перешла на установку параметров. Хотя можно обходиться и без этого.

...можно и из отдельных кусков псевдомультизадачностью например так

http://blog.ksduino.org/post/42862084042/pseudo-multitasking-using-timer-in-arduino-sketch

Если Вы научились работать с лсд1602 и семисегментным индикатором, сложности в понимании структуры программы странны.

kriss
Offline
Зарегистрирован: 24.01.2014

 Спасибо inspiritus!     Это интересные ссылки.  а насчет  странностей - не стоит акцентировать.  Я привык к  монтажу  и  наладке  самого разного оборудования и при этом ПО было всегда под строжайшим запретом. А    ардуиной заинтересовался  только потому что    есть  возможность  использовать готовые скетчи    и быстро макетировать собственные идеи.  Но найти пример для подражания оказалось сложно.  А   понять структуру мне мешает незнание основ: где   оператор, где имя переменной и синтаксис.

Не получится - вернусь к старому способу:  жесткая логика на прессшпане и навесной монтаж.

 

inspiritus
Offline
Зарегистрирован: 17.12.2012

Хмм ... Сервис инженер ??

kriss
Offline
Зарегистрирован: 24.01.2014

 Меня  коллеги кличут Лифтанутый -   организатор внедрения  микроэлектронных лифтов в России.  Давно  пенсионер, но продолжаю  работать как эксперт по новой технике, а она  теперь  только микропроцессорная.     Но "пора привыкать к земле"  : http://www.forumhouse.ru/useralbums/34865/list

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

Вставка программного кода в тему/комментарий

int inA, inB, inC;         //   входы

int counter = 0;   // Счетчик

int newInState = 0;  //текущее состояние  
int prevInState = 0; // пердыдущее Состояние  
int state1 = 0; // Состояние конечного автомата 1 (KA1)
int state2 = 0; // Состояние конечного автомата 2  (KA2)

void setup ()
{
  
}

void loop()
{
  counter_super_func();
}


void counter_super_func() {
  newInState = inA<<2 | inB<<1 | inC;
  if (newInState != prevInState) {
    func_1();
    func_2();  
  }
  prevInState = newInState;
}


// КА для последовательност A-B-C
void func_1 () {
  switch (state1) {
  case 0:
    if (inA && !inB && !inC) {
      state1= 1;
    } 
    else {
      state1=0;
    }
    break;
  case 1:
    if (!inA && inB && !inC) {
      state1= 2;
    } 
    else {
      state1=0;
    }
    break;
  case 2:
    if (!inA && !inB && inC) {
      state1= 3;
    } 
    else {
      state1=0;
    }
    break;
  case 3:
    if (!inA && !inB && !inC) {
      state1= 0;
      counter++;
    } 
    else {
      state1=0;
    }
    break; 
  }
}

// КА для последовательност С-B-A
void func_2 () {
  switch (state2) {
  case 0:
    if (!inA && !inB && inC) {
      state2= 1;
    } 
    else {
      state2= 0;
    }
    break;
  case 1:
    if (!inA && inB && !inC) {
      state2= 2;
    } 
    else {
      state2= 0;
    }
    break;
  case 2:
    if (inA && !inB && !inC) {
      state2= 3;
    } 
    else {
      state2=0;
    }
    break;
  case 3:
    if (!inA && !inB && !inC) {
      state2= 0;
      counter--;
    } 
    else {
      state2=0;
    }
    break;  
  }
}
#define inA 2
#define inB 3
#define inC 4         //   входы

int counter = 0;   // Счетчик

int newInState = 0;  //текущее состояние  
int prevInState = 0; // пердыдущее Состояние  
int state1 = 0; // Состояние конечного автомата 1 (KA1)
int state2 = 0; // Состояние конечного автомата 2  (KA2)

void setup ()
{
  
}

void loop()
{
  counter_super_func();
}


void counter_super_func() 
{
  newInState = (digitalRead(inA)<<2) | (digitalRead(inB)<<1) | digitalRead(inC);
  if (newInState != prevInState) 
  {
    func_1();
    func_2();  
    prevInState = newInState;
  }
  
}


// КА для последовательност A-B-C
void func_1 () 
{
  switch (state1) 
  {
  case 0:
    if (newInState == 0b100) state1 = 1;
    else state1 = 0;
    break;
    
  case 1:
    if (newInState == 0b010) state1 = 2;
    else state1 = 0;
    break;
    
  case 2:
    if (newInState == 0b001) state1 = 3;
    else state1 = 0;
    break;
    
  case 3:
    if (newInState == 0b000) 
    {
      state1 = 0;
      counter++;
    } 
    else state1 = 0;
    break; 
  }
}

// КА для последовательност С-B-A
void func_2 () 
{
  switch (state2) 
  {
  case 0:
    if (newInState == 0b001) state2 = 1;
    else state2= 0;
    break;
    
  case 1:
    if (newInState == 0b010) state2 = 2;
    else state2 = 0;
    break;
    
  case 2:
    if (newInState == 0b100) state2= 3;
    else state2=0;
    break;
    
  case 3:
    if (newInState == 0b000) 
    {
      state2= 0;
      counter--;
    } 
    else state2=0;
    break;  
  }
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

спасибо большое! 

Начну вникать.  

kriss
Offline
Зарегистрирован: 24.01.2014

Скомпилировал, с другим скетчем, который перебирает контакты -но результат не получил.

Может  проще считать импульсы от одного контакта?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kriss, может я не внимательно прочёл, но мне показалось, что вы не объясняли, что же нужно получить в итоге от этих трёх импульсов на трёх входах.  У вас у самого есть чёткая блок-схема алгоритма? Правильно составленный алгоритм -это как минимум половина готового решения)

kriss
Offline
Зарегистрирован: 24.01.2014

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

 в 1989г я сделал   эмулятор на жесткой логике, чтобы быстрее освоить новую технику и он до сих пор работает  (на фото).   Вместо него хочу Ардуину. Но, системы управления теперь намного разнообразнее и  многопроцессорнее, поэтому   нужна  возможность гибкаой подстройки под алгоритм, чтобы например, "замедлить  или ускорить движение" и пр. 

Я знаю что хочу и   уверен  что сделаю -"не мытьем, так катаньем". Потому и обращаюсь  за помощью к знающим программирование Ардуино.      А спаять  девайс я смогу, даже если руки будут дрожать.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kriss, ещё раз, что вы хотите сделать, эмулятор движения кабины, то есть генератор неких импульсов, или анализатор движения кабины, то есть организовать чтение и разбор импульсов?

kriss
Offline
Зарегистрирован: 24.01.2014

мне от  АРДУИНЫ нужно имитировать простейший лифтовый алгоритм – перебирать  срабатывание датчиков и считать этажи с выводом на индикацию.   К Ардуино,  через  интерфейс,  будет подключаться лифтовой контроллер.

Контроллер должен "ездить", не зная,что самого привода и шахты лифта нет. Лифтом будет АРДУИНО - эмулятор. Так можно быстро проверить  контроллер  на отключенном лифте.

      

 

       

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

kriss,  Вы очень в общих чертах описали, для понимания сути человеком достаточно, а для алгоритма это почти ничего. Помочь можно только когда задача разложена по полкам на уровне алгоритма.  Я так понял у вас что-то напоминающее функцию енкодера. Допустим на дисплее нарисованы цифры с 1 по 10 (этажи лифта) Код меняется по одной закономерности  - на дисплее символ курсора перемещается вдоль цифр в  одну сторону, направление импульсов кодировки сменилось - курсор едет по цифрам в другую сторону. Счёт остановился - дисплей моргает цифрой виртуального этажа. Похоже на вашу задачу?

maksim
Offline
Зарегистрирован: 12.02.2012
#define inA 2
#define inB 3
#define inC 4         //   входы

int counter = 0;   // Этаж
byte prevState = 0;
char flag = 0;

void setup ()
{
  Serial.begin(9600);
  Serial.println("START");
}

void loop()
{
  byte state = (digitalRead(inA)<<2) | (digitalRead(inB)<<1) | digitalRead(inC);
  //byte state = (!digitalRead(inA)<<2) | (!digitalRead(inB)<<1) | !digitalRead(inC); // инверсия
  if (state != prevState)
  {
    prevState = state;
    if(state == 0b010)
    {
      counter += flag;
      Serial.println(counter);
      flag = 0;
    }
    else if(state == 0b100) flag = 1;
    else if(state == 0b001) flag = -1;
    delay(10); // задержка для игнорирования дребезга контактов
  }
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

 Я мыслю так:

поступил сигнал направления ( ОТ проверяемого контроллера) - для АРДУИНО  как нажатие кнопки.  неважно как он появится -но   пока без АРДУИНО.

Ардуино начинает   "перебирать"   виртуальные датчики селекции, т.е.  на  трех  ее выходах появляются   последовательно импульсы, в порядке соответственно направлению : А_В_С, либо В_С_А.   Такой скетч, переработанный   МАКСИМОМ   работает нормально.

Эти импульсы А,В и С поступают НА вход проверяемого контроллера, который отрабатывает их (если исправный), и возвращает взад эмулятору правильные команды (их несколько).  Это первая функция проверки контроллера.

Вторая функция - это проверка правильности счета этажей (остановок) контроллером. Для этого в эмуляторе нужно вести этот же подсчет по тем же импульсам, что отправляются на контроллер.  Сразу будет видна неисправность.

Для упрощения задачи можно по  включению питания, "поставить" кабину на любой этаж, кроме первого.

Например записать этаж3 на индикаторе АРДУИНО. При начале движения прибавлять или отнимать от этого значения и выводить на индикатор.

 Я в первом посту спрашивал может достаточно  использовать  ТОЛЬКО один датчик для счета?  Теперь точно уверен -да, потому что контроллеру нужно для этого три импульса, а АРДУИНО - один.

 

Пока писал -увидел скетч от МАКСИМА - спасибо большое" опять выручил!

 

 

Бадеевский
Offline
Зарегистрирован: 24.02.2014

kriss пишет:
мне от  АРДУИНЫ нужно имитировать простейший лифтовый алгоритм – перебирать  срабатывание датчиков и считать этажи с выводом на индикацию.   К Ардуино,  через  интерфейс,  будет подключаться лифтовой контроллер.

Контроллер должен "ездить", не зная,что самого привода и шахты лифта нет. Лифтом будет АРДУИНО - эмулятор. Так можно быстро проверить  контроллер  на отключенном лифте.

 

Уважаемый Александр Крисман!

Рекомендую в дополнение к ардуино использовать программируемое реле,  у него интерфейс программиста графический и интуитивно намного проще, программа рисуется в виде электрической схемы из функциональных блоков, триггеров, счетчиков, дискретной логики  и др.

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

Необязательно именно такую, можно любой аналог с удобной средой разработки похожей на  EasyLogic.

 

 

http://www.owen.ru/catalog/89272529

 

среда программирования www.kipshop.ru/Soft/Configurators/OwenLogic/owenlogic_setup.zip

kriss
Offline
Зарегистрирован: 24.01.2014

Уважаемый Бадеевский!

Спасибо, но   мне никак не подходит программируемая логика. За то время, что я буду программировать  жесткую схему - я успею собрать живую.   Мне нравится гибкость Ардуино, которая уже  лежит на столе.

 

kriss
Offline
Зарегистрирован: 24.01.2014
 Уважаемые профи!

Попытался из скетчей МАКСИМА склеить один, чтобы перебирать три датчика и вести счет . Однако не понимая  некоторые строки кода ( скорее большинство) допустил ошибки.  

#include <LiquidCrystal.h>        // библиотека дисплея
#define inA 2       // датчик замедления вниз
#define inB 3        // ДТО
#define inC 4         //   датчик замедления вверх
#define pinN 31 // команда на включение привода кабины вниз ( кнопка и резистор дотяжки 15ком) 
#define pinV 30 // команда на включение привода кабины вверх
#define DEL_1 150 // длительность импульса
#define DEL_2 250 // задержка между импульсами  в пачке  из трех
#define DEL_3 700 // задержка между пачками импульсов от inA до inC
byte pins[3] = {inA, inB, inC};     //  все переменные  целые  числа
char state = 1;       //............
int counter = 0;   // Счетчик
byte prevState = 3;   // начальное состояние на 3 этаже prevState = 3;    
char flag = 0;
LiquidCrystal lcd( 6,7,8,9,10,11); // Инициализируем дисплей по пинам подключения
// Задаем размерность индикатора,  
#define LCD_WIDTH 16
#define LCD_HEIGHT 2


void setup ()
{
lcd.begin(LCD_WIDTH, LCD_HEIGHT); // Инициация дисплея
  pinMode(inA, OUTPUT); // назначение   выходов
pinMode(inB, OUTPUT);
pinMode(inC, OUTPUT); 
digitalWrite(inA, 1);  // назначение входов
digitalWrite(inB, 1); 
digitalWrite(inC, 1);
  Serial.begin(9600);  
  Serial.println("ETAG #");  
}

void loop()
{
if(digitalRead(pinV))
{
state++;
if(state == 4) state = 0;
State(state);
}
if(digitalRead(pinN))
{
state--;
if(state == -1) state = 3;
State(state);
}
}
void State(byte state) ///........................
{
if(state)
{
byte pin = pins[state-1];
digitalWrite(pin, 0); 
delay(DEL_1);
digitalWrite(pin, 1);
delay(DEL_2);
}
else delay(DEL_3);
}
// Заставка при включении
void screenInit()

  lcd.clear();
   lcd.print("= LIFT  =");
   lcd.setCursor(3,1);
   lcd.print(" station UUL ");
       // Вывод номера этажа
void screenShowTemplate()
{
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("ETAG #   ");
  lcd.setCursor(0,1);
  lcd.print("VNIZ  ");  //попытка  указать направление нужна переменная
}     //Вывод показаний счетчика местоположения
void screenShowData() 
{
  

              //Вывод показаний счетчика  местоположения после слова ЭТАЖ№
  lcd.setCursor(9,0);          
  lcd.print("    ");   
  }

}
     // пытаюсь вставить   прцедуру счета   ругается на фигурные скобки. Я не понимаю действий с переменной  state
     //void state(state)                 
{
  byte state = (digitalRead(inA)<<2) | (digitalRead(inB)<<1) | digitalRead(inC);///   ????????????????????
  //byte state = (!digitalRead(inA)<<2) | (!digitalRead(inB)<<1) | !digitalRead(inC); // инверсия
  if (state != prevState)
  {
    prevState = state;
    if(state == 0b100) flag = 1;
    else if(state == 0b001) flag = -1;
    else if(state == 0b010)
    {
      counter += flag;
      Serial.println(counter);
      flag = 0;
    }}
             //   delay(10); //   игнорирования дребезга контактов   но контактов не будет - можно убрать
  
 
 
maksim
Offline
Зарегистрирован: 12.02.2012

Вы должны определиться каким образом устройство будет переключаться между режимами: иммитации движения кабины и считывания положения кабины. Вы же понимаете что запускать оба режима одновременно бессмысленно. Например можно переключать режим при нажатии двух кнопок одновременно.

#include <LiquidCrystal.h>        // библиотека дисплея
LiquidCrystal lcd( 6,7,8,9,10,11); // Инициализируем дисплей по пинам подключения

#define inA 2       // датчик замедления вниз
#define inB 3        // ДТО
#define inC 4         //   датчик замедления вверх
#define pinN 31 // команда на включение привода кабины вниз ( кнопка и резистор дотяжки 15ком) 
#define pinV 30 // команда на включение привода кабины вверх

#define DEL_1 150 // длительность импульса
#define DEL_2 250 // задержка между импульсами  в пачке  из трех
#define DEL_3 700 // задержка между пачками импульсов от inA до inC

byte pins[3] = {inA, inB, inC};     //  все переменные  целые  числа
char state = 1;       //............
int counter = 0;   // Счетчик
byte prevState = 3;   // начальное состояние на 3 этаже prevState = 3;    
char flag = 0;

bool mode = 0;  // переменная, которая определяет текущий режим

void setup ()
{
  //Serial.begin(9600);  
  lcd.begin(16, 2);     // Инициация дисплея
  screenInit();
  delay(1000);
  PinsMode(mode);  
}

void loop()
{
  if(mode)  // Режим иммитации
  {
    Emulation();
  }
  else      // Режим счета
  {
    Counter();
  }
}


void PinsMode(byte state)
{
  pinMode(inA, state); // назначение   выходов
  pinMode(inB, state);
  pinMode(inC, state); 
  digitalWrite(inA, state);  // назначение входов
  digitalWrite(inB, state); 
  digitalWrite(inC, state);
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print(state?"EMULAT":"READER");
}

// Заставка при включении
void screenInit()
{
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("= LIFT =");
  lcd.setCursor(3, 1);
  lcd.print("station UUL");
}

void Change()
{
  if(digitalRead(pinV) && digitalRead(pinN))  // Переключение режимов
  {
    mode = !mode;
    if(mode)
    {
      PinsMode(OUTPUT);
      lcd.setCursor(0, 1);
      lcd.print("DTO   ");
    }
    else 
    {
      PinsMode(INPUT);
      lcd.setCursor(0, 1);
      lcd.print("ETAG #   ");
      lcd.setCursor(6, 1);
      if(counter < 10) lcd.print(' ');
      lcd.print(counter);
    }
    delay(1000);
  }
}



//////////////////////////// РЕЖИМ ИММИТАЦИИ //////////////////////////////

void Emulation()
{
  if(digitalRead(pinV) && !digitalRead(pinN))
  {
    state++;
    if(state == 4) state = 0;
    State(state);
  }
  else if(digitalRead(pinN) && !digitalRead(pinV))
  {
    state--;
    if(state == -1) state = 3;
    State(state);
  }
  else Change();
}

void State(byte state)
{
  if(state)
  {
    lcd.setCursor(0, 1);
    if(state == 1) lcd.print("DVV");
    if(state == 2) lcd.print("DTO");
    if(state == 3) lcd.print("DVN");
    byte pin = pins[state-1];
    digitalWrite(pin, 0); 
    delay(DEL_1);
    digitalWrite(pin, 1);
    delay(DEL_2);
  }
  else delay(DEL_3);
}



//////////////////////////// РЕЖИМ ПОДСЧЕТА //////////////////////////////

void Counter()
{
  byte state = (digitalRead(inA)<<2) | (digitalRead(inB)<<1) | digitalRead(inC);///   ????????????????????
  //byte state = (!digitalRead(inA)<<2) | (!digitalRead(inB)<<1) | !digitalRead(inC); // инверсия
  if (state != prevState)
  {
    prevState = state;
    if(state == 0b100) flag = 1;
    else if(state == 0b001) flag = -1;
    else if(state == 0b010)
    {
      counter += flag;
      lcd.setCursor(6, 1);
      if(counter < 10) lcd.print(' ');
      lcd.print(counter);
      //Serial.println(counter);
      flag = 0;
    }
  }
  //   delay(10); //   игнорирования дребезга контактов   но контактов не будет - можно убрать
  
  if(digitalRead(pinV) && !digitalRead(pinN))
  {
    counter++;
    delay(300);
  }
  else if(digitalRead(pinN) && !digitalRead(pinV))
  {
    counter--;
    delay(300);
  }
  else Change();
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

Во как?   нужна  проверка  в реальном времени,   Это связоно с особенностями  именно Ардуино, или  ....? 

   Ардуино порождает импульсы, выдает их вовне, а один из них  складывает или отнимает.   Вроде  бы просто.

А включать   одновременно   направление движения вверх и вниз  лифтовому контроллеру запрещено.

В 1987 году я собрал компьютер  из журнала "Радио -86РК" на КР580, так на нем я подобное  сделал на Бейсике- даже осталась программа на бумаге.  Правда были проблемы с выводом -  делал  разные платы сопряжения  и надо было каждый раз загружать интерпретатор и саму программу с кассеты. только поэтому  забросил и сделал на жесткой логике.

Объясните пожалуйста в чем тут дело.  негде сохранить промежуточное значение?  чего нехватает?

может тогда две ардуины одновременно  надо включать.

 

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

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

Вы лучше тогда все таки обьясните что оно должно делать, где стоять и как работать.

kriss
Offline
Зарегистрирован: 24.01.2014

Не увидел код. Спасибо большое, Максим!

kriss
Offline
Зарегистрирован: 24.01.2014

 

  Возможно я не смог донести, хотя старался изложить  в посту #17.   Но  от Вашего  вопроса   что-то   у меня забулькало....

 Импульсы в  ардуино формируются как нужно.   Они поступят с ардуины на вход проверяемого контроллера и он будет их обрабатывать, в том числе и считать.           Его алгоритм  счета достаточно  навороченный.  У него много   настроек, учитывающих пропуски этажей и дополнительных посадочных датчиков.  Много всего.     А мне надо знать   ХОТЯБЫ СКОЛЬКО РАЗ  на выходе Ардуино появился  один  только    импульс точной остановки (  inB ) .      

Если ардуино "проскакал"   4 остановки, а контроллер насчитал только 3 - это  для меня сигнал  проверить настроечные параметры лифта в этом же контроллере.     Бывают   нередко сбои в работе лифта  из-за "сбитых" настроек.    Т.е. нужна информация о том,  скоко  ардуино выдал.   Может есть другой способ, кроме прямого счета?

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

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

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

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

Примерно так

#include <LiquidCrystal.h>        // библиотека дисплея
LiquidCrystal lcd( 6,7,8,9,10,11); // Инициализируем дисплей по пинам подключения

#define VN 2         // датчик замедления вниз
#define TO 3         // ДТО
#define VV 4         // датчик замедления вверх
#define pinN 31      // команда на включение привода кабины вниз ( кнопка и резистор дотяжки 15ком) 
#define pinV 30      // команда на включение привода кабины вверх

#define DEL_1 150    // длительность импульса
#define DEL_2 250    // задержка между импульсами  в пачке  из трех
#define DEL_3 700    // задержка между пачками импульсов от inA до inC

byte pins[3] = {VV, TO, VN};

char state = 1;
int etag = 3;

void setup() 
{
  //Serial.begin(9600);
  lcd.begin(16, 2);     // Инициация дисплея
  screenInit();
  delay(500);
  pinMode(VN, OUTPUT);
  pinMode(TO, OUTPUT);
  pinMode(VV, OUTPUT); 
  digitalWrite(VV, 1); 
  digitalWrite(TO, 1); 
  digitalWrite(VN, 1); 
  Display();
}

void loop()
{
  if(digitalRead(pinV))
  {
    state++;
    if(state == 4) state = 0;
    State(state);
  }

  if(digitalRead(pinN))
  {
    state--;
    if(state == -1) state = 3;
    State(state);
  }
}

void State(byte state)
{
  if(state)
  {
    static char flag = 0;
    if(state == 2)
    {
      etag += flag;
      Display();
      //Serial.println(etag);
      flag = 0;
    }
    else if(state == 1) flag = 1;
    else if(state == 3) flag = -1;

    byte pin = pins[state-1];
    digitalWrite(pin, 0); 
    delay(DEL_1);
    digitalWrite(pin, 1);
    delay(DEL_2);
  }
  else delay(DEL_3);
}

void Display()
{
  lcd.setCursor(0, 1);
  lcd.print("ETAG #   ");
  lcd.setCursor(6, 1);
  if(etag < 10) lcd.print(' ');
  lcd.print(etag);
}

// Заставка при включении
void screenInit()
{
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("= LIFT =");
  lcd.setCursor(3, 1);
  lcd.print("station UUL");
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

Счет идет, но заставка застыла. цифры и этаж не появляются.   пока

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

Попробуйте добавить

void Display()
{
  lcd.clear();
  lcd.setCursor(0, 1);
  lcd.print("ETAG #   ");
  lcd.setCursor(6, 1);
  if(etag < 10) lcd.print(' ');
  lcd.print(etag);
}

 

maksim
Offline
Зарегистрирован: 12.02.2012
#include <LiquidCrystal.h>        // библиотека дисплея
LiquidCrystal lcd(6, 7, 8, 9, 10, 11); // Инициализируем дисплей по пинам подключения

#define VN 2         // датчик замедления вниз
#define TO 3         // ДТО
#define VV 4         // датчик замедления вверх
#define pinN 31      // команда на включение привода кабины вниз ( кнопка и резистор дотяжки 15ком) 
#define pinV 30      // команда на включение привода кабины вверх

#define DEL_1 150    // длительность импульса
#define DEL_2 250    // задержка между импульсами  в пачке  из трех
#define DEL_3 700    // задержка между пачками импульсов от inA до inC

byte pins[3] = {VV, TO, VN};

char state = 1;
int etag = 3;

void setup() 
{
  //Serial.begin(9600);
  lcd.begin(16, 2);     // Инициация дисплея
  screenInit();
  delay(500);
  lcd.clear();
  pinMode(VN, OUTPUT);
  pinMode(TO, OUTPUT);
  pinMode(VV, OUTPUT); 
  digitalWrite(VV, 1); 
  digitalWrite(TO, 1); 
  digitalWrite(VN, 1); 
  Display();
}

void loop()
{
  if(digitalRead(pinV))
  {
    lcd.setCursor(0, 0);
    lcd.print("VNIZ   ");
    state++;
    if(state == 4) state = 0;
    State(state);
  }
  else if(digitalRead(pinN))
  {
    lcd.setCursor(0, 0);
    lcd.print("VVERH  ");
    state--;
    if(state == -1) state = 3;
    State(state);
  }
  else 
  {
    lcd.setCursor(0, 0);
    lcd.print("STOP  ");
  }
}

void State(byte state)
{
  if(state)
  {
    static char flag = 0;
    if(state == 2)
    {
      etag += flag;
      Display();
      //Serial.println(etag);
      flag = 0;
    }
    else if(state == 1) flag = 1;
    else if(state == 3) flag = -1;

    byte pin = pins[state-1];
    digitalWrite(pin, 0); 
    delay(DEL_1);
    digitalWrite(pin, 1);
    delay(DEL_2);
  }
  else delay(DEL_3);
}

void Display()
{
  lcd.setCursor(0, 1);
  lcd.print("ETAG #   ");
  lcd.setCursor(6, 1);
  if(etag < 10) lcd.print(' ');
  lcd.print(etag);
}

// Заставка при включении
void screenInit()
{
  lcd.setCursor(4, 0);
  lcd.print("= LIFT =");
  lcd.setCursor(3, 1);
  lcd.print("station UUL");
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

Лифт  поехал, этажи считает.   Максим - ПРОФИ!! 

Теперь мне надо  временно  сымитировать  команды контроллера  на замедление на макетной плате, чтобы проверить  точнее.

  По датчикам  VV и  VN   (это датчики  для замедления) кабина переходит на малую скорость и если вдруг не появится ТО  ( на реальном лифте шунт -железка отвалился) или  внутри подвесного кабеля при данном перегибе пропадает контакт, то  последствия  Вы правильно описали.  И счет неправильный. Это я буду проверять кнопкой стоп, без выключения питания.

Еще раз спасибо! 

kriss
Offline
Зарегистрирован: 24.01.2014

Выявил, что нужно останавливать счет на крайнем этаже - 1-ом . Иначе  считает 0, -1 и... Конечно проверяемый контроллер сам должен снять команду движения, но лучше предусмотреть в скетче остановку счета на 1 этаже.

кстати в самом лифте при  подобном сбое контроллера срабатывает электроблокировка - цепь безопасности №1  и полностью вырубается  силовая часть .

 

kriss
Offline
Зарегистрирован: 24.01.2014

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

Теперь буду  связывать ардуину с подопытным контроллером через  интерфейс.   Потом настраивать скетч на дополнительные функции. На фото подопытный лифтовой контроллер 2014г.

 

drew
Offline
Зарегистрирован: 26.04.2014

Здравствуйте. занимаюсь подобной проблемой.

-лифт 3 и более остановок. но не симулятор, ардруно и будет им собственно управлять.

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

как у Вас успехи? я так понял Вы пытаетесь создать эмулятор шахты для могилева, чтоб ремонтировать плату вне лифта.?

kriss
Offline
Зарегистрирован: 24.01.2014

ИМЕННО ТАК. Для диагностики платы контроллера  на месте ( в машинном). 

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

  до 10 остановок можно  взять микропроцессорную плату "МЯУ" ( бывш.УЛЖ-10).