Общение двух Atmega328p по COM порту

Тема в разделе "Arduino & Shields", создана пользователем Rauf, 6 окт 2016.

  1. Tomasina

    Tomasina Сушитель лампочек Модератор

    непонятно.
     
  2. Rauf

    Rauf Нерд

    Событие это изменение состояния любых из 8 входов на 1 устройстве. Если это событие длится 5 сек только тогда посылать сигнал тревоги.
     
  3. Rauf

    Rauf Нерд

    Я сейчас подключил бухту 600 метров сигнал идёт отличный. Но я читал нужно терминаторов ставить.
    Можно ли вообще обойтись без delay? Он у меня и в пищалке присутствует и в мигании лампочки
     
  4. Tomasina

    Tomasina Сушитель лампочек Модератор

    так ведь не надо тупить все эти 5 сек.
    Отметили время начала изменения состояния, и дальше бежим по кругу, периодически проверяя время - если более чем за 5 сек событие не изменилось на обратное - значит пора бить тревогу.
    delay тут вообще не нужен.
     
  5. Rauf

    Rauf Нерд

    Как побороть данную проблему
     
  6. Rauf

    Rauf Нерд

    Код (C++):
    #include <LiquidCrystal_I2C.h>

    #include <Wire.h>

    #include <Bounce2.h>
    Bounce bouncer = Bounce();
    LiquidCrystal_I2C lcd(0x27,16,2);  // устанавливаем адрес 0x27, и дисплей 16 символов в 2 строки (16х2)
    //LiquidCrystal_I2C lcd(0x3F,20,4);  // устанавливаем адрес 0x27, и дисплей 16 символов в 2 строки (16х2)

    #define LED_PINA 3   //relay 1
    #define LED_PINB 4   //relay 2
    #define LED_PINC 5   //relay 3
    #define LED_PIND 6   //relay 4
    #define LED_PINE 7   //relay 5
    #define LED_PINF 8   //relay 6
    #define LED_PING 9   //relay 7
    #define LED_PINJ 10  //relay 8

    #define LCD_HEIGHT                 2
    #define LCD_WIDTH                  16
    #define MSG_COUNT                  8

    #define RXTX_PIN 17       // RXTX ACTIVATION

    #define BEEP_PINK 2 // Пищалка сигнал при сработке

    #define LED_PINS 11 // Лед сигнал о нормальной связи

    #define BUTTON_TEST 12     // Тестовая кнопка проверки связи

    boolean needUpdateLCD =            true;                    // флаг-признак необходимости одновить данные на дисплее
    String lcdBuffer[LCD_HEIGHT];
    const unsigned int updateTime =    5000;                    // интервал смены надписей в нижней строке
    const unsigned int flashTime =     250;                     // интервал мигания цифр (при аварии)
    boolean msgFlag[MSG_COUNT] =      {0, 0, 0, 0, 0, 0, 0, 0}; // флаги текущих состояний UPS (1 - это авария)
    const String message[MSG_COUNT] = {                         // сообщения об авариях
      "1 Inverter Off  ",
      "1 On Battery    ",
      "1 General Alarm ",
      "1 Other         ",
      "2 Inverter Off  ",
      "2 On Battery    ",
      "2 General Alarm ",
      "2 Other         ",
    };

    #define TIMEOUT(tm, lastTm) (millis() - lastTm > tm)         // принять как аксиому :)

    int _previousValueTEST = 0;
    int soundPin = 2; //объявляем переменную с номером пина, на который мы подключили пьезоэлемент

    void setup()
    {
      bouncer.attach(12); // устанавливаем кнопку
      bouncer.interval(150); // устанавливаем параметр stable interval = 150 мс
      Serial.begin(9600);
     
      lcd.init();                     // инициализация LCD
      lcd.backlight();                // включаем подсветку
      SobitieLogo();
      //SobitieLCD;

      pinMode(LED_PINA, OUTPUT);  // LED 1
      pinMode(LED_PINB, OUTPUT);  // LED 2
      pinMode(LED_PINC, OUTPUT);  // LED 3
      pinMode(LED_PIND, OUTPUT);  // LED 4
      pinMode(LED_PINE, OUTPUT);  // LED 5
      pinMode(LED_PINF, OUTPUT);  // LED 6
      pinMode(LED_PING, OUTPUT);  // LED 7
      pinMode(LED_PINJ, OUTPUT);  // LED 8
      pinMode(soundPin, OUTPUT);  // BEEPER
      pinMode(LED_PINS, OUTPUT);  // LED TEST

      pinMode(RXTX_PIN, OUTPUT);  // RX/TX on off

      pinMode(BUTTON_TEST, INPUT);

      digitalWrite(RXTX_PIN, LOW);
     
    _previousValueTEST = digitalRead(BUTTON_TEST);

    }


    void loop()
    {
      displayData();                // отображение информации
      if (bouncer.update())
      { //если произошло событие
        if (bouncer.read()==0)
         { //если кнопка нажата
           digitalWrite(RXTX_PIN, HIGH);
           delay(1);
           Serial.print('Z'); //вывод сообщения о нажатии
           delay(1);
           digitalWrite(RXTX_PIN, LOW);
         }
      }
      if(Serial.available()>0)
      {
        readSerial();
      }
    }
     
  7. Rauf

    Rauf Нерд

    Код (C++):
    void displayData()
    {
      // формирование первой строки для вывода на дисплей
      static unsigned long lastFlashTime;
      lcdBuffer[0] = "1 2 3 4 5 6 7 8 ";          // шаблон для первой строки
      if (TIMEOUT(flashTime, lastFlashTime))     // каждые 0,25 сек формируем первую строку
      {
        static boolean flashFlag = true;
        if (flashFlag)
        {                                        // проверяем флаги на наличие ошибок
          for (byte ups = 1; ups <= MSG_COUNT; ups++)
            if (msgFlag[ups - 1]) lcdBuffer[0].replace(String(ups), "x"); // где ошибка - ставим хер
        }
        flashFlag = !flashFlag;
        lastFlashTime = millis();
        needUpdateLCD = true;
      }

      // формирование второй строки для вывода на дисплей
      static unsigned long lastUpdateTime;
      if (TIMEOUT(updateTime, lastUpdateTime))   // каждые 2 сек формируем вторую строку
      {
        lcdBuffer[1] = "                ";   // 20 пробелов (у меня 20 знаков на дисплее)
        lastUpdateTime = millis();
        //needUpdateLCD = true;                  // не нужно, т.к. первая строка все равно чаще обновляет ЖК
        byte ups = 0;
        while (!msgFlag[ups])                    // проверяем флаги на наличие ошибок
        {
          ups++;
          if (ups >= MSG_COUNT)                  // если нет ни одной ошибки, то выходим
          {
            ups = 0;
            return;
          }
        }
        // сюда попадаем, если есть хоть одна ошибка
        static byte c = 0;
        while (!msgFlag[c]) c++;                 // пропускаем сообщения, к которым ошибка не относится
        lcdBuffer[1] = message[c];               // буферизуем сообщение
        c++;                                     // чередуем все сообщения об ошибках
        if (c > MSG_COUNT - 1) c = 0;
      }

      // обновление данных на дисплее
      if (needUpdateLCD)
      {
        lcd.setCursor(0, 0);
        lcd.print(lcdBuffer[0]);

        lcd.setCursor(0, 1);
        lcd.print(lcdBuffer[1]);

        needUpdateLCD = false;
      } // if
    } // displayData
     
  8. Rauf

    Rauf Нерд

    В коде есть что то что приводит к проблеме как показано на видео. Циклично по всему экрану пробегают непонятные символы.
     
  9. Tomasina

    Tomasina Сушитель лампочек Модератор

    у меня такого не наблюдается ни разу, при любом количестве сработок.
    Интервал появления какой-то есть, или произвольно в любом момент?
    Возможно, наводки на длинные провода, или пропадает контакт у линий I2C.
     
  10. Rauf

    Rauf Нерд

    Эта проблема бывает если включён 6 тумблер. Первые 5 если будут включены то всё нормально. А включил 1 и 6 начинается абракадабра
     
  11. Rauf

    Rauf Нерд

    Провода длиной 20см. Интервал стабильный, по циклу идёт 1 сообщение, 2 сообщение, абракадабра и так повторяется.
     
  12. Tomasina

    Tomasina Сушитель лампочек Модератор

    к пинам А4 (SDA) и А5 (SCL) кроме дисплея ничего не подключено?
    Длина сообщений не превышает 16 знаков?
    К какому пину подключен 6-й тумблер?
     
  13. Rauf

    Rauf Нерд

    Длина 16 символов
    Digital Pin 7 - это 6 тумблер
    Кроме дисплея нет ничего на пинах.
     
  14. Rauf

    Rauf Нерд

    Сейчас видео загружу на ютуб
     
  15. Rauf

    Rauf Нерд

  16. Rauf

    Rauf Нерд

    Данная ошибка бывает при сработки комбинаций (1 и 6) и (2 и 6)
     
  17. Rauf

    Rauf Нерд

    Та же самая проблема наблюдается при подключении другого экрана LCD 2004A, I2c на нём другой
     
  18. Rauf

    Rauf Нерд

    Уважаемый Tomasina. Помните вы посылали мне код. На нём если включить 1 и 6 событие происходит тоже самое. Прошу Вас если будет время взгляните.
    Код (C++):
    #include <LiquidCrystal_I2C.h>

    #include <Wire.h>

    LiquidCrystal_I2C lcd(0x27,16,2);  // устанавливаем адрес 0x27, и дисплей 16 символов в 2 строки (16х2)

    #define BUTTON_PIN                 2
    #define RX_PIN                     0
    #define TX_PIN                     1
    #define BUZZER_PIN                 9
    #define BACKLIGHT_PIN              13
    #define LCD_HEIGHT                 2
    #define LCD_WIDTH                  16
    #define MSG_COUNT                  8

    boolean needUpdateLCD =            true;                    // флаг-признак необходимости одновить данные на дисплее
    String lcdBuffer[LCD_HEIGHT];
    const unsigned int updateTime =    2000;                    // интервал смены надписей в нижней строке
    const unsigned int flashTime =     250;                     // интервал мигания цифр (при аварии)
    boolean msgFlag[MSG_COUNT] =      {0, 0, 0, 0, 0, 0, 0, 0}; // флаги текущих состояний UPS (1 - это авария)
    const String message[MSG_COUNT] = {                         // сообщения об авариях
      "UPS 1 Inverter Off ",
      "UPS 1 On Battery   ",
      "UPS 1 General Alarm",
      "UPS 1 Inverter Off ",
      "UPS 2 Inverter Off ",
      "UPS 2 On Battery   ",
      "UPS 2 General Alarm",
      "UPS 2 Inverter Off ",
    };

    #define TIMEOUT(tm, lastTm) (millis() - lastTm > tm)         // принять как аксиому :)

    /*-----( Import needed libraries )-----*/




    // Set the pins on the I2C chip used for LCD connections:
    //                    addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
    //LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

    //LiquidCrystal_I2C lcd(0x27, BACKLIGHT_PIN, POSITIVE);  // Set the LCD I2C address

    // Прототипы функций (чтобы компилятор не ругался)
    void displayData();
    void dataManager();
    void buzzer(byte pin);
    void readButtons(byte pin);
    void readSerial(byte rxPin);
    void sendData(byte txPin);


    void loop()
    {
      readButtons(BUTTON_PIN);      // сканируем кнопку
      readSerial(RX_PIN);           // слушаем Serial
      dataManager();                // обработка данных
      sendData(TX_PIN);             // отправка данных
      displayData();                // отображение информации
      buzzer(BUZZER_PIN);           // звуковые уведомления
      ledControl();                 // моргание нужными LED
    }


    void dataManager()
    {
      // тут обработка каких-то данных
      // ...

      // эмуляция неисправности трех UPS через 1 мин после включения питания
      if (millis() > 10000)
      {
        msgFlag[0] = true;  // авария на 2-м UPS
        msgFlag[5] = true;  // авария на 7-м UPS
        //msgFlag[7] = true;  // авария на 8-м UPS
      }

    }



    void displayData()
    {
      // формирование первой строки для вывода на дисплей
      static unsigned long lastFlashTime;
      lcdBuffer[0] = "1 2 3 4 5 6 7 8";          // шаблон для первой строки
      if (TIMEOUT(flashTime, lastFlashTime))     // каждые 0,25 сек формируем первую строку
      {
        static boolean flashFlag = true;
        if (flashFlag)
        {                                        // проверяем флаги на наличие ошибок
          for (byte ups = 1; ups <= MSG_COUNT; ups++)
            if (msgFlag[ups - 1]) lcdBuffer[0].replace(String(ups), "x"); // где ошибка - ставим хер
        }
        flashFlag = !flashFlag;
        lastFlashTime = millis();
        needUpdateLCD = true;
      }

      // формирование второй строки для вывода на дисплей
      static unsigned long lastUpdateTime;
      if (TIMEOUT(updateTime, lastUpdateTime))   // каждые 2 сек формируем вторую строку
      {
        lcdBuffer[1] = "                    ";   // 20 пробелов (у меня 20 знаков на дисплее)
        lastUpdateTime = millis();
        //needUpdateLCD = true;                  // не нужно, т.к. первая строка все равно чаще обновляет ЖК
        byte ups = 0;
        while (!msgFlag[ups])                    // проверяем флаги на наличие ошибок
        {
          ups++;
          if (ups >= MSG_COUNT)                  // если нет ни одной ошибки, то выходим
          {
            ups = 0;
            return;
          }
        }
        // сюда попадаем, если есть хоть одна ошибка
        static byte c = 0;
        while (!msgFlag[c]) c++;                 // пропускаем сообщения, к которым ошибка не относится
        lcdBuffer[1] = message[c];               // буферизуем сообщение
        c++;                                     // чередуем все сообщения об ошибках
        if (c >= MSG_COUNT - 1) c = 0;
      }

      // обновление данных на дисплее
      if (needUpdateLCD)
      {
        lcd.setCursor(0, 0);
        lcd.print(lcdBuffer[0]);

        lcd.setCursor(0, 1);
        lcd.print(lcdBuffer[1]);

        needUpdateLCD = false;
      } // if
    } // displayData



    void ledControl()
    {
    }



    void buzzer(byte pin)
    {
    }



    void readButtons(byte pin)
    {
    }



    void readSerial(byte rxPin)
    {
    }



    void sendData(byte txPin)
    {
    }


    void setup()
    {
      lcd.init();                     // инициализация LCD
      lcd.backlight();                // включаем подсветку
      pinMode ( BACKLIGHT_PIN, OUTPUT );
      digitalWrite ( BACKLIGHT_PIN, HIGH );
      lcd.begin(LCD_WIDTH, LCD_HEIGHT);
      lcd.backlight(); // finish with backlight on
      lcd.clear();
    }
     
  19. qwone

    qwone Гик

    Переписал вашу программу под себя (скорее всего эскизно)Не думаю что код вам поможет. но запустите и смотрите. Подождите больше 10 сек.
    Код (C++):

    /*
    #1 светодиоды led1-led8
    #2 I2C LCD1602          GND -> GND
                          +5V -> +5V
                          SDA -> A4(SDA)
                          SCL -> A5(SCL)
      подсветка ->13 (backlight_pin)
    #3 кнопка ->2 (BUTTON_PIN)
    #4 пищалка ->9 (BUTTON_PIN)
    #5 RХ->0
       TХ->1
    */

    //#1 флаги
    const int MSG_End = 8 ; // количество исслед каналов
    uint8_t msgFlag[MSG_End] =      {0, 0, 0, 0, 0, 0, 0, 0}; // флаги текущих состояний UPS (1 - это авария)
    void ledControl() { // моргание нужными LED
    }
    //#2  дисплей
    const char * message[MSG_End] = {  // сообщения об авариях
      "1:UPS1 Inver OFF",
      "2:UPS1 On Batter",
      "3:UPS1 Gen Alarm",
      "4:UPS1 Inver OFF",
      "5:UPS2 Inver OFF",
      "6:UPS2 ON Batter",
      "7:UPS2 Gen Alarm",
      "8:UPS2 Inver OFF",
    };
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    const int backlight_pin = 13;
    LiquidCrystal_I2C lcd(0x27, 16, 2); // Устанавливаем дисплей

    void displayData() {// отображение информации
      static uint8_t number_step = 0; // номер шага вывода
      lcd.setCursor(0, 0);
      // вывод верхней строки
      for (int i = 0; i < MSG_End; i++) {
        if (!msgFlag[i]) {
          lcd.print(i + 1);
          lcd.print(" ");
        }
        else {
          if (number_step & 1) lcd.print("X");
          else lcd.print(i + 1);
          lcd.print(" ");
        }
      }
      // вывод нижней строки
      lcd.setCursor(0, 1);
      if (msgFlag[number_step] )lcd.print(message[number_step]);
      number_step++;
      if (number_step >= MSG_End) number_step = 0;
    }
    //#3 кнопка
    const int BUTTON_PIN = 2;
    void readButtons(byte pin) {// сканируем кнопку
    }
    //#4 пищалка
    const int BUZZER_PIN = 9;
    void buzzer(byte pin) { // звуковые уведомления
    }
    //#5 сериал
    const int RX_PIN = 0;
    const int TX_PIN = 1;
    void readSerial(byte rxPin) {// слушаем Serial
    }
    void dataManager() {  // обработка данных
        msgFlag[0] = true;  // авария на 2-м UPS
        msgFlag[5] = true;  // авария на 7-м UPS
        //msgFlag[7] = true;  // авария на 8-м UPS
    }
    void sendData(byte txPin) {// отправка данных
    }
    // mail
    void setup() {
      //#1   флаги
      //#2   дисплей
      lcd.init()             ; // инициализация LCD
      pinMode ( backlight_pin, OUTPUT );
      digitalWrite ( backlight_pin, 1 );
      lcd.backlight(); // Включаем подсветку дисплея
      //#3 кнопка
      //#4 пищалка
      //#5 сериал
    }
    void loop() {
      static uint32_t MILLIS ;
      MILLIS = millis() ;
      //#1 флаги
      ledControl();                 // моргание нужными LED
      //#2 1000 милисек дисплей
      static uint32_t future2 = 0 ;
      if (MILLIS >= future2) {
        future2 = MILLIS + 1000 ;
        displayData();       // отображение информации
      }
      //#3 кнопка
      readButtons(BUTTON_PIN);      // сканируем кнопку
      //#4 пищалка
      buzzer(BUZZER_PIN);           // звуковые уведомления
      //#5 сериал
      static uint32_t future5 = 10000 ;
      if (MILLIS >= future5) {
        future5 = MILLIS + 1000 ;
        readSerial(RX_PIN);           // слушаем Serial
        dataManager();                // обработка данных
        sendData(TX_PIN);             // отправка данных
      }
    }
     
     
    Последнее редактирование: 30 окт 2016
    Rauf нравится это.
  20. Rauf

    Rauf Нерд

    Уважаемый добрый Человек с ником qwone. Хочу выразить огромную благодарность. Я совместил ваш код с моим и всё прекрасно работает. Вы оказали неоценимую помощь.