Где может быть ошибка кода?

Тема в разделе "Arduino & Shields", создана пользователем sanik, 8 окт 2013.

  1. Unixon

    Unixon Оракул

    Покажите код в текущем состоянии.
     
  2. sanik

    sanik Гик

    Код (Text):
    #include <Bounce.h>
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>

    LiquidCrystal_I2C lcd(0x27,16,2);

    // время подавления дребезга кнопок, мс
    #define DEBOUNCE_INTERVAL 50

    // номера пинов для кнопок
    #define btn_SELECT 3
    #define btn_PLUS  7
    #define btn_MINUS  6
    #define btn_START  4
    #define btn_STOP 5 // перепаять со 2
    // номера пинов мотора
    #define pin_A 12
    #define pin_B 11
    #define pin_ENABLE 10
    // пин потенциометра
    #define pin_dist A0
    boolean stop1 = false;// переменная для хранения флага концевика 1
    boolean stop2 = false;// переменная для хранения флага концевика 2
    //пин реле
    #define pin_foc 8 // пин реле фокусировки
    #define pin_shot 9 // пин реле затвора
    #define pin_Rd A2 // пин датчика концевиков
    #define pin_Pit 13 // питание фотоинтерраптора
    int posInt = 0;  // пин фотоинтерраптора, Пин 2 внешнее прерывание 0
    //Таймеры
    unsigned long currentTime;
    unsigned long TimePause,TimeExposure,TimeLag;
    // максимальные значения
    #define MAX_POS_VALUE  4000// для положения каретки
    #define MAX_PAUSE_VALUE  60000// для времени паузы
    #define MAX_EXPOSURE_VALUE  20000// для времени экспозиции
    #define MAX_SHOT_VALUE  4000
    // шаги алгоритма
    typedef enum STEPS {
      STEP1_HELLO,
      STEP2_GET_POTS,
      STEP3_GET_POSITION,
      STEP4_GET_PAUSE,
      STEP5_GET_EXPOSURE,
      STEP6_GET_COUNT,
      STEP7_GET_START,
      STEP8_PAUSE,
      STEP9_EXP,
      STEP_10MOT
    };

    // текущий шаг алгоритма
    STEPS currentStep = STEP1_HELLO;

    // создаем "давилки дребезга" для кнопок
    Bounce bouncerBtnSelect(btn_SELECT, DEBOUNCE_INTERVAL);
    Bounce bouncerBtnPlus(btn_PLUS, DEBOUNCE_INTERVAL);
    Bounce bouncerBtnMinus(btn_MINUS, DEBOUNCE_INTERVAL);
    Bounce bouncerBtnStart(btn_START, DEBOUNCE_INTERVAL);
    Bounce bouncerBtnStop(btn_STOP, DEBOUNCE_INTERVAL);

    void setup()
    {
      Serial.begin(9600);
      // инициализация дисплея, включаем подсветку, очищаем экран
      lcd.init();
      lcd.backlight();
      lcd.clear();
      currentTime = millis();// считываем время, прошедшее с момента запуска программы
      TimePause = currentTime; // таймер паузы
      TimeExposure = currentTime; //таймер эксозиции
      TimeLag = currentTime;// таймер задержки
      attachInterrupt(posInt, handleInt0, RISING);
      pinMode (btn_SELECT, INPUT);
      pinMode (btn_PLUS, INPUT);
      pinMode (btn_MINUS, INPUT);
      pinMode (btn_START, INPUT);
      pinMode (btn_STOP, INPUT);
      pinMode (pin_A, OUTPUT);
      pinMode (pin_B, OUTPUT);
      pinMode (pin_foc, OUTPUT);
      pinMode (pin_shot, OUTPUT);
      pinMode (pin_Pit, OUTPUT);
    }


    int potValue  = 0; // значение потенциометра 1
    volatile int pulse = 0 ;//считаем импульсы с фотоинтерраптора
    int pauseValue = 0; // значение времени паузы
    int exposValue = 0; // значение времени экспозиции
    int countValue = 0; // значение количества кадров
    int shootValue = 0; //значение счетчика кадров
    int control = 0; //значение датчика концевиков
    int posValue  = 0; // значение положения каретки
    int a;//значение скорости мотора
    int LagValue = 20;// задержка на 20мс.


    void hello()
    {
      // установка курсора, печать надписи
      lcd.setCursor(5, 0);
      lcd.print("Hello");
      delay(200);
      lcd.setCursor(0, 1);
      lcd.print(" Slider Timelaps");
      delay(2000);
      lcd.clear();// очистка дисплея.
    }
    void handleInt0() // функция прерывания
    {
      pulse++; //при поступлении импульса увеличиваем счетчик на 1
    }
    void RunMotor1(byte a)
    {
      digitalWrite (pin_A, LOW);
      digitalWrite(pin_B, HIGH);
      analogWrite(pin_ENABLE,a);
    }
    void RunMotor2(byte a)
    {
      digitalWrite (pin_A, HIGH);
      digitalWrite(pin_B, LOW);
      analogWrite(pin_ENABLE,a);
    }

    void StopMotor()
    {
      digitalWrite(pin_ENABLE, 0);
      digitalWrite(pin_A, LOW);
      digitalWrite(pin_B, LOW);
    }
    boolean limit1()
    {
      control = analogRead(pin_Rd);
      return control>= 320 && control <= 360; //есть сигнал с концевика 1
    }
    boolean limit2()
    {
      control = analogRead(pin_Rd);
      return control>= 150 && control <= 180;
    }
     
  3. sanik

    sanik Гик

    Код (Text):
    void loop()
    {
      //обновление состояния кнопки
      bouncerBtnSelect.update();
      bouncerBtnPlus.update();
      bouncerBtnMinus.update();
      bouncerBtnStart.update();
      bouncerBtnStop.update();

      switch(currentStep)
      {
        bouncerBtnPlus.rebounce(500);
        bouncerBtnMinus.rebounce(500);
      case STEP1_HELLO:
        hello();
        currentStep = STEP2_GET_POTS;
        break;

      case STEP2_GET_POTS:
        digitalWrite (pin_Pit, LOW);
        lcd.setCursor(0,0);
        lcd.print("    Manyal    ");
        potValue = analogRead(pin_dist);
        if(potValue >= 480 && potValue <= 530)
        {
          StopMotor();
        }
        else if(potValue <= 490 && !stop1)
        {
          if (stop2)//сбрасываем флаг если мотор поменял направление
          {
            stop2=!stop2;
          }
          RunMotor1(map(potValue, 0, 490, 255, 10));
        }
        else if(potValue >= 530 && !stop2 )
        {
          if (stop1)
          {
            stop1=!stop1;
          }
          RunMotor2(map(potValue, 530, 1023, 10, 255));
        }
        stop1 = control>= 320 && control <= 360; //есть сигнал с концевика 1
        stop2 = control>= 150 && control <= 180; //есть сигнал с концевика 2
        if (stop1 || stop2)StopMotor();
        if(debounce(btn_SELECT))// проверяем, нажата ли кнопка
        {
          currentStep = STEP3_GET_POSITION; //переходим к шагу 3
        }

        break;

      case STEP3_GET_POSITION:
        lcd.setCursor(0,0);
        lcd.print("Setting position");
        // гоним каертку на исходную позицию
        // плавный разгон a = 25 Начальное напряжение, подаваемое на двигатель
        // a <= 150 Условие для шага. a+=30 шаг, и исходя из условия выше, шаг не может быть больше 150
        for(int x = 25; x<=150; x +=30)
        {
          RunMotor1(x);
          delay(10);
          limit1();//читаем датчик концевик, и останавливаем каретку в крайней позиции
          StopMotor();
        }
        // кнопка нажата и значение меньше максимально допустимого?
        if(debounce(btn_PLUS) && posValue < MAX_POS_VALUE)
        {
          posValue++;
          lcd.setCursor(0,1);
          lcd.print("Position");
          lcd.print(posValue);
        }
        // кнопка нажата и значение больше минимально допустимого (нуля)?
        if(debounce(btn_MINUS) == HIGH && posValue > 0)
        {
          posValue--;
          lcd.setCursor(0,1);
          lcd.print("Position");
          lcd.print(posValue);
        }
        if (debounce(btn_SELECT))
        {
          currentStep = STEP4_GET_PAUSE; // переходим к шагу 4
        }
        break;

      case STEP4_GET_PAUSE:
        lcd.setCursor(0,0);
        lcd.print("Setting interval");
        if(debounce(btn_PLUS) && pauseValue < MAX_PAUSE_VALUE)
        {
          pauseValue+=1000;
          lcd.setCursor(0,1);
          lcd.print("Interval");
          lcd.print(pauseValue/1000);
        }
        if(debounce(btn_MINUS)&& pauseValue > 0)
        {
          pauseValue-=1000;
          lcd.setCursor(0,1);
          lcd.print("Interval");
          lcd.print(pauseValue/1000);
        }
        if (debounce(btn_SELECT))
        {
          currentStep = STEP5_GET_EXPOSURE;
        }
        break;
      case STEP5_GET_EXPOSURE:
        lcd.setCursor(0,0);
        lcd.print("Setting exposure");
        if(debounce(btn_PLUS) && exposValue < MAX_EXPOSURE_VALUE)
        {
          exposValue+=1000;
          lcd.setCursor(0,1);
          lcd.print("exp time");
          lcd.print(exposValue/1000);
        }
        if(debounce(btn_MINUS) && exposValue > 0)
        {
          exposValue-=1000;
          lcd.setCursor(0,1);
          lcd.print("exp time");
          lcd.print(exposValue/1000);
        }
        if (debounce(btn_SELECT))
        {
          currentStep = STEP6_GET_COUNT;
        }
        break;

      case STEP6_GET_COUNT:
        lcd.setCursor(0,0);
        lcd.print("Setting shooting");
        if(debounce(btn_PLUS) && shootValue < MAX_SHOT_VALUE)
        {
          shootValue++;
          lcd.setCursor(0,1);
          lcd.print("num shots");
          lcd.print(shootValue);
        }
        if(debounce(btn_MINUS) && shootValue > 0)
        {
          shootValue--;
          lcd.setCursor(0,1);
          lcd.print("num shots");
          lcd.print(shootValue);
        }
        if (debounce(btn_SELECT))
        {
          currentStep = STEP7_GET_START;//Переходим к шагу 7
        }
        break;

      case STEP7_GET_START:
        lcd.setCursor(0,0);
        lcd.print("Start shooting");

        if (debounce(btn_START))
        {
          currentStep = STEP8_PAUSE;//Переходим к шагу 8
        }
        if (debounce(btn_STOP))
        {
          lcd.setCursor(0,0);
          lcd.print("    Manyal    ");
          lcd.setCursor(0,1);
          lcd.print("                ");

          currentStep = STEP2_GET_POTS;//Переходим к шагу 2
        }
        break;
      case STEP8_PAUSE:
        lcd.setCursor(0,0);
        lcd.print("Start shooting");
        lcd.setCursor(0,1);
        lcd.print("shut shots");
        lcd.print(shootValue);
        currentTime = millis();// считываем время, прошедшее с момента запуска программы
        if (currentTime >= (TimePause + pauseValue)) // сравниваем текущий таймер с переменной TimePause
        {
          currentStep = STEP9_EXP;//Переходим к шагу 9
        }
        if (debounce(btn_STOP))
        {
          lcd.setCursor(0,0);
          lcd.print("    Manyal    ");
          lcd.setCursor(0,1);
          lcd.print("                ");

          currentStep = STEP2_GET_POTS; //Переходим к шагу 2
        }
        TimePause = currentTime; // в currentTime записываем новое значение
        break;

      case STEP9_EXP:
        digitalWrite (pin_Pit, HIGH);// включаем питание фотоинтерраптора
        lcd.setCursor(0,0);
        lcd.print("Start shooting");
        lcd.setCursor(0,1);
        lcd.print("shut shots");
        lcd.print(shootValue);
        currentTime = millis();// считываем время, прошедшее с момента запуска программы
        digitalWrite (pin_foc, HIGH);
        if (currentTime >= (TimeLag + LagValue)) // сравниваем текущий таймер с переменной LagValue
        {
          digitalWrite (pin_shot, HIGH);
          TimeLag = currentTime; // в currentTime записываем новое значение
        }
        if( shootValue > 0)// Отсчет кличества кадров
        {
          countValue++;
        }
        // значение кадров достигнуто выставленному Переходим к шагу 2
        if(shootValue==countValue)
        {
          digitalWrite (pin_foc, LOW);
          digitalWrite (pin_shot, LOW);
          lcd.setCursor(0,0);
          lcd.print("    Manyal    ");
          lcd.setCursor(0,1);
          lcd.print("                ");

          currentStep = STEP2_GET_POTS; //Переходим к шагу 2
        }
        if(currentTime >= (TimeExposure + exposValue)) // сравниваем текущий таймер с переменной exposValue
        {
          digitalWrite (pin_foc, LOW);
          digitalWrite (pin_shot, LOW);

          currentStep = STEP_10MOT;
        }
        if (debounce(btn_STOP))
        {
          digitalWrite (pin_foc, LOW);
          digitalWrite (pin_shot, LOW);
          lcd.setCursor(0,0);
          lcd.print("    Manyal    ");
          lcd.setCursor(0,1);
          lcd.print("                ");

          currentStep = STEP2_GET_POTS; //Переходим к шагу 2

          TimeExposure = currentTime; // в currentTime записываем новое значение
        }
        break;

      case STEP_10MOT:
        digitalWrite (pin_Pit, HIGH);// включаем питание фотоинтерраптора
        currentTime = millis();// считываем время, прошедшее с момента запуска программы
        limit1();// если положение 1 - крутить в направлении 2
        for(int x = 25; x<=150; x +=30) // плавный разгон
        {
          RunMotor2(x);
        }
        limit2();// если положение 2 - крутить в направлении 1
        for(int x = 25; x<=150; x +=30) // плавный разгон
        {
          RunMotor1(x);
        }
        if (pulse == posValue)//считаем количество импульсов,достигли значение
        {
          pulse=0; // сброс счетчика на 0
          StopMotor();
        }
        if (currentTime >= (TimePause + pauseValue)) // сравниваем текущий таймер с переменной TimePause
        {
          StopMotor();
          currentStep = STEP9_EXP; //Переходим к шагу 9
        }
        if (debounce(btn_STOP))
        {
          StopMotor();
          lcd.setCursor(0,0);
          lcd.print("    Manyal    ");
          lcd.setCursor(0,1);
          lcd.print("                ");

          currentStep = STEP2_GET_POTS; //Переходим к шагу 2

          TimePause = currentTime;
        }

        break;
      }
    }

     
     
  4. Megakoteyka

    Megakoteyka Оракул

    bouncerBtnPlus.rebounce(500);
    bouncerBtnMinus.rebounce(500);
    rebounce() нужно все же поставить на срабатывание соответствующих кнопок. Я первый раз неверно посоветовал (ошибся), но потом исправился, помните? Иначе кнопки будут срабатывать постоянно.

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

    Есть еще такой вариант: привязать кнопку "стоп" к прерыванию, в прерывании устанавливать флаг "СТОП_нажата".
    Алгоритм автоматического режима реализовать в виде простого цикла:
    for(int i = 0; i < количество_снимков; i++)
    {
    передвинуть каретку();
    сделать снимок();
    if("СТОП_нажата" == HIGH)
    {
    step = STEP2_GET_POTS;
    bresk; // прервать выполнение цикла
    }
    }
    Тогда при нажатии кнопки программа прервет выполнение только после того, как камера сделает снимок, во время которого была нажата кнопка. Мне кажется, это не критично.

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

    Кстати говоря, Вы все же не зря так долго бились - код стал гораздо лучше за это время, появились хорошие комментарии, исчезли бессмысленные скобки {}, Вы многому научились - время потрачено не зря!
     
  5. Unixon

    Unixon Оракул

    Не не, весь скетч целиком. Сделаю из него тесты для отдельных стадий.
     
  6. sanik

    sanik Гик

    Теперь на данный момент тестирование не возможно так как нахожусь не дома.Для вывода состояний придется ждать когда все таки придет посылка с заказанным переходником. Наверное в нем сейчас еще больше ошибок так как я пытался наладить... Скорей всего еще хуже сделал..
     

    Вложения:

  7. sanik

    sanik Гик

    Он весь целиком и есть просто не влезает я его поделил на две части..