lunes, 1 de junio de 2015

Grabar PIC's de Microchip en linux


La presente entrada pretende resumir de una vez por todas la manera más sencilla de poder "quemar" nuestros microcontroladores pic de microchip desde GNU/Linux. La experiencia la inicié desde que tenía instalado debian 6 (Squeeze), osea hace 4 años, pasando por debian 7 (mi tan querida debian wheezy) y ahora en debian 8.
Uno de los software más usados para programar los pics de microchip en Wind2 es de lejos Pickit en sus versiones 2 y 3 que usa el puerto USB. Microchip ha publicado el esquemático de la placa programadora así que existen muchos clones personalizados en la web. Este hardware usa un microcontrolador 12f2550 que tiene un bootloader específico para interactuar con la pc, así que si necesitamos crear nuestra propia placa a partir de los planos, es necesario quemar el bootloader desde otro programador.
Para linux, Microchip ha puesto a nuestra disposición la herramienta pk2cmd, que no tiene interfaz gráfica y sólo se maneja por comandos desde la terminal, por lo que para los que recién se inician en linux y microchip puede resultar un poco complicado entender.

La placa que actualmente uso es prestada de un compañero del trabajo
(Gracias VISU) y es la que usaré para poder exponer este artículo.



El pic será "quemado" a través del método ICSP. Probaremos con los pic's 16F877A y 12F675 (cuya ventaja es que posee un oscilador interno, ideal para proyectos compactos).
Voy a dejar el código fuente en mi dropbox y compartiré el link para que lo puedan descargar y así evitarse tanto dolor de cabeza leyendo muchos artículos que lo que me generaron fue confusión, ya que unos hablaban de una versión, otros de otra versión, otros ponían una sintaxis y a vaces funcionaba, a veces no, etc.
Ahora paso a detallar la instalación.
Antes de instalar, debemos tener instalado las librerías que manejan el puerto usb.
$ sudo aptitude install libusb++-dev

1. Bajar código fuente.
Bajamos el código fuente de aquí. Descomprimir con el siguiente comando:
$ tar -xjf pk2cmd_v1.21.tar.bz2

Luego ingresar a la carpeta descomprimida:
$ cd pk2cmd

Compilar el código fuente:
$ make linux

Al culminar la compilación, generará el ejecutable pk2cmd. Éste debemos copiarlo dentro del /usr/local/bin.
$ sudo cp pk2cmd /usr/local/bin

Luego darle permisos de ejecución.
$ sudo chmod 755 /usr/local/bin/pk2cmd

Luego hay instalar la base de datos de los microcontroladores soportados por esta versión. Existen varias versiones de este archivo. Yo usé el que se puede encontrar en la página de archlinux.
Bajamos la base desde aquí. Descomprimimos.

$ unzip PK2DeviceFile_1.63.148.zip

Creamos la siguiente carpeta donde se copiará ese archivo y luego lo copiamos:
$ sudo cp /usr/share/pk2 && sudo cp PK2DeviceFile.dat /usr/share/pk2/

Damos permisos de lectura y escritura.
$ sudo chmod 777 /usr/share/pk2/PK2DeviceFile.dat

Luego creamos el grupo microchip y nos agregamos a ese grupo.
$ sudo groupadd microchip
$ sudo gpasswd -a $USER microchip

Luego creamos este archivo para poder interactuar con el quemador:
$ sudo nano /etc/udev/rules.d/026_microchip.rules

Ydentro del archivo creado copiamos lo siguiente:
#PICKit 2
ATTR{idVendor}=="04d8", ATTR{idProduct}=="0033", OWNER:="root", GROUP:="microchip",MODE:="0660"

Dentro de nuestro /home/$USER/.bashrc, agregamos la siguiente línea:
export PATH=$PATH:/usr/share/pk2

Reiniciamos y cuando conectamos el "quemador" pickit2 a nuestro linux, verificamos que lo haya reconocido:
$lsusb.
Bus 002 Device 004: ID 0bda:58de Realtek Semiconductor Corp.
Bus 002 Device 025: ID 046d:c534 Logitech, Inc.
Bus 002 Device 022: ID 04d8:0033 Microchip Technology, Inc. PICkit2
Bus 002 Device 014: ID 152d:2329 JMicron Technology Corp. / JMicron USA Technology Corp. JM20329 SATA Bridge
Bus 002 Device 005: ID 058f:9254 Alcor Micro Corp. Hub
Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port
Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

$pk2cmd -?v

Executable Version     :   1.21.00
Device File Version     :   1.63.148
OS Firmware Version :   2.32.00


Operation Succeeded

2. Quemando el pic.
Con eso ya podemos grabar nuestros .hex en el microcontrolador.
Por ahora sólo me dedicaré al proceso de quemar, la programación y la compilación la presentaré en una nueva entrada.

El pic que usaremos en esta ocasión es 16f877A y lo que hace nuestro programa es parpadear un led en el puerto RB0 (pin 33)

Primero borramos el pic.
$pk2cmd -PPIC16F877A -E

Para grabar usaremos la siguiente sintaxis:
$pk2cmd -PPIC16F877A -M -F/ruta_donde_está_el_hex.hex

En mi caso, yo tengo el .hex en mi home:

kiko@debian8:~$ pk2cmd -PPIC16F877A -M -F/home/kiko/bled.hex
PICkit 2 Program Report
2-6-2015, 0:40:06
Device Type: PIC16F877A

Program Succeeded.

Operation Succeeded

Lamentablemente no poseo un cristal, por lo que no puedo poner una foto del pic funcionando :-(. Pero voy a darme un tiempo para comprarlo y actualizar el post.

Ahora programaremos el pic 12F675



Ejecutamos los mismos comandos:
Borramos el pic:
$pk2cmd -PPIC16F675 -E

Pasamos el hex al pic. Este hex linkea un led conectado al pin 2.
$pk2cmd -PPIC12F675 -M -F/home/kiko/blink_12f675.hex
PICkit 2 Program Report
2-6-2015, 1:06:18
Device Type: PIC12F675

Program Succeeded.

Operation Succeeded


Como en este caso, el pic tiene un oscilador interno, en la programación he aprovechado para configurarlo y así poder tener un video con "quemada" realizada y el pic funcionando.

El video lo pueden ver aquí.


Ahora resumo los comandos que se van a necesitar al momento de trabajar con pk2cmd.

$ pk2cmd -P{PICxxx} -E   --------------- este comando borra el pic PICxxx definido

$ pk2cmd -P{PICxxx} -M -F/ruta.hex ----- graba el .hex en el pic PICxxx

$ pk2cmd -P{PICxxx} -Y -F/ruta.hex ------ compara el firmware cargado con el original para verificar si grabó correctamente.

$ pk2cmd -P{PICxxx} -GF/tmp.hex ---- lee el hexadecimal grabado en el pic y lo guarda en tmp.hex

$ pk2cmd -?v -------- verifica la versión de pk2cmd instalada.


Puerto serial con python y Arduino Mega2560

Siguiendo con las entradas al blog y aprovechando que ésta semana he tenido un poco de tiempo y teniendo a la madrugada como espacio de inspiración, publico un tema que tenía en el tintero desde ya hace tiempo. Manejo de puerto serial de la pc y comunicación a través de éste con el mundo exterior.
Si bien es cierto que el puerto serial está rezagado por el puerto USB, es necesario indicar que la comunicación serial es aún muy usada, ya que la comunicación bluetooth la usa, los xbee también, así como muchos otros equipos aún usan la comunicación serial bajo el protocolo RS232.
En este caso, el ejercicio que he realizado es el siguiente: Realizar una programación en python (lenguaje que últimamente he venido trabajando y en el cual he encontrado mucho potencial en la aplicación a mi maestría) que escriba datos en el puerto serial de tal manera que sean reconocidos por la interfaz externa y ejecute eventos en base a lo que reciben.
La interfaz externa usada es Arduino, que contiene 4 puertos seriales y cuya programación está diseñada para usar uno de ellos para recibir los datos que son enviados por python y ejecutar los eventos configurados.
El programa escrito en python envía a través del puerto serial 4 caracteres: R, G, Y, C que hacen referencia a los colores Red, Green, Yellow y el caracter C que hace referencia a la palabra Clear. Los caracteres RGY son generados y enviados de forma aleatoria. Esto lo realiza en un bucle que realiza 100 iteraciones ha razón 20 combinaciones por segundos y después de ello envía el caracter C para apagar los leds.
El programa escrito en Arduino configura el puerto Serial1 en modo escucha; al momento de recibir los caracteres enviados por la pc. Si recibe el caracter R, prende el led rojo, si recibe G, prende el verde y si recibe Y, prende el led amarillo. Cada color reconocido apaga los otros dos restantes.

Ahora, vamos a ver los programas escritos. Ambas configuraciones usan 9600 baudios de velocidad.

1. Programa en python
#!/usr/bin/python
#User: linux-pipux
#Ver : 0.1
#S.O.: debian 8
#Python 2.7
import serial
import time
import random

### parametros para el puerto serial ####
port = "/dev/ttyUSB0"
baurate = "9600"

### configuracion del puerto serial #####
s=serial.Serial(port, baurate, timeout=1)

#bucle
for i in range(100):
    a = random.choice(["G", "Y", "R"])
    s.write(str(a).encode() + '\r\n')
    time.sleep(0.05) # tiempo de transicion ON-OFF


#terminado el bucle, se escribe C para apagar los LED's
s.write(str('C').encode() + '\n')

exit();

2. Programa en arduino mega2560

#include <SoftwareSerial.h>
int red=7;
int yellow=6;
int green=5;
int entrada;
void setup() {
Serial1.begin(9600);
pinMode(red,OUTPUT);
pinMode(green,OUTPUT);
pinMode(yellow,OUTPUT);
}
void loop() {
if(Serial1.available()>0){
int entrada=Serial1.read();
if(entrada=='G'){
  digitalWrite(green, HIGH);
  digitalWrite(yellow, LOW);
  digitalWrite(red, LOW);
  Serial1.write(entrada);
}
if(entrada=='Y'){
  digitalWrite(green, LOW);
  digitalWrite(yellow, HIGH);
  digitalWrite(red, LOW);
  Serial1.write(entrada);
}
if(entrada=='R'){
  digitalWrite(green, LOW);
  digitalWrite(yellow, LOW);
  digitalWrite(red, HIGH);
  Serial1.write(entrada);
}
if(entrada=='C'){
  digitalWrite(green, LOW);
  digitalWrite(yellow, LOW);
  digitalWrite(red, LOW);
  Serial1.write(entrada);
}
}
}


En la placa arduino, los LED's están conectados a los puertos 5, 6, 7 con los colores verde, amarillo, rojo respectivamente.
Como mi placa no tiene puerto serie, estoy usando un convertidor USB-TTL que tiene salidas de 5V que alimenta a la placa arduino una vez programado.

imagen



Imagen de la programación en python y arduino.


En el siguiente enlace pongo un video donde se verifica su funcionamiento.
Video

En una próxima entrega, publicaré un post donde python lea temperatura de un sensor DS18B20 y que en función a la temperatura, se prenda un led en el arduino. Por ejemplo si la temperatura está por encima de los 25°C que se prenda el led rojo, si está entre los 23-25°C que se prenda el led amarillo y si está por debajo de los 23°C que se prenda el led verde. Esta vez lo haré con arduino, RaspberryPi y python.