Работа с шумом в прерывании arduino

Я делаю два модуля, модуль 2 получает сигнал датчика и посылает беспроводное сообщение модулю 1 с помощью HC-12. Затем module1 собирается выполнить некоторую работу, которую он должен сделать. Конфигурация схемы изображена на рисунке.

Я проверил связь HC-12, и они хорошо посылают и принимают. Но моя проблема заключается в том, что когда модуль 1 включается, прерывание активируется (НИЗКОЕ), и модуль 2 посылает сигнал, который не должен посылаться. Похоже, это из-за шума электромагнитных волн, исходящих от HC-12.

Как я могу отфильтровать этот шум, используя код ? Теперь я застрял на последние 3 дня.

код Module1

#include <SimpleTimer.h>

#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

// #define IDlen 4
#define maxID 5

SoftwareSerial mySerial(2,3);
LiquidCrystal_I2C lcd(0x27, 16, 2);
int upButtonPin = 7;
int selectButtonPin = 6;
int downButtonPin = 5;
int sensors[maxID] = {1001,9999,9999,9999,9999};
int receivedID = 0;
int currentPos = 0;
String rcvMsg = "xxxx";

//void printSensor(int intID);
void menu();
void showAllSensors();
int removeID(int senNumInt);

void setup()
{
  Serial.begin(9600);
  Serial.println("Serial began.");

  mySerial.begin(9600);
//  mySerial.println("0000");
  
  lcd.begin();
  pinMode(upButtonPin,  INPUT_PULLUP);
  pinMode(selectButtonPin, INPUT_PULLUP);
  pinMode(downButtonPin, INPUT_PULLUP);
}

void loop()
{
  rcvMsg = "xxxx";
  lcd.setCursor(1,1);
  lcd.clear();
  lcd.print("Ready");
  if(digitalRead(upButtonPin)==LOW){
    lcd.clear();
    lcd.print("Up btn pressed!");
  }
  if(digitalRead(downButtonPin)==LOW){
    lcd.clear();
    lcd.print("Down btn pressed!");
  }
  if(digitalRead(selectButtonPin)==LOW){
    lcd.clear();
    lcd.print("Registered sensors:");
    delay(1000);
    lcd.clear();
    showAllSensors();
    menu();
  }
  if(mySerial.available()>0){
    
//    String rcvMsg = mySerial.readStringUntil('\n');
    rcvMsg = mySerial.readStringUntil('\n');
    Serial.print("Received msg: ");
    Serial.print(rcvMsg);
    Serial.print('\n');
    receivedID = rcvMsg.substring(0,4).toInt();
    Serial.println(receivedID);
    delay(50);
    
    for (int i=0;i<maxID;i++){
      if(sensors[i] == receivedID){
        String temp = String(receivedID);
        String ack = String(temp + "01"); // 01: success 02: reject (ID does not exist)
        mySerial.println(ack);
        Serial.print("Ack sent: ");
        Serial.print(ack);
      }
    }
  }
}

void menu(){
  lcd.print("UP: add sensor");
  lcd.setCursor(0,1);
  lcd.print("DOWN: del sensor");
  lcd.setCursor(0,0);
  
  while(1){  
    if(digitalRead(upButtonPin)==LOW){
      lcd.clear();
      lcd.print("Add sensor:");
      delay(1500);
      lcd.clear();
      int senNumInt = 1000;
      char senNum[IDlen];
      sprintf(senNum, "%d", senNumInt);
      
      while(1){   
        lcd.print(senNum);
        if(digitalRead(upButtonPin)==LOW){
          senNumInt++;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(downButtonPin)==LOW){
          senNumInt--;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(selectButtonPin)==LOW){
          lcd.clear();
          lcd.print(senNum);
          lcd.setCursor(0,1);
          lcd.print("Menu: OK, Down: Cancel");
          //센서 입력값을 받아서, 리스트에 넣어 놓기
          sensors[currentPos] = senNumInt;
          lcd.clear();
          showAllSensors();       
          delay(1500);
          break; // 값 입력 후 저장한 것 보여주고... 나가기.
        }
        delay(200);
        lcd.clear();
      }
      delay(200);
      break;
    } // up button 누름 메뉴 끝

    if(digitalRead(downButtonPin)==LOW){
      lcd.clear();
      lcd.print("Remove sensor:");
      delay(1500);
      lcd.clear();
      int senNumInt = 1000;
      char senNum[IDlen];
      sprintf(senNum, "%d", senNumInt);

      while(1){   
        lcd.print(senNum);
        if(digitalRead(upButtonPin)==LOW){
          senNumInt++;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(downButtonPin)==LOW){
          senNumInt--;
          sprintf(senNum, "%d", senNumInt);
          lcd.clear();
          lcd.print(senNum);
        }
        if(digitalRead(selectButtonPin)==LOW){
          lcd.clear();
          lcd.print(senNum);
          lcd.setCursor(0,1);
          lcd.print("Delete sensor");
          delay(600);
          lcd.clear();
          
          //센서 입력값을 받아서, 리스트에서 찾은 후 삭제
          int result = removeID(senNumInt);
          if(result==1){
            lcd.print("Deleted.");
            showAllSensors();       
          }else{
            lcd.print("No such ID!!");
          };
          delay(1500);
          break; // 값 입력 후 저장한 것 보여주고... 나가기.
        }
        delay(200);
        lcd.clear();
      }
      delay(200);
      break;
    } // down button 누름 메뉴 끝
    
    
    
    delay(200);
  }
  return;
}

void showAllSensors(){
  char imsi[IDlen];
  for(int i=0;i<maxID;i++){
    Serial.println(sensors[i]);
    sprintf(imsi, "%d", sensors[i]);
    lcd.print(imsi);
    delay(800);
    lcd.clear();
  }
  return;
}

int removeID(int senNumInt){
  int isFound = 0;
  for(int i=0;i<maxID;i++){
    if(sensors[i] == senNumInt){
      sensors[i] = 9999;
      isFound = 1;
    }
  }
  return isFound;
}

кодовыйМодуль2

#include <SoftwareSerial.h>
#include <avr/sleep.h> 
#include <SimpleTimer.h>

SimpleTimer timer;
const int wakeUpPin = 2; // вывод прерывания 0
const int LED = 8;
const int numMsg = 1; // Для безопасности каждый раз отправляйте несколько сообщений.  
boolean armed = false;
SoftwareSerial mySerial(4,5);
String ID = "1001";
String code = "01";
String msg = "xxxx";
String rcvMsg = "xxxx";
int timerID = 0;
boolean isWaked = false;
int pulseWidth = 0;

/*
  Протокол связи
  01: включено питание
  02: Сенсор коснулся (Подача полная)
  03: живой
*/


void setup()
{
  String msg = String(ID + code);
  pinMode(wakeUpPin, INPUT_PULLUP);
  pinMode(LED, OUTPUT);
  timerID = timer.setInterval(1000, sendMsg);
  
  Serial.begin(9600);  
  mySerial.begin(9600); 
  Serial.println(msg);
  delay(100);
}

void loop() // 반복
{
  pulseWidth = pulseIn(wakeUpPin, LOW, 100000);
  Serial.println("start loop.");
  armed = true;
  delay(100);
  Serial.println("Now sleeping.."); 
  delay(200);
  sleepNow(); 

  Serial.println(pulseWidth);
  if(armed){
    Serial.println("Waked up. Send Feed full msg.");
    
    delay(200);
    code = "02";
    msg = String(ID + code);
    sendMsg();
    int count = 0;
    while(1){
      count++;
      if(count>200){      //предотвратить бесконечный цикл
        count = 0;
        break;
      }
      Serial.print('*');
      if(mySerial.available()>0){
        Serial.println("RECEIVED!!!!");
        rcvMsg = mySerial.readStringUntil('\n');
        if(rcvMsg.substring(0,4).equals(ID)){
//          timer.deleteTimer(timerID);
          Serial.println("My msg is received successfully. Now sleep again..\n");
          break;
        }
      }
      delay(50);  
    }
    armed = false;
  }
}  

void wakeUpNow(){
  isWaked = true;
  return;
}

void sleepNow(){
  Serial.println("Entered sleep now()");
  delay(100);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  sleep_enable(); 
  attachInterrupt(0,wakeUpNow, LOW); 
  sleep_mode(); 
  // Когда проснется, возобновите коды отсюда. 
  sleep_disable(); 
  
  
  detachInterrupt(0);   
  return;
}

void sendMsg(){
  for (int i=0;i<numMsg;i++){
    mySerial.println(msg);
  }
  return;
}

, 👍1

Обсуждение

Я не уверен, является ли это диагностическим тестом или ответом, потому что это может быть примерно одно и то же. Я предполагаю, что вы тестируете их в непосредственной близости. Что я бы посоветовал вам сделать, так это сильнее подтянуть штифт 2. Поместите 1 Ком (просто для выбора числа) с контакта 2 на 5 В и переключите "PIN-режим" на "ВХОД", а не "INPUT_PULLUP". Посмотрите, какое это имеет значение, если таковое имеется., @timemage

дроссельные манжеты emi/rfi/ферритовые "бусинки" на vcc и сигнальных проводах могут решить вашу проблему с оборудованием. Попробуйте немного из старого шнура miniUSB и посмотрите, помогут ли они., @dandavis


1 ответ


1

Я знаю, это не совсем то, о чем вы просили, но я рекомендую аппаратную фильтрацию. У меня были проблемы с шумом на прерываниях, и я смог решить их с помощью этого компонента: https://www.st.com/content/st_com/en/products/emi-filtering-and-signal-conditioning/integrated-emi-filtering-and-esd-protection/computer-legacy-port-ipad/kbmf.html#overview

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

,