Балансировочный стробоскоп.

Тема в разделе "Глядите, что я сделал", создана пользователем Riper69, 9 сен 2018.

  1. Riper69

    Riper69 Нуб

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



    Код от чайника:

    Код (C++):
    void setup(){
      //Serial.begin (9600);
      pinMode(7, OUTPUT);
    }
    void loop(){
      int u1 = analogRead(A1);
      int u2 = analogRead(A2);
      //Serial.println (u1);
      //Serial.println (u2);
      if (u1 > u2){
        digitalWrite(7, HIGH);
      }else if(u2 > u1)
        digitalWrite(7, LOW);
    }
     
  2. Tomasina

    Tomasina Сушитель лампочек Модератор

    Штатные функции digitalWrite и особенно analogRead очень медленные - это особенность совместимости с любой платой Arduino.
    Если с конкретной платой уже определились, гораздо быстрее читать/писать эти порты напрямую:
    https://habr.com/post/141442/
    https://forum.arduino.ua/viewtopic.php?id=1071
    http://codius.ru/articles/Тюнинг_Arduino_или_ускоряем_работу_платы
    http://codius.ru/articles/Arduino_у...ого_цифровой_преобразователь_АЦП_и_analogRead
     
  3. Riper69

    Riper69 Нуб

    Т.е. сделав вот так, мы сразу экономим почти 1,8 мс только на digitalWrite для 7-го пина?
    Код (C++):
    void setup(){
    DDRD = DDRD | B11111100; // устанавливает выходы от 2 до 7 в качестве выходов
    }
    void loop(){
      int u1 = analogRead(A1);
      int u2 = analogRead(A2);
      if (u1 > u2){
      PORTD = B10000000; // sets digital pins 7 HIGH
      }else if(u2 > u1)
      PORTD = B00000000; // sets digital pins 7 LOW
    }
     
    Последнее редактирование: 9 сен 2018
  4. parovoZZ

    parovoZZ Гуру

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

    Limoney Гик

    прикольно конечно
    разработчики печатной платы виноваты
     
  6. Riper69

    Riper69 Нуб

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

    Код (C++):
    uint8_t analog_ref = DEFAULT;

    void setup()
    {
      DDRD = DDRD | B11111100; // устанавливает выходы от 2 до 7 в качестве выходов
      ADC_init(); // Все настройки АЦП вынесены в отдельную процедуру
    }

    void ADC_init()
    {
      ADCSRA = 0;             // Сбрасываем регистр ADCSRA
      ADCSRB = 0;             // Сбрасываем регистр ADCSRB
      ADMUX |= (1 << REFS0);  // Задаем ИОН

      //ADMUX |= (1 << ADLAR);  // Меняем порядок записи бит, чтобы можно было читать только 8 бит регистра ADCH

      analog_ref = ADMUX;     // Запоминаем состояние регистра - из него мы будем формировать маску для смены входного пина
      ADMUX |= (0 & 0x07);    // Выбираем пин A0 для преобразования

      // Устанавливаем предделитель - 32 (ADPS[2:0]=101)
      ADCSRA |= (1 << ADPS2) | (1 << ADPS0);      //Битам ADPS2 и ADPS0 присваиваем единицу
      ADCSRA &= ~ (1 << ADPS1);                   //Биту ADPS1 присваиваем нули

      ADCSRA |= (1 << ADATE); // Включаем автоматическое преобразование
      ADCSRA |= (1 << ADIE);  // Разрешаем прерывания по завершении преобразования
      ADCSRA |= (1 << ADEN);  // Включаем АЦП
      ADCSRA |= (1 << ADSC);  // Запускаем преобразование
    }

    int currentLEDValue1 = 0;
    int currentLEDValue2 = 0;

    volatile int currentSensorValue1 = 0;
    volatile int currentSensorValue2 = 0;

    void loop(){
        if (currentSensorValue1 > currentSensorValue2){
      PORTD = B10000000; // sets digital pins 7 HIGH
      }else if(currentSensorValue2 > currentSensorValue1)
      PORTD = B00000000; // sets digital pins 7 LOW
    }

    volatile int analogPin = A0;
    volatile bool trueValue = false;

    ISR(ADC_vect) {
      if (trueValue) {
        int result = ADCL | (ADCH << 8);  // ADLAR=1, Получаем 8-битный результат, остальными битами пренебрегаем
        if (analogPin == A0) {            // Если актуальный входной пин A0, то присваиваем значение соответствующей переменной
          currentSensorValue1 = result;
        }
        else {
          currentSensorValue2 = result;
        }

        analogPin += 1;                   // Перебираем входные пины по кругу (А0...А1 - их может быть больше)
        if (analogPin > A1) {             // Все нужные перебрали...
          analogPin = A0;                 // ...возвращаемся к первому
        };

        int pin = analogPin;              // Приводим пин вида A0 (14) к удобному для регистра ADMUX - 0. A0=14, A1=15, ...
        if (pin >= 14) pin -= 14;

        ADMUX = analog_ref | (pin & 0x07);// Устанавливаем новый вход для преобразования
        trueValue = false;                // Устанавливаем флаг смены входного пина - следующее прерывание пропускаем
      }
      else {
        trueValue = true; // Первый раз пропускаем считывание и устанавливаем флаг на чтение в следующий раз
      }
    }
     
  7. Riper69

    Riper69 Нуб

    Предыдущий скетч не заработал, мигания какие-то. Пока остановился на установке предделителя 16, работает. Возможно, этого вполне и достаточно в такой приблуде, ускорение в 7 раз по analogRead.
    Код (C++):
    void setup(){
      DDRD = DDRD | B11111100; // устанавливает выходы от 2 до 7 в качестве выходов
      ADCSRA |= (1 << ADPS2);                     //Биту ADPS2 присваиваем единицу - коэффициент деления 16
      ADCSRA &= ~ ((1 << ADPS1) | (1 << ADPS0));  //Битам ADPS1 и ADPS0 присваиваем нули
    }
    void loop(){
      int u1 = analogRead(A1);
      int u2 = analogRead(A2);
      if (u1 > u2){
      PORTD = B10000000; // sets digital pins 7 HIGH
      }else if(u2 > u1)
      PORTD = B00000000; // sets digital pins 7 LOW
    }