помогите с кодом включения светодиодной ленты

Тема в разделе "Arduino & Shields", создана пользователем Karbofoss, 13 ноя 2013.

  1. Karbofoss

    Karbofoss Нуб

    все здрасте.

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

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

    #define LED 9
    int Sharp=A0;
    int i = 0;
    int on=0;
    int off=1;
    int s=7;
    unsigned long timeron;
    unsigned long timeroff;

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

    void loop(){

    int val=analogRead(Sharp);

    if (val1>250&&timeron!=0)
    {timeron=millis();}



    if (val>250&&on==0&&millis()-timeron>1700)
    {for (i = 0; i < 255; i++) {
    analogWrite(LED, i);
    delay(s);}on=1;off=0;timeron=0;}

    else if (val>250&&on==1)
    {analogWrite(LED,255);off=0;timeron=0;}

    else if (val<250&&timeroff!=0)
    {timeroff=millis();}

    else if (val<250&&off==0&&millis()-timeroff>15000)
    {for (i = 255; i > 0; i--) {

    analogWrite(LED, i);
    delay(s);
    }off=1;on=0;timeroff=0;}
    else if (val<250&&off==1)
    {analogWrite(LED,0);on=0;timeroff=0;}

    }
     
  2. fr0ster

    fr0ster Гик

    Как то кучеряво написано.
    Если правильно понял, чего вы хотите то где то так можно
    1 проверяем что тело далеко и лента включена, если проверка пройдена ждем 15 секунд и опять проверяем не приблизилось ли тело и если нет - гасим плавно ленту.
    2 проверяем что тело близко и лента выключена, если проверка пройдена, включаем плавно ленту.
    Код (Text):

    #define LED 9
    int Sharp = A0;
    int timedelay = 1000;
    int delstep = 15;
    int timeout = 100;
    int cross_line = 250;

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

    void loop() {
      if (analogRead(Sharp) >= cross_line && digitalRead(LED) == HIGH)
      {
      int step = 0;
      while (step++ < delstep)
      {
      if (analogRead(Sharp) <= cross_line) break;
      delay(timedelay);
      }
      if (analogRead(Sharp) >= cross_line)
      for (int i = 0; i <= 255; i++) {
      analogWrite(LED, i);
      delay(timeout);
      }
      }
      else if (analogRead(Sharp) < cross_line && digitalRead(LED) == LOW)
      {
      for (int i = 255; i >= 0; i--) {
      analogWrite(LED, i);
      delay(timeout);
      }
      }

    }
     
    У такого подхода главный косяк в том, что если после выхода тело вернется, мвы узнаем не сразу. Потому вместо простого ожидания в 15 секунд мы в цикле 15 раз проверяем не вернулось ли тело и если нет то ждем 1 секунду, если вернулось, то идем дальше.
     
  3. ИгорьК

    ИгорьК Гуру

    Может так, если я правильно понял задачу:
    Код (C):

    #define LED 9                                    // Нога включения освещения
    #define delayLed 7                                // Задержка шагов при плавном изменении освещения
    #define lightDistance 250                        // Расстояние включения освещения
    int Sharp=A0;                                    // Нога датчика расстояния
    boolean on=0;                                    // Флаг включения освещения

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

    void loop(){

        if (analogRead(Sharp) < lightDistance && 0 == on)  {    // Если меньше 250 и освещение выключено
            for (byte i = 0; i < 255; i++) {        // Плавно включаем
                analogWrite(LED, i);
                delay(delayLed);
            }
            on = 1;                                    // Флаг включения установлен
        }

        do {                                        // Ждем, пока кто-то близко
            val=analogRead(Sharp);
        } while ( val < lightDistance);
     
        delay(15000);                                // Как ушел - ждем еще 15 секунд
         
        if (1 == on && (analogRead(Sharp)>lightDistance )) {    // Если свет включен и никого близко нет
     
            for (byte i = 255; i > 0; i--) {        // Плавно гасим
                analogWrite(LED, i);
                delay(delayLed);
            }
            on = 0;                                    // Флаг включения сброшен
        }
    }

     
     
    Последнее редактирование: 13 ноя 2013
  4. fr0ster

    fr0ster Гик

    Мне кажется такую задачу правильно решать с сохранением состояния и обработкой по таймеру.
     
  5. ИгорьК

    ИгорьК Гуру

    Без таймера все таки можно обойтись. А что касается состояний, то да, нужно сохранять, если тело туда-сюда ходит.
     
  6. fr0ster

    fr0ster Гик

    Можно конечно, но с таймером управляющая схема гибче и меньше жрет, тут явно большая часть тиков придется на случаи когда тело рядом и лента включена или тело далеко и лента выключена.
     
  7. fr0ster

    fr0ster Гик

    В общем полагаю проблема в датчике, он аналоговый.
    Если подключить его через компаратор так чтоб с него уже HIGH или LOW шло, то можно использовать с него сигнал как прерывание и на прерыввание повесить обработку смены состояния.

    Вот кстати все украдено до нас.
    http://easyelectronics.ru/avr-uchebnyj-kurs-ispolzovanie-analogovogo-komparatora.html
    Правда там на примере ATMega16, но это не проблема :)
    Бешеному кобелю семь верст не крюк :)
     
    Последнее редактирование: 13 ноя 2013
  8. Unixon

    Unixon Оракул Модератор

    Код (Text):
    const byte PIN_LED = 9;
    const byte PIN_SENSOR = A0;
    const int FADE_DELAY = 7;
    const int SENSOR_THRESHOLD = 250;
    const unsigned long ON_DELAY = 1700UL;
    const unsigned long OFF_DELAY = 15000UL;
    bool state = false;
    unsigned long t_on = millis();
    unsigned long t_off = millis();

    void setup()
    {
     pinMode(PIN_LED, OUTPUT);
     pinMode(PIN_SENSOR, INPUT);
    }

    void fadeIn()
    {
     for (byte i = 0; i <= 255; i++)
     {
      analogWrite(PIN_LED, i);
      delay(FADE_DELAY);
     }
    }

    void fadeOut()
    {
     for (byte i = 255; i > 0; i--)
     {
      analogWrite(PIN_LED, i);
      delay(FADE_DELAY);
     }
    }

    void loop()
    {
     unsigned long t = millis();
     int v = analogRead(PIN_SENSOR);
     if (state)
     {
      if ((v < SENSOR_THRESHOLD) && (t > (t_on + OFF_DELAY)))
      {
       fadeOut();
       t_off = t;
       state = false;
      }
     }
     else
     {
      if ((v >= SENSOR_THRESHOLD) && (t > (t_off + ON_DELAY)))
      {
       fadeIn();
       t_on = t;
       state = true;
      }
     }
    }
     
  9. fr0ster

    fr0ster Гик

    На основе примера кода работы с компаратором из книги пана Прокопенко В.С. сваял пример включения выключения LED при изменении напруги от датчика.
    Программа для МК AT90S2313, так как схема на протеусе была именно под этот камень.
    Код (Text):
    #include <avr/io.h> //средства ввода/вывода периферии контроллера. Заголовочный файл включает соответствующие IO определения для устройства который используется в проекте.
    #include <avr/interrupt.h>
    #include <avr/sleep.h>

    void check_aco(){
        if (ACSR & _BV(ACO)) {
            PORTD |= (1 << 0);
            PORTD &= ~(1 << 1);
        } else
        {    PORTD &= ~(1 << 0);
            PORTD |= (1 << 1);
        }
    }

    //НАЧАЛО основная программа
    int main(void) {
        //разрешаем прерывания компаратора, записав 1 в биты 3 и 4 (ACIE и ACI)
        ACSR |= _BV(ACIE) | _BV(ACI);
        //разрешаем использование аналогового компаратора, записав 0 в 7й бит(ADC)
        //разрешаем прерывания при повышении и понижении входного напряжения
        //по отношению к опорному, записав 0 в 7й бит(ADC). в 0 и 1 биты(ACIS0 и ACIS1)
        ACSR &= ~(_BV(ACIS0) | _BV(ACIS1) | _BV(ACD));

        //ножки PD0,PD1 как выход
        DDRD = 0x03;
        //на ножки PD0,PD1 подать 0 вольт(на весь порт D 0 вольт)
        PORTD = 0x00;

        //ножки PB0,PB1 как вход
        DDRB &= ~(1 << 0) & ~(1 << 1);
        //ножки PB0,PB1 высокоомный вход(без внутренних подтягивающих сопротивлений)
        PORTB &= ~(1 << 0) & ~(1 << 1);
        //проверяем выход компаратора и устанавливаем состояние индикаторных LED
        check_aco();
        sei();
        //начало бесконечный цикл
        while (1) {
    /*
            if (ACSR & (1 << 5)) {
                PORTD |= (1 << 0);
                PORTD &= ~(1 << 1);
            } //если в пятом бите(ACO) регистра ACSR появилась единица то на вывод PD0 подать +5 вольт, а на вывод PD1 подать 0 вольт
            else {
                PORTD &= ~(1 << 0);
                PORTD |= (1 << 1);
            } //иначе если в пятом бите регистра ACSR ноль то на вывод PD0 подать 0 вольт, а на вывод PD1 подать +5 вольт
    */      
            //уводим схему в спячку
            sleep_mode();
        }
        //конец бесконечный цикл

    }
    //КОНЕЦ основная программа
    ISR (ANA_COMP_vect) {
        //проверяем выход компаратора и устанавливаем состояние индикаторных LED
        check_aco();
    }
     
    По уму надо еще добавить ШИМ с одного таймера и по другому включать выключать датчик.
    А вообще заменить датчик инфракрасного дальномера на пару фото- свето-диод инфракрасный. С простой обвязкой.
     
  10. Karbofoss

    Karbofoss Нуб

    Вчера внес исправления, вот что получилось

    #define LED 9
    int Sharp=A0;
    int i = 0;
    int on=0;
    int off=1;
    int s=2;
    unsigned long timeron;
    unsigned long timeroff;

    void setup() {
    pinMode(LED, OUTPUT);
    pinMode(Sharp, INPUT);

    }

    void loop(){
    int val1=analogRead(Sharp);
    delay(10);
    int val2=analogRead(Sharp);
    if (val1>270&&val2>270&&timeron==0)
    {timeron=millis();}



    if (val1>270&&val2>270&&on==0)
    {for (i = 0; i < 255; i++) {
    analogWrite(LED, i);
    delay(s);}on=1;off=0;timeron=0;}

    else if (val1>270&&val2>270&&on==1)
    {analogWrite(LED,255);off=0;timeron=0;timeroff=0;}

    else if (val1<270&&val2<270&&timeroff==0)
    {timeroff=millis();}

    else if (val1<270&&val2<270&&off==0&&millis()-timeroff>7000)
    {for (i = 255; i > 0; i--) {

    analogWrite(LED, i);
    delay(s);
    }off=1;on=0;timeroff=0;}
    else if (val1<270&&val2<270&&off==1)
    {analogWrite(LED,0);on=0;timeroff=0;timeron=0;}
    }

    ошибка была в этой части
    if (val>250&&timeron!=0) зачем-то я вставил не равно, хотя должно быть ровно
    {timeron=millis();}

    Много интересных кодов предложили, спасибо, буду изучать. Вообще это мой второй проект, до этого про контролеры ни знал ни чего а про электричество на уровне вилки с разеткой.

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

    вопрос не по теме: как в сообщение вставить код в отдельное окно с полосой прокрутки?
     
  11. fr0ster

    fr0ster Гик

    У знакомого такая система была покупная, на пятый день ее выкинул.
    У него кот повалился туда сюда шастать и датчик на него реагировал.
     
  12. Karbofoss

    Karbofoss Нуб

    я писал что это мой второй проект, так вот первый был точно такой же только вместо диодной ленты была обыкновенная лампа и реле, эта система работала год, жене нравилось а кот не беспокоил т.к. стоит это все в ванной а он туда не очень ходит
     
  13. Megakoteyka

    Megakoteyka Оракул Модератор

    19-я по счету слева кнопка меню над окном редактирования сообщения. Со значком "<>".
    Либо тэг CODE.
     
  14. fr0ster

    fr0ster Гик

    У нас как раз ванна любимое место кота. Там пол теплый :)
     
  15. Витя

    Витя Гик

    Немного не по теме.

    Заметил что в коде мосфет управляется путем подачи разного уровня напряжения. Но если это не какая-нибудь мега где есть подлинный аналоговый выход, то значит здесь уровень будет задаваться через ШИМ. А это не совсем хорошо, точнее даже плохо. Тоже собирал похожую систему (только у меня был 540 мосфет) и как-то услышал писк. Начал читать, с чем это может быть связано и узнал, что при ШИМе мосфет может не только работать с проблемами, сгорать и сильно греться но и даже взрывается! Я бы рекомендовал для надежности переделать схему. Вы же не хотите чтобы у вас например случился пожар. Я поставил конденсатор на 220 мкФ перед gate, получается тоже плавное включение, причем без ШИМа.

    p.s.
    А так, по-науке если, мосфетами нужно управляться специальными драйверами.
     
    Последнее редактирование: 17 ноя 2013
  16. fr0ster

    fr0ster Гик

    А это значит что напрямую выводить ШИМ на МОСФЕТ нельзя.
    Сглаживающий фильтр после ШИМ вывода и перед МОСФЕТом нужен.
     
  17. Unixon

    Unixon Оракул Модератор

    Наоборот. Фильтр после ключа. Иначе у вас мосфет в линейном режиме комнату обогревать будет.
     
  18. Unixon

    Unixon Оракул Модератор

    На меге нет, есть на Due.

    Смотря для чего. Для полевого транзистора работа в ключевом режиме - благо. Когда транзистор закрыт, он не греется, поскольку имеет огромное спотивление и не пропускает ток. Когда он полностью открыт, то тоже не греется, поскольку Rds.on крайне мало (а вот на это нужно было обращать внимание при выборе транзистора). Единственная проблема здесь - правильно выбрать максимальную частоту переключений. Если не превышать допустимых параметров, все работает ОК.

    Вот и зря, нужно было ставить перед нагрузкой. Теперь у вас время переключения транзистора офигительно увеличилось, потому как вы к ничтожной емкости затвора (которая определяет быстродействие транзистора и чем она меньше, тем лучше) добавили свои жуткие микрофарады, а промежуточные значения сопротивления приведут к тому, что в определенные моменты времени ключ будет есть больше нагрузки. Вот еще теплоотвод остается не рассчитать и гори оно все синим пламенем. Замечательно. С чем боролись, на то и напорлись. :D

    Есть и такие звери, но они всего лишь помогают обходится меньшим количество деталей и никакой магии не творят.
     
    Последнее редактирование: 17 ноя 2013
  19. Unixon

    Unixon Оракул Модератор

    p.s. Это только в слаботочных сигнальных цепях можно такие фокусы делать с полевиками, вешая им НЧ фильтр на затвор. А в силовых цепях либо сразу крепите полевик к батарее, либо рассчитывайте частоту ШИМа так, чтобы транзистор в промежуточном состоянии находился не больше допустимого.
     
  20. Витя

    Витя Гик

    Я так пробывал ставить, еще когда только просто ленту к питанию подключал, но никакого влияния это не оказывало :( Может я как-то не правильно включал?
    Screen Shot 2013-11-17 at 7.05.36 PM.png
    Я так подумал сразу, что наверное слишком большая мощность и что с этим делать не знал. А потом уже через МК все делал.