РЕШЕНО Полное сглаживание данных фоторезистора.

Тема в разделе "Arduino & Shields", создана пользователем Gritsan, 13 дек 2019.

  1. parovoZZ

    parovoZZ Гуру

    Саныч, вот есть три таких фоторезистора
    ФР-764
    ФР-765
    ФР1-3
    Какой из них более точный? И точность какого параметра подразумевается?
     
    Gritsan нравится это.
  2. Airbus

    Airbus Радиохулиган Модератор

    Главное чтоб не китайский был?Так?
     
  3. parovoZZ

    parovoZZ Гуру

  4. Sergku

    Sergku Нерд

    тут вопрос не в том что лучше или хуже, а то что есть под рукой. И для людей задающих подобные вопросы, это вопросы из серии "Стакан на половину пуст или полон". АЦП шумит.. Корявый резистор... уже не суть
     
    Gritsan нравится это.
  5. Gritsan

    Gritsan Нерд

    Мне нужна только плавность смены подсветки, чтобы глаза не напрягались. Конденсатор керамический подойдет?
     
  6. Ariadna-on-Line

    Ariadna-on-Line Гуру

    1. Вы должны уяснить, что глаз очень широко-диапазонный прибор. Если у вас минимальная яркость (от значения ШИМ-ма ) = 1/255-я, то следующая яркость будет - 2/255-х. То есть - скачек ВДВОЕ. И никак плавнее на малых яркостях сделать не получится в принципе.
    2. Сейчас лампы разные. Накаливания, газоразрядные и светодиодные. Они все мерцают, но с разной частотой и амплитудой, просто мы не видим. АЦП процессора открывает свой вход на короткие интервалы времени, оцифровывая "моментальные" значения. Поэтому возникает эффект интерференции частоты мерцания и частоты оцифровки с возникновением двух боковых частот. Именно они и проявляются в виде скачков на графике. Поэтому надо ставить интегратор на входе.
    3. Ориентируемся на самый медленно-мерцающий источник - лампу накаливания (100Гц) и фоторезистор 1МОм. Нам требуется постоянная времени (берем с 10кратным запасом - хотите пересчитайте) 10* ((1/100Гц) =100мСек.= 1,4*RC. Получаем - С =7200pF.
    4. Точнее я мог бы посчитать, видя конкретную схему входа и её сопротивление. Принцип такой, но сопротивление фотоприёмной цепи не определяется сопротивлением только фоторезистора.
     
    Последнее редактирование: 16 дек 2019
    Gritsan нравится это.
  7. parovoZZ

    parovoZZ Гуру

    Не понимаю тогда - зачем в этой схеме МК?
     
    Gritsan нравится это.
  8. Gritsan

    Gritsan Нерд

    Мне интересно это. Без Мк нет такой тонкой настройки.
    При этом я прекрасно понимаю, что уровень знаний у меня крайне низкий. По этому обратился сюда. Изучаю все предложенные фильтры и варианты.
     
  9. Gritsan

    Gritsan Нерд

    Безусловно, я это понимаю. Минимальная яркость все равно будет выше, главное чтобы не скакала рандомно.
     
  10. parovoZZ

    parovoZZ Гуру

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

    Gritsan Нерд

    Если это не совсем глупый вопрос, куда вставить данные с фоторезистора?
    Программа сгенерировала код, я этот код включил в скетч, как в примере.
     
  12. Airbus

    Airbus Радиохулиган Модератор

    Да вообще не нужен.


    Чем проще тем лучше дешевше и надежнее!
     
    Gritsan нравится это.
  13. Asper Daffy

    Asper Daffy Иксперд

    Показывай чё сгенерила, куда вставил, у меня нет хрустального шара.
     
    Gritsan и DetSimen нравится это.
  14. Gritsan

    Gritsan Нерд

    :) Все! Нашел нужный код. Яркость меняется плавно, нет никаких скачков и мерцаний.

    Всем огромное спасибо, за помощь, разъяснения и подаренный бесценный опыт.:oops:
    Код (C++):
    #define LED 1                    //светодиод
    int inputPin = A1;               //фоторезистор

    const int numReadings = 50;      //чем выше значение,тем больше и медленнее сглаживание.
    int readings[numReadings];      // the readings from the analog input
    int readIndex = 0;              // the index of the current reading
    int total = 0;                  // the running total
    int average = 0;                // the average

    void setup() {
      pinMode(LED, OUTPUT);
    for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
    }
    }
    void loop() {
      // subtract the last reading:
      total = total - readings[readIndex];
      // read from the sensor:
      readings[readIndex] = analogRead(inputPin);
      readings[readIndex] = constrain(readings[readIndex], 0, 600);
      // add the reading to the total:
      total = total + readings[readIndex];
      // advance to the next position in the array:
      readIndex = readIndex + 1;

      // if we're at the end of the array...
      if (readIndex >= numReadings) {
        // ...wrap around to the beginning:
        readIndex = 0;
      }
       // calculate the average:
      average = (total / numReadings)-50;
      // send it to the computer as ASCII digits
      delay(20);        // delay in between reads for stability
      average = constrain(average, 5, 500);
      analogWrite(LED, average);          
    }
    код взял отсюда - https://www.arduino.cc/en/Tutorial/Smoothing
     
  15. asam

    asam Гик

    Во-первых в analogWrite максим это 255, поэтому если ограничивать, то уж не до 500 а до 255. А вообще проще просто отбросить 2 младших байта-
    readings[readIndex]= analogRead(inputPin)>>2;

    Во-вторых алгоритм не совсем правильный,
    // subtract the last reading:
    total = total - readings[readIndex];

    Вычитать надо не предыдущее значение, а самое старое в массиве.
     
    Gritsan нравится это.
  16. asam

    asam Гик

    Вот так должно быть правильнее

    Код (C++):
    #define LED 1                    //светодиод
    #define inputPin A1           //фоторезистор

    #define BUF_SZ 16             //размер буфера для усреднения. Должен быть кратен степени 2 - 4,8,16,32,64 или 128
    #define BUF_MASK (BUF_SZ-1)

    uint8_t GetNextAvrg(uint8_t in)
    {
        static uint8_t buf[BUF_SZ];
        static uint8_t head = 0;
        static uint8_t tail = 0;
        static uint8_t num  = 0;
        static uint16_t sum = 0;
       
        sum = sum + in;
        if (++num > BUF_SZ)
        {
            num = BUF_SZ;
            sum = sum - buf[tail];    //удаляем самое старое значение если буфер заполнен
            tail = ++tail & BUF_MASK;  //и cдвигаем указатель на следующее старое, заворачивая если выходит за пределы буфера
        }
        buf[head] = in;
        head = ++head & BUF_MASK;     //сдвигаем указатель на "голову" и заворачиваем его если выходит за пределы буфера
        return uint8_t(sum/num);
    }

    void setup() {
      pinMode(LED, OUTPUT);
    }

    void loop() {

      uint8_t data = analogRead(inputPin) >>2;
      analogWrite(LED, GetNextAvrg(data));
    }
     
    Gritsan нравится это.
  17. Gritsan

    Gritsan Нерд

    Благодарю, вечером попробую. Это ограничение "отсебятина", т.к. при высокой освещенности "average" принимала отрицательные значения или скачки.
     
  18. Gritsan

    Gritsan Нерд

    А если нужно ограничить минимальную яркость?
     
  19. asam

    asam Гик

    Код (C++):
    #define MIN_BR 50
    void loop() {

      uint8_t data = analogRead(inputPin) >>2;
      data = GetNextAvrg(data);
      if (data<MIN_BR) data = MIN_BR;
      analogWrite(LED, data);
    }  
     
    Gritsan нравится это.
  20. Gritsan

    Gritsan Нерд

    К сожалению, есть мерцания.
    Монитор порта digispark не поддерживает, только через библиотеку клавиатуры. Может поэтому такие значения.(в других скетчах только числа)
    Код (C++):
    /
    /
    0
    0
    1
    1
    2
    2
    3
    3
    3
    3
    3
    3
    3
    2
    1
    1
    0
    0
    0
    0
    1
    1
    2
    2
    3
    3
    3
    3
    4
    4
    4
    3
    2
    1
    1
    0
    0
    0
    1
    1
    2
    2
    2
    3
    3
    3
    3
    4
    4
    4
    3
    2
    1
    0
    0
    0
    0
    0
    1
    1
    2
    2
    3
    3
    3
    3
    3
    4
    4
    3
    2
    1
    1
    0
    0
    0
    0
    1
    1
    2
    2
    3
    3
    4
    3
    3
    3
    5
    5
    1
    0
    0
    /
    /
    /
    1
    3
    2
    3
    3