Прерывания по 6 входам - помехи(ардуино Nano)
- Войдите на сайт для отправки комментариев
Делаю приспособление для намотки бумаги на рулон. Натяжение обеспечивается качающейся рамкой. Рулонов 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 }
А осциллогаф видит помехи?
А осциллогаф видит помехи?
Налицо типовое идеологическое противостояние между быстродействующим низковольтным микроконтроллером (да ещё и настроенным на срабатывание по фронтам!) и грубой реальностью в виде электодвигателей с их широкополосными ("по непредсказуемой траектории") помехами при коммутации.
Помеха может лезть по питанию датчика, по проводу от датчика к ардуине, по питанию ардуины или по любому сочетанию. Нужно с реальной схемой разбираться.
Ну и подумать об отказе от прерываний по фронтам и аппаратных + программных защитах от "дребезга". Плюс некоторые варианты срабатывания датчиков контроллер должен признавать явно ошибочными и соответственно обрабатывать, а не тупо дергать двигатели.
Да я конечно понимаю что придется внести некоторое усложнение в код с целью отсечения как помех так и неправильных ситуаций. Но сначала хочу точно выяснить что может происходить
Вот схема с указанием пространственных размеров
На голый провод в 2 метра вы прерыванием наловите даже включение паяльника в розетку. Я ловил на простой 20см дюпонт, лежащий около провода удлинителя. Щелкаешь выключателем настольной лампы - в течении 200ns помехи летят в пин. МК их отлично засекает.
можете оценить на какое время срабатывают датчики : секунда, 100мс, 10мс, 10мкс и т.д.
может он просто остается в таклм состоянии, пока мотор не включится
т.е. в засимости от условий можно использовать разные методы.
а старая добрая схема на двух микропереключателях чем не устроила?
таузен, мильёнен конденсаторов было намотано, работало годами
Концевички это не гибко и не интересно. Там еще и другие функции иногда нужны бывают
Концевички это не гибко
Бывают и гибкие. Например, https://www.etm.ru/cat/nn/548417/
Уберите нафиг прерывания, сделайте переопросы датчиков.
Концевички это не гибко и не интересно. Там еще и другие функции иногда нужны бывают
ага, стоял механический программируемый счетчик оборотов, сколько слоёв (метров) мотаем...