Прерывания по 6 входам - помехи(ардуино Nano)

Proset
Offline
Зарегистрирован: 01.03.2016

Делаю приспособление для намотки бумаги на рулон. Натяжение обеспечивается качающейся рамкой. Рулонов 2, моторов 2, рамки 2 шт. Положение рамки отслеживается оптодатчиками(использую Sharp от Canon 1215).

Датчиков по 3 на рамку(средний вспомогательный). Отслеживается срабатывание нижнего положения по нему вкючаю мотор, по достижении верхнего положения мотор выключаю.

Все сделал на прерываниях, датчики верхнего положения на честных прерываниях(D2 D3), датчики нижнего положения - на прерываниях по изменению состояния порта. Использовал библиотеку (мог и сам написать но смысла не видел пока делалось для теста)

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

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

Вопрос как можно побороть это явление кроме как усложнением логики работы программы, т.е. уменьшив вероятность проскакивания помех?

код привожу ниже

#include <Arduino.h>
#include <MsTimer2.h>
#include "PinChangeInterrupt.h"

#define ON LOW
#define OFF HIGH
#define MANUAL 1
#define AUTO 2

// Назначение портов

#define UF_MIDDLE A1//
#define UF_LOW A0//
#define UPF_MIDDLE A3//
#define UPF_LOW A2//

const byte LOW_HIGHPOS=2; // port for higgh pos low position sensor (under frame)
const byte FWD1=8; //2
const byte RWD1=4; //4
const byte ENB1=9; // 3 можно использовать порты 3 5 6 10 11 тк используем PWM
const byte FWD2=5;  // второй канал L298
const byte RWD2=7;
const byte ENB2=6; // с таймером 2 не работает 


const byte LOW_POS=1; // dancer at bottom 
const byte HIGH_POS=2; // dancer at top (stop rotate stepper)
const byte UNDEF_POS=3; // dancer at middle
const byte MOVES_UP=4; // stepper tights roll
const byte MOVES_DOWN=5; // Printer print roll

const byte Now_LOW=9;
const byte Now_UP=10;
const byte Now_Middle=11;
const byte UP=1;
const byte DOWN=2;

int DANCER_STATE=UNDEF_POS;
int current_state=Now_Middle;
int MAXSPEED=234;
int SPD=200;
byte oldLOWPOS,oldHIGHPOS,oldMIDDLEPOS,oldLOWPOS1,oldHIGHPOS1,oldMIDDLEPOS1;
volatile unsigned int timerCount3=0;
volatile boolean TIMEOUT=false;
volatile boolean EXPIRED=false;
unsigned int DELAY=1300;

void  timerInterupt() {
  if(TIMEOUT){
  timerCount3++;  // + 1 к счетчику таймера 3
  if ( timerCount3 >= DELAY ) {
    timerCount3= 0; // сброс счетчика
    TIMEOUT=false; EXPIRED=true;   
    // код программы вызывается каждые ???? мс    
   } 
  } 
}
// UP FRAME (RIGHT DANCER)
void UPF_TOP_POS(void) {
  // stop motor1
  digitalWrite(FWD2,LOW);digitalWrite(RWD2,LOW);digitalWrite(ENB2,LOW);
}
void UPF_LOW_ACT(void) {
  // start motor1
  cli();
  digitalWrite(FWD2,LOW);digitalWrite(RWD2,HIGH);digitalWrite(ENB2,HIGH);
  for(int i=0; i<20; i++) {}
  sei();
}
void UPF_MD_ACT(void) {
  analogWrite(ENB2,150);
}

// Under frame (LEFT DANCER) 
void UF_TOP_POS(void) {
  // stop motor 2
  digitalWrite(FWD1,LOW);digitalWrite(RWD1,LOW);digitalWrite(ENB1,LOW);
}

void UF_LOW_ACT(void) {
  // start motor 2
  cli();
  digitalWrite(FWD1,LOW);digitalWrite(RWD1,HIGH);digitalWrite(ENB1,HIGH);
  for(int i=0; i<20; i++) {}
  sei();
}

void UF_MD_ACT(void) {
  analogWrite(ENB1,150);
}
//disablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTock));
//enablePinChangeInterrupt(digitalPinToPinChangeInterrupt(pinTick));
void setup() {
      Serial.begin(9600);
      Serial.println("test L298");
    pinMode(A6,INPUT); pinMode(A7,INPUT);
    pinMode(A0,INPUT_PULLUP); // low pos under frame
    pinMode(A1,INPUT_PULLUP); // middle pos under frame
    pinMode(A2,INPUT_PULLUP);pinMode(A3,INPUT_PULLUP);
    pinMode(2,INPUT_PULLUP);pinMode(3,INPUT_PULLUP);
    pinMode (FWD1,OUTPUT);pinMode (RWD1,OUTPUT);
    pinMode (ENB1,OUTPUT);pinMode (FWD2,OUTPUT);
    pinMode (RWD2,OUTPUT); pinMode (ENB2,OUTPUT);
    digitalWrite(FWD1,LOW); // Brake motor
    digitalWrite(RWD1,LOW);
    digitalWrite(FWD2,LOW); // Brake motor
    digitalWrite(RWD2,LOW);   
    Serial.println("Continue");
#ifdef TIMER_2
      MsTimer2::set(2, timerInterupt); // задаем период прерывания по таймеру 2 мс 
      MsTimer2::start();
      Serial.print("Timer2 started");
#endif
  oldLOWPOS=0;oldHIGHPOS=0;oldMIDDLEPOS=0;oldLOWPOS1=0;oldHIGHPOS1=0;oldMIDDLEPOS1=0;
// вся логика в прерывании по ФРОНТУ
  attachInterrupt (digitalPinToInterrupt (2), UF_TOP_POS, RISING);
  attachInterrupt (digitalPinToInterrupt (3), UPF_TOP_POS, RISING);
  attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(UF_MIDDLE), UF_MD_ACT, RISING);
  attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(UF_LOW), UF_LOW_ACT, RISING);  
  attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(UPF_MIDDLE), UPF_MD_ACT, RISING);
  attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(UPF_LOW), UPF_LOW_ACT, RISING);  
}
byte STATE=MANUAL;
byte keystate=OFF;
byte keypress=LOW;
int sensorValue = 0; 

byte LOWPOS,HIGHPOS,MIDDLEPOS,LOWPOS1,HIGHPOS1,MIDDLEPOS1;



void loop() {
  // Кроме чтения ничего не делаем
  HIGHPOS=digitalRead(2);
  HIGHPOS1=digitalRead(3);
  MIDDLEPOS=digitalRead(A1);
  MIDDLEPOS1=digitalRead(A3);
  LOWPOS=digitalRead(A0);
  LOWPOS1=digitalRead(A2);
#ifdef SPRINT 
  if(HIGHPOS != oldHIGHPOS) {Serial.print("(UNDERFRAME HIGH)D2=");Serial.println(HIGHPOS); oldHIGHPOS=HIGHPOS;}
  if(HIGHPOS1 != oldHIGHPOS1) {Serial.print("(HIGHFRAME HIGH)D3=");Serial.println(HIGHPOS1); oldHIGHPOS1=HIGHPOS1;}
  if(MIDDLEPOS != oldMIDDLEPOS) {Serial.print("UF-A1=");Serial.println(MIDDLEPOS); oldMIDDLEPOS=MIDDLEPOS;}
  if(MIDDLEPOS1 != oldMIDDLEPOS1) {Serial.print("HF-A3=");Serial.println(MIDDLEPOS1); oldMIDDLEPOS1=MIDDLEPOS1;}
  if(LOWPOS != oldLOWPOS) {Serial.print("UF-A0=");Serial.println(LOWPOS); oldLOWPOS=LOWPOS;}
  if(LOWPOS1 != oldLOWPOS1) {Serial.print("HF-A2=");Serial.println(LOWPOS1); oldLOWPOS1=LOWPOS1;}
#endif  

}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А осциллогаф видит помехи?

SLKH
Offline
Зарегистрирован: 17.08.2015

ЕвгенийП пишет:

А осциллогаф видит помехи?

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

Налицо типовое идеологическое противостояние между быстродействующим низковольтным микроконтроллером (да ещё и настроенным на срабатывание по фронтам!) и грубой реальностью в виде электодвигателей с их широкополосными ("по непредсказуемой траектории") помехами при коммутации.

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

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

Proset
Offline
Зарегистрирован: 01.03.2016

Да я конечно понимаю что придется внести некоторое усложнение в код с целью отсечения как помех так и неправильных ситуаций. Но сначала хочу точно выяснить что может происходить

 

Вот схема с указанием пространственных размеров

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

На голый провод в 2 метра вы прерыванием наловите даже включение паяльника в розетку. Я ловил на простой 20см дюпонт, лежащий около провода удлинителя. Щелкаешь выключателем настольной лампы - в течении 200ns помехи летят в пин. МК их отлично засекает.

ВН
Offline
Зарегистрирован: 25.02.2016

Proset пишет:
Положение рамки отслеживается оптодатчиками(использую Sharp от Canon 1215).

можете оценить на какое время срабатывают датчики : секунда, 100мс, 10мс, 10мкс и т.д.

может он просто остается в таклм состоянии, пока мотор не включится

т.е. в засимости от условий можно использовать разные методы. 

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

а старая добрая схема на двух микропереключателях чем не устроила?
таузен, мильёнен конденсаторов было намотано, работало годами

Proset
Offline
Зарегистрирован: 01.03.2016

Концевички это не гибко и не интересно. Там еще и другие функции иногда нужны бывают

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Proset пишет:

Концевички это не гибко 

Бывают и гибкие. Например, https://www.etm.ru/cat/nn/548417/

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Уберите нафиг прерывания, сделайте переопросы датчиков.

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

Proset пишет:

Концевички это не гибко и не интересно. Там еще и другие функции иногда нужны бывают

ага, стоял механический программируемый счетчик оборотов, сколько слоёв (метров) мотаем...