Ещё раз про функцию millis(); ...

Тема в разделе "Arduino & Shields", создана пользователем Eragon, 10 апр 2017.

  1. Eragon

    Eragon Нерд

    Всем доброго времени суток у меня такой вопрос. Хочу написать (чисто для самообучения) скетч который должен выполнять ряд функций, а именно:
    - Считывать значение с датчика света и отображать их на дисплее 5110
    - В зависимости от считанного значения при заданных условиях также на дисплей должен выводиться один из следующих параметров: LOW; MEDIUM; HIGH; VERY_HIGH; Device_error.
    - При каждом из параметров должен мигать с определённой частотой свой светодиод
    Так вот... С первыми двумя задачами я справился, оно даже работает))
    Код (C++):

    #include <LCD5110_Basic.h>
    LCD5110 myGLCD(2,3,4,6,5);
    //LCD5110(SCK, MOSI, DC, RST, CS)  
    extern uint8_t SmallFont[];
    extern uint8_t MediumNumbers[];
    bool State = false;            
    unsigned long previousMillis = 0;  
    unsigned long previousMillis_2 = 0;  
    unsigned long currentMillis=0;
    unsigned long currentMillis_2 = 0;
         
    void setup()
    {
      myGLCD.InitLCD();
      pinMode(8,OUTPUT);
      pinMode(9,OUTPUT);
      pinMode(10,OUTPUT);
    }

    void loop()
    {
      currentMillis = millis();
      currentMillis_2 = millis();
      bool LED_STATUS = period(currentMillis);
      int value = analogRead(0);
      value=constrain(value,0,500);
      String res = status(value,LED_STATUS);
      if(currentMillis_2 - previousMillis_2 > 1000)
       {
        previousMillis_2 = currentMillis_2;
        myGLCD.clrScr();
        myGLCD.setFont(MediumNumbers);
        myGLCD.print(String(value),CENTER,5);
        myGLCD.setFont(SmallFont);
        myGLCD.print(String(res),CENTER,30);
       }
    }

    String status (int value,bool LED_STATUS)
    {
      String result;
      if (value>=0 && value<=100)
       {
        result="LOW";
        digitalWrite(8,LED_STATUS);digitalWrite(9,0);digitalWrite(10,0);
       }
        else if (value>101 && value<=200)
         {
          result="MEDIUM";
          digitalWrite(8,0);digitalWrite(9,LED_STATUS);digitalWrite(10,0);
         }
         
          else if (value>201 && value<=300)
           {
            result="HIGH";
            digitalWrite(8,0);digitalWrite(9,0);digitalWrite(10,1);
           }
             else if (value>301 && value<=400)
              {
               result="VERY_HIGH";
               digitalWrite(8,0);digitalWrite(9,0);digitalWrite(10,1);
              }
          else result="Device_error";
          return result;
    }

    bool period (unsigned long currentMillis)
    {
      if(currentMillis - previousMillis > 200)
       {
        previousMillis = currentMillis;
        State = !State;  
       }
         
       return State;
       
    }

       

    Но дальше начались проблемы(( Написал функцию которая возвращает 0 или 1 в зависимости от заданного периода:
    Код (C++):

    bool period (unsigned long currentMillis)
    {
     if(currentMillis - previousMillis > 200)
       {
        previousMillis = currentMillis;
        State = !State;
       }
       return State;
      }
     
    Вроде всё хорошо, светодиод мигает с заданной частотой - на экране LOW. Но...

    Проблема №1
    - значение на экране прыгают в пределах 30-40 единиц как раз с частотой 1 сек. (и это не свет от зажигающегося светодиода, я его полностью закрыл. Но всё же, если убрать светодиод значение прыгать перестают) Я использую датчик на фототранзисторе - temt6000, с простым фоторезистором такая же история - значения прыгают...
    Проблема №2 это продолжение первой. Если к уровню MEDIUM присвоить значение той же переменной
    LED_STATUS значения так же начинают прыгать. И если это значение на границе этих 2 периодов постоянно зажигается то один светодиод то другой, что не есть хорошо((
    Код (C++):
     

    if (value>=0 && value<=100)
       {
        result="LOW";
        digitalWrite(8,LED_STATUS);digitalWrite(9,0);digitalWrite(10,0);
       }
        else if (value>101 && value<=200)
         {
          result="MEDIUM";
          digitalWrite(8,0);digitalWrite(9,LED_STATUS);digitalWrite(10,0);
         }
         
     
    Вот сижу и думаю... В чём тут дело в неправильно написанном коде или же проблема в самой конструкции схемы...Кто, что думает помогите советом!
     
  2. rkit

    rkit Гуру

    Ну а где схема-то?
     
  3. Eragon

    Eragon Нерд

  4. rkit

    rkit Гуру

    Замеряйте напряжение на пине 5v. Сопротивление соединений земли. Номиналы резисторов на светодиодах.
     
  5. Eragon

    Eragon Нерд

    Как мне кажется это тут не причём, изначально светодиоды просто загорались при достижении нужных значений и проблем никаких не было...
    Код (C++):
    if (value>=0 && value<=100)
       {
        result="LOW";
        digitalWrite(8,1);digitalWrite(9,0);digitalWrite(10,0);
       }
    Что-то с кодом не то, только, что именно понять не могу((
     
  6. 9xA59kK

    9xA59kK Гик

    Зависеть может от чего угодно и от номиналов резисторов на светодиодах тоже. Если сопротивления слишком маленькие, при зажигании светодиода ток может значительно вырасти, что приведет к небольшой(или большой) просадке питающего напряжения контроллера, что в свою очередь приведет к изменениям показаний на аналоговом входе(в данном случае). Но это надо разбираться и все можно проверить, отключив светодиоды и понаблюдать за показаниями датчика света.
     
  7. sslobodyan

    sslobodyan Гик

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