помогите сформировать код последовательности

Тема в разделе "Arduino & Shields", создана пользователем MESS, 20 май 2014.

  1. MESS

    MESS Гик

    Сделал 20 лет назад имитатор лифта для проверки плат управления лифтом на жесткой логике. Он до сих пор хорошо работает. А его микропроцессорнй аналог наскоком не получился.
    Для освоения Ардуино решил сделать программный имитатор лифта–скетч. С помощью отдельных проектов и благодаря помощи форумчан в программировании, я слепил его, но работает он неправильно из-за ошибок при формировании импульсов управления движением. Формирование движения осуществляется двумя герконовыми датчиками: ТО (точная остановка) и DZ (датчик замедления). При движении кабины лифта датчики движутся вдоль линии шунтов, расположенных в определенной последовательности. Когда стальной шунт входит в датчик он прерывает магнитный поток и геркон размыкается, выдавая сигнал в виде импульса размыкания ( низкого уровня). Диаграмму работы датчиков привожу.
    upload_2014-5-20_15-0-44.png
    Из нее видно, что сигнал от датчика имееи высокий уровень( «1»), а короткий импульс «0» появляется только при пересечении шунта.
    Для работы имитатора нужна последовательность импульсов соответствующая диаграмме:

    TO-DZ-DZ-TO (проехал один этаж) TO-DZ-DZ-TO (проехал еще этаж) TO-DZ-DZ-TO….и т.д. не выше 16-ти и не ниже 1-го.

    Подскажите пожалуйста свои варианты формирования такой последовательности на двух пинах.
     
  2. Mitrandir

    Mitrandir Гуру

    Интервалы произвольны между импульсами?
    Ат тини45 научить отдавать импульсы

    Дешего и сердито.

    Или свободные пины ардуины замкгуть на сенсорные и в прерывании по таймеру генерить себе последовательность
     
    Последнее редактирование: 20 май 2014
  3. thearr

    thearr Нерд

    Вот простейший вариант, дальше можно доработать по необходимости:
    Код (Text):
    const int to = 9;
    const int dz = 10;
    const int signal_time = 100;    // интервал времени, в котором датчик выдает 0
    const int travel_time = 10000;  // интервал времени, в который лифт движется между датчиками
    const int storeys = 16;            // количество этажей

    void setup() {
        pinMode(to, OUTPUT);
        pinMode(dz, OUTPUT);
        digitalWrite(to, HIGH);
        digitalWrite(dz, HIGH);
    }

    void loop() {
        int s = 1;
        while (s <= storeys) {
            sensor_signal(to, travel_time);
            sensor_signal(dz, travel_time);
            sensor_signal(dz, travel_time);
            sensor_signal(to, travel_time);
            s++;
        }
    }

    void sensor_signal(int sensor, int t_time) {
        digitalWrite(sensor, LOW);
        delay(signal_time);
        digitalWrite(sensor, HIGH);
        delay(t_time);
    }
     
  4. Arduinщик

    Arduinщик Нерд

    А для чего нужен const почему нельзя просто int?
     
  5. MESS

    MESS Гик

    Интервалы не совсем произвольные. Большая скорость лифта =1м/сек, расстояние между двумя точными остановками (этажный пролет) не меньше3м. значит между ТО интервал 3сек. Для имитации можно принять 2сек. ширина импульса 150мс.
    Остальное не понял - я не программист.
     
  6. Megakoteyka

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

    Можно. Но хорошим тоном является объявлять константу в виде константы. Если программист случайно напишет код, пытающийся изменить константу, компилятор выдаст ошибку. В противном случае ошибка могла бы остаться незамеченной.
     
    Mitrandir нравится это.
  7. MESS

    MESS Гик

     
    Последнее редактирование: 20 май 2014
  8. Arduinщик

    Arduinщик Нерд

    Ну тогда обучайся вот тебе ссылка на обучение http://wiki.amperka.ru/программирование:оглавление и уроки http://wiki.amperka.ru/видеоуроки:оглавление , и учись на примерах которые даны в Arduino IDE.
     
  9. MESS

    MESS Гик

    Совет для меня бесполезный. На что у меня хватает времени и памяти, я уже прочитал. Лишнего времени у меня нет - я уже 10 лет ветеран пенсионер и до сих пор работаю наладчиком лифтовой электроники. Так что программист из меня уже не получится. Лучше бы перевел с "птичьего" то, что мне непонятно.
     
  10. Megakoteyka

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

    Если с программированием совсем тяжело, можно решить задачу "в лоб" - посчитать все интервалы времени между всеми перепадами всех сигналов и формировать нужный сигнал вызовами digitalWrite и delay. Тогда код программы будет большим, неудобным для редактирования и неуниверсальным, но зато предельно простым.
     
  11. Arduinщик

    Arduinщик Нерд

    Ой простите за "ты" я просто привык всё быстро писать и у меня времени много вот и изучаю.
     
  12. MESS

    MESS Гик

    thearr - Я опробовал Ваш скетч он перебирает импульсы, но они на обеих пинах симметричны: TO-TO-DZ-DZ-TO-TO... а найти где засада не смогу. Примерно такая же ситуация и с моим первым скетчем-
    у меня в дружном коллективе все электронщики на ты от 25 до 60, так что никаких обид!
    А времени у меня реально мало- у меня много дачных хобби- ажурная сварка, светодиодная досветка, автоматизация всего и вся... Хочется успевать, пока здоровье позволяет.
     
  13. thearr

    thearr Нерд

    Измените loop вот так:

    Код (Text):
    void loop() {
        int s = 1;
        while (s <= storeys) {
            sensor_signal(dz, travel_time);
            sensor_signal(dz, travel_time);
            sensor_signal(to, travel_time);
            s++;
        }
    }
     
  14. thearr

    thearr Нерд

    Это функция имитации герконовых датчиков, имеет 2 параметра: 1 - геркон (TO или DZ) и 2 - время движения лифта до следующего по последовательности геркона в милисекундах. Соответственно, если написать ее три раза подряд, как в предыдущем сообщении получим последовательность DZ-DZ-TO (этаж проехали за travel_time * 3 мс) и так 16 раз.
     
    MESS нравится это.
  15. thearr

    thearr Нерд

    Еще один плюс, это то, что для конечного продукта в виде скетча объявление константы const int a = 5 и макро #define a 5 абсолютно идентичны, однако в первом случае компилятор проследит, чтобы случайно не передать константу в виде параметра функции, которой нужен другой тип данных.
     
  16. MESS

    MESS Гик

    Я с этого и начал и сделал. Но потом отказался -понял что delay останавливает процессор, а ведь кроме движения у имитатора и другие функции- переход на малую скорость, остановка, управление дверьми, датчики крайних положений..
    Я думал реализовать программный аналог двоичного счетчика на 16. Как бы определить три двоичных состояния (три дешифрованных числа), например 2-это сигнал ТО, а 5 и 10 - это сигнал DZ. счетчик работает циклично. Еще один подобный счетчик мог бы считать количество этих циклов -вести счет пройденных этажей. Спаять и отладить подобную схему мне очень просто, а написать в виде скетча - проблема.
     
  17. MESS

    MESS Гик

    Все понял и уже поправил как надо - убрал лишнюю функцию sensor_signal(to, travel_time);
    Все работает как нужно! Спасибо! теперь буду пытаться дальше мудрить. нужно организовать вывод номера этажа в виде переменной.
    ..хотя она уже тут вроде есть -S
     
    Последнее редактирование: 20 май 2014
    Megakoteyka нравится это.
  18. MESS

    MESS Гик

    Добрый день, уважаемые программисты!

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

    У меня происходит перебор импульсов ТО и DZ , но мне нужно добиться того чтобы цикл МГНОВЕННО ПРЕКРАЩАЛСЯ, когда пропадает команда на движение.

    Что происходит: «лифт» должен останавливаться только в точной остановке (сигнал ТО = «0»). Но получается так, что после «остановки», импульс ТО опять перебрасывается в «1» (как бы цикл продолжается).

    А ТО не должен изменять свой нулевой уровень, когда появился «0» и пропала команда на движение!

    Дело в том, что по заднему фронту этого импульса работает счетчик остановок ( в самом лифте) и, вместо первой остановки (1этаж) лифт отнимает лишнюю 1 и определяет – 1 остановку. (при этом ардуина считает правильно) Это приводит к последующим сбоям в счете.

    Как ввести дополнительный цикл проверки такого условия:
    Если ТО=0 и TR= 0, то ТО должен оставаться ТО=0.


    (TR это один из сигналов движения- снятие тормоза. Для движения нужно чтобы был снят тормоз и включено направление движения V(вверх) и N(вниз).
     
  19. MESS

    MESS Гик

    Вот мой скетч :
    Код (Text):
    //Корректировка 27мая
    #include <LiquidCrystal.h>
    LiquidCrystal lcd( 6,7,8,9,10,11);

    // группа входных сигналов. на каждый пин делитель 24-5 Вольт
    #define pinN 50 // включение привода вниз
    #define pinV 52 // включение привода вверх
    #define pinTR 36 // включение ТОРМОЗА
    #define OD 34  // открыть дверь
    #define ZD 32  // закрыть дверь

    // группа выходных сигналов. каждый к УЭЛ через 1-2кОм: разъем однорядный
    #define VN 3 // датчик замедления
    #define TO 4 // датчик точной остановки
    //#define VV 5
    #define VKO 28 // сигнал открытия
    #define VKZ 30// сигнал закрытия
    #define DHE 24 // сработал датчик низа
    #define DVE 26 // сработал датчик верха
    #define DEL_1 200 // длительность импульса
    #define DEL_2 400 // задержка между импульсами
    #define DEL_3 400 // задержка между пачками импульсов
    #define DEL_4 200 // задержка крайних датчиков
    #define DEL_DV 1500 // время откр/закр

    byte pins[3] = {TO, VN, VN};
    char state = 1;
    int etag = 3; // при подаче питания "лифт" должен стоять на 3 этаже

    void setup()
    {
    Serial.begin(9600);
    lcd.begin(16, 2); // включается дисплей
    screenInit();
    delay(500);
    pinMode(VN, OUTPUT);
    pinMode(TO, OUTPUT);
    //pinMode(VV, OUTPUT);
    pinMode(DHE, OUTPUT);
    pinMode(DVE, OUTPUT);
    pinMode(VKO, OUTPUT);
    pinMode(VKZ, OUTPUT);
    //digitalWrite(VV, 1);
    digitalWrite(TO,1 );
    digitalWrite(VN,0 );
    digitalWrite(VKZ, 1);

    Display();
    }

    void loop()
    {

    //****************************************************
    //*********пытаюсь усмирить  ТО    ******************************************
      if(digitalRead(TO) == 0 && digitalRead(pinN) == 0)
    {
      digitalWrite (TO, 0);
      delay(DEL_1);
      digitalWrite (pinN, 0);
      delay(DEL_1);
    }
     
    //*********************************
    if(digitalRead(pinTR) == 1)  //тормоз снят, подано напряжение на каатушку
    {
    if(digitalRead(pinV) == 1)      // лифт дал команду направления движения вверх
    {
    if(etag < 16)
    {
    state++; //

    if(state == 4) state = 0;
    State(state);
    }
    }

    if(digitalRead(pinN) == 1)              //  движение вниз
    {
    if(etag > 1)
    {
    state--;
    if(state == -1) state = 3;
    State(state);
    }
    }
    }



    if(digitalRead(OD) == 1 && digitalRead(ZD) == 0)
    {
    digitalWrite(VKZ, 0);
    delay(DEL_DV);
    digitalWrite(VKO, 1);
    }

    if(digitalRead(ZD) == 1 && digitalRead(OD) == 0)
    {
    digitalWrite(VKO, 0);
    delay(DEL_DV);
    digitalWrite(VKZ, 1);
    } //********
    }

    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, 1);    // ===invers?0
    delay(DEL_1);
    digitalWrite(pin, 0);    //==== invers?1

    if(state == 1 || state == 3)//ввожу крайние датчики
    {
    delay(DEL_2 - DEL_4); // датчик нижнего этажа срабатываетчуть раньше датчика точной остановки ТО
    if(etag == 2) digitalWrite(DHE, 1);
    else digitalWrite(DHE, 0);
    if(etag == 15) digitalWrite(DVE, 1);
    else digitalWrite(DVE, 0);
    delay(DEL_4);
    }
    else delay(DEL_2);
    }
    else delay(DEL_3);
    }


    void Display()
    {
    lcd.clear();
    lcd.setCursor(2, 1);
    lcd.print("ETAG # ");
    lcd.setCursor(8, 1);
    if(etag < 10) lcd.print(' '); // обеспечиваем несмещение текста
    lcd.print(etag);
    if(etag == 1)
    {
    lcd.setCursor(1, 1);
    lcd.print("DNE");
    }

    if(etag == 16)
    {
    lcd.setCursor(1, 1);
    lcd.print("DVE");
    }
    }

    // заставка при включении
    void screenInit()
    {
    lcd.clear();
    lcd.setCursor(3, 0);
    lcd.print("=ELEVATOR=");
    delay(2000);
    }
     
     
  20. acos

    acos Официальный гик Администратор