Вроде все просто, а ничего не понимаю.

Densl
Offline
Зарегистрирован: 28.11.2018

Есть САМОПИСНЫЙ и частично стыренный код. Сижу уже вторые сутки, втыкаю, читаю датащиты и не пойму как это все вообще работает и что он делает.

Есть  клавиатура 4х4 и расширитель портов mcp23017 в виде модуля ардуиновского. Всем этим управляет 328p. Мне нужно без задержек реагировать на нажатия клавиш. Был создан бесконечный цикл, в котором крутиться шаговик. Проверять этот порт расширителя mcp очень расточительно, т.к. задержка полуается приличная около 510 мкс.  Для этого было решено использовать прерывания. В общем в итоге две кнопки из всей клавиатуры более менее отрабатывают прерывание, остальные тоже, но из прерываний выходить не желают. Там же вроде схема управления простая, а чего не работает не понимаю.

Клавиатура какая-то такая.

Densl
Offline
Зарегистрирован: 28.11.2018
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <AccelStepper.h>

byte arduinoIntPin     = 2;

// ... and this interrupt vector
byte arduinoInterrupt  = 1;

volatile boolean awakenByInterrupt = false;
volatile boolean awakenByInterruptPin[10];


#define BalanceStepPin   3
#define BalanceDirPin    4

#define RightLegStepPin  5
#define RightLegDirPin   6

#define LeftLegStepPin   7
#define LeftLegDirPin    8

#define RightFootStepPin 9
#define RightFootDirPin  10

#define LeftFootStepPin 11
#define LeftFootDirPin  12

const char Balance   = 0;
const char RightLeg  = 1;
const char LeftLeg   = 2;
const char RightFoot = 3;
const char LeftFoot  = 4;

volatile uint8_t pin;

Adafruit_MCP23017 mcp;

float oldSpeed = 0;
const int Motor_number = 5;
const byte ROWS = 4; //
const byte COLS = 4; //
const char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

byte rowPins[ROWS] = {3, 2, 1, 0};
byte colPins[COLS] = {7, 6, 5, 4};

AccelStepper* motorLink[Motor_number];
//

bool Rotate(int num, bool rotating, int param, int Speed, int Accel)
{
  Serial.println("InRotate");
  awakenByInterruptPin[0] = true;
  long long Stopor = 6000000;
  if (rotating) Stopor = -Stopor;
  motorLink[num]->setMaxSpeed(Speed);
  motorLink[num]->setAcceleration(Accel);
  motorLink[num]->moveTo(Stopor);
  //  while (mcp.digitalRead(colPins[param - 1]) == HIGH)
  Serial.println(String(awakenByInterruptPin[colPins[param - 1]]));
  Serial.print(String(colPins[param - 1]));
  Serial.print(String(" = "));
  Serial.println(String(pin));
  int iteration = 0;
  attachInterrupt(arduinoInterrupt, intCallBack, RISING);
  while (awakenByInterruptPin[0/*colPins[param - 1]*/])
  {
    iteration++;
    motorLink[num]->run();
    Serial.print("InWhile");
      Serial.println(iteration);
    //  delay(500);
    if (awakenByInterrupt)
    {
      awakenByInterruptPin[0] = false;
      Serial.println("awaken_from_While");
      handleInterrupt();
    }
    if (iteration > 100) awakenByInterruptPin[0] = false;
  }
  detachInterrupt(arduinoInterrupt);
  if (awakenByInterrupt) handleInterrupt();
  Serial.println("after_while");
  oldSpeed = motorLink[num]->speed();
  motorLink[num]->setMaxSpeed(0);
  while (motorLink[num]->speed() != 0)
  {
    motorLink[num]->run();
    Serial.println("InNextWhille");
  }
  motorLink[num]->setMaxSpeed(oldSpeed);
  Serial.println("OutRotate");

  return 1;
}

void setup()
{
  Serial.begin(9600);
  pinMode(arduinoIntPin, INPUT);

  Serial.println("inSetup");
  mcp.begin();      // use default address 0
  mcp.setupInterrupts(false, false, LOW);

  mcp.pinMode(0, OUTPUT);
  mcp.pinMode(1, OUTPUT);
  mcp.pinMode(2, OUTPUT);
  mcp.pinMode(3, OUTPUT);

  mcp.pinMode(4, INPUT);
  mcp.pullUp(4, HIGH);
  mcp.setupInterruptPin(4, FALLING);
  mcp.pinMode(5, INPUT);
  mcp.pullUp(5, HIGH);
  mcp.setupInterruptPin(5, FALLING);
  mcp.pinMode(6, INPUT);
  mcp.pullUp(6, HIGH);
  mcp.setupInterruptPin(6, FALLING);
  mcp.pinMode(7, INPUT);
  mcp.pullUp(7, HIGH);
  mcp.setupInterruptPin(7, FALLING);
  Serial.println("ExitSetup");

  motorLink[RightLeg]  = new AccelStepper(AccelStepper::FULL2WIRE, RightLegDirPin, RightLegStepPin);
  motorLink[LeftLeg]   = new AccelStepper(AccelStepper::FULL2WIRE, LeftLegDirPin, LeftLegStepPin);
  motorLink[RightFoot] = new AccelStepper(AccelStepper::FULL2WIRE, RightFootDirPin, RightFootStepPin);
  motorLink[LeftFoot]  = new AccelStepper(AccelStepper::FULL2WIRE, LeftFootDirPin, LeftFootStepPin);
  motorLink[Balance]   = new AccelStepper(AccelStepper::FULL2WIRE, BalanceDirPin, BalanceStepPin);

  for (int i = 0; i < 10; i++) awakenByInterruptPin[i] = false;

  //  attachInterrupt(arduinoInterrupt, intCallBack, FALLING);
}

void intCallBack() {
  awakenByInterrupt = true;
}

void handleInterrupt() {
  Serial.println("InHandleInterrupt");
  pin = mcp.getLastInterruptPin();
  uint8_t val = mcp.getLastInterruptPinValue();

  // we have to wait for the interrupt condition to finish
  // otherwise we might go to sleep with an ongoing condition and never wake up again.
  // as, an action is required to clear the INT flag, and allow it to trigger again.
  // see datasheet for datails.
  while ( ! (mcp.digitalRead(4) && mcp.digitalRead(5) && mcp.digitalRead(6) && mcp.digitalRead(7) ));
  // and clean queued INT signal
  cleanInterrupts();
  Serial.println("OutHandleInterrupt");
}

// handy for interrupts triggered by buttons
// normally signal a few due to bouncing issues
void cleanInterrupts() {
  EIFR = 0x01;
  awakenByInterrupt = false;
}

void matrix ()
{
  for (int i = 1; i <= 4; i++) //
  {
    mcp.digitalWrite(rowPins[i - 1], LOW); //
    for (int j = 1; j <= 4; j++) //
    {
      if (mcp.digitalRead(colPins[j - 1]) == LOW) //
      {
        mcp.setupInterruptPin(colPins[j - 1], RISING);
        switch (keys[i - 1][j - 1])
        {
          case '2':
            Rotate(Balance, 1, j, 6000, 1000);
            Serial.println("2");
            break;
          case '3':
            Serial.println("3");
            Rotate(Balance, 0, j, 6000, 2000);
            break;

          case '1':
            Serial.println("1");
            Rotate(LeftLeg, 1, j, 6000, 5000);
            break;
          case '4':
            Serial.println("4");
            Rotate(LeftLeg, 0, j, 6000, 5000);
            break;

          case 'A':
            Serial.println("A");
            Rotate(RightLeg, 1, j, 6000, 5000);
            break;
          case 'B':
            Serial.println("B");
            Rotate(RightLeg, 0, j, 6000, 5000);
            break;
          case '*':
            Serial.println("^");
            Rotate(LeftFoot, 1, j, 60, 50);
            break;
          case '0':
            Serial.println("0");
            Rotate(LeftFoot, 0, j, 60, 50);
            break;

          case '#':
            Serial.println("#");
            Rotate(RightFoot, 1, j, 60, 50);
            break;
          case 'D':
            Serial.println("D");
            Rotate(RightFoot, 0, j, 60, 50);
            break;

          case '5':
            break;
          case '6':
            break;
          case '7':
            break;
          case '8':
            break;
          case '9':
            break;
          case 'C':
            break;
        }
      }
      mcp.setupInterruptPin(colPins[j - 1], FALLING);
    }
    mcp.digitalWrite(rowPins[i - 1], HIGH); //
  }
}

void loop()
{
  while (!awakenByInterrupt)
    matrix();
  if (awakenByInterrupt) handleInterrupt();
  delay(500);
  Serial.println("delay(500)");
}

 

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Что будет если перед delay(500); дописать else?

sadman41
Offline
Зарегистрирован: 19.10.2016

В #155 попечатайте состояния "входов" MCP-шки. Эта конструкция лично мне не нравится.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

В #155 попечатайте состояния "входов" MCP-шки. Эта конструкция лично мне не нравится.

"всей свадьбе невеста нравится, а жениху нет" )))

А по существу, на таких конструкциях и влетаешь ...

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Инструкция в строке 248, на мой взгляд, не имеет смысла. Если вышли из цикла - значит awakenByInterrupt не ложь (не равно 0).