Capitulo III. - FirtecOnline

Anuncio
Capitulo III.
Pantalla LCD Hitachi 44780.
Si bien para visualizar datos los dígitos de siete segmentos son muy usados y útiles las pantallas
LCD como la clásica Hitachi 44780 que brinda una solución elegante y de bajo costo.
Básicamente podemos imaginar una pantalla LCD como una memoria de 40 caracteres de los cuales
solo 16 son visibles (pantallas 16x2).
Estas pantallas se pueden manejar en 8 o 4 bit's. En este manual usaremos el enfoque de 4 bit's ya
que esta modalidad nos libera mas pines en el puerto de la Raspberry PI.
El manejo de un LCD, no es nada del otro
mundo si comprendemos la arquitectura de
un modulo LCD.
Los módulos LCD, llevan integrado a sus
circuitos, 3 regiones de memorias que serán
la base fundamental para el funcionamiento
del modulo.
Por un lado, tenemos dos regiones donde se
albergan datos temporales con características RAM. Estas dos regiones, son las llamadas CGRAM y
DDRAM, que son en si los espacios donde se almacenan los datos que se van a mostrar en pantalla.
La diferencia entre una y otra, es que la CGRAM (Character Generator RAM), nos permite definir y
Electrónica Digital con RaspberryPI
Pagina 54 de 81
alojar 8 nuevos caracteres personalizados. En la CGRAM, es donde se alojan los caracteres creados
por el usuario con matrices personalizadas, y la DDRAM (Data Display RAM), es un espacio
temporal donde se almacenan los caracteres que se van a mostrar en pantalla.
La DDRAM, tiene una capacidad de 80 bytes, 40 por cada línea, de los cuales sólo 32 se pueden
visualizar a la vez (16 bytes por línea).
Las dos direcciones más importantes de la DDRAM son:
• Dirección 0x00, que es el comienzo de la primera línea.
• Dirección 0x40, que es el comienzo de la segunda línea.
Por otro lado, tenemos un espacio de memoria interna no volátil del tipo ROM, llamada CGROM
(Character Generator ROM), que es donde se almacena una tabla con los 192 caracteres que pueden
ser visualizados (ver el siguiente cuadro).
Cada uno de los caracteres tiene su representación binaria de 8 bits. Para visualizar un carácter debe
recibir por el bus de datos el código correspondiente. El módulo LCD además de tener definidos
todo el conjunto de caracteres ASCII, permite al usuario definir 4 u 8 caracteres gráficos. La
composición de estos caracteres se va guardando en una memoria llamada CGRAM con capacidad
Electrónica Digital con RaspberryPI
Pagina 55 de 81
para 64 bytes. Cada carácter gráfico definido por el usuario se compone de 16 u 8 bytes que se
almacenan en sucesivas posiciones de la CGRAM.
Se debe establecer la dirección en la memoria CGRAM a partir de la cual se irán almacenando los
bytes que definen un carácter gráfico.
Para la creación de caracteres gráficos hagamos un poco de memoria. Cuando enviamos el código
de un carácter alfanumérico a la DDRAM del LCD, su chip interno buscará en la CGROM el patrón
correspondiente y luego lo visualizará en la pantalla. Así se escriben todos los textos.
Ahora bien, si el código enviado vale entre 0x00 y 0x07 (o 0x08 y 0x0F), el chip interno buscará su
patrón de visualización en la CGRAM. Siendo ésta una RAM de lectura/escritura, podemos
programar en ella los diseños que se nos ocurran.
La CGRAM (Character Generator RAM) consta de 64 bytes en los que se pueden escribir los
patrones de 8 nuevos caracteres de 5×7 puntos ó 4 caracteres de 5×10 puntos.
Cuando los caracteres son de 5×7 puntos los 64 bytes se dividen en 8 bloques de 8 bytes cada uno, y
cada bloque almacena el patrón de un nuevo carácter. El esquema mostrado arriba indica que:
• El primer bloque de CGRAM, con direcciones desde 0b00000000 hasta 0b00000111,
corresponde al código 0x00 (ó 0x80) de la DDRAM.
• El segundo bloque CGRAM, con direcciones desde 0b00001000 hasta 0b00001111,
corresponde al código 0x01 (ó 0x88) de la DDRAM; y así sucesivamente.
Por ejemplo, la figura de arriba indica que se han rellenado los dos primeros bloques con los
Electrónica Digital con RaspberryPI
Pagina 56 de 81
patrones de dos pacmans. Hasta ahí solo se han creado dos nuevos caracteres. Para mostrarlos en el
LCD habría que escribir un código con las funciones adecuadas para esto.
Es importante dejar claro que los caracteres creados por el usuario se contienen en RAM por lo
tanto cuando el LCD pierda su alimentación el carácter se perderá, esto implica que el código
dentro del controlador debe contemplar la creación del carácter cada vez que el LCD arranque
consumiendo en esto memoria de programa.
Para el manejo de estas pantallas contamos con una librería que trabaja conjuntamente con WiringPi
y siempre antes de usar comando para el LCD se debe haber ejecutado la función wiringPiSetup() y
luego la función
lcdInit(2, 16, 4, RS, EN, D0, D1, D2, D3, D0, D1, D2, D3);
Donde 2 es la cantidad de líneas, 16 los caracteres visibles y el resto son los pines de acuerdo a la
definición.
const int RS = 3;
const int EN = 14;
const int D0 = 4;
const int D1 = 12;
const int D2 = 13;
const int D3 = 6;
GPIO_3
GPIO_14
GPIO_4
GPIO_12
GPIO_13
GPIO_6
Pines usados por el LCD.
La función lcdPosition(lcdFD,0,1) indica donde estará l cursor, en este caso primera columna de la
segunda fila (primer casillero-caracter de la segunda línea). La librería para el manejo de la pantalla
consiste en dos archivos lcd.c y lcd.h que siempre estarán formando parte de los proyectos en que
usemos la pantalla LCD.
Distribución de pines en la pantalla Hitachi 44780.
El pin R / W (pin 5) en la pantalla LCD debe estar conectado a 0V (GND), esto es muy importante
si utiliza una pantalla de 5V, si conecta este pin a Raspberry destruirá el puerto. Esto es porque la
pantalla intentará escribir en la Raspberry enviando niveles lógicos de 5V a un puerto que solo
admite 3V.
Veamos un pequeño código en C que verifica el funcionamiento de la pantalla.
#include
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<stdint.h>
<unistd.h>
<string.h>
<wiringPi.h>
Electrónica Digital con RaspberryPI
Pagina 57 de 81
#include "lcd.h"
#include <errno.h>
const
const
const
const
const
const
int
int
int
int
int
int
RS
EN
D0
D1
D2
D3
=
=
=
=
=
=
3;
14;
4;
12;
13;
6;
int main(){
if (wiringPiSetup() < 0){
fprintf (stderr, "No puedo configurar el dispositivo %s\n", strerror
(errno)) ;
return 1 ;
}
int lcdFD;
lcdFD = lcdInit(2, 16, 4, RS, EN, D0, D1, D2, D3, D0, D1, D2, D3);
lcdPosition(lcdFD,2 ,0);
lcdPrintf(lcdFD,"RaspBerry PI");
lcdPosition(lcdFD,0,1);
lcdPrintf(lcdFD, "Firtec Argentina");
return 0;
}
Conversión Analógica Digital.
En muchos proyectos tenemos que tratar con las señales o información del mundo analógico, como
la temperatura, presión, corriente, etc .
Estas señales son analógicas de forma predeterminada y en la mayoría de los casos se utilizan
sensores que convierten estas señales a analógico de tensión eléctrica que será presentada en un pin
del microcontrolador para hacer algún trabajo.
Por desgracia, los microcontroladores son digitales y no pueden hacer frente a las señales
analógicas por lo que estas señales deben ser convertidas en señales digitales que sean
comprensibles por el núcleo del microcontrolador.
Para este propósito, los fabricantes de microcontroladores suelen incorporar estos módulos en los
microcontroladores sin embargo los chips Broadcom de Raspberry no lo tienen por lo que será
necesario conectarlos como periféricos y vincularlos a Raspberry a través de un bus o línea de
comunicaciones.
Básicamente digitalizar algo es simplemente convertirlo a una secuencia de números de tal forma
que si hacemos el proceso inverso de leer esos números podemos reconstruir la información
original.
Electrónica Digital con RaspberryPI
Pagina 58 de 81
El valor analógico a digitalizar puede ser cualquiera pero los números que se puede tratar en el
conversor tienen valores finitos que dependen de la precisión del conversor A/D.
La operación de digitalización nos devuelve una secuencia de números que si usamos un
convertidor de 12 bits serian entre 0 y 4095.
En la mayoría de los conversores analógico-digitales hay dos operaciones se cumplen de forma
separada.
Sample y Hold convierte la señal en una señal que sigue siendo analógica, pero tiene valores sólo en
instantes de tiempo discretos (muestreo y retención ). El ADC convierte la serie de muestras en
números (conversor analógico a digital ).
Electrónica Digital con RaspberryPI
Pagina 59 de 81
Conversor A/D MCP3201.
Como ejemplo vamos a implementar el conversor analógico digital MCP3201 fabricado por la
empresa Microchip.
Este conversor tiene una resolución de 12 bits pudiendo generar 4096 números por cada medición.
Puede ser alimentado de 2.7 a 5V por lo que cubre perfectamente el rango de voltajes que nos
interesa (3V) para Raspberry.
El MCP3201 cuenta con un registro de aproximación sucesiva (SAR) y una interface serial SPI, lo
que permite la capacidad de añadir un ADC de 12bits a cualquier Microcontrolador que implemente
el protocolo de comunicaciones SPI. Algunas características del MCP3201 son la capacidad de
tomar 100k muestras/segundos, posee un canal de entrada, muy bajo consumo de energía (5nA en
standby, 400uA máximo en estado activo) y esta disponible en encapsulado de 8 pines PDIP, SOIC
y TSSOP.
Algunas de las aplicaciones donde puede incluirse el MCP3201 son adquisición de datos,
instrumentos de medición, procesadores de datos, mediciones industriales, control de motores,
robótica, automatismos industriales, pequeños sensores para instrumentación portátil y aplicaciones
de medicina.
Protocolo de comunicaciones SPI.
El SPI es un protocolo de comunicación sincrónica de 4 cables. Desarrollado por Motorola en 1982
y con gran aceptación en la industria como sistema de comunicación de muy corta distancia,
normalmente dentro la placa de circuito impreso vinculando distintos chips.
Es un protocolo de transmisión que permite alcanzar velocidades muy altas y que se diseñó
pensando en comunicar un microcontrolador con distintos periféricos y que funciona a full dúplex
(Una forma retorcida de decir que puede enviar y recibir datos al mismo tiempo).
SPI utiliza una solución síncrona, porque utiliza unas líneas diferentes para los datos y el reloj. El
reloj (Clock) es una señal que indica al que escucha exactamente cuándo leer las líneas de datos,
con lo que el problema de perdida de sincronía se elimina de raíz.
Electrónica Digital con RaspberryPI
Pagina 60 de 81
Por eso mismo, no se necesita pactar la velocidad de transmisión, ya que será el Clock quien fije la
velocidad y puede ser variable a lo largo de la comunicación sin que sea un problema (Aunque por
supuesto según el dispositivo habrá un límite de velocidad).
Uno de los motivos por los que SPI es tan popular es que el hardware de recepción puede ser
sencillo lo que es una solución mucho más simple que una UART que trataremos en el siguiente
capítulo.
En un bus SPI una de las partes genera el Clock al que llamamos master, (en nuestro caso raspberry
es master) y el resto son los esclavos, pudiendo haber uno o varios en el bus. A la señal de reloj se le
suele llamar CLK por Clock o SCK por Serial Clock.
Cuando el master envía información, lo hace por una línea de datos normalmente de nombre MOSI
(Master Out Slave In) y si el esclavo responde lo hace a través de una línea llamada MISO (Master
In Slave Out).
Como es el master quien genera el Clock, necesita saber de antemano, si un esclavo va a devolver
una respuesta y de que longitud, para mantener el Clock hasta que la transferencia esté completa.
Hay una última línea de control, llamada Slave Select o SS, que indica a un esclavo que el mensaje
que viene es para él, o bien que se reclama que envié una respuesta a una petición del master.
Electrónica Digital con RaspberryPI
Pagina 61 de 81
La línea SS normalmente se mantiene alta y se activa con nivel bajo, lo que “despierta” al esclavo
seleccionado. Cuando se termina la transferencia la línea es puesta a nivel alto y el esclavo se
desactiva. Hay dos maneras de conectar múltiples esclavos a un bus SPI. Con una línea SS por cada
esclavo o en cascada. En general cada esclavo requiere su propia línea SS para ser activado, y así
evitar que dos hablen a la vez, porque el resultado sería ruido inútil. Basta con activar la línea
correspondiente y el esclavo esta listo para recibir sus órdenes.
Cuando el número de esclavos crece suele ser más frecuente conectarlos en cascada, con el MISO
de uno (Salida), conectado al MOSI (Entrada) del siguiente. En este caso solo usamos una única
línea SS, que se comparte entre todos los esclavos.
Esta configuración es típica de una situación en la que le master envía datos pero no recibe nada de
vuelta, como en el caso de una cadena de múltiples display LEDs ( Matrices de 8×8) , en los que se
envía información para ser mostrada pero, no hay datos de retorno.
Electrónica Digital con RaspberryPI
Pagina 62 de 81
En este caso incluso podemos desconectar la línea MISO.
En la placa Raspberry el periférico SPI no está activada de forma predeterminada.
Para habilitarlo, haga lo siguiente.
En la configuración de nuestra Raspberry, en la lengüeta interfaces debemos activar los puertos que
nos interesan, reiniciamos el sistema. Luego desde la consola verificamos que los dos puertos SPI
están activos escribiendo:
ls /dev/*spi*
Lo que debería responder:
/dev/spidev0.0
Electrónica Digital con RaspberryPI
/dev/spidev0.1
Pagina 63 de 81
Conectando el conversor MCP3201 a Raspberry.
Una vez que tenemos todo preparado a nivel de protocolo SPI podemos pasar al hardware para
obtener un resultado como el que se ve en la siguiente captura.
Usaremos el siguiente conexionado para medir las variaciones de voltaje en el punto medio del
potenciómetro de 10K.
El siguiente es el programa para verificar el funcionamiento del puerto SPI con el conversor
analógico digital MCP3201, Raspberry tiene dos puertos SPI, estamos usando el puerto 0.
#include
#include
#include
#include
#include
#include
<stdio.h>
<stdlib.h>
<stdint.h>
<unistd.h>
<string.h>
<wiringPi.h>
Electrónica Digital con RaspberryPI
Pagina 64 de 81
#include <wiringPiSPI.h>
#include "lcd.h"
#include <errno.h>
void MCP3201(void);
const
const
const
const
const
const
int
int
int
int
int
int
RS
EN
D0
D1
D2
D3
=
=
=
=
=
=
// Se informa que se creara una función llamada MCP3201.
3;
11;
4;
5;
6;
7;
char buf [14];
int ce = 0;
unsigned char ByteSPI[2];
unsigned char low;
unsigned char hi;
unsigned short int dato;
unsigned int M0;
unsigned char muestras =0;
double Va;
int lcdFD;
int main(){
if (wiringPiSetup() < 0){
fprintf (stderr, "No puedo configurar wiringPI!! %s\n", strerror (errno)) ;
return 1 ;
}
printf ("Conversor MCP3201\n") ;
printf ("www.firtec.com.ar\n") ;
if (wiringPiSPISetup (0, 100000) < 0) // Conexión a 1 MHz sobre SPI 0
{
fprintf (stderr, "Error en dispositivo SPI 0: %s\n", strerror (errno)) ;
exit (1) ;
}
lcdFD = lcdInit(2, 16, 4, RS, EN, D0, D1, D2, D3, D0, D1, D2, D3);
lcdPosition(lcdFD, 0,0);
lcdPrintf(lcdFD, "Conversor MCP3201");
while(1){
MCP3201();
// Función para leer el conversor.
}
return 0;
}
void MCP3201(void){
wiringPiSPIDataRW (0, ByteSPI,
usleep(100);
hi = (ByteSPI[0] & 0x1F);
low = (ByteSPI[1] & 0xFe);
dato = (hi << 8) | low;
M0 += dato;
2); // Lee dos Byte
// Espera 100 uS.
// Salva la parte alta del byte.
// Salva la parte baja del byte.
// Alinea los bytes y los une en dato
// Acumula en M0 16 mediciones.
if (15 == muestras++){
// Ya se hicieron 16 mediciones?
dato = M0/16;
M0 =0;
// Borra las variables para la siguiente medición.
muestras =0;
Va = (double) (dato) * 3.3 / 8192.0;
// Escala el dato a voltios.
sprintf (buf, "Voltios:%3.3f",Va); // Convierte el dato a valores ASCII.
Electrónica Digital con RaspberryPI
Pagina 65 de 81
lcdPosition(lcdFD,0,1);
lcdPuts(0, buf);
// Coloca el cursor en posición.
// Muestra el voltaje.
}
}
Escritorios remotos.
Todo lo visto supone que usted tiene conectado a su Raspberry un monitor y un teclado lo cual está
perfecto pero esto no es absolutamente necesario para usar Raspberry siendo que puede manejar
todo desde su computadora conectada a la red y a través de escritorios virtuales.
Para poder responder a las conexiones entrantes todo lo que hemos de hacer es instalar el paquete
xrdp en nuestra Raspberry, primero ejecutamos el comando de actualización.
sudo apt-get update
y, a continuación, lanzamos la instalación del servidor de escritorios virtuales.
sudo apt-get install xrdp
Una vez instalado podemos conectarnos con cualquier cliente para escritorios remotos.
El imagen siguiente se aprecia una computadora con GNU Linux Debian corriendo el cliente de
escritorios remotos para KDE denominado KRDC.
Observe podemos ver el mismo escritorio que vemos en el monitor conectado a Raspberry y
ejecutar los mismos programas tal cual como si estuviéramos trabajando físicamente sobre nuestra
placa Raspberry.
Todo esto lo podemos hacer a través de nuestra red Wi-Fi sin necesidad incluso que la placa
Raspberri se encuentra físicamente en el mismo lugar donde estamos trabajando.
Desde el sistema Windows es lo mismo con la facilidad agregada que Windows ya trae un cliente
Electrónica Digital con RaspberryPI
Pagina 66 de 81
para escritorios virtuales por defecto solo debemos llamar a la aplicación y colocar la dir IP de
nuestra placa Raspberry, podemos averiguarlo ejecutando.
sudo ifconfig -a
Ponemos el usuario (por defecto pi) y la clave que hayamos definido para nuestra Raspberry.
Una vez cumplido estos pasos podemos conectarnos a nuestra Raspberry por la red Wi-Fi.
Windows 7 mostrando el escritorio de Raspberry.
Un detalle a tener presente es que siempre la conexión por escritorio remoto será un tanto mas lenta
que si estamos vinculados físicamente a nuestra Raspberry.
También nos puede ser muy útil instalar un servidor FTP para transferir archivos hacia y desde
nuestra Raspberry por la misma red Wi-Fi.
Para instalar el servidor en nuestra Raspberry escribimos en la terminal.
sudo apt-get install vsftpd
Luego que el programa se instala vamos a configuración para indicar que siempre lo queremos
Electrónica Digital con RaspberryPI
Pagina 67 de 81
activo, para esto escribimos en a terminal.
sudo nano /etc/vsftpd.conf
Y realizamos las siguientes reformas.
Editando o descomentando las siguientes líneas
Anonymous_enable = NO
Local_enable = SI
Write_enable = SI
Ascii_upload_enable = SI
Ascii_download_enable = SI
Salvamos el archivo y reiniciamos el servicio con sudo /etc / init.d / vsftpd restart.
Luego con cualquier cliente FTP podemos conectarnos a nuestra Raspberry para transferir archivos.
El FileZilla es una buena opción, siendo muy simple de utilizar solo requiere que indiquemos la dir
IP del servidor (IP de nuestra RaspBerry) el usuario (generalmente pi) y la clave de acceso de
nuestra placa Raspberry. (El número de puerto lo podemos dejar libre FileZilla lo configura por
defecto).
Electrónica Digital con RaspberryPI
Pagina 68 de 81
Sensor Analógico LM35
El LM35 es un sensor de temperatura con una precisión calibrada de 1ºC. Su rango de medición
abarca desde -55°C hasta 150°C. La salida es lineal y cada grado Celsius equivale a 10mV.
Por lo tanto las mediciones serian 1500 milivoltios equivalen a 150 ºC y -550 milivoltios serán -55
ºC .
Sus características más relevantes son:
•
Está calibrado directamente en grados Celsius.
•
La tensión de salida es proporcional a la temperatura.
•
Tiene una precisión garantizada de 0.5 °C a 25 °C.
•
Baja impedancia de salida.
•
Baja corriente de alimentación (60 μA).
•
Bajo coste.
El LM35 no requiere de circuitos adicionales para calibrarlo externamente. La baja impedancia de
salida, su salida lineal y su precisa calibración hace posible que este integrado sea instalado
fácilmente en un circuito de control. Debido a su baja corriente de alimentación se produce un
efecto de auto calentamiento muy reducido. Se encuentra en diferentes tipos de encapsulado, el más
común es el TO62 utilizada por transistores de baja potencia.
La salida del sensor de temperatura se conecta a la entrada del conversor analógico. El mismo
circuito que usamos con el potenciómetro cambiando el potenciómetro por el sensor de temperatura.
Si bien se puede conectar el sensor a 3V la hoja de datos indica que su funcionamiento correcto se
obtiene con un voltaje de alimentación mínimo de 4V.
Para verificar su funcionamiento vamos a escribir el siguiente programa en C (también lo
encontrará en las carpetas de ejemplos del curso).
Debe prestar especial cuidado al conectar el sensor, invertir alguna conexión dañará el LM35.
Electrónica Digital con RaspberryPI
Pagina 69 de 81
Programa para el LM35.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include "lcd.h"
#include <errno.h>
void MCP3201(void);
const int RS = 3;
const int EN = 11;
const int D0 = 0;
const int D1 = 5;
const int D2 = 6;
const int D3 = 7;
char buf [14];
int ce = 0;
unsigned char ByteSPI[2];
unsigned char low;
unsigned char hi;
unsigned short int dato;
unsigned int M0;
unsigned char muestras =0;
double Va, temperatura;
int lcdFD;
int main(){
if (wiringPiSetup() < 0){
fprintf (stderr, "No puedo configurar el dispositivo %s\n", strerror
(errno)) ;
return 1 ;
}
printf ("Probando el conversor MCP3201 y LM35\n") ;
printf ("www.firtec.com.ar\n") ;
if (wiringPiSPISetup (0, 100000) < 0){
fprintf (stderr, "ERROR en SPI 0: %s\n", strerror (errno)) ;
}
exit (1) ;
Electrónica Digital con RaspberryPI
Pagina 70 de 81
lcdFD = lcdInit(2, 16, 4, RS, EN, D0, D1, D2, D3, D0, D1, D2, D3);
lcdPosition(lcdFD, 1,0);
lcdPrintf(lcdFD, "MCP3201 & LM35");
while(1){
MCP3201();
}
return 0;
}
void MCP3201(void){
wiringPiSPIDataRW (0, ByteSPI, 2);
usleep(100);
hi = (ByteSPI[0] & 0x1F);
low = (ByteSPI[1] & 0xFe);
dato = (hi << 8) | low;
M0 += dato;
if (15 == muestras++){
dato = M0/16;
M0 =0;
muestras =0;
Va = (double) (dato) * 3.3 / 8192.0;
temperatura = Va / (10.0 / 1000);
sprintf (buf, "Temp:%2.1f",temperatura);
lcdPosition(lcdFD,0,1);
lcdPuts(0, buf);
}
}
Sensor 1-Wire DS18B20
El sensor de temperatura DS18B20 es un dispositivo que se comunica de
forma digital. Cuenta con tres terminales, los dos de alimentación y el pin de
datos.
Con Raspberry podemos “leer” la temperatura que registra este sensor que
posee una característica muy peculiar. Utiliza la comunicación OneWire, la
cual es un poco complicada para los que no tienen mucha experiencia en el
área de electrónica digital.
Básicamente se trata de un protocolo especial que permite enviar y recibir
datos utilizando un solo cable, a diferencia de la mayoría de los protocolos
que requiere dos vías. De hecho, Raspberry posee pines RX y TX que son
los encargados de enviar y recibir información mediante la UART.
Para muchas personas que intenten aprender a utilizar el sensor DS18B20 probablemente sea un
poco difícil encontrar información precisa y concisa, debido a que se habla mucho de este protocolo
de comunicación de un solo cable y los códigos de ejemplo normalmente complejos tratando de
explicar al usuario una serie de conceptos que para nuestros propósitos no tienen relevancia.
El sensor DS18B20 es un termómetro digital de alta precisión, entre 9 y 12 bits de temperatura en
Electrónica Digital con RaspberryPI
Pagina 71 de 81
grados Celsius (el usuario puede escoger la precisión deseada).
Su temperatura operativa se encuentra entre -50 y 125 grados Celsius. La precisión, en el rango
comprendido entre -10 y 85 grados es de ±0.5 grados.
Su precio es económico, su interfaz de funcionamiento es sencilla y su uso es muy provechoso para
proyectos que requieran mediciones precisas y confiables.
Una particularidad interesante de estos sensores es que poseen un número ID, algo así como un
número MAC único grabado por el fabricante en cada sensor lo que posibilita tener muchos
sensores y direccionarlos por su ID para conocer la temperatura en ese punto en particular.
Podemos ver en el siguiente diagrama la forma de conectar tres sensores (o mas) al pin GPIO-4 de
Raspberry. El protocolo 1-Wire exige una resistencia de 4,7K colocada entre el pin de datos y 3,3V,
recuerde estos sensores son en realidad un microcontrolador completo con un puerto de
comunicaciones y claro un sensor de temperatura pero su electrónica interna es verdaderamente
compleja a pesar de su aspecto simple. Recuerde, parecen un transistor pero no lo son.
Rspberry no trae un puerto de comunicaciones en este protocolo y para hacerlo funcionar
deberemos seguir algunos pasos. Primero vamos a editar un de configuración para definir un pin
para este protocolo,para esto escribimos en la terminal.
sudo nano /boot/config.txt
Y al final del archivo agregamos lo siguiente.(preste atención a no cometer un error en la sintaxis de
lo que escribe).
dtoverlay=w1-gpio,gpiopin=4
Luego reiniciamos la Raspberry y ejecutamos los siguientes pasos:
Dentro del directorio /sys/bus/w1/devices se encontrarán dos capetas, uno de ellos tendrá como
Electrónica Digital con RaspberryPI
Pagina 72 de 81
nombre el ID del sensor. Si tiene varios sensores cada uno tendrá una carpeta con su ID.
Siempre primero deberá editar el archivo config.txt de lo contrario no funcionará.
Una vez que tenemos nuestros sensores ubicados podemos escribir un simple programa en C para
verificar su funcionamiento. (El proyecto completo lo encontrará en las carpetas de ejemplos).
Con este programa veremos la temperatura en la pantalla Hitachi44780 como se aprecia en la
imagen siguiente.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/fcntl.h>
#include <time.h>
#include <wiringPi.h>
#include "lcd.h"
#include <errno.h>
const int RS = 3;
const int EN = 11;
const int D0 = 0;
const int D1 = 1;
Pines GPIO asignados a la pantalla LCD
const int D2 = 2;
const int D3 = 10;
static int lcdHandle ;
char buf [4] ;
char temp [5];
int main(int argc, char *argv[]){
int fd = -1, ret;
char *tmp1, tmp2[10], ch='t';
char devname_head[50] = "/sys/devices/w1_bus_master1/28-00000482b243";
char devname_end[10] = "/w1_slave";
char dev_name[100];
long value;
Electrónica Digital con RaspberryPI
ID del sensor conectado
Pagina 73 de 81
int integer, decimal;
char buffer[100];
printf ("Corriendo DS18B20 & LCD 16*2\n") ;
printf ("www.firtec.com.ar\n") ;
if (wiringPiSetup() < 0){
}
fprintf (stderr, "No puedo configurar el dispositivo %s\n", strerror
(errno)) ;
return 1 ;
pinMode (0, OUTPUT) ;
digitalWrite (0, 0) ;
strcpy(dev_name, devname_head);
strcat(dev_name, devname_end);
int lcdFD;
lcdFD = lcdInit(2, 16, 4, RS, EN, D0, D1, D2, D3, D0, D1, D2, D3);
lcdPosition(lcdFD, 0,0);
lcdPosition(lcdFD,1,0);
lcdPrintf(lcdFD, "Sensor DS18B20");
lcdPuts(0, buf);
lcdPosition(lcdFD,1,1);
lcdPrintf(lcdFD, "Temp:
");
while(1){
if ((fd = open(dev_name, O_RDONLY)) < 0){
perror("Error abriendo archivo");
exit(1);
}
lcdPosition(lcdFD,6,1);
ret = read(fd, buffer, sizeof(buffer));
if (ret < 0){
perror("Error de Lectura");
exit(1);
}
close(fd);
tmp1 = strchr(buffer, ch);
sscanf(tmp1, "t=%s", tmp2);
value = atoi(tmp2);
integer = value / 100;
sprintf (buf, "%03d", integer) ;
temp [0]= buf[0];
temp [1]= buf[1];
temp [2]= '.';
temp [3]= buf[2];
Electrónica Digital con RaspberryPI
Pagina 74 de 81
lcdPuts(lcdHandle, temp);
delay (50) ;
}
return 0;
}
Funcionamiento de la UART.
En la actualidad y ante la ausencia de puertos RS232
en las computadoras, acostumbramos a trabajar con
puentes USB-RS232 que solucionan muchos o todos
los problemas a la hora de vincularnos con
computadoras a través del viejo protocolo 232.
Raspberry tiene un puerto UART que utiliza el
GPIO_15 para transmitir (TX) y el GPIO_16 para
recibir (RX).
El controlador no resuelve la capa física, es
decir que para implementar las
comunicaciones deberemos utilizar ya sea el
clásico MAX232 o los modernos puentes USB232.
Esto es particularmente interesante porque con
esta tecnología podemos reutilizar los viejos
programas en puertos COM que por cuestiones
de licencias o complejidad son mas simples de
implementar que las aplicaciones USB nativas.
Protocolo RS-232
El protocolo RS-232 es una norma o estándar mundial que rige
los parámetros de uno de los modos de comunicación serial.
Por medio de este protocolo se estandarizan las velocidades de
transferencia de datos, la forma de control que utiliza dicha
transferencia, los niveles de voltajes utilizados, el tipo de cable
permitido, las distancias entre equipos, los conectores, etc.
Además de las líneas de transmisión (Tx) y recepción (Rx), las
comunicaciones seriales poseen otras líneas de control de flujo
(Hands-hake), donde su uso es opcional dependiendo del dispositivo a conectar.
A nivel de software, la configuración principal que se debe dar a una conexión a través de puertos
seriales. RS-232 es básicamente la selección de la velocidad en baudios (1200, 2400, 4800, etc.), la
verificación de datos o paridad (parida par o paridad impar o sin paridad), los bits de parada luego
de cada dato(1 ó 2), y la cantidad de bits por dato (7 ó 8), que se utiliza para cada símbolo o carácter
enviado.
La Norma RS-232 fue definida para conectar un ordenador a un modem. Además de transmitirse los
datos de una forma serie asíncrona son necesarias una serie de señales adicionales, que se definen
en la norma. Las tensiones empleadas están comprendidas entre +15/-15 voltios para el puerto
original en computadoras en el caso de Raspberry los niveles son de 3,3 Voltios.
Electrónica Digital con RaspberryPI
Pagina 75 de 81
Para una comunicación punto a punto a una distancia no superior a 15 metros es lo que indica la
norma.
Para visualizar los datos recibidos vamos a usar la aplicación terminal.exe que se encuentra entre
las herramientas del curso.
Dato recibido
Dato enviado
El ejemplo que vamos a ver recibe los datos enviados desde el teclado de una PC y los re-transmite
como un eco por el mismo puerto serial.
Observe que la velocidad en baudios debe ser la misma en programa receptor que en el emisor.
Condición absolutamente necesaria para que una transmisión serial asincrónica funcione.
Electrónica Digital con RaspberryPI
Pagina 76 de 81
Un detalle importante para hacer funcionar la UART con nuestra electrónica es que tenemos
primero que deshabilitar el serial desde las opciones de Raspberry.
Esto es necesario porque Linux hace uso del puerto serial, supone que lo usaremos para
transferencias seriales con el propio sistema Linux y si no sacamos esta condición nuestros
programas que hacen uso del serial se verán afectados por el propio sistema operativo que es
“propietario” de la UART.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringSerial.h>
Velocidad de comunicación en
Baudios. Misma que la fijada
en el programa Terminal.exe.
int main ()
{
int fd ; // Descriptor del puerto serial
char dato;
if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0){
fprintf (stderr, "ERROR al abrir el dispositivo: %s\n", strerror (errno)) ;
return 1 ;
}
if (wiringPiSetup () == -1){
fprintf (stdout, "ERROR al iniciar wiringPi: %s\n", strerror (errno)) ;
return 1 ;
}
for (;;){
while (serialDataAvail (fd)){
dato = serialGetchar (fd); // Lee el carácter y lo guarda en dato.
serialPutchar (fd, dato) ; // Envía el carácter por el puerto UART.
fflush (stdout) ;
// Limpia buffer interno
}
}
return 0 ;
}
El ejemplo que sigue incorpora varios de los puntos vistos como son, el protocolo SPI para
Electrónica Digital con RaspberryPI
Pagina 77 de 81
conectarnos a un conversor analógico digital, una pantalla LCD 16x2 y el puerto UART conectado a
un software informático que representa un voltímetro virtual donde veremos el voltaje leído por el
conversor al mismo tiempo que se muestra en la pantalla LCD. (Todo el proyecto como el software
informático está en la carpeta de ejemplos).
/*******************************************************************************
* Ejemplo para UART + SPI + LCD con Raspberry PI.
* Mide la diferencia de voltaje generado con un potenciómetro aplicado a un
conversor A/D MCP3201. El voltaje se muestra en una pantalla LCD 16x2 y se
envía por la UART para ser interpretado por un voltímetro virtual en la PC.
*
www.firtec.com.ar - [email protected]
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include "lcd.h"
#include <wiringSerial.h>
#include <errno.h>
// Función para el conversor A/D
void MCP3201(void);
// Pines de la pantalla LCD
const int RS = 3;
const int EN = 11;
const int D0 = 0;
const int D1 = 1;
const int D2 = 2;
const int D3 = 6;
// Variables del programa
char buf [14];
unsigned char TX_HI=0;
unsigned char TX_Low=0;
unsigned char bandera_medir =0;
int ce = 0;
Electrónica Digital con RaspberryPI
Pagina 78 de 81
unsigned char ByteSPI[2];
unsigned char low;
unsigned char hi;
unsigned short int dato;
unsigned int M0;
unsigned char muestras =0;
double Va;
int lcdFD;
Función Principal del Programa
int main(){
int fd ;
// Descriptor del puerto serial
if ((fd = serialOpen ("/dev/ttyAMA0", 9600)) < 0)
{
fprintf (stderr, "ERROR al abrir el dispositivo: %s\n", strerror (errno)) ;
return 1 ;
}
if (wiringPiSetup() < 0)
{
fprintf (stderr, "No puedo configurar el dispositivo %s\n", strerror (errno)) ;
return 1 ;
}
printf ("Probando el conversor MCP3201\n") ;
printf ("www.firtec.com.ar\n") ;
if (wiringPiSPISetup (0, 100000) < 0)//Conexion SPI a 1 MHz
{
fprintf (stderr, "Unable to open SPI device 0: %s\n", strerror (errno)) ;
exit (1) ;
}
lcdFD = lcdInit(2, 16, 4, RS, EN, D0, D1, D2, D3, D0, D1, D2, D3);
lcdPosition(lcdFD, 0,0);
lcdPrintf(lcdFD, "Conv A/D MCP3201");
Bucle Principal del Programa
while(1){
unsigned char dato_rx = 0;
if(!(bandera_medir))
MCP3201();
// Se pueden tomar nuevos datos?
// Obtiene nuevos datos desde el conversor
while (serialDataAvail (fd))
Electrónica Digital con RaspberryPI
Pagina 79 de 81
{
if(serialDataAvail (fd) != 0){ // Algún dato para leer?
dato_rx = serialGetchar (fd); // Obtiene el caracter recibido por la UART
fflush (stdout) ;
if(dato_rx == 0xFD)
bandera_medir = 0;
// Boton Conectar/Desconectar envía órden para
// asegurar que no se bloquee el conversor.
if(dato_rx == 0xFE){ // Soft-PC pide parte baja del dato.
serialPutchar (fd, TX_Low) ;
bandera_medir = 1;
// No medir mientras se pasan los bytes.
}
if(dato_rx == 0xFF){
// Soft-PC pide parte alta del byte.
serialPutchar (fd, TX_HI) ;
bandera_medir = 0;
// Permite medir nuevamente.
}
fflush (stdout) ;
// Limpio registros
}
}
}
return 0;
}
Función para Leer el Conversor
void MCP3201(void){
wiringPiSPIDataRW (0, ByteSPI, 2);
usleep(100);
hi = (ByteSPI[0] & 0x1F);
low = (ByteSPI[1] & 0xFe);
dato = (hi << 8) | low;
M0 += dato;
if (15 == muestras++){
dato = M0/16;
M0 =0;
muestras =0;
TX_HI = dato/256;
TX_Low = dato - (TX_HI * 256);
Va = (double) (dato) * 3.3 / 8192.0;
sprintf (buf, "Voltios:%3.2f",Va);
lcdPosition(lcdFD,0,1);
Electrónica Digital con RaspberryPI
Pagina 80 de 81
lcdPuts(0, buf);
}
}
/************ Fin de programa *************************************************/
En el próximo capitulo veremos como agregar a nuestra Raspberry un calendario y el manejo de
otro protocolo importante en electrónica, el I2C y el manejo de datos por RF (Radio Frecuencia)
muy útil a la hora de enviar y recibir información como teclados remotos, sensores de presencia, etc
evitando tener que pasar cables con toda la incomodidad que esto presenta.
También veremos el diseño de un sistema de seguridad con ingreso codificado y monitoreo por mail
y video.
Electrónica Digital con RaspberryPI
Pagina 81 de 81
Descargar