Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   ComPort RxChar, Delphi vs Arduino (byte de lectura) (https://www.clubdelphi.com/foros/showthread.php?t=95323)

Franciscogc1988 06-08-2021 01:51:36

ComPort RxChar, Delphi vs Arduino (byte de lectura)
 
Buenas noches,
estoy programando un modulo MPU6050 para calcular los ángulos de giro en e pilotaje de una avión RC,

Ya tengo el código generado en Arduino y me devuelve correctamente en el monitor serie,
respecto a Delphi, estoy intentando leer los valores a través de las librerías comport y imprimir en un memo, el problema es que no recibo correctamente la cadena de texto, se come caracteres.

he estado indagando y debe tener alguna relacion con la velocidad de lectura de los bytes, al aumentar los BaudRate, parece que mejora, pero aun poniéndolos al máximo, sigue generando problemas.

he intentado también ponerle un sleep(70) después de la impresión en el memo, para darle tiempo a leer la cadena entera al buffer, pero sigue sin ser la solución definitiva., alguna sugerencia?

Codigo arduino:
Cita:

#include <I2Cdev.h>
#include <helper_3dmath.h>
#include <MPU6050.h>
#include <Wire.h>

const int mpuAddress = 0x68; // Puede ser 0x68 o 0x69
MPU6050 mpu(mpuAddress);
int ax, ay, az;
int gx, gy, gz;
void setup()
{
Serial.begin(9600);
Wire.begin();
mpu.initialize();
Serial.println(mpu.testConnection() ? F("IMU iniciado correctamente") : F("Error al iniciar IMU"));
}
void loop()
{
// Leer las aceleraciones
mpu.getAcceleration(&ax, &ay, &az);
//Calcular los angulos de inclinacion
float accel_ang_x = atan(ax / sqrt(pow(ay, 2) + pow(az, 2)))*(180.0 / 3.14);
float accel_ang_y = atan(ay / sqrt(pow(ax, 2) + pow(az, 2)))*(180.0 / 3.14);
//Mostrar resultados
Serial.print(("X:"));
Serial.print(accel_ang_x);
Serial.print(("/"));
Serial.print(("Y:"));
Serial.println(accel_ang_y);
delay(100);
}
ejemplo resultado monitor serie arduino:
X:32.60/Y:-6.03
X:32.75/Y:-6.18
X:32.63/Y:-6.15
X:32.81/Y:-5.93


Codigo Delphi:
Cita:

procedure TForm1.Button1Click(Sender: TObject);
begin
comport1.Port:='COM3';
comport1.BaudRate:=br9600;
try
comport1.Open;
if comport1.Connected then
begin
memo1.Text:=memo1.Text+'conexion serial establecida con exito('+comport1.Port+')';
memo1.Lines.Add('');
end
else
begin
memo1.Text:=memo1.Text+'ERROR en conexion serial';
end;
finally
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
comport1.Close;
memo1.Text:=memo1.Text+'conexion cerrada';
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
comport1.ShowSetupDialog;
end;

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
Str: String;
begin
// Recibe mensajes desde Arduino.
ComPort1.ReadStr(Str, comport1.InputCount);
sleep(70);
// Muestra los mensaj,es en pantalla.
MEMO1.Lines.Add( Str );
end;
ejemplo resultado memo Delphi:

X:32
.88/Y:-6.01

X:3
2.76/Y:-5.85

X
:32.80/Y:-6.14

X:32
.69/Y:-6.28

X:
32.89/Y:-5.91




Agradecido x la ayuda!

Neftali [Germán.Estévez] 06-08-2021 09:57:06

En estos casos siempre recomiendo realizar la lectura primero con el HyperTerminal de windows.
De esta manera descartas problemas con librerías y te permite realizar diferentes configuraciones del puerto (velocidad,...).

Una vez que con el HyperTerminal leas los valores de forma correcta, puedes pasar a Delphi.
Si buscas en los foros encontrarás hilos que hablan de cómo trabajar con HT y cómo configurarlo, si no lo has hecho nunca.

Franciscogc1988 06-08-2021 17:15:56

Cita:

Empezado por Neftali [Germán.Estévez] (Mensaje 542242)
En estos casos siempre recomiendo realizar la lectura primero con el HyperTerminal de windows.
De esta manera descartas problemas con librerías y te permite realizar diferentes configuraciones del puerto (velocidad,...).

Una vez que con el HyperTerminal leas los valores de forma correcta, puedes pasar a Delphi.
Si buscas en los foros encontrarás hilos que hablan de cómo trabajar con HT y cómo configurarlo, si no lo has hecho nunca.


Muchas Gracias por tu respuesta Neftali, he probado la lectura desde la HyperTerminal y lee y imprime correctamente los datos, igual que desde el terminal de arduino.
Definitivamente y por la forma de imprimir en el Memo de Delphi, deduzco que la lectura de delphi corre más rápida que el envío desde el comport, por eso imprime las string a trozos.

sinceramente me encuentro algo bloqueado, alguna sugerencia?

Neftali [Germán.Estévez] 09-08-2021 09:03:02

Una vez que sabes que desde HyperTerminal la lectura es correcta y por lo tanto tienes los parámetros de confiiguración, ahora puedes probar con la misma configuración dede Delphi, e incluso hacer la prueba con varios componentes, no sea que el que estás probando tenga algun bug.

Franciscogc1988 09-08-2021 19:34:35

Buenas, como me dijiste probé con la HyperTerminal y configure las mismas propiedades en delphi.
para comprobar que no fuera un defecto del componente he realizado una prueba simplemente haciendo un ping en bucle cada 1 seg a la arduino uno y a su vez escribiendo un texto en la terminal, en la hyperterminal funciona también correctamente, pero Delphi sigue comiéndose caracteres.

los parámetros que utilizo son:
*COM3
*9600 Bits x segundo
*8 bits de datos
*ninguna paridad
*1 bits de parada
*ningún control de flujo

crees que hay algún otro parámetro que no este teniendo en cuenta?
como explique en el primer post cuando aumento los bits x segundo (BaudRates), poniéndolos al valor máximo, parece que mejora, pero sigue sin leer del todo correctamente.

según parece, con la configuración que te he detallado, cuando el componente envía una string "hello world", Delphi imprime sin acabar de recibir la cadena completa y a su vez acumula el resto de caracteres en la memoria para la siguiente impresión, de esta forma imprime el texto así:

"hell
o wor
ld"

es decir, la función ComPort1RxChar se ejecuta nuevamente sin finalizar la lectura, alguna idea de como poder corregir este procedimiento?

también podría estar relacionado con el buffer, actualmente tengo 1024 inputsize y 1024 outputsize..

egostar 09-08-2021 21:57:09

Cita:

Empezado por Franciscogc1988 (Mensaje 542284)
....
es decir, la función ComPort1RxChar se ejecuta nuevamente sin finalizar la lectura, alguna idea de como poder corregir este procedimiento?

también podría estar relacionado con el buffer, actualmente tengo 1024 inputsize y 1024 outputsize..

Como en todo protocolo de comunicación, necesitas incluir el caracter de terminación de la cadena, en algunos protocolos requieren de un inicio de texto y termino de texto, aunque asumo que en tu caso es muy básico y debes leer hasta que te llegue el caracter "End of Text" o "Carrier Return" y no solo hasta finalizar una lectura ya que como te está pasando te gana el evento RxChar del comport.

Saludos

Franciscogc1988 10-08-2021 17:03:15

Buenas egostar, gracias x tu aporte.

Ante todo comentar que tambien realice una prueba con la terminal de la librería COM y he observado que las terminales concatenan la información de la lectura por lo que la solución para obtener un memo como terminal es tan sencilla como concatenar el mismo memo: memo.text:=memo.text+STR,

actualmente en el proyecto tengo hecho un Blink a un led, cada segundo enciende/apaga un led y envía la string LED ON / LED OFF, el objetivo es poder recoger la string exacta "LED ON" y trasladarla a un label

según tu aporte estuve indagando y la libreria de Comport tine unas propiedades llamadas EofChar y EventChar he estado haciendo varias pruebas pero no he conseguido integrarlos.
también probé con el componente ComDataPacket, dispone de dos propiedades llamadas StartString y Sopstring tambien sin éxito..

alguno podría guiarme sobre como establecer el final de la cadena?

egostar 11-08-2021 02:46:02

Cita:

Empezado por Franciscogc1988 (Mensaje 542295)
Buenas egostar, gracias x tu aporte....


Hola, intenta con esto:

Código Delphi [-]
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
  Str: String;
begin
  ComPort1.ReadStr(Str, Count);  
  Memo1.Text := Memo1.Text + Str;
end;

Saludos

Franciscogc1988 11-08-2021 18:33:22

La solución temporal que realizado ha sido agregar un condicional de escritura y gestionar la petición de los datos desde un timer en delphi,

de esta forma cuando delphi envia un "ok" al puerto COM arduino envia los angulos del giroscopio:

codigo arduino
Cita:

void loop(){

while (Serial.available() > 0){
caracter = Serial.read();
comando.concat(caracter);
delay(10);
}

// Si los carácteres es recibido y verdadero.
if (comando.equals("ok") == true) {
Serial.print (accel_ang_x);
Serial.print("/");
Serial.print(accel_ang_y);
}

// Limpiamos la cadena para volver a recibir el siguiente comando.
comando = "";
}
desde delphi, el timer envia un "ok" al puerto COM, y lee los datos con el RXChar para guardarlos en un Label, con Label1:=Label1+srt,

Codigo Delphi:
Cita:

procedure TForm1.Button1Click(Sender: TObject);
begin
comport1.Open;
if timer1.Enabled=false then
begin
timer1.Enabled:=true;
end
else
begin
timer1.Enabled:=false;
end;
end;

procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
var
Str: String;
begin
// Recibe mensajes desde Arduino.
ComPort1.ReadStr(Str, Count);
// Muestra los mensajes en pantalla.
label1.Text:=label1.Text+str;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
comport1.Port:='COM3';
comport1.BaudRate:=br115200;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
comport1.Close;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin

label1.text:='';
ComPort1.WriteStr('ok'); // Envía el comando "ok" al puerto.

end;

Gracias a todos x los consejos


La franja horaria es GMT +2. Ahora son las 02:32:49.

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