Случайный сброс Arduino Nano

В настоящее время я борюсь с периодически возникающей проблемой в проекте Arduino.

Предыстория

Я использую программу LabVIEW для управления несколькими аппаратными средствами. Одним из них является шаговый двигатель NEMA 17, который приводит в действие реечный привод. Я использую подлинный Arduino Nano с (официальным) драйвером двигателя EasyDriver для управления NEMA 17. Arduino отслеживает состояние DI-контакта, и если он вытянут высоко, он выдвигает стойку до тех пор, пока U-образный датчик не отправит высокий входной сигнал в крайнем крайнем положении, затем он прослушивает, чтобы этот DI-контакт был вытянут низко, и втягивает стойку, пока датчик приближения не отправит высокий входной сигнал. входной сигнал.

В чем проблема

Я заметил, что мой привод либо перестал реагировать на входные сигналы от LabVIEW DAQ, либо застрял в середине срабатывания (у двигателя достаточно крутящего момента для этого приложения). После изменения кода для печати обновлений на последовательный порт я понял, что после нескольких циклов Arduino сбрасывается и снова входит в функцию Setup ().

Я сменил Nano, и это не имело никакого значения. Я впервые использую функцию тайм-аута, и мне было интересно, может ли использование памяти этой функции вызывать проблемы, однако я закомментировал эту часть кода, и Arduino все еще сбрасывается. Код приведен ниже - очень хотелось бы услышать какие-либо мысли о том, может ли это быть аппаратной или программной проблемой. Я подключаю Arduino к сети 7 В от источника питания к порту Vin. Датчик prox работает при 24 В, но я делю напряжение выходного сигнала так, чтобы входное напряжение составляло ~ 4,8 В (я измерил это). Я использую тот же U-образный датчик с несколькими другими Arduino, и я не вижу этой проблемы. В прошлом я подключал ардуино к той же 7-вольтовой линии и также никогда не видел, чтобы они сбрасывались подобным образом.

Дайте мне знать, что вы думаете, спасибо!

 const int uSensor = 12;
const int proxSensor = 10;

const int labViewHomePin = 9;
const int labViewInputPin = 8;

const int labViewOutFeedback = 7;
const int labViewInFeedback = 6;

const int StepperStepPin = 2;
const int StepperDirectionPin = 3;
const int ENPin = 13;

enum {IdleState, ForwardState, BackwardState} State;            // этот случай переключения используется для вызова правильной функции, которая поворачивает двигатель в нужном направлении

boolean rampDone = false;
boolean pusherIn = false;
boolean pusherOut = false;
boolean homingDone = false;

boolean updateGiven = false;

int motorSpeed = 300;
int rampStartSpeed = 500;
int rampStepCountNo = 800;

boolean boolInitialMove = true;
unsigned long timeInitialMove = 6000;
unsigned long startTime;
unsigned long endTime;


void setup() {
  Serial.begin(9600);
  pinMode(uSensor, INPUT);
  pinMode(proxSensor, INPUT);
  pinMode(labViewHomePin, INPUT);                                  // инициализация входных контактов
  pinMode(labViewInputPin, INPUT);                                  // инициализация входных контактов

  pinMode(StepperDirectionPin, OUTPUT);                             //
  pinMode(StepperStepPin, OUTPUT);                                  // Шаг
  pinMode(ENPin, OUTPUT);                                           // Включить
  
  Serial.println();
  Serial.println("Setup phase called");
  Serial.println();
  
  pinMode(labViewInFeedback, OUTPUT);                             
  pinMode(labViewOutFeedback, OUTPUT);  

  State = IdleState;                                                
  digitalWrite(ENPin,HIGH);                                         // По умолчанию диск отключен
                                    
  
  homingDone = false;
}

void loop() {
  if ((digitalRead(labViewHomePin) == HIGH) && (homingDone == false)) {
    Serial.println("Homing Pin High Detected");
    homingRoutine();
    homingDone = true;  
    Serial.print("Homing Done = ");
    Serial.println(homingDone);
    State = IdleState;

    if(digitalRead(proxSensor) == HIGH) {
      digitalWrite(labViewInFeedback,HIGH);
      digitalWrite(labViewOutFeedback,LOW);
    }
    else if(digitalRead(uSensor) == HIGH)  {
      digitalWrite(labViewInFeedback,LOW);
      digitalWrite(labViewOutFeedback,HIGH);
    }
    else {
      digitalWrite(labViewInFeedback,LOW);
      digitalWrite(labViewOutFeedback,LOW);
    }
  
  }
  
  switch (State) {
    case IdleState:
    boolInitialMove = true;
    digitalWrite(ENPin,HIGH);

      if(updateGiven == false) {
        Serial.println("I am in IdleState");
        Serial.print("Pusher Out Boolean = ");
        Serial.println(pusherOut);
        Serial.print("Pusher In Boolean = ");
        Serial.println(pusherIn);
        Serial.print("Prox Sensor status: ");
        Serial.println(digitalRead(proxSensor));
        Serial.print("U-Sensor status: ");
        Serial.println(digitalRead(uSensor));
        updateGiven = true;
      }

        
      if ((digitalRead(labViewInputPin) == HIGH) && (pusherOut == false) && (homingDone == true)) {
        digitalWrite(ENPin,LOW);                                    // Включить привод
        State = ForwardState;        
        Serial.println("LabVIEW High detected. Case switched to ForwardState");
        Serial.println("");
        updateGiven = false;
      }
      else if ((digitalRead(labViewInputPin) == LOW) && (pusherIn == false) && (homingDone == true)) {
        digitalWrite(ENPin,LOW);                                    // Включить привод
        State = BackwardState;                                       
        Serial.println("LabVIEW Low detected. Case switched to BackwardState");
        Serial.println("");
        updateGiven = false;
      }
      else {
        // ничего не делать
      }
      
      if(digitalRead(uSensor) == HIGH) {
        pusherOut = true;
        pusherIn = false; 
      }
      else if(digitalRead(proxSensor) == HIGH) {
        pusherOut = false;
        pusherIn = true;
      }
      else {
        // ничего не делать
      }
      
      break;
      

    case ForwardState:

    if(updateGiven == false) {
        Serial.println("I am in ForwardState");
        Serial.print("LabVIEW Actuate Pin = ");
        Serial.println(digitalRead(labViewHomePin));
        updateGiven = true;
      }
      
    if(boolInitialMove == true) {
        digitalWrite(StepperDirectionPin, LOW);
        rampUpCosineWave(rampStartSpeed, rampStepCountNo, motorSpeed);
        startTime = millis();
        endTime = startTime;
        boolInitialMove = false;
      }
      
      endTime = millis();
      rotateForward(motorSpeed);                                            // это вызывает функцию ForwardState, которая начинает выталкивать толкатель
      
      if (digitalRead(uSensor) == HIGH) {
        digitalWrite(labViewInFeedback,LOW);                   
        digitalWrite(labViewOutFeedback,HIGH);
        Serial.println("U-Sensor High detected. Case switched to Idlestate");
        Serial.println("");
        updateGiven = false;
        
        pusherOut = true;
        pusherIn = false;
        State = IdleState;                                   
      }
      else if((endTime-startTime) > timeInitialMove) {
        digitalWrite(ENPin,HIGH);
        digitalWrite(StepperStepPin, LOW);
        digitalWrite(StepperDirectionPin, LOW);
        digitalWrite(labViewOutFeedback,HIGH);
        digitalWrite(labViewInFeedback,HIGH);

        
        Serial.println("");
        Serial.println("**TIMEOUT DETECTED**");
        Serial.println("");
        
        State = IdleState; 
      }
      break;
      

    case BackwardState:

    if(updateGiven == false) {
        Serial.println("I am in BackwardState");
        Serial.print("LabVIEW Actuate Pin = ");
        Serial.println(digitalRead(labViewHomePin));
        updateGiven = true;
      }
      
    if(boolInitialMove == true) {
        digitalWrite(StepperDirectionPin, HIGH);
        rampUpCosineWave(rampStartSpeed, rampStepCountNo, motorSpeed);
        startTime = millis();
        endTime = startTime;
        boolInitialMove = false;
      }
      
      endTime = millis();
      rotateBackward(motorSpeed);                                          
      
      if (digitalRead(proxSensor) == HIGH) {
        digitalWrite(labViewInFeedback,HIGH);                   
        digitalWrite(labViewOutFeedback,LOW);                                // Отключить диск
        Serial.println("Prox Sensor High detected. Case switched to Idlestate");
        Serial.println("");
        updateGiven = false;
        
        pusherOut = false;
        pusherIn = true;
        State = IdleState;                                      
      }
      else if((endTime-startTime) > timeInitialMove) {
        digitalWrite(ENPin,HIGH);
        digitalWrite(StepperStepPin, LOW);
        digitalWrite(StepperDirectionPin, LOW);
        digitalWrite(labViewOutFeedback,HIGH);
        digitalWrite(labViewInFeedback,HIGH);

        Serial.println("");
        Serial.println("**TIMEOUT DETECTED**");
        Serial.println("");
        
        State = IdleState; 
      }
      break;
 
  } // конечный выключатель
}

void rotateForward(int mtrSpeed) {                                          
  digitalWrite(StepperDirectionPin, LOW);
  digitalWrite(StepperStepPin, HIGH);
  delayMicroseconds(mtrSpeed);
  digitalWrite(StepperStepPin, LOW);
}

void rotateBackward(int mtrSpeed) {
  digitalWrite(StepperDirectionPin, HIGH);
  digitalWrite(StepperStepPin, LOW);
  delayMicroseconds(mtrSpeed);
  digitalWrite(StepperStepPin, HIGH);
}

void homingRoutine() {
  digitalWrite(ENPin,LOW);
  Serial.println("Homing Routine called");
  bool firstCycle = false;
  bool secondCycle = false;
  bool thirdCycle = false;
  bool fourthCycle = false;
   
  while(digitalRead(uSensor) != HIGH) {
    rotateForward(rampStartSpeed);
  }
  delay(500);
  Serial.println("First home movement completed");
  while(digitalRead(proxSensor) != HIGH) {
    rotateBackward(rampStartSpeed);
  }
  delay(500);
  Serial.println("Second home movement completed");
  while(digitalRead(uSensor) != HIGH) {
    rotateForward(rampStartSpeed);
  }
  delay(500);
  Serial.println("Third home movement completed");
  while(digitalRead(proxSensor) != HIGH) {
    rotateBackward(rampStartSpeed);
  }

  delay(500);

  
  homingDone = true;
  pusherIn = true;
  pusherOut = false;

}
  
  int rampUpCosineWave(int startSpeed, int rampUpSteps, int maximumSpeed) {
  int countedSteps = 0;
  float amp = ((startSpeed-maximumSpeed)/2);
  for(int currentSpeed = startSpeed; currentSpeed > maximumSpeed; currentSpeed = (int)((amp + maximumSpeed)+(amp*(cos((PI/rampUpSteps)*countedSteps))))) {
    digitalWrite(StepperStepPin, LOW);
    delayMicroseconds(currentSpeed);
    digitalWrite(StepperStepPin, HIGH);
    countedSteps++;
  }

  return countedSteps;
}

, 👍3

Обсуждение

Можете ли вы отслеживать линии Vin и +5 В с помощью прицела _ во время работы шагового движка_? Электродвигатели могут создавать шум и нестабильность в источниках питания., @Edgar Bonet

Ваш счетчик * может * также иметь минимальный режим, который отслеживает минимальное напряжение, наблюдаемое с момента запуска. Это не так хорошо, как использование прицела, как предлагает Эдгар, но иногда это может помочь., @timemage


2 ответа


Лучший ответ:

3

Спасибо вам всем за ваш вклад. Мне удалось найти проблему и решить проблему с прерывистым сбросом. Я ожидал найти аппаратную проблему в качестве основной причины, но на всякий случай, если это было связано с программным обеспечением, я тоже хотел проверить. Это оказалось аппаратным обеспечением

Гил, безусловно, ставит под сомнение правильность выбора оборудования. Это действительно была проводка датчика Prox. Я подключил как общие рельсы передачи данных, так и питания, чтобы облегчить работу датчика prox, но при проверке я решил оставить их раздельными, а напряжение разделить датчик prox подальше от рельсов и вместо этого подключить прямую линию 4,8 В к Arduino. Какой бы шум ни создавал шаговый двигатель, он не мог повлиять на линии передачи данных Arduino, и с тех пор я не видел, чтобы проблема возвращалась.

Очень ценю вашу помощь всем. Я не подключал линии питания к Arduino, так как проблема продолжалась независимо от того, что я подключал arduino только через COM-порт ПК, комбинацию COM-порта и 7V к линии Vin (предположим, что Arduino подключается к линии 7V, но я не уверен) и только Линия 7В. По-видимому, это был шум, нарушающий общую магистраль передачи данных Arduino.

,

1

Я ожидаю, что у вас много работы над вашим дизайном. Деление вниз никогда не является хорошим источником напряжения (мощности), независимо от того, что вы измеряете, если только вы не используете хороший прицел для измерения и его хорошо обходят стороной. Подумайте о понижающем регуляторе от одного из китайских поставщиков, он стоит всего несколько долларов и стабилизирует вашу цепь. Если датчик prox потребляет всего несколько мельниц, подумайте о том, чтобы запитать его от Arduino напряжением 5 вольт. Двигатели, как и другие индуктивные устройства, генерируют множество транзисторов, которые одновременно проводятся и излучаются, что-то подобное может попадать в вашу систему, возможно, через датчик prox. Это должно помочь вам начать.

,