Logic Machine Forum
RS232 read problem - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: RS232 read problem (/showthread.php?tid=2655)



RS232 read problem - JRP - 26.05.2020

Hello

I have written the following script to control the power off of an LG TV using the RS232 serial port.

The scrip works perfectly and the TV turns on, the command changes the value to turn it off and on, to write without problem. I have a log of the message that is sent and it is correct.


Code:
-- Se obtiene el valor del objeto de escenas y se guarda en la variable value
value = event.getvalue()

-- si el valor de la variable value es igual a 3 (número de escena), entonces enviamos el comando de encendido
if (value == 3) then
 
  -- Es necesario incluir la librería de las funciones de comunicación serie
    if not port then
    require('serial')
    -- Configuración y apertura del puerto serie
    port = serial.open('/dev/RS232', {
  baudrate = 9600,
  databits = 8,
  stopbits = 1,
  parity = 'none',
  duplex = 'full'
    })
    --  Limpiar bytes no leídos o enviados
    port:flush() 
    -- Escribir datos en el puerto serie para encender la TV
    msg = string.char(0x6B, 0x61, 0x20, 0x30, 0x31, 0x20, 0x30, 0x31, 0x0D)
    port:write(msg)
    log (msg) -- Esta línea permite ver el comando en el registro para comprobar que se está enviando
   port:flush()
    res = port:read(10)
    log (res) -- Esta línea permite ver el comando en el registro para comprobar que se está recibiendo
   port:flush()
    port:close()
    end
end


Now what I want is to manage the confirmation of messages, according to the TV manual, the response has the following format:
[Comando 2][Espacio][Set ID][OK][Dato][x] --- for correct reception.
[b][Comando 2][Espacio][Set ID][NG][Dato][x] --- for incorrect reception.[/b]


This is when the problems come, I read 10 bytes from the port, the question is that the answers obtained in the log appear bytes from previous answers, so I don't know how to discriminate them.

This is the result of the log, after sending several commands to turn on in a row.

RS232 26.05.2020 13:30:03
* string: ka 01 01


RS232 26.05.2020 13:30:03
* string: 01 NGxa 01


RS232 26.05.2020 13:30:35
* string: ka 01 01


RS232 26.05.2020 13:30:35
* string:  OK01xa 01




I have tried the flush function before and after reading but nothing.

Or do I have to reset the variable "res" before reading the port?
Any ideas?


Thank you.


RE: RS232 reed problem - admin - 26.05.2020

Since you have a log call between write and flush you basically have adding a random delay. Flush will discard all buffered data but the TV might not have sent the response completely.

You should remove flush after write and use read with timeout. Something like this:
Code:
res, err = port:read(100, 1)
log(res, err)



RE: RS232 reed problem - JRP - 01.06.2020

(26.05.2020, 11:57)admin Wrote: Since you have a log call between write and flush you basically have adding a random delay. Flush will discard all buffered data but the TV might not have sent the response completely.

You should remove flush after write and use read with timeout. Something like this:
Code:
res, err = port:read(100, 1)
log(res, err)
Hello
I have already successfully communicated with the TV and it responds perfectly to commands.
I have removed the logs and adjusted the number of bytes read and the timeout.
I have added a delay after the power on command, as the TV takes time to power on and then a command to select HDMI 1 input.
I have also added the control of the correct answer I have incorrect, repeated in both commands. Would there be a way to put it only once and it would work for both commands? In the style of an external function or an internal jump and that returns the value, and thus not repeat it for each command.
Thank you very much Admin for your help.
a greeting
Code:
value = event.getvalue() -- Se obtiene el valor del objeto de escenas y se guarda en la variable value
if (value == 3) then -- Si el valor de la variable value es igual a 3 (número de escena), entonces enviamos el comando de encendido
  if not port then   -- Si el puerto no está ya abierto entonces se abre y configura
    require('serial') --Es necesario incluir la librería de las funciones de comunicación serie
    port = serial.open('/dev/RS232', { -- Configuración y apertura del puerto serie
          baudrate = 9600,
          databits = 8,
             stopbits = 1,
          parity = 'none',
          duplex = 'full'
            })
    port:flush() --  Limpiar bytes no leídos o enviados
    TV_ON = string.char(0x6B, 0x61, 0x20, 0x30, 0x31, 0x20, 0x30, 0x31, 0x0D) -- Escribir comando encender TV en la variable "TV_ON"
    port:write(TV_ON) -- Escribir contenido variable "TV_ON" el puerto serie para encender la TV
   end
  ack = port:read(10,2) --Leer la confirmación
    if ack == 'a 01 OK01x' -- Si la respuesta de la TV es OK, entonces
    then alert('TV encendida') -- Activar objeto estado TV encendida
     elseif ack == 'a 01 NGx'
    then alert('TV error comunicación')
    end
  sleep(5) -- Esperamos a que la TV se encienda.
  hdmi1 = string.char(0x78, 0x62, 0x20, 0x30, 0x31, 0x20, 0x39, 0x30, 0x0D) -- Escribir comando cambio entrada HDMI 1
  port:write(hdmi1) -- Escribir contenido variable en el puerto serie para cambio entrada HDMI 1
  ack = port:read(10,2) --Leer la confirmación
    if ack == 'a 01 OK01x' -- Si la respuesta de la TV es OK, entonces
    then alert('HDMI 1 Seleccionado') -- Activar objeto estado TV encendida
     elseif ack == 'a 01 NGx'
    then alert('TV error comunicación')
    end
  port:close() -- Se cierra el puerto serie.   
end