Скорость работы DigitalWrite и DigitalRead

nevkon
Offline
Зарегистрирован: 20.01.2015

Здравствуйте.

Собственно интересно наскольлко быстро отрабатывают функции.

Хочу поиграть с оптопарами, проверить их быстродействие. Реально это сделать через DigitalWrite и DigitalRead или придется напрямую обращаться к контроллеру? Если что смерть оптрона во время экспериментов меня не беспокоит, есть халявные из сгоревших БП.

Не пишите пожалуйста "попробуй - узнаешь", просто кто-нибудь уже наверняка ковырял эти функции и знает их возможности.

bwn
Offline
Зарегистрирован: 25.08.2014
nevkon
Offline
Зарегистрирован: 20.01.2015

Такой код будет работать? Я еще не работал с регистрами и не могу проанализировать полностью.

boolean onetime = false;
unsigned long t1, t2;
int incomingByte = 0;

void setup() {
  Serial.begin(9600);
  DDRB = B110111; // 13 12 11 10 9 8
  PORTB = B000000;
}

void loop() {
  if (onetime) {
    t1 = micros();
    for (int i=1; i <= 100000; i++){
      PORTB = B000100;
      while (PINB != B001100) {}
      PORTB = B000000;
      while (PINB != B000000) {}
    }
    t2 = micros();

    Serial.print("Time test: ");
    Serial.print((t2-t1)/1000);
    Serial.println(" millis for 100k cycle");
    
    Serial.print("Frequency: ");
    Serial.print(1000000/(t2-t1)*100000);
    Serial.println(" Hz");

    onetime = false;
  }
  if (Serial.available() > 0) {  //если есть доступные данные
        // считываем байт
        incomingByte = Serial.read();
        // отсылаем то, что получили
        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
        onetime = true;
    }
}

Код компилируется, но есть сомнения именно что так можно с регистрами получить обмен.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

nevkon пишет:

  DDRB = B110111; // 13 12 11 10 9 8
  PORTB = B000000;

Весь код не проверял, но это сразу бросилось в глаза. Порты 8-битные, в такой записи нужно указывать все 8 бит, например DDRB = B11011100; PORTB = B00000000. Что принудительно установит значение сразу всех 8-ми бит порта.

Если нужно указать отдельные биты, можно воспользоваться такой конструкцией: PORTB |= (1<<7);  - установить PB7 в единицу или PORTB &= ~(1<<7);  - сбросить PB7 в ноль.

Или сразу несколько: PORTB |= (1<<7) | (1<<3) | (1<<0);  - установить в единицу биты PB7, PB3, PB0

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

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

nevkon
Offline
Зарегистрирован: 20.01.2015

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

А осициллографом к сожалению пока еще не разжился - бюджет не позволяет. Это все для меня пока на уровне развлечений.

melvladimir
Offline
Зарегистрирован: 08.03.2013

DigitalWrite/DigitalRead - примерно 1-2мс время срабатывания (проверял не я, была статья на Хабре). Читаю/пишу напрямую, только при первичной настройке пользуюсь этими упрощенными функциями.

vov4ik
Offline
Зарегистрирован: 10.09.2013

Ребят что вы тут паритесь у уно есть два скоростных порта работающие по внешним прерываниям, которые можно использовать, в лопе чтоб был чистый сигнал берется пин 4 в хай, подключив к пин2 и к оптике через резистор (т.к. там обычный светик) запомнить сколько было миллесекунд, далее пин 3 вычисление значение миллесикунд.


long previousMillis = 0;
unsigned long currentMillis = 0;
int ip = 0;
int io = 0;
void setup() {
  Serial.begin(9600);  
  pinMode(4, OUTPUT);
    attachInterrupt(0, button1, RISING);
    attachInterrupt(1, button2, RISING);
delay(1000);
}
void loop() {
for(int x = 0; x < 100;  x++){
  digitalWrite(4, HIGH);
        delay(100);
          io += ip;
            digitalWrite(4, LOW);
              delay(100);
}
      Serial.println(io);//втыкаеш оптику ждеш первые показания игнорируеш, см на второе, а лучше см на максимальное
      io = 0;
   }
void button1() {
    currentMillis = millis();
}
void button2() {
    ip = millis() - currentMillis;
}

Показания будут обстракные но понять какая из оптик работает быстрей можно.