Работа с ком портом

Askella
Offline
Зарегистрирован: 05.04.2016

Пишу скетч для связи с адсл модемом по uart, ардуино должен выполнить авторизацию на модеме войти в определенный пункт меню и вывести на экран информацию, вместо экрана использую монитор ком порта,

const int buttonPin = 2;     // номер входа, подключенный к кнопке
const int ledPin =  13;      // номер выхода светодиода
char* AT_command_string0 = "admin";        //логин и пароль
char* AT_command_string1 = "9";
char* AT_command_string2 = "2";// команда
// переменные
int buttonState = 0;         // переменная для хранения состояния кнопки
void setup() {
  //Скорость порта
  Serial.begin (115200);
  // инициализируем пин, подключенный к светодиоду, как выход
  pinMode(ledPin, OUTPUT);
  // инициализируем пин, подключенный к кнопке, как вход
  pinMode(buttonPin, INPUT);
 
}
void loop(){
  // считываем значения с входа кнопки
  buttonState = digitalRead(buttonPin);
  // проверяем нажата ли кнопка
  // если нажата, то buttonState будет HIGH:
  if (buttonState == HIGH) {
     digitalWrite(ledPin, HIGH);     //зажигаем пин
      Serial.write(0x0A);          // переход на новую строку (в некоторых модемах можно не выполнять)
     delay(2000);                   // ждем 2 сек.
    Serial.write(AT_command_string0);// отправляем логин
    Serial.write(0x0A);             // переход на новую строку
    delay(1000);                    // ждем секунду
    Serial.write(AT_command_string0);// отправляем пароль
    Serial.write(0x0A);             // переход на новую строку
    delay(1000);                    // ждем секунду
    Serial.write(AT_command_string1); // отправляем команду
    Serial.write(0x0A);
     delay(1000); 
     Serial.flush();
    Serial.write(AT_command_string2); // отправляем команду
    Serial.write(0x0A);
     delay(1000); // переход на новую строку
 char s;              // переменная временного хранения данных
  if (Serial.available()) // если в буфере есть что-то
  {
    delay(100);          //ждем 1 млс
    while (Serial.available() > 0)  // выводим информацию, пока буфер не будет пустой
    {
      s=Serial.read();              // получение данных (посимвольно)
        Serial.println(s);          // вывод полученных данных (посимвольно)
    }
}
  }
}

 

Askella
Offline
Зарегистрирован: 05.04.2016

проблема в том что нужно запихать в ардуино и обработать примерно такой объем данных

-------------------------------------------------------------------------
                        Statistics -- ADSL
-------------------------------------------------------------------------
This page shows the current ADSL statistics.
-------------------------------------------------------------------------
Mode                    : 2
Latency                 : 2
Trellis Coding          : Enable
Status                  : ACTIVATING.
Power Level             : L0
 
                                                Downstream      Uptream
SNR Margin (dB)                                 : 0.0           0.0
Attenuation (dB)                                : 0.0           0.0
Power (dBm)                                     : 0.0           25.5
Attainable Rate (Kbps)                          : 0             0
Rate (Kbps)                                     : 0             0
K (number of bytes in DMT frame)                : 0             0
R (number of check bytes in RS code word)       : 0             0
S (RS code word size in DMT frame)              : 0             0
D (interleaver depth)                           : 0             0
Delay (msec)                                    : 0             0
FEC                                             : 0             0
CRC                                             : 0             0
Total ES                                        : 0             0
Total SES                                       : 0             0
Total UAS                                       : 0             0
 
Из этого всего нужно выбрать и вывести на экран 5 параметров, но буфер последовательного порта ограничен 128 байтами, можно ли как нибудь впихнуть такой объем данных в ардуино для обработки?
Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Serial.availableForWrite() // возвращает размер свободного места в буфере сериала.

т.е. пихаешь в компорт по условию if (Serial.availableForWrite() == 128) {}, т.е. когда всё предыдущее отправлено и буфер свободен полностью.

Askella
Offline
Зарегистрирован: 05.04.2016

Можно объяснить подробней чем это поможет? Правильно ли я представляю обмен данными модема и ардуино: Модем посылает в буфер обмена  информацию о соединении но так как этой информации больше чем 128 байт то часть её просто теряется, так? Размер буфера последовательного порта для всех плат одинаковый? нельзя ли его как нибудь увеличить?

diakin
diakin аватар
Offline
Зарегистрирован: 04.06.2016

Ну так по приходу информации в буфер порта, ардуино начинает чтение и забирает данные из буфера куда-нибудь в массив, тем самым освобождая место в буфере.

Клапауций 232
Offline
Зарегистрирован: 05.04.2016

Askella пишет:

Можно объяснить подробней чем это поможет? Правильно ли я представляю обмен данными модема и ардуино: Модем посылает в буфер обмена  информацию о соединении но так как этой информации больше чем 128 байт то часть её просто теряется, так? Размер буфера последовательного порта для всех плат одинаковый? нельзя ли его как нибудь увеличить?

это поможет, если у тебя есть возможность настроить сериал модема.

но, очевидно, что увеличение буфера обмена тебя не спасёт - здесь явно не хватает сигнала сериала дуино сериалу модема

Запрос передачи RTS 4 7 8 5 CTS

https://ru.wikipedia.org/wiki/%D0%9D%D1%83%D0%BB%D1%8C-%D0%BC%D0%BE%D0%B...

uni
uni аватар
Offline
Зарегистрирован: 24.09.2015

Можно обработать построчно. Не разбирался как это устроено в Serial, но алгоритм такой. Принимаем данные кусочно и складываем в свой буфер нужного размера. Если встретился символ перевода строки ('\r\n' или просто 'n'), то обрабатываем строку в своём буфере и перемещаем указатель буфера на начало - принимаем следующую строку и т.д. 
Пока мы обрабатываем строку, ISR usart'а складывает данные в свой внутренний буфер (по идее должно быть так). Как только мы обработали строку в своём буфере, "обнуляем" его и запоняем принятыми данными.
Таким образом можно построчно распарсить вывод модема, сохранить данные во внутренних структурах и затем только их вывести.

IgorKa
Offline
Зарегистрирован: 06.11.2016

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











String bufer = "";
String string1 = "ADSL2/ADSL2+ connection\n";
String string2 = "ADSL link down\n";



void setup() {
  pinMode(13, OUTPUT);
 }


void analyzer() {
  if (bufer.length() > 1) {
  if (string1 == bufer) {digitalWrite(13, HIGH);   }
  if (string2 == bufer) {digitalWrite(13, LOW);    }
  } 
}


void read_serial() {
  if (Serial.available() > 0) {
    char ByteRead = Serial.read(); //чтение данных с порта
    if (ByteRead == char(13)) { //окончание строки
      analyzer();   //передача данных на обработку
      bufer = "";
        }  //освобождение буфера
    else {
      bufer = bufer + char(ByteRead);
    }   ///накопление данных в буфер
  }
}

void loop() {
 read_serial();
}

Все работает нормально.

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













int sinhro = 0;
String bufer = "";
String string1 = "ADSL2/ADSL2+ connection\n";
String string2 = "ADSL link down\n";

String bufer1 = "";
String bufer2 = "";
String bufer3 = "";
String bufer4 = "";

char* AT_command_string = "admin";        //логин и пароль
char* AT_command_string2 = "adsl info --show";   // команда

void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, INPUT_PULLUP);
  
}


void analyzer() {
  if (bufer.length() > 1) {

    if (bufer.startsWith("SNR"))
    {
      digitalWrite(12, HIGH);
      bufer1 = bufer;
   Serial.print(F("SNR  ")); Serial.println(bufer1);
    }

    if (bufer.startsWith("Attn"))  {
      digitalWrite(11, HIGH);
      bufer2 = bufer;
    Serial.print(F("ATT  "));      Serial.println(bufer2);
    }
    
    if (bufer.startsWith("Max"))   {
      digitalWrite(10, HIGH);
      bufer3 = bufer;
    Serial.print(F("MAX  "));      Serial.println(bufer3);
    }
    
    if (bufer.startsWith("Rate"))  {
      digitalWrite(9, HIGH);
      bufer4 = bufer;
   Serial.print(F("RATE "));      Serial.println(bufer4);
    }

  } 
 
}


void read_serial() {
  if (Serial.available() > 0) {
    char ByteRead = Serial.read(); //чтение данных с порта
    if (ByteRead == char(13)) { //окончание строки
      analyzer();   //передача данных на обработку
      bufer = "";
          }  //освобождение буфера
    else {
      bufer = bufer + char(ByteRead);
    }   ///накопление данных в буфер
  }
}



void loop() {
  //read_serial();

  if (digitalRead(8) == LOW) {
    digitalWrite(13, HIGH);
    sinhro = 1;
  }


  if (sinhro == 1) {
    delay(1000);
    Serial.write(0x0A);            // переход на новую строку (в некоторых модемах можно не выполнять)
    delay(2000);                   // ждем 2 сек.
    Serial.write(AT_command_string);// отправляем логин
    Serial.write(0x0A);             // переход на новую строку
    delay(2000);                    // ждем секунду
    Serial.write('\n');// отправляем пароль
    delay(2000);                    // ждем 
    Serial.flush();                 // очищаем буфер
    Serial.write(AT_command_string2); // отправляем команду
    Serial.write(0x0A);               // переход на новую строку
    sinhro = 0;
    read_serial();

  }
}

И вот здесь уже засада - ничего не работает. Светодиоды не загораются, вывод в Serial либо пустой, либо какие-то вырванные куски строк.

Написал третий код, в котором весь ответ модема собираю в одну строку и топором под названием substring отсекаю все лишнее и оставляю нужные мне куски информации, которую дальше думаю уже можно будет причесать и вывести на экран.









int sinhro = 0;
String bufer = "";
String data="";


char* AT_command_string = "admin";        //логин и пароль
char* AT_command_string2 = "adsl info --show";   // команда


void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, INPUT_PULLUP);
}


void read_serial1() {
  if(Serial.available() > 0) {
      data = Serial.readString(); // data - информация с серийного порта
 
}
}

void loop() {
 
  if (digitalRead(8) == LOW) {
    digitalWrite(13, HIGH);
    sinhro = 1;
  }


  if (sinhro == 1) {Serial.flush();                 // очищаем буфер
    delay(1000);
    Serial.write(0x0A);            // переход на новую строку (в некоторых модемах можно не выполнять)
    delay(2000);                   // ждем 2 сек.
    Serial.write(AT_command_string);// отправляем логин
    Serial.write(0x0A);             // переход на новую строку
    delay(2000);                    // ждем секунду
    Serial.write('\n');// отправляем пароль
    delay(2000);                    // ждем 
    Serial.flush();                 // очищаем буфер
    Serial.write(AT_command_string2); // отправляем команду
    Serial.write(0x0A);               // переход на новую строку
    sinhro = 0;
    read_serial1();
    delay(1000);
    
    Serial.println(data);

  String toWait=data.substring(339,453);
  String toWait1=data.substring(645,750);

   Serial.println(" ");
   Serial.println("out:");
   Serial.println(toWait);
   Serial.println(" ");
   Serial.println(toWait1);

  }
}

Но хотелось бы разобраться почему работает третий код (в bufer получается собрать и вывести полный ответ от модема) и не работает построчный вывод во втором коде?

-Agafon-
Offline
Зарегистрирован: 07.02.2018

Askella пишет:

Из этого всего нужно выбрать и вывести на экран 5 параметров, но буфер последовательного порта ограничен 128 байтами, можно ли как нибудь впихнуть такой объем данных в ардуино для обработки?

Приветствую! Получилось сделать адсл-тестер на ардуино? Скетчем поделитесь?

У меня модем Интеркросс 5633Е, там такая же последовательность (admin/admin/9/2). Но у меня не получается авторизоваться через ардуино, точнее в монитор порта после нажатия кнопки летят непонятные символы.