Страница 33 из 57 ПерваяПервая ... 23313233343543 ... ПоследняяПоследняя
Показано с 321 по 330 из 688

Тема: Программирование ПЛК110 [М02] для задач реального времени

Комбинированный просмотр

Предыдущее сообщение Предыдущее сообщение   Следующее сообщение Следующее сообщение
  1. #1
    Пользователь Аватар для rovki
    Регистрация
    03.01.2010
    Адрес
    Чехов
    Сообщений
    12,125

    По умолчанию

    Из-за смены фаз А и В при реверсе и алгоритме обработки их .
    электронщик до мозга костей и не только

  2. #2

    По умолчанию

    Цитата Сообщение от rovki Посмотреть сообщение
    Из-за смены фаз А и В при реверсе и алгоритме обработки их .
    Можете на пальцах объяснить?

    Попозже добавлю тест, который будет случайным образом крутить фазы A/B (ну, в смысле, виртуальный энкодер будет крутиться в случайных направлениях, и его ABZ будут подаваться на вход тестируемому блоку) и проверять, что распознаётся правильно.

    Такой тест работает:
    Код:
        abz.setA(cpu, 1); // A: 0 -> 1
        executeBlock(cpu);
        assertEquals(abz.getCounter(cpu), 1, "counter");
        assertEquals(abz.getPosition(cpu), ((-1) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        executeBlock(cpu); // Если входы не менялись, выходы меняться не должны
        assertEquals(abz.getCounter(cpu), 1, "counter");
        assertEquals(abz.getPosition(cpu), ((-1) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        abz.setB(cpu, 1); // B: 0 -> 1
        executeBlock(cpu);
        assertEquals(abz.getCounter(cpu), 2, "counter");
        assertEquals(abz.getPosition(cpu), ((-2) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        abz.setA(cpu, 0); // A: 1 -> 0
        executeBlock(cpu);
        assertEquals(abz.getCounter(cpu), 3, "counter");
        assertEquals(abz.getPosition(cpu), ((-3) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        // Теперь крутим обратно
        abz.setA(cpu, 1); // A: 0 -> 1
        executeBlock(cpu);
        assertEquals(abz.getCounter(cpu), 4, "counter");
        assertEquals(abz.getPosition(cpu), ((-2) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        abz.setB(cpu, 0); // B: 1 -> 0
        executeBlock(cpu); // Если входы не менялись, выходы меняться не должны
        assertEquals(abz.getCounter(cpu), 5, "counter");
        assertEquals(abz.getPosition(cpu), ((-1) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        // Теперь снова меняем направление
    
        abz.setB(cpu, 1); // B: 0 -> 1
        executeBlock(cpu); // Если входы не менялись, выходы меняться не должны
        assertEquals(abz.getCounter(cpu), 6, "counter");
        assertEquals(abz.getPosition(cpu), ((-2) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    
        abz.setA(cpu, 0); // A: 1 -> 0
        executeBlock(cpu);
        assertEquals(abz.getCounter(cpu), 7, "counter");
        assertEquals(abz.getPosition(cpu), ((-3) & 0xffff), "position");
        assertEquals(abz.getZeroDetected(cpu), 0, "zero detected");
    Последний раз редактировалось Владимир Ситников; 07.10.2016 в 16:45.

  3. #3
    Пользователь
    Регистрация
    24.07.2012
    Адрес
    Россия
    Сообщений
    1,492

    По умолчанию

    Владимир, объясните на пальцах как java даёт команды в плк110?
    Через сеть?

  4. #4

    По умолчанию

    Цитата Сообщение от Scream Посмотреть сообщение
    Владимир, объясните на пальцах как java даёт команды в плк110?
    Через сеть?
    Объясню: пока ещё никак.
    Код выше работает на эмуляторе PRU сопроцессора.

    Эмулятор повторяет логику процессора (регистры, память, IO), поэтому мне не нужен ПЛК, чтобы тестировать логику ФБ. Тем не менее, тут тестируется почти тот же самый бинарный код, который будет загружен в ПЛК.

    До тестирования "в железе" ещё доберёмся, но попозже
    Последний раз редактировалось Владимир Ситников; 07.10.2016 в 17:16.

  5. #5
    Пользователь Аватар для rovki
    Регистрация
    03.01.2010
    Адрес
    Чехов
    Сообщений
    12,125

    По умолчанию

    Цитата Сообщение от Владимир Ситников Посмотреть сообщение
    Можете на пальцах объяснить?

    ]
    Приходит фаза А ,а В сигнала еще нет ...и приходит команда на реверс или есть А и В и приходит команда не реверс ...То есть может потеряться импульс с энкодера при реверсе ...
    электронщик до мозга костей и не только

  6. #6

    По умолчанию

    Цитата Сообщение от rovki Посмотреть сообщение
    Приходит фаза А ,а В сигнала еще нет ...и приходит команда на реверс
    Начальные состояния: 0,0.

    Код:
        // Приходит фаза A; B ещё нет
        abz.setA(cpu, 1); executeBlock(cpu);
        System.out.println("position = " + (short)(abz.getPosition(cpu)) + ", counter = " + abz.getCounter(cpu));
    
        // Реверс -- фаза A пропала, B тоже молчит
        abz.setA(cpu, 0); executeBlock(cpu);
        System.out.println("position = " + (short)(abz.getPosition(cpu)) + ", counter = " + abz.getCounter(cpu));
    
    Вывод:
    
    position = -1, counter = 1 
    position = 0, counter = 2
    
    Если при исходных нулях моргнёт и пропадёт фаза B, то будет такой вывод:
    position = 1, counter = 1
    position = 0, counter = 2
    Импульсы не пропали. Сначала один посчитался как -1, потом рервес и он учёлся как +1 -- в итоге 0.


    Цитата Сообщение от rovki Посмотреть сообщение
    есть А и В и приходит команда не реверс ...То есть может потеряться импульс с энкодера при реверсе ...
    Тут немного непонятно. Что значит "есть A и B и команда на реверс". В каком порядке должны мигать A/B?
    Последний раз редактировалось Владимир Ситников; 07.10.2016 в 17:03.

  7. #7
    Пользователь Аватар для rovki
    Регистрация
    03.01.2010
    Адрес
    Чехов
    Сообщений
    12,125

    По умолчанию

    энкодер.jpgКоманда на реверс может придти в любое время (00,10,11,01,00 или 00,01,11,10,00) ..однозначно можно судить ,что это не помеха ,в момент +- импульс .-то есть ловим задний фронт А или В на одном и потенциал "1" на другом входе В или А .
    электронщик до мозга костей и не только

  8. #8

    По умолчанию

    Цитата Сообщение от rovki Посмотреть сообщение
    энкодер.jpgКоманда на реверс может придти в любое время (00,10,11,01,00 или 00,01,11,10,00) ..однозначно можно судить ,что это не помеха ,в момент +- импульс .-то есть ловим задний фронт А или В на одном и потенциал "1" на другом входе В или А .
    Предлагается ловить только 1 фронт одной фазы? (при одном направлении вращения)
    Это же в 4 раза снижает точность получаемых данных.

    Можно же ловить все фронты (и передние и задние обоих сингалов) и тем самым повысить получаемую точность.

    И, да, в моём алгоритме все переходы между 00,10,11,01,00 будут правильно обрабатываться. Грубо говоря: мы знаем прошлое состояние, мы видим какой фронт пришёл, и можем понять в какую сторону крутили.

    О каких потерях идёт речь -- не могу понять.

  9. #9
    Пользователь Аватар для rovki
    Регистрация
    03.01.2010
    Адрес
    Чехов
    Сообщений
    12,125

    По умолчанию

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

  10. #10

    По умолчанию

    Цитата Сообщение от rovki Посмотреть сообщение
    Фронты по алгоритму ловятся все ,а не один ,но кроме фронта нужного я еще всегда анализирую потенциал на противоположном входе ,что бы уменьшить влияние помех .
    Рад за вас и ваш алгоритм. Но в моей PRU программе используется не ваш алгоритм.

    Как и обещал, проверил на случайном вращении "виртуального энкодера".
    Забегая вперёд скажу, что проблем не нашлось. Т.е. программа работает верно.

    Иными словами, вращение из любого состояния в любом направлении будет отрабатывать правильно.

    10'000'000 импульсов эмулируются за 2-4 секунды.

    Собственно, класс "эталонного энкодера". Это тот, который выдаёт эталонные A-B импульсы.
    Код:
    package com.github.vlsi.pru;
    
    import static com.github.vlsi.pru.VirtualAbEncoder.EncoderState.S01;
    import static com.github.vlsi.pru.VirtualAbEncoder.EncoderState.S10;
    import static com.github.vlsi.pru.VirtualAbEncoder.EncoderState.S11;
    
    public class VirtualAbEncoder {
      private final static EncoderState[] ENCODER_STATES = EncoderState.values();
    
      enum EncoderState {
        S00,
        S01,
        S11,
        S10,
      }
    
      private EncoderState state = EncoderState.S00;
      private int count;
      private int position;
    
      public boolean getA() {
        return state == S10 || state == S11;
      }
    
      public boolean getB() {
        return state == S01 || state == S11;
      }
    
      public void reset() {
        state = EncoderState.S00;
        count = 0;
        position = 0;
      }
    
      public void left() {
        step(true);
      }
    
      public void right() {
        step(false);
      }
    
      public void step(boolean left) {
        count++;
        int diff = left ? 1 : -1;
        position += diff;
        state = getStateByOrdinal(state.ordinal() + diff);
      }
    
      private EncoderState getStateByOrdinal(int i) {
        int length = ENCODER_STATES.length;
        return ENCODER_STATES[(i + length) % length];
      }
    
      public int getPosition() {
        return position;
      }
    
      public int getCount() {
        return count;
      }
    }
    Теперь натравливаем рандомное вращение на исходную PRU программу:

    Код:
      @Test
      public void drunkEncoder() {
        PRU_ABZ_ENCODER_CodeGenerator abz = new PRU_ABZ_ENCODER_CodeGenerator();
    
        Pru cpu = new Pru();
        CodeEmitter ce = new CodeEmitter();
        abz.accept(ce);
        cpu.setCode(ce.visitEnd());
    
        VirtualAbEncoder encoder = new VirtualAbEncoder();
    
        ThreadLocalRandom random = ThreadLocalRandom.current();
        for(int i = 0; i < 10_000_000; i++) {
          encoder.step(random.nextBoolean());
    
          abz.setA(cpu, encoder.getA() ? 1 : 0);
          abz.setB(cpu, encoder.getB() ? 1 : 0);
          executeBlock(cpu);
          assertEquals(abz.getCounter(cpu), encoder.getCount() & 0xffff, "counter");
          assertEquals(abz.getPosition(cpu), encoder.getPosition() & 0xffff, "position");
        }
      }
    Ничего особенного не происходит, всё отрабатывает верно.

Страница 33 из 57 ПерваяПервая ... 23313233343543 ... ПоследняяПоследняя

Похожие темы

  1. Ответов: 38
    Последнее сообщение: 24.01.2022, 11:56
  2. Ответов: 10
    Последнее сообщение: 11.06.2021, 14:55
  3. часы реального времени
    от vetaly в разделе ПЛК1хх
    Ответов: 4
    Последнее сообщение: 28.08.2015, 16:21
  4. Таймер реального времени УТ1-РiС
    от ser10 в разделе Трёп (Курилка)
    Ответов: 0
    Последнее сообщение: 16.09.2010, 12:24

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •