none
Enviar comandos AT por el puerto serie

    Pregunta

  • Buenas, soy nuevo programando en C# y tengo un problemilla.

    Debo enviar un comando AT a un dispositivo, y esperar a recibir la respuesta del mismo para procesarla. El dispositivo envia la respuesta terminando en "\r".

     

    Lo he intentado de las siguientes formas pero nada.


    DateTime TimeOut = DateTime.Now.AddSeconds(5);
    string AT_Response = "";
    COMPort.Write(AT_Command);
    do
    {
    ATResponse += COMPort.ReadExisting();
    if (DateTime.Now > TimeOut)
    {
    throw new Exception("AT Command timed out without receiving 'OK'.");
    }
    }
    while (!ATResponse.Contains("OK"));


    ************************************************************************
     Otra manera

     


    COMPort.ReadTimeout = 5000;
    COMPort.NewLine = "\r";
    COMPort.Write(AT_Command);
    AT_Response = COMPort.ReadLine();

     

     

    Agradeceria que me ayudaseis.

    jueves, 29 de marzo de 2007 18:23

Todas las respuestas

  • Hola Gonzalo :

     

    Porqué no haces una pausa:

     

    _SerialPort.Write(sTrama);
      System.Threading.Thread.Sleep(iSegundos*1000);
      sRespuesta = _SerialPort.ReadExisting();
       _SerialPort.DiscardInBuffer();

     

    De todas maneras  a ver si se pasa Pep y lo lee que el es el experto en estos temas.

     

    Salu2

    viernes, 30 de marzo de 2007 6:31
  • Gracias Luis y Hola Gonzalo.

    Tienes que empezar, definiendo el evento de recepcion (puede estas justo despues de ‘InitializeComponent()’…

    this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.Recepcion);

     

    Luego puede procesar los caracteres recibidos en espera de ‘\r’ que supuestamente es el carácter 13 de la tabla ASCII.

    // Al recibir datos

    private void Recepcion(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)

       {

       // Acumular los caracteres recibidos a nuestro 'buffer' (string)

       Recibidos += this.serialPort1.ReadExisting();

       // Invocar al proceso de tramas

       // para evitar la llamada ilegal entre threats

       this.Invoke(new EventHandler(Actualizar));

       }

     

    Como observaras en este caso usaremos un (string RecibidosWink para procesar los caracteres. Cada vez que se reciba algun carater dispararemos la actualizacion para controlar si la trama de recepcion esta completa.

    private void Actualizar(object s, EventArgs e)

       {

       int Inicio = Recibidos.IndexOf("\x01"); // Posicion Inicio trama (Ejemplo)

       int Final = Recibidos.IndexOf("\x0D");  // Posicion Final trama (13 en hex)

       //

       // Si exiset posicion de inicio y una despues del final

       if ((Inicio > -1) & (Final > Inicio))

          {

          // procesar la trama completa

          }

          else

          // De no cumplirse las condiciones de Inicio/Fin

          {

          }

        }

     

    No dudes en continuar este hilo para ir discutiendo los detalles,

    Saludos a los dos,

    Pep Lluis,

    viernes, 30 de marzo de 2007 7:54
    Moderador
  • Gracias por intentar ayudarme Luis y Pep Lluis.

     

    Mi problema es que defino el evento de recepcion:

     

    COMPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);

     

      Envio datos al dispositivo y tambien los recivo (estos datos solamente hay que mostrarlos en una ventana de texto),

    pero cuando envio un comando AT, debo recoger la respuesta y comprobar si se a ejecutado correctamente (recibir "OK\r").

     

     

    private void ReceiveData(object sender, SerialDataReceivedEventArgs e)

    {

         if (CurrentDataMode == DataMode.Text)   // modo texto

         {

           string Data_R = COMPort.ReadExisting();

            Message(TxtType.Incoming, Data_R);   //mostrar en ventana de texto

         }

         else    // modo hexadecimal

         {

            int Bytes = COMPort.BytesToRead;

            byte[] Buffer = new byte[Bytes];

           COMPort.Read(Buffer, 0, Bytes);

          Message(TxtType.Incoming, ByteArrayToHexString(Buffer) + "\r");  //mostrar en ventana de texto

        }

    }

     

     

    Para entrar en el modo de comandos AT, debo enviar "+++" y esperar a recibir la respuesta "OK\r"

     

     

    string Response = "";

    DateTime TimeOut = DateTime.Now.AddSeconds(2);

    try

      {

        COMPort.Write("+++");

        do

        {

          Response += COMPort.ReadExisting();

          if (DateTime.Now > TimeOut)

          {

            throw new Exception("AT Command timed out without receiving 'OK'.");

          }

        }

        while (!Response.Contains("OK"));

      }

     

    catch (Exception)

      {

        MessageBox.Show(this, "AT Command timed out.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

      }

     

     

    En internet encontre que se podria hacer de la siguiente manera tambien:

     

     

    string Response = "";

    COMPort.Write("+++");

     

    try

      {

        Response = COMPort.ReadLine();

      }

     

    catch (Exception)

      {

        MessageBox.Show(this, "AT Command timed out.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

      }

     

    para ello antes he configurado los parametros del puerto:

     

    COMPort.NewLine = "\r"//caracter que determina fianl de linea

    COMPort.ReadTimeout = 5000; // tiempo de lectura maximo

     

    de las formas anteriores hay veces que funciona y otras que no pero no encuentro el fallo.

     

    Salu2.

     

    viernes, 30 de marzo de 2007 11:18
  • Hola de nuevo,

    El error reside en que nunca puedes esperar la respuesta de una comunicacion dentro de un bucle, ni tampoco en un readline... :-(

     

    En muchas ocasiones dependiendo del dispositivo, no respondera la primera vez que envies el '+++' o dependiendo de la configuracion del mismo, no respondera con un "OK"... si te parece bien vamos a empezar de nuevo. Dime exactamente el primer objetivo a conseguir y que tipo de dispositivo estas enchufando al puerto... si un modem / telefono... y si me das tiempo montamos un ejemplo especifico.

    Saludos,

    Pep Lluis,

     

    viernes, 30 de marzo de 2007 16:20
    Moderador
  •  

    Hola Pep Lluis.

     

    Creo que ya he conseguido resolver el fallo, te explico.

     

    Una vez definido el evento recibirpor el puerto serie,

     

    COMPort.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);

     

     

    private void ReceiveData(object sender, SerialDataReceivedEventArgs e)

    {

      if (CurrentDataMode == DataMode.Text)

      {

        if (ATMode == true)

        {

          Response = COMPort.ReadLine();

        }

        else

        {

          string Data_R = COMPort.ReadExisting();

          Message(TxtType.Incoming, Data_R);

        }

      }

      else

      {

        int Bytes = COMPort.BytesToRead;

        byte[] Buffer = new byte[Bytes];

        COMPort.Read(Buffer, 0, Bytes);

        Message(TxtType.Incoming, ByteArrayToHexString(Buffer) + "\r");

      }

    }

     

     

    He creado una funcion para entrar en el modo de comandos AT:

     

     

    private bool EnterATCommandMode()

    {

      bool EnterAT = false;

      DateTime TimeOut = DateTime.Now.AddSeconds(2);

      try

      {

        COMPort.Write("+++");

        ATMode = true;

        do

        {

          if (DateTime.Now > TimeOut)

          {

            ATMode = false;

            throw new Exception("AT Command timed out without receiving 'OK'.");

          }

        }

        while (!Response.Contains("OK"));

      }

      catch (Exception)

      {

        ATMode = false;

        MessageBox.Show(this, "AT Command timed out.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

      }

      if (Response.Contains("OK"))

      {

        EnterAT = true;

        TimeOutATMode = DateTime.Now.AddSeconds(9);

        Response = "";

      }

      return EnterAT;

    }

     

    Podrias decirme si lo que he heco estaria bien.

     

     

    El dispositivo que conecto al puerto serie, es un kit de desarrollo ZigBee.

    Si envias mensajes al dispositivo, este los envia a los dispositivos indicados en la configuracion.

    Para configurar las direcciones de envio debo entrar en el modo de comandos AT y comprobar que la configuracion es correcta.

     

     

    Salu2.

     

    sábado, 31 de marzo de 2007 8:22
  • Hola:

    Puedes descargar el manual en pdf sobre VB y  puerto serie.

    Saludo.

    http://electronica-pic.blogspot.com
    martes, 26 de mayo de 2009 8:36
  • Hola Pep. soy nuevo en C#, y debo programar los APN de unos modem GSM, hice esta prueba y no de da ningun error, pero la informacion enviada por comandos at, no queda, 

     

                _serialPort = new SerialPort();

                    _serialPort.PortName = "COM8";

                    _serialPort.BaudRate = 9600;

                    _serialPort.WriteTimeout = 500;

                   _serialPort.Open();

                    _serialPort.WriteLine("AT+CIPCSGP=1,\"wap.voicestream.com\"\r");

                       _serialPort.WriteLine("AT+CIPMODE=1\r");

                       _serialPort.WriteLine("AT+CIPCCFG=3,10,1024,1\r");

                        _serialPort.WriteLine("at+ciphead=0\r");

                        _serialPort.WriteLine("AT+CIPSCONT\r");

                        _serialPort.WriteLine("AT+CSMP=17,167,0,0\r");

                        _serialPort.WriteLine("AT+CSAS\r");

                    _serialPort.Close();

    Las funciones Recibir y Actualizar como se aplicarian para ver o esperar que el modem responda OK, como en Hypertrerminal

    Gracias

     


    fernnado
    miércoles, 07 de julio de 2010 21:25