¿Qué es este blog?

La idea de este blog nace para compartir los avances que se vayan realizando a lo largo de un estudio sobre cómo interconectar los distintos sensores que se pueden encontrar en el mercado, o fabricar de forma casera, con la plataforma Mindstorms de LEGO. Para ello se hará uso ARDUINO, un entorno de desarrollo abierto basado en microcontrolador.

lunes, 10 de enero de 2011

Manejo del protocolo I2C con el lenguaje PbLua


Las cuatro funciones básicas que se encuentran en la API de pbLua son las siguientes [25]:
  • nxt.I2CInitPins()
  • nxt.I2CGetStatus()
  • nxt.I2CSendData()
  • nxt.I2CRecvData()
Configurando el puerto I2C
            Lo primero que se necesita conocer es el puerto al que está conectado el sensor. Como ya vimos, los puertos están numerados del 1 al 4 y será un valor que se use en todas las llamadas que usemos.  Un posible código para preparar el puerto para la comunicación sería el siguiente:
-- Initialize port 4 for I2C communication    
nxt.I2CInitPins(4)  
-- Use a variable to hold the port number    
port = 4    nxt.I2CInitPins(port) 

Envío y recepción de datos
            Como vimos, la comunicación va a tener dos partes: una primera en la que se envía un dato al dispositivo, y una segunda en la que éste puede contestar al maestro, La función nxt.I2CSendData() se encarga de manejar esta comunicación. En el siguiente ejemplo de código se puede ver cómo se configura un puerto para usar el protocolo I2C y cómo a continuación establece las tres cadenas de texto necesarias para obtener la información básica del dispositivo:

-- setupI2C() - sets up the specified port to handle an I2C sensor  
function setupI2C(port)   
nxt.InputSetType(port,2)   
nxt.InputSetDir(port,1,1)   
nxt.InputSetState(port,1,1)    
nxt.I2CInitPins(port) end  
-- Now put the standard I2C messages into the nxt table 
nxt.I2Cversion    = string.char( 0x02, 0x00 ) 
nxt.I2Cproduct    = string.char( 0x02, 0x08 ) 
nxt.I2Ctype       = string.char( 0x02, 0x10 ) 
nxt.I2Ccontinuous = string.char( 0x02, 0x41, 0x02 ) 
nxt.I2Cdata       = string.char( 0x02, 0x42 ) 

La función string.char() forma parte de la librería básica de cadenas de Lua, y su función es la de ensamblar cadenas a partir de bytes individuales.
El envío de cadenas I2C al sensor se puede realizar de esta forma:

-- Use the ultrasound sensor in port 4, make sure the 
-- previous sample has been loaded  setupI2C(4)  
-- Now send the product string, up to 8 bytes can be sent by the sensor  
nxt.I2CSendData( 4, nxt.I2Cproduct, 8 ) 


Y la lectura es igualmente sencilla:

-- Reading the data is simple. Make sure the previous example has been 
-- loaded. The = notation is a short form for "print"  
=nxt.I2CRecvData(4) 

Comprobar el estado I2C

Envíar y recibir datos en este lenguaje es sencillo, pero para que todo funcione correctamente debemos, como siempre, tener en cuenta los tiempos y velar porque todo se haya producido correctamente.
La función I2CGetStatus() nos ayuda a conocer cuál es el estado del puerto I2C. Devuelve tres valores: el estado global del puerto I2C, el segundo es la fase en la que se encuentra la transmisión, y el tercero es el estado en el que se encuentra la recepción. Cuando una transacción I2C se ha completado (o ha agotado su tiempo) el primer valor devuelto por esta función debe ser cero, así que la función que hace que se espere a que la transacción se complete es la siguiente:

-- waitI2C() - sits in a tight loop until the I2C system goes idle 
function waitI2C( port )   
     while( 0 ~= nxt.I2CGetStatus( port ) ) do   
     end 
end 

-- Put it all together in a function that prints out a report of which 
-- sensor is connected to a port  
function checkI2C(port)   
     setupI2C(port)    
     nxt.I2CSendData( port, nxt.I2Cversion, 8 )   
     waitI2C( port )   
     print( "Version    -> " .. nxt.I2CRecvData( port, 8 ) )    
 
     nxt.I2CSendData( port, nxt.I2Cproduct, 8 )   
     waitI2C( port )   
     print( "Product ID -> " .. nxt.I2CRecvData( port, 8 ) )    
 
     nxt.I2CSendData( port, nxt.I2Ctype, 8 )   
     waitI2C( port )   
     print( "SensorType -> " .. nxt.I2CRecvData( port, 8 ) ) 
end  
-- And now run the function to see if it recognizes the sensor checkI2C(4)  
-- Results are below, do not paste the following text to the console! 
Version    -> V1.0 
Product ID -> LEGO 
SensorType -> Sonar 


Lectura de datos de forma continua
Para concluir esta explicación de cómo acceder al puerto I2C usando Lua, vamos a ver un ejemplo de cómo leer un dato del puerto I2C de manera continua mientras se mantenga pulsado el botón naranja del NXT. El código es el siguiente:
function I2CRead(port)
     -- Set up the port and report on the sensor type
     checkI2C(port)
     -- Put it into continuous sample mode
     nxt.I2CSendData( port, nxt.I2Ccontinuous, 0 
     waitI2C( port )    
     -- Read and print the results until the orange button is pressed
     repeat
     -- Read 8 bytes of data from the sensor
          nxt.I2CSendData( port, nxt.I2Cdata, 8 )
          waitI2C( port )
          s = nxt.I2CRecvData( port, 8 )
     -- Break the resulting string into 8 bytes and print the results
          c1,c2,c3,c4,c5,c6,c7,c8 = string.byte(s,1,8)
          print( string.format( "Result: %3i %3i %3i %3i %3i %3i %3i %3i",                                
                                             c1, c2, c3, c4, c5, c6, c7, c8 ) )
     until( 8 == nxt.ButtonRead() )
end 
-- And using the function - press the orange button on the NXT to stop it
I2CRead(4)

----------------------------------------------------------------------------------------------------------------------------
Referencias: 
 

No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.