Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 25-02-2008
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Comunicaciones RS232 - Tratamiento de la información.

Hola:

Empelando el componente Async Professional (Apro) trato de obtener los datos que proporciona una la estación meteorológica WST 7000C.

La estructura del mensaje transmitido por la estación la detallo al final del post.

He pensado emplear el componente ApdDataPacket para leer como un paquete completo, creo haberlo configurado correctamente y en su evento OnPacket pretendo leer el contenido.

En este evento se recibe como argumentos:
Data: pointer
Size: integer

Mi problema está como no puede ser de otra forma en mis escasos conocimientos. Mi pregunta es ¿cómo obtengo de Data cada uno de los bytes que componen el mensaje y los transformo en el su valor adecuado?


Código Delphi [-]
Byte nº 1
El primer byte transmitido indica que la sonda está empezando a enviar un nuevo mensaje.
El valor de este byte es fijo en el 85 decimal.

Byte nº 2
Informa sobre la "longitud del mensaje" que falta por recibir, su valor depende del tipo de sonda que envía el mensaje.
El valor en mi caso es 18 decimal.

Byte nº 3
Este es el byte del sistema automático interno de control de validación de datos.
El valor de cada bit del byte depende de la validez de la medición de cada uno delos parámetros meteorológicos.
El valor lógico "1" indica que la medición es válida.
El valor lógico "0" indica que la medición no es válida.
Para una función no puesta en marcha, el bit que representa se coloca al valor lógico "1".

Tabla de autotest

Bit número  Función Observada 
O LSB           Velocicidad del viento
1    Dirección del viento
2    Temperatura del aire
3    Presión barométrica
4     Humedad relativa
5    Punto de rocio
6    Ninguna - Puesto a 1
7 MSB    Ángulo medido por la brújula.
    
  
Bytes nº 4 a xx “Valores de los parámetros meteorológicos”
Cada parámetro meteorológico se transmite con un formato de 2 bytes.
12 bits se utilizan para representar los números enteros y 4 bits para las fracciones del número entero. La estructura de los bytes se representa a continuación.
El primer byte transmitido representa 8 de los 12 bits usados para representar el entero.
El segundo byte transmitido utiliza los primeros 4 bits para representar el resto de los enteros y los cuatro últimos bits para representar las fracciones.
El bit menos significativo (LSB) tiene un valor de 1/16º de la unidad de tamaño medida.
Los números negativos se expresan usando el valor 2.


              High byte                              Low byte
     ----------------------------------------- --------------------------- 
MSB> 15 | 14 | 14 | 13 | 12 | 11 | 10 | 9 | 8 || 7 | 6 | 5 | 4 | 3 | 2 | 1  < LSB


Cálculo del valor de dos bytes = ((Byte alto * 256) + (Byte bajo))/16

Una velocidad del viento de  22,75 m /s   se codifica 016C Hex
Una dirección del viento de   22,00 grados   se codifica 0160 Hex
Una temperatura de     -22,75 °C   se codifica FE94 Hex
Una presión de       1013 hPa   se codifica 3F50 Hex



Bytes nº 16 & 17
Tipo de sonda  Función medida     Metodología de decodificación
WST 7000 C   Ángulo entre el norte   Según el párrafo 4.3.4
    y el acimut 0°

Bytes Nº 18 y 19 Entrada analógica externa
Los bytes 18 y 19 se usan para transmitir la representación en 12 bits de una tensión analógica en el rango de 0 a +10 VCC.
El byte 18 transmite los 4 bits más significativos. El byte 19 transmite los 8 bits menos significativos.
La resolución es 10 V / 212 es decir, 2,4414 mV.

Último byte del mensaje, control de validez de los datos
El último byte transmitido es el de la "Checksum". Su valor se calcula tomando el "OR Exclusivo" de todos los bytes de mensaje transmitidos, excepto el último.
El mensaje recibido es válido si esta "Checksum" es idéntica al último byte transmitido.


Guía completa: http://juanpedro.l.googlepages.com/Manual.pdf


Muchas gracias de antemano
Un saludo
Juan P.
__________________
Sonríe. Mañana puede ser peor.

Última edición por jplj fecha: 25-02-2008 a las 23:51:44.
Responder Con Cita
  #2  
Antiguo 25-02-2008
[egostar] egostar is offline
Registrado
 
Registrado: feb 2006
Posts: 6.557
Poder: 25
egostar Va camino a la fama
Por lo que comentas los paquetes de datos me parece que estan representados de esta forma:

Cita:
<STX> DATOS <ETX> <BCC>
Si las cadenas tienen una longitud fija, no deberias de tener problemas para obtener la información al indicar el número de caracteres esperados y usando el evento OnPacket.

El CheckSum <BCC> es un simple XOR (OR exclusivo) desde el primer caracter <STX> hasta el caracter anterior al <ETX>.

Si pudieras mostrar una cadena ejemplo podriamos ayudarte con mas certeza.

Salud OS.

PD, el link que pones no se puede acceder.
__________________
"La forma de empezar es dejar de hablar y empezar a hacerlo." - Walt Disney
Responder Con Cita
  #3  
Antiguo 25-02-2008
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Ahora no puedo poner los datos porque no tengo el equipo conmigo, mañana pondré lo que me sale, y también el código que empleo.

El link está dirigido a un pdf y efectivamente no funciona, no sé. Si copias y pegas la dirección en el navegador sí accedes al pdf.
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #4  
Antiguo 26-02-2008
Avatar de Crandel
[Crandel] Crandel is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Parana, Argentina
Posts: 1.475
Poder: 23
Crandel Va por buen camino
Por lo que entiendo tenes tu evento OnPacket donde recibis los datos, ahi copias el contenido a un buffer interno o lo procesas directamente (preferible lo primero)

Código Delphi [-]
procedure CargarDatos(Data : PByte)
var 
....
begin
  // tengo datos nuevos
  if (Data[0] <> 85) then Exit; 
  // verifico que sean los datos de compatible al modelo que tengo
  if (Data[1] <> 18) then Exit;
  // Verifico que los datos sean validos
  if (Data[2] <> 1) then Exit;
  // Vel veinto
  FVelViento = WordToFloat(Data[3] * 16 + Data[4]);
 ....
end;

esto es una idea de lo que tenes que hacer.

falta definir tambien tu funcion WordToFloat que es la que te transforma tu formato de dato.

Espero que te ayudea empezar
__________________
[Crandel]
Responder Con Cita
  #5  
Antiguo 26-02-2008
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Hola:

En la línea que indica Crandel he hecho el procedimiento que listo más abajo. La salida del procedimiento también la listo a continuación.

He hecho algunas modificaciones:

En :
Código Delphi [-]
if (Data[0] <> 85) then Exit;

Se producía un error al compilar
Cita:
Array type required
De ahí :

Código Delphi [-]
var
   datos: PChar;
....
begin
....
   datos:= Data;

También modifiqué la formula para obtener los datos.

Código Delphi [-]
  // La que propone Crandel:
  FVelViento = WordToFloat(Data[3] * 16 + Data[4]);

  // La que he hecho:
   FVelViento:= ((Ord(datos[ 3])*256) + Ord(datos[ 4]))/16;

Creo que los datos que obtengo son correctos, tengo que contrastarlos con los de otra estación meteorológica para verlo.
Agradecería que me dijerais si encontráis algún error.

Si todo fuera correcto, me quedan dos preguntas:

1.- Determinar el resultado de la autoverificación:
A la luz de los resultado que obtengo para el 2 byte, cualquier valor diferente a 255 indicaría un error. Pero quería saber cómo puedo determinar cuál es en base a la tabla de auto-test.

2.- Control de validación "Checksum".
¿Cómo implemento en pascal la verificación del paquete?


Código Delphi [-]

procedure TForm1.ApdDataPacket1Packet(Sender: TObject; Data: Pointer;
  Size: Integer);
var
   datos: PChar;
   s: string;
   FVelViento: Double;
   FDirViento: Double;
   FTempAire : Double;
   FPresion  : Double;
   FHumRelat : Double;
   FPuntRocio: Double;
   FAzi_Nort : Double;

begin

   datos:= Data;
  if (datos[0] <> #85) then Exit else s:= 'Inicio ';
  // verifico que sean los datos de compatible al modelo que tengo
  if (datos[1] <> #18) then Exit else s:= s + ' WST ';

  // Verifico que los datos sean validos
  s:= s + #13#10 + 'byte nº  2: ' +IntToStr(Ord(datos[2]));

  s:= s + #13#10 + 'byte nº  3: ' +IntToStr(Ord(datos[3]));
  s:= s + #13#10 + 'byte nº  4: ' +IntToStr(Ord(datos[4]));
  s:= s + #13#10 + 'byte nº  5: ' +IntToStr(Ord(datos[5]));
  s:= s + #13#10 + 'byte nº  6: ' +IntToStr(Ord(datos[6]));
  s:= s + #13#10 + 'byte nº  7: ' +IntToStr(Ord(datos[7]));
  s:= s + #13#10 + 'byte nº  8: ' +IntToStr(Ord(datos[8]));
  s:= s + #13#10 + 'byte nº  9: ' +IntToStr(Ord(datos[9]));
  s:= s + #13#10 + 'byte nº 10: ' +IntToStr(Ord(datos[10]));
  s:= s + #13#10 + 'byte nº 11: ' +IntToStr(Ord(datos[11]));
  s:= s + #13#10 + 'byte nº 12: ' +IntToStr(Ord(datos[12]));
  s:= s + #13#10 + 'byte nº 13: ' +IntToStr(Ord(datos[13]));
  s:= s + #13#10 + 'byte nº 14: ' +IntToStr(Ord(datos[14]));
  s:= s + #13#10 + 'byte nº 15: ' +IntToStr(Ord(datos[15]));
  s:= s + #13#10 + 'byte nº 16: ' +IntToStr(Ord(datos[16]));
  s:= s + #13#10 + 'byte nº 17: ' +IntToStr(Ord(datos[17]));
  s:= s + #13#10 + 'byte nº 18: ' +IntToStr(Ord(datos[18]));
  s:= s + #13#10 + 'byte nº 19: ' +IntToStr(Ord(datos[19]));
  s:= s + #13#10 + 'byte nº 20: ' +IntToStr(Ord(datos[20]));

//  FVelViento:= (Ord(datos[3]) * 16 + Ord(datos[4]));

   FVelViento:= ((Ord(datos[ 3])*256) + Ord(datos[ 4]))/16;
   FDirViento:= ((Ord(datos[ 5])*256) + Ord(datos[ 6]))/16;
   FTempAire := ((Ord(datos[ 7])*256) + Ord(datos[ 8]))/16;
   FPresion  := ((Ord(datos[ 9])*256) + Ord(datos[10]))/16;
   FHumRelat := ((Ord(datos[11])*256) + Ord(datos[12]))/16;
   FPuntRocio:= ((Ord(datos[13])*256) + Ord(datos[14]))/16;
   FAzi_Nort := ((Ord(datos[15])*256) + Ord(datos[16]))/16;

{  if (Ord(datos[2]) <> 1) then Exit else s:= s + IntToStr(Ord(datos[2]));;
  // Vel veinto
  FVelViento = WordToFloat(Data[3] * 16 + Data[4]);
 ....}

   Memo1.Lines.Add('Paquete: '+s);
   Memo1.Lines.Add('Velocidad Viento   : '+ FloatToStr(FVelViento));
   Memo1.Lines.Add('Dirección Viento   : '+ FloatToStr(FDirViento));
   Memo1.Lines.Add('Temperatura        : '+ FloatToStr(FTempAire));
   Memo1.Lines.Add('Presión            : '+ FloatToStr(FPresion));
   Memo1.Lines.Add('Humedad relativa   : '+ FloatToStr(FHumRelat));
   Memo1.Lines.Add('Punto Rocio        : '+ FloatToStr(FPuntRocio));
   Memo1.Lines.Add('Angulo Azimut-Norte: '+ FloatToStr(FAzi_Nort));


   Memo1.Lines.Add('-------------------------------------------------');

end;


Cita:
Salida del procedimiento:
Paquete: Inicio WST
byte nº 2: 255
byte nº 3: 0
byte nº 4: 3
byte nº 5: 19
byte nº 6: 95
byte nº 7: 1
byte nº 8: 132
byte nº 9: 62
byte nº 10: 94
byte nº 11: 3
byte nº 12: 51
byte nº 13: 0
byte nº 14: 215
byte nº 15: 9
byte nº 16: 97
byte nº 17: 0
byte nº 18: 66
byte nº 19: 223
byte nº 20: 1
Velocidad Viento : 0,1875
Dirección Viento : 309,9375
Temperatura : 24,25
Presión : 997,875
Humedad relativa : 51,1875
Punto Rocio : 13,4375
Angulo Azimut-Norte: 150,0625
-------------------------------------------------
Nuevamente muchas gracias por el tiempo que me dedicáis.
Un Saludo
Juan Pedro.
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #6  
Antiguo 26-02-2008
Avatar de Crandel
[Crandel] Crandel is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Parana, Argentina
Posts: 1.475
Poder: 23
Crandel Va por buen camino
parece que vas avanzado bien

Cita:
Empezado por jplj Ver Mensaje
También modifiqué la formula para obtener los datos.

Código Delphi [-]
  // La que propone Crandel:
  FVelViento = WordToFloat(Data[3] * 16 + Data[4]);

  // La que he hecho:
   FVelViento:= ((Ord(datos[ 3])*256) + Ord(datos[ 4]))/16;
perdon por explicarte bien la funsión WordToFloat o como la quieras llamar. lo que pasa es que la parte enterea solo tiene 4 bits en la parte baja, por eso el producto x 16 y no 256. Aun asi tambien esta mal lo que escribi.

La conversion correcta seria:

Código Delphi [-]
function WordToFloat(byteAlto, byteBajo: byte): double;
var
  val: double;
begin
  val := byteAlto * 16 + byteBajo div 16;
  val := val + (byteBajo and $0F) / 10000;
  Result := val;
end;

Cita:
Empezado por jplj Ver Mensaje
1.- Determinar el resultado de la autoverificación:
A la luz de los resultado que obtengo para el 2 byte, cualquier valor diferente a 255 indicaría un error. Pero quería saber cómo puedo determinar cuál es en base a la tabla de auto-test.
para saber cual es el error debes fijarte en el bit correspondiente a cada uno, por ejemplo:

Código Delphi [-]
  if (datos[2] and $01) <> 0 then 
   //  vel del viento correcta

Cita:
Empezado por jplj Ver Mensaje
2.- Control de validación "Checksum".
¿Cómo implemento en pascal la verificación del paquete?
debes hacer un ciclo for para todos datos de tu paquete haciendo xor entre ellos y comparar el resultado con el byte del checksum
__________________
[Crandel]
Responder Con Cita
  #7  
Antiguo 28-02-2008
jplj jplj is offline
Miembro
 
Registrado: oct 2003
Posts: 189
Poder: 21
jplj Va por buen camino
Thumbs up

Hola:

Ya he resuelto los problemas, pero surgen otros:

En relación a la verificación del autotest, la sentencia que propones:
Código Delphi [-]
if (datos[2] and $01) <> 0 then
genera un error al compilar:
Cita:
Operator not applicable to this operand type
Finalmente lo he resuelto de la siguiente forma:
Código Delphi [-]

FAutoTest: Array[0..7] of integer;

...

   procedure AutoTest(valor:integer);
   var
      i:integer;
   begin
      i:= 0;
      while i < 8 do
      begin
         if ((1 shl i) and valor) > 0 then
            FAutoTest[i]:= 1
         else
            FAutoTest[i]:= 0;
         inc(i);
      end;
    end;

var

    ....

begin
    ...
     // 3.- Verificación del autotest.
   if (Ord(datos[2])) <> 255 then
   begin
      AutoTest((Ord(datos[2])));
      Exit;
   end;

Luego se puede comprobar los valores de FAutoTest.

El problema que tengo ahora es con los valores negativos de las magnitudes, en concreto con la temperatura:
Cita:
Bytes nº 4 a xx “Valores de los parámetros meteorológicos”
Cada parámetro meteorológico se transmite con un formato de 2 bytes.
12 bits se utilizan para representar los números enteros y 4 bits para las fracciones del número entero. La estructura de los bytes se representa a continuación.
El primer byte transmitido representa 8 de los 12 bits usados para representar el entero.
El segundo byte transmitido utiliza los primeros 4 bits para representar el resto de los enteros y los cuatro últimos bits para representar las fracciones.
El bit menos significativo (LSB) tiene un valor de 1/16º de la unidad de tamaño medida.

Los números negativos se expresan usando el valor 2.


High byte Low byte
----------------------------------------- ---------------------------
MSB> 15 | 14 | 14 | 13 | 12 | 11 | 10 | 9 | 8 || 7 | 6 | 5 | 4 | 3 | 2 | 1 < LSB


Cálculo del valor de dos bytes = ((Byte alto * 256) + (Byte bajo))/16

Una velocidad del viento de 22,75 m /s se codifica 016C Hex
Una dirección del viento de 22,00 grados se codifica 0160 Hex
Una temperatura de -22,75 °C se codifica FE94 Hex
Una presión de 1013 hPa se codifica 3F50 Hex
¿Qué significa "Los números negativos se expresan usando el valor 2"?



Nuevamente muchas gracias por el tiempo que me dedicáis.
Un Saludo
Juan Pedro.
__________________
Sonríe. Mañana puede ser peor.
Responder Con Cita
  #8  
Antiguo 28-02-2008
Avatar de Crandel
[Crandel] Crandel is offline
Miembro Premium
 
Registrado: may 2003
Ubicación: Parana, Argentina
Posts: 1.475
Poder: 23
Crandel Va por buen camino
Perdon por pasarte los codigos sin verificar. Es que no tengo Delphi en el trabajo.

Por un lado la comprobacion seria:

Código Delphi [-]
if (Ord(datos[2]) and $01) <> 0 then}

y la funcion de conversion correcta es:

Código Delphi [-]
function WordToFloat(byteAlto, byteBajo: byte): double;
var
  val: Smallint;
begin
  val := (byteAlto * 256 + byteBajo);
  Result := val  / 16;
end;
__________________
[Crandel]
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Servidor Web + Comunicaciones phrodo Internet 10 07-07-2007 12:29:40
Mandar datos RS232 CARSOFT_AR Varios 3 14-07-2006 23:01:25
Comunicaciones electronicas EDI Toni Conexión con bases de datos 0 18-04-2006 13:06:34
Comunicacion RS232 y LPT Cronos Varios 0 06-02-2005 08:10:16
Conexion Serial RS232 Pavlov Varios 2 06-10-2003 17:47:37


La franja horaria es GMT +2. Ahora son las 22:21:28.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi