Две функции не работают вместе.

Life23
Offline
Зарегистрирован: 10.08.2013

Простите, за корявость и похабность кода - я пытаюсь учиться.

int pwm = 11;

volatile unsigned long encoderSet = 0; //необходимое количество оборотов
volatile unsigned long encoderValue = 0; //значение счетчика
volatile unsigned long vvod_vitkov = 0; //количество витков

volatile unsigned long accSpeed = 0; //начальное значение числа ускорения

#define accPin A3   // потенциометр подключен к аналоговому входу 3
#define maxSpeedPin A2 // потенциометр подключен к аналоговому входу 2
volatile unsigned long maxSpeed = 0; //максимальная скорость двигателя (0-255)

//volatile unsigned long time = 0;
//volatile unsigned long time_old = 0;
//volatile unsigned long sped = 0;
int flag = 0;


//void count(void);


#include <Wire.h>
#include <i2ckeypad.h>
#define ROWS 4
#define COLS 4
#define PCF8574_ADDR 0x38

i2ckeypad kpd = i2ckeypad(PCF8574_ADDR, ROWS, COLS);

volatile unsigned long mililiters = 0, kolichestvo = 0, promejutok = 0;

void setup() {
  //  encoderSet = vvod_vitkov * 4;  //Количество импульсов на один полный оборот
  Serial.begin(9600);
  pinMode(2, INPUT);  //Пин энкодера D2
  attachInterrupt(0, count, FALLING); // 0 - таймер прерывания на D2, count - вызываемая функция при сработке таймера


  Serial.begin(9600);
  Serial.println("Starting...");
  Wire.begin();
  kpd.init();
}

void loop() {
  keybord();

  counterMotor();
}


void keybord() {
  char key = kpd.get_key();

  if (key) {
    delay(150);
    Serial.println(key);
    static int chislo = 0;
    static byte vvod = 0;
    if (key >= 'A' && key <= 'D')
    {
      chislo = 0;
      if (key == 'A') vvod = 1;
      if (key == 'B') vvod = 2;
      if (key == 'C') vvod = 3;
    }
    else if (key == '#' && vvod > 0)
    {
      if (vvod == 1) mililiters = chislo, Serial.print("mililiters = "), Serial.println(mililiters);
      if (vvod == 2) {
        kolichestvo = chislo;
        Serial.print("kolichestvo = ");
        encoderSet = kolichestvo * 4;
        Serial.println(kolichestvo);
      }
      if (vvod == 3) promejutok = chislo, Serial.print("promejutok ="), Serial.println(promejutok);
      chislo = 0;
      vvod = 0;
    }
    else if (key >= '0' && key <= '9')
    {
      if (vvod > 0)
      {
        chislo *= 10;
        chislo += key - 48;
        }
    }
  }
}

void count()
{
  encoderValue++;
}


void perPwm (int percent)
{
  maxSpeed = analogRead(maxSpeedPin); // читать аналоговый вход
  accSpeed = analogRead(accPin);
  maxSpeed = map(maxSpeed, 0, 1023, 70, 230);
  accSpeed = map(accSpeed, 0, 1023, 0, 50);
  percent = percent + accSpeed;
  percent = constrain(percent, 0, 100);
  maxSpeed = (maxSpeed * percent) / 100;
  analogWrite(pwm, maxSpeed);
}

void counterMotor()
{
  if (encoderValue < encoderSet)
  {
    if (encoderValue < (encoderSet * 5) / 100 && encoderValue != 0) //Разгон до 5%
    {
      perPwm(20);
      if (flag==0)
      {
        Serial.println("5%");
        ++flag;
      }
    }
    if (encoderValue > (encoderSet * 5) / 100 && encoderValue < (encoderSet * 10) / 100) //Разгон до 10%
    {
      perPwm(50);
      if (flag==1)
      {
        Serial.println("10%");
        ++flag;
      }
    }
    if (encoderValue > (encoderSet * 5) / 100 && encoderValue > (encoderSet * 10) / 100 && encoderValue < (encoderSet * 20) / 100) //Разгон до 20%
    {
      perPwm(70);
      if (flag==2)
      {
        Serial.println("20%");
        ++flag;
      }
    }
    if (encoderValue > (encoderSet * 5) / 100 && encoderValue > (encoderSet * 10) / 100 && encoderValue > (encoderSet * 20) / 100 && encoderValue < (encoderSet * 30) / 100) //Разгон до 30%
    {
      perPwm(100);
      if (flag==3)
      {
        Serial.println("30%");
        ++flag;
      }
    }
    if (encoderValue > (encoderSet * 70) / 100 && encoderValue < (encoderSet * 80) / 100) //Остановка 70%
    {
      perPwm(70);
      if (flag==4)
      {
        Serial.println("70%");
        ++flag;
      }
    }
    if (encoderValue > (encoderSet * 80) / 100 && encoderValue < (encoderSet * 90) / 100) //Остановка 80%
    {
      perPwm(50);
      if (flag==5)
      {
        Serial.println("80%");
        ++flag;
      }
    }
    if (encoderValue > (encoderSet * 90) / 100) //Остановка 90%
    {
      perPwm(20);
      if (flag==6)
      {
        Serial.println("90%");
        ++flag;
      }
    }
  }
  if (encoderValue >= encoderSet)
  {
    if (flag==7)
    {
      analogWrite(pwm, 0);
      Serial.println("END 100% namotano");
      Serial.println("PWM = 0 STOP!");
      ++flag;
    }
  }
}

Отдельно keybord и counterMotor работают так как надо. Клавиатура выводит в сериал число после #.

counterMotor отрабатывает введенное как константу количество оборотов.

А вот вместе в одном коде - какая то беда.. ((

На двигателе 4 лепестка для датчика. 

Клавиатура матричная подлючена через i2c.

Два переменника: максимальная скорость и скорость разгона.

Когда шторка закрывает датчик, после ввода числа и нажатия # - стартует только если толкну его и откроется шторка.

Бывает что наберет обороты определенные и крутит без остановки.

Заметил, что зависит от положения переменных резисторов.

подскажите косяки в коде, пожалуйста. Мучаюсь уже долгое время.. ((

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Сериал не тормозит всю программу?
Я уже давно кроме Serial.begin(115200); других цыфр не использую.
Проверял реалтермом 921600 прекрасно работает.   Но Ардуино ИДЕ не поддерживает

Да и на i2c не самая быстрая переферия....

Arhat109
Offline
Зарегистрирован: 26.05.2015

Осталось непонятным, при совместной работе все println() выводят нормальные значения или нет? Какой конкретно из них выводит не то? Как понимаю, они у вас натыканы для отладки.

Ну и по косякам в коде. Условия прописаны вроде бы верно, но сильно избыточно. Не так просто понять какое из них срабатывает, а какое нет. Откройте для себя "вложенные условные операторы" или switch(), чтобы использовать предыдущую проверку и не повторять её заново. Но, можно оставить и так, вроде бы все условия верные.

Ну и переменная flag... я бы описал её в начале функции... да и её роль не очень понятна. Как "блокировщик" вывода - она будет работать только при последовательном прохождении ситуаций.

Ну и по сути encoderSet устанавливается keyword. При этом вы должны видеть его значение. При совместной работе - оно показывается? Попробуйте вывести в начале значение encoderValue до проверок...

nevkon
Offline
Зарегистрирован: 20.01.2015

counterMotor() я так понимаю надо вызывать после ввода всего числа? Поставьте условие что у вас ввод завершен.

Life23
Offline
Зарегистрирован: 10.08.2013

Спасибо большое всем за ответы! сериал не тормозил в данном случае. Вывел в начале значение encoderValue до проверок... и офигел... считал мне со скоростью звука при том что двигатель стоял на месте. Оказалась причина в питании. Пин прерывания ловил помехи.

 

to Arhat109 - переменная flag так и задумывалась в начале для отладки. Что бы не дублировал  мне в монитор одно и тоже.

"Условия прописаны вроде бы верно, но сильно избыточно." - подскажите, как проще переписать? 

Число вводиться с клавиатуры разное (от 30 до 400), плавно разогнать в зависимости от введенного числа я додумался только считать процент от него и менять скорость. Хотел сделать разгон и остановку еще плавней, добавив еще условий. Но вообще тогда условий будет "гора". А вот как сделать еще "плавней" и упростить код - не могу сообразить.