# Control del Puerto Serie con Python GNU/Linux



## sangreaztk (Dic 17, 2008)

Como una continuación del https://www.forosdeelectronica.com/f26/control-puerto-paralelo-python-gnu-linux-17617/ que realice como una contribución a un programa de munguis, ahora presento el manejo del puerto Serie con Python. Para este además del código de Python vamos a necesitar un hardware, que sera a partir de un microcontrolador, el PIC16F876, los parámetros importantes son que el PORTB será de salida y el cristal a usar será de 4MHz para una comunicación a 9600 Bauds, no se olviden de usar un max232 para la comunicación. El código asm para ensamblar y programar al PIc es el siguiente:


```
;       readf.asm
;
;       CopyLeft 2008 Aztk
;
;       This program is free software; you can redistribute it and/or modify
;       it under the terms of the GNU General Public License as published by
;       the Free Software Foundation; either version 2 of the License, or
;       (at your option) any later version.
;
;       This program is distributed in the hope that it will be useful,
;       but WITHOUT ANY WARRANTY; without even the implied warranty of
;       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;       GNU General Public License for more details.
;
;       You should have received a copy of the GNU General Public License
;       along with this program; if not, write to the Free Software
;       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
;       MA 02110-1301, USA.
; -----------------------------------------------------------------------
;  Este programa configura al PIC para leer 1 byte enviado del PC a
;   una velocidad de 9600 bauds con un cristal de 4MHz.
;   El dato se imprimirá en el PORTB.

    processor	16f877
; -----------------------------------------------------------------------
; Template source file generated by piklab
    #include 

; -----------------------------------------------------------------------
; Bits de configuración:
    __CONFIG	0x3F71

; -----------------------------------------------------------------------
; inicio

	        org	        0x00		        ; Respetamos vector de
	        goto	start		                ; interrupción
	        org	        0x05
start:	bsf	        STATUS,RP0	; Bank01
	        clrf	        TRISB		        ; PORTB = 'ssss ssss
	        movlw	.25		                ; Fosc = 4MHz
	        movwf	SPBRG		        ; BaudRate = 9600
	        bsf	        TXSTA,BRGH	; High-Speed
	        bcf	        TXSTA,SYNC	; Modo asíncrono
	        bcf	        STATUS,RP0	; Bank00
	        bsf	        RCSTA,SPEN
	        bsf	        RCSTA,CREN	; Habilitar recepción
	        clrf	        PORTB		        ; Limpiar primero el PORTB
readf:
wait:	btfss	PIR1,RCIF	        ; ¿Dato recibido?
	        goto	wait		                ; No, esperar
	        movf	RCREG,W		; Si, cargar dato a W
	        movwf	PORTB		        ; imprimir dato de W al PORTB
	        goto	readf		        ; Regresar para esperar
				                                ; otro dato
end
```

Ahora para el programa en Python, es prácticamente el mismo que utilice con el Control del Puerto Paralelo con Python, a excepción de que no utilizo el modulo parport sino es el PySerial, ventajas de usar este puerto es que para mi se me hace más fácil que el puerto paralelo, se pueden usar todos los pines del micro y definir cuantos serán de entrada y cuantos de salida (aunque en este ejemplo solo hemos definido 8 bits de salida) además de que NO! son necesarios permisos del superUser.
Los requisitos para este programa es que se tengan instalado Python, las librerías del escritorio GTK+, las librerías PyGTK y el modulo Pyserial (pueden buscarlas en Synaptic). Les recuerdo que Python también puede funcionar en 'Ventanas' (Windows) para eso dirijanse a la pagina del proyecto para descargar Python y las librerías, aunque como no lo he probado en dicha plataforma la neta que no sé si funcione correctamente, este programa fue probado en Ubuntu 8.04.


```
#!/usr/bin/env python
#
#       serieAztk.py
#       
#       CopyLeft 2008 aztk
#       
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#       
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#       
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

# 'pySerial'('serial') is a module that encapsulates the access
#   for the serial port, to know how install it visit:
#      [url]http://pyserial.wiki.sourceforge.net/pySerial[/url]
import serial

import pygtk
pygtk.require('2.0')
import gtk

s = serial.Serial(0)	# Open port '/dev/tty0', BaudRate 9600
pdatax = 0

class SerialX:
	
	# This callback write a data in serial port
	def writex(self, widget, data=None):
		global pdatax
		
		# When a button is hold on
		if (widget.get_active()):
			pdatax = pdatax + data
			print "data = %s" %(pdatax)
			s.write(chr(pdatax))
		
		# When a button is hold off
		else:
			pdatax = pdatax - data
			print "data = %s" %(pdatax)
			s.write(chr(pdatax))
	
	# This callback quits the program
	def delete_event(self, widget, event, data=None):
		s.write('\x00')	# Clear the seril port
		s.close()		# Close the seril port
		return gtk.FALSE
	
	def destroy(self, widget, data=None):
		s.write('\x00')
		s.close()
		print "data = 0"
		print "Good Wave! :)"
		gtk.main_quit()
	
	def __init__(self):
		
		# Create a new window
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_title("SerialX")
		self.window.connect("delete_event", self.delete_event)
		self.window.set_border_width(20)
		self.window.set_resizable(gtk.FALSE)
		
		# Create a vertical box
		vbox = gtk.VBox(gtk.TRUE, 2)
		self.window.add(vbox)
		
				# Create the data buttons (D0:D7)
		# D0
		d0 = gtk.ToggleButton("D0")
		d0.connect("toggled", self.writex, 0x01)
		vbox.pack_start(d0, gtk.TRUE, gtk.TRUE, 2)
		# D1
		d1 = gtk.ToggleButton("D1")
		d1.connect("toggled", self.writex, 0x02)
		vbox.pack_start(d1, gtk.TRUE, gtk.TRUE, 2)
		# D2
		d2 = gtk.ToggleButton("D2")
		d2.connect("toggled", self.writex, 0x04)
		vbox.pack_start(d2, gtk.TRUE, gtk.TRUE, 2)
		# D3
		d3 = gtk.ToggleButton("D3")
		d3.connect("toggled", self.writex, 0x08)
		vbox.pack_start(d3, gtk.TRUE, gtk.TRUE, 2)
		# D4
		d4 = gtk.ToggleButton("D4")
		d4.connect("toggled", self.writex, 0x10)
		vbox.pack_start(d4, gtk.TRUE, gtk.TRUE, 2)
		# D5
		d5 = gtk.ToggleButton("D5")
		d5.connect("toggled", self.writex, 0x20)
		vbox.pack_start(d5, gtk.TRUE, gtk.TRUE, 2)
		# D6
		d6 = gtk.ToggleButton("D6")
		d6.connect("toggled", self.writex, 0x40)
		vbox.pack_start(d6, gtk.TRUE, gtk.TRUE, 2)
		# D7
		d7 = gtk.ToggleButton("D7")
		d7.connect("toggled", self.writex, 0x80)
		vbox.pack_start(d7, gtk.TRUE, gtk.TRUE, 2)
		
		# Add a separator for the quitbutton
		separator = gtk.HSeparator()
		separator.set_size_request(120, 5)
		vbox.pack_start(separator, gtk.FALSE, gtk.TRUE, 5)
		
		# Create the "Quit" button
		buttonq = gtk.Button("Quit")
		buttonq.connect("clicked", self.destroy, None)
		vbox.pack_start(buttonq, gtk.TRUE, gtk.TRUE, 2)
		
		self.window.show_all()

def main():
	gtk.main()
	return 0

if __name__ == '__main__':
	SerialX()
	main()

# This code is inspirated in a munguis' code
# Thanks munguis
# ython/...

# [url]http://www.pygtk.org/pygtk2tutorial-es/[/url]
# A great tuto about pygtk
```

Buena Vibra!


----------



## Ardogan (Dic 21, 2008)

Buen aporte!, al parecer Python es la chica del momento para programar en Linux no?. Me da un poco de cosa eso de que sea interpretado o semi-interpretado.
Hace tiempo vengo postergando mi trasbordo de Win a Linux, lo voy a marcar para cuando me decida a dar ese paso.
Gracias


----------



## Meta (Dic 23, 2008)

Muy bueno.

Aunque debería explicarlo un poco más el cómo lo hiciste paso a paso. Mira el ejemplo que hice con Visual C# en puerto serie.

http://www.slideshare.net/Metaconta/pic-rs232-puerto-serie-con-pic16f84a-presentation

Saludo.


----------



## pepechip (Dic 23, 2008)

El Python parece muy facil de utilizar, me recuerda al viejo basic. 
antes de mirarlo mas afondo, estaba interesado en la representacion de graficos en pantalla, pero no si dipone de tal funcion.
¿se podria hacer un programa en Python que quede la pantalla como si fuera una pagina web, pero los botones que aprarezcan en el monitor, poder controlarlos por el teclado en lugar del raton?


----------



## mockba (May 6, 2009)

Hola a todos, tenía mcho que no volvía por acá. antes que nada gracias sangreaztk, puest el código que he estado utilizando para hacer algunas pruebas con un hardware que estoy diseñando las he logrado a usando el código que se posteó en la página de munguis.

Últimamente he estado rondando la idea de usar el puerto serie, ví este foro y cuando reconocí el código que he estado utilizando qué mejor que preguntarte directamente. Lo que sucede es que no puedo hacer correr el código que posteas aquí para manejar el puerto serie. El shell me devuelve el siguiente error cuando tipeo: _python serial.py..._

```
Traceback (most recent call last):
  File "serial.py", line 26, in <module>
    import serial
  File "/home/xxxxxx/Escritorio/serial.py", line 32, in <module>
    s = serial.Serial(0)   # Open port '/dev/tty0', BaudRate 9600
AttributeError: 'module' object has no attribute 'Serial'
```
La verdad es que soy bastante novato aún en las cuestiones de programación (_mi fuerte son las cuestiones de electrónica, pero he decidido cruzar las barreras jejeje_) y aunque he logrado resolver varias cuestiones que se me han ido presentando, me gustaría saber si tienes una idea de qué significa ese error. Estoy utilizando Ubuntu 8.04 y hasta el momento creo haber entendido algunas cosas que he estado programando en python, pero esto no lo interpreto.

Primero pensé que talves había instalado de forma incorrecta el módulo pyserial, pero ya he revisado eso... recuerdo qeu cuando probé con pyparallel el problema que tenía era un conflicto entre módulos, pero eso se arregla utilizando comandos de linux. Pero es éste caso no he enconrado alguna información que me diga algo similar. ¿Alguien tiene alguna idea?... Gracias.


----------



## sangreaztk (May 6, 2009)

El problema es que que el script lo nombraste como 'serial.py' y luego dentro del mismo llamas al modulo 'serial'. Eso hace que python se confunda y te dé ese error. La solución entonces es renombrar el script, que te parece 'serialxxx.py' jeje.

Por cierto, al ver de nuevo este viejo código me doy cuenta que está muy chafa, jejeje. Se puede hacer mucho más limpio y más corto.

Buena Vibra!


----------



## mockba (May 6, 2009)

jajajaja... pero qué bruto... eso mismo me pasó cuando intentaba utilizar utilizar la librería de pyparallel... pero lo curioso es que esta vez no estaba utilizando nombrando mi archivo como serial.py, sino que tenía otro archivo nombrado de esa forma en la mismo directorio.

Ojo con eso... sólo el hecho de tener otro archivo con ese nombre en el directorio el intérprete lo asume como el archivo referenciado, fue el problema... lo saqué y ya...

Gracias. No pensé que fuera a responder tan rápido. Espero que podamos seguir compartiendo información más adelante.

Saludos...


----------



## Meta (May 6, 2009)

He logrado funcionar y tengo hecho lo del puerto serie con MonoDevelop C# de openSUSE 11.1


----------



## Tomasito (May 6, 2009)

Tengo una duda, siempre se pone "#!/usr/bin/env python"? Porque yo habia probado con "#!/usr/bin/python" y no me andaba bien


----------



## sangreaztk (May 6, 2009)

DriX dijo:
			
		

> Tengo una duda, siempre se pone "#!/usr/bin/env python"? Porque yo habia probado con "#!/usr/bin/python" y no me andaba bien




Viendo un tutorial de python de mundo geek muy bueno, dice:



			
				Tutorial Python dijo:
			
		

> Si utilizas Linux (u otro Unix) para conseguir este comportamiento, es decir, para que el sistema operativo abra el archivo .py con el intérprete adecuado, es necesario añadir una nueva línea al principio del archivo:
> #!/usr/bin/python
> print “Hola Mundo”
> raw_input()
> ...



Buena Vibra!


----------



## mockba (May 6, 2009)

En otras palabras, utiliza la shebang con _env_, porque de esa forma tu sistema operativo se encarga de buscar el intérprete de python. A mí siempre me ha funcionado así.

Saludos...


----------



## mockba (May 6, 2009)

Oye sangreaztk, ¿tendrás alguna forma de poner el diagrama que utilizar para hacer la prueba del puerto serial?, lo que sucede es que no me  queda muy claro cómo se utilizan los pines de ese puerto.

Gracias de antemano camarada.


----------



## sangreaztk (May 6, 2009)

mockba dijo:
			
		

> Oye sangreaztk, ¿tendrás alguna forma de poner el diagrama que utilizar para hacer la prueba del puerto serial?, lo que sucede es que no me  queda muy claro cómo se utilizan los pines de ese puerto.
> 
> Gracias de antemano camarada.




...................la neta no recuerdo si conservo el diagrama, dame tiempo y veo si lo conservo aún.
Aunque tu puedes usar el que quieras, el programa en python solo pide que la comunicación sea a 9600 bauds y solo es en un sentido, del PC al micro (o lo que sea que este del otro lado). Aunque queda claro que el modulo PySerial puede trabajar en full duplex, si es que te interesa.


----------



## mockba (May 6, 2009)

Claro que me interesa el full duplex, muchas gracias por buscar, si lo encuentras te lo agradeceré aún más. Por el momento trataré con un pic16f84a que es el que tengo a la mano. ¿Qué carrera estudias?... ¿eres electrónico?...

Jejeje, ahora sólo falta aprender a usar el módulo pyusb para poder implementar interfases USB...

Saludos...


----------



## sangreaztk (May 7, 2009)

mockba dijo:
			
		

> Claro que me interesa el full duplex, muchas gracias por buscar, si lo encuentras te lo agradeceré aún más. Por el momento trataré con un pic16f84a que es el que tengo a la mano. ¿Qué carrera estudias?... ¿eres electrónico?...
> 
> Jejeje, ahora sólo falta aprender a usar el módulo pyusb para poder implementar interfases USB...
> 
> Saludos...



Nel bro! no encontré el diagrama.
Pero dices que el PIC que tienes es el 16F84, entonces dale una leída al tutorial de Meta (está mensajes más arriba), que él ocupa precisamente un 16f84.
Para conocer las funciones que usa el modulo PySerial, y así implementar fullduplex, visita la página del proyecto ---> http://pyserial.wiki.sourceforge.net/pySerial
Y sobre que estudio, pss una ingeniería: "Mecatronica", así que a h debo de aprender electrónica, mecánica, programación, etc. Y una forma chevere de aprender todo eso es tratar de ayudar a lo demás, por lo que si necesitas un cable pss nomás pregunta (aunque te conviene investigar primero) y ya veremos.
Y tu bro, en que andas?............................. ahhhhhhh! y sobre lo del PyUSB igual quería aprender a usarla pero mendigos micros andan caros, ja.
Buena Vibra!


----------



## mockba (May 8, 2009)

Jejeje, conozco el módulo PyUSB, pero como apenas me estoy metiendo en la programación con Python no sé usarlo aún. Gracias a que éstas dos últimas semanas me he etado metiendo con los puerto ahora sé que no es tan dificil... yo jalé para electrónica, pero a mi siempre me ha gustado la mecánica y he manejado algunas máquinas, algo que a muchos de mis amigos les valió pura m. Se podría decir que soy mecatrónico autodidácta. También sé algo de instrumentación y electrónica de potencia.

¿En qué ando?... se de plantas y de cultivo orgánicos. Ando metido en la implementación de un vivero/invernadero. En realidad existen invernaderos y espacios controlados muy sofisticados, llenos de todo tipo de sensores y equipo de computo controlando parámetros como humendad, temperatura del suelo y del aire... etc. Pero a mi lo que me interesa en más por el momento es el "manejo marginal" de aguas de micro riego... es decir, usar el agua justa para las plantas sin desperdiciar. Y para eso puedes usar una computadora.

Para mí, manejar los puertos como salidas de datos significa controlar dispositivos como válvulas y bombas... y leer información exterior desde el puerto se puede usar para contabilizar el agua utilizada por cada cama de cultivo y los niveles de agua en las sisternas.

Por cierto, gracias a tu código tengo interfase gráfica GTK, mis programas hasta ese momento eran pura línea de comando para prender y apagar motores a través de tarjetas de potencia que estoy probando, jejeje... aun no sé manipular pyGTK, pero ya le estoy metiendo mano a algunos códigos.

Si te interesa algo de eso, aquí estamos pa' platicar cuando gustes, también me puedes encontrar en http://pomexico.superforo.net/. Te recomiendo entrar si te interesan temas como las energías alternativas, cuestiones sociales en México y temas como el cambio climático o las consecuencias no difundidas del agotamiento del petróleo. Saludos...


----------



## Ghost Riderx (Jun 30, 2009)

Amigo puedo decir que probé tu programa, solo la parte de python, bajo windows y despues de tantos tropiezos (en la instalación de los modulos necesarios)pues ha funcionado correctamente... de esta forma se comprueba que python se puede usar independientemente del sistema operativo usado.. como era de esperar!


----------

