You are on page 1of 24

Como simular Arduino en Proteus

El mejor programa que he visto para simular la placa Arduino UNO, es Proteus. Por una parte se
necesita el programa con la plantilla de Arduino, y por otra se necesita el programa que queremos
simular con la extensión HEX.

Proteus y Arduino
Una vez instalado el programa proteus, descargaremos el fichero correspondiente a la placa de
Arduino que queramos simular.

Si abrimos el esquema correspondiente al UNO con el Proteus , (versión 7.7 o superior) nos
encontraremos con la siguiente vista:

El Arduino UNO con sus pines de conexión

En ella se puede ver el modelo UNO de Arduino con los elementos que componen dicha placa, como
el LED de indicación de encendido, el led 'L' conectado a la patilla digital 13, las patillas nombradas,
etc.

Para poder simular el código, deberemos decirle al chip qué código y dónde se encuentra y para ello
deberemos acceder al microcontrolador del Arduino. Esto lo conseguiremos haciendo clic encima del
Arduino, con la combinación de teclas 'CTRL+C' accederemos al circuito que forma el Arduino en sí y
haciendo doble clic sobre el microcontrolador se nos abrirá la ventana de configuración del
ATmega328.

El ATmeg329 que compone el Arduino Uno


Una vez allí sólo nos queda cargar el código haciendo clic en el icono de la carpeta de 'Program File:'
y buscar el archivo '.hex' generado por el Arduino durante la compilación.

Ventana de configuración del ATmega

El microcontrolador ya sabe que tiene que ejecutar, por lo que salimos de la ventana aceptando los
cambios, pulsamos 'CTRL+X' para volver al circuito del Arduino y hacemos clic sobre el boton de play
para iniciar la ejecución del código, pudiendo ver su resultado si todo ha ido bien.
Una vez que hayamos indicado la ruta al archivo .hex, no hace falta que se la volvamos a indicar,
directamente modificamos el código, le damos a verificar y al darle al play en el Proteus,
automáticamente tomará la nueva versión del código. También se puede verificar el código mientras
la simulación está en curso sin ningún problema.

Si en vez de indicar la ruta al archivo .hex usamos el .elf podremos comprobar los errores del
programa, ejecutándose paso a paso. Para ello primero pulsamos el 'play' en Proteus, para luego
pulsar 'pausa', entonces saldrán las pantallas del código y de las variables. En mi opinión la pega que
le he encontrado a ejecutar paso a paso, es que el código sale en C puro y no en wiring por lo que
cuesta más la comprensión de este.

Obteniendo el .hex o .elf


Por defecto, al verificar el código (compilar) el archivo .hex se guarda en una carpeta temporal, por lo
que su acceso no será sencillo. Tenemos dos posibilidades, se puede cambiar para siempre donde
guardar el archivo .hex de Arduino o sino que Arduino nos diga en que carpeta se ha creado el
archivo. Como la primera opción ya la tratamos en otro artículo aquí hablaremos sobre la segunda
opción.

En las versiones del IDE anteriores al v1.0 para conocer la ruta en que el compilador guarda el '.hex'
y el '.elf' mantendremos pulsada la tecla 'Mayus' o 'Shift' mientras hacemos clic sobre el botón de
compilar, obteniendo en la pantalla de depuración la dirección de dicho archivo.
En la versión del IDE v1.0 para conocer la ruta, hay que ir a la pestaña 'File', 'Preferences' y marcar
la opción 'Show verbose output during: Compilación'. Se podría seleccionar Carga pero no tiene
demasiado sentido ya que si estamos simulando es porque no queremos tener la placa Arduino
conectada al PC, por lo que tener pulsada esta pestaña no da más que problemas.

En ambos casos obtendríamos la ruta del archivo en el propio IDE.

Hay que tener en cuenta que la ruta del archivo puede pasar por carpetas ocultas y para mostrarlas
haremos la siguiente secuencia:

1. Inicio -> Panel de control -> Opciones de carpeta


2. Abrimos la pestaña 'Ver'
3. Activamos 'Mostrar todos los archivos y carpetas ocultas'

Podeis ver paso a paso la creación de un circuito en Proteus y la simulación con el archivo .hex

Si os ha gustado simular con Arduino podéis ver como se ve la simulación del


control de un servomotor con un potenciometro.
Esta documentación está actualizada para la placa Arduino UNO con las versiones
superiores del IDE 1.0. El documento original está escrito por para versiones
anteriores a la 023, por Chiva.
Motor paso a paso unipolar

En éste ejemplo veremos dos ejemplo de como trabajar con un motor paso a paso unipolar.
Este tipo de motores los podemos encontrar en disqueteras antiguas, y son muy fáciles de
controlar. El que utilizamos en este ejercicio tiene seis conectores en los que dos (o uno
dependiendo del diseño del motor) es el voltaje de referencia (VCC) y otros cuantro se
utilizan para manejar el motor enviando señales sincronizadas.

En este enlace se muestra más información sobre el funcionamiento de motores paso a


paso

El primer ejemplo muestra el código básico para hacer girar el motor en una dirección.
Pretende orientar a aquellos que nunca han manejado un motor paso a paso. El segundo
ejemplo muestra un código más complejo, que permite hacer girar el motor a distintas
velocidades y en ambas direcciones, controlando ambas cosas con un potenciómetro.

En la placa protoboard se ha empleado un potenciómetro de 10K Ohmios que está


conectado a una entrada analágica y a un driver ULN2003A. Este driver cuenta con un
puñado de transistores en su interior. Estos permiten conectar componentes y dispositivos
que necesitan mucha más corriente que la que puede ofrecer el Atmaga8 de la placa
Arduino.

Detalle del conexionado del motor paso a paso


Detalle del conexionado del driver ULN2003A
Esquema válido para ambos ejemplos. Para el ejemplo 1 hay que eliminar el
potenciómetro
Imagen de una placa protoboard con un potenciómetro y un driver ULN2003A conectados a
una placa Arduino

Código fuente

Ejemplo 1: Código básico para manejar un motor paso a paso

/* Motor paso a paso de Copal


* ---------------------------
*
* Programa para manejar un motor paso a paso unipolar extraido de una
* unidad de disquette de 5'25. De acuerdo a la documentación que
* he encontrado, este: "[...] motor paso a paso fabricado por
* Copal Electronics, con 1,8 grados por paso y 96 ohmios por cada
* vuelta (de la bobina), con una etapa central conectada a diferentes
* cables [...]"
* [http://www.cs.uiowa.edu/~jones/step/example.html]
*
* Es un motor paso a paso unipolar con cinco cables:
*
* - rojo: conector de alimentación, lo tengo a 5V y funciona bien
* - naranja y negro: bobina 1
* - marrón y amarillo: bobina 2
*
* (cleft) 2005 DojoDave for K3
* http://www.0j0.org | http://arduino.berlios.de
*
* @author: David Cuartielles
* @date: 20 Oct. 2005
*/
int motorPin1 = 8; // PIN-es del Motor
int motorPin2 = 9;
int motorPin3 = 10;
int motorPin4 = 11;
int delayTime = 500; // Delay que determina la
velocidad de giro

void setup() {

pinMode(motorPin1, OUTPUT); // Configuración de los


PIN-es como salida digital
pinMode(motorPin2, OUTPUT);
pinMode(motorPin3, OUTPUT);
pinMode(motorPin4, OUTPUT);

void loop() {

digitalWrite(motorPin1, HIGH); // Los pines se activan en


secuencia
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin4, LOW);
delay(delayTime);
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, HIGH);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin4, LOW);
delay(delayTime);
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin3, HIGH);
digitalWrite(motorPin4, LOW);
delay(delayTime);
digitalWrite(motorPin1, LOW);
digitalWrite(motorPin2, LOW);
digitalWrite(motorPin3, LOW);
digitalWrite(motorPin4, HIGH);
delay(delayTime);

Ejemplo 2: Código avanzado para manejar un motor paso a paso

/* Motor paso a paso unipolar avanzado


* ------------------------------------
*
* Programa para manejar un motor paso a paso unipolar extraido de una
* unidad de disquette de 5'25. De acuerdo a la documentación que
* he encontrado, este: "[...] motor paso a paso fabricado por
* Copal Electronics, con 1,8 grados por paso y 96 ohmios por cada
* vuelta (de la bobina), con una etapa central conectada a diferentes
* cables [...]"
* [http://www.cs.uiowa.edu/~jones/step/example.html]
*
* Es un motor paso a paso unipolar con cinco cables:
*
* - rojo: conector de alimentación, lo tengo a 5V y funciona bien
* - naranja y negro: bobina 1
* - marrón y amarillo: bobina 2
*
* (cleft) 2005 DojoDave for K3
* http://www.0j0.org | http://arduino.berlios.de
*
* @author: David Cuartielles
* @date: 20 Oct. 2005
*/
int motorPins[] = {8, 9, 10, 11}; // PIN-es del motor
int count = 0; // Contador 1
int count2 = 0; // Contador 2
int delayTime = 500; // Delay que determina
la velocidad de giro
int val = 0;

void setup() {

for (count = 0; count < 4; count++) { // Configuración de


los PIN-es como salida digital
pinMode(motorPins[count], OUTPUT);
}

void moveForward() {

if ((count2 == 0) || (count2 == 1)) { // Mueve el motor hacia


delante. Para hacerlo desplaza los
count2 = 16;
} // bits de la vable
count2 entre los PIN-es del motor.
count2>>=1;
for (count = 3; count >= 0; count--) { // 16 = 00010000 -->
00001000 --> 00000100 --> 00000010 ...
digitalWrite(motorPins[count], count2>>count&0x01);
}
delay(delayTime);

void moveBackward() {

if ((count2 == 0) || (count2 == 1)) { // Mueve el motor


hacia delante. Para hacerlo desplaza los
count2 = 16; // bits de la vable
count2 entre los PIN-es del motor.
}
count2>>=1;
for (count = 3; count >= 0; count--) { // 16 = 00010000 -->
00001000 --> 00000100 --> 00000010 ...
digitalWrite(motorPins[3 - count], count2>>count&0x01);
}
delay(delayTime);

void loop() {
val = analogRead(0);
if (val > 540) { // Cuanto mayor es el
valor del potenciómetro
delayTime = 2048 - 1024 * val / 512 + 1; // más rápido se
mueve hacia delante
moveForward();
} else if (val < 480) { // Cuanto menor es el
valor del potenciómetro
delayTime = 1024 * val / 512 + 1; // más rápido se
mueve hacia atrás
moveBackward();
} else {
delayTime = 1024; // Cuando el valor del
potenciometro se encuentra
} // en la zona media,
el motor se para.

Manejando múltiples salidas con un driver de LED-s

En este ejemplo pretendemos mostrar la forma de utilizar un número elevado de LED-s


utilizando tan sólo 4 PIN-es. Para ello utilizaremos un driver 4794 de Phiplips.

Un driver de LED-s tiene incorporado un registro de desplazamiento que recibe los datos en
formato serie y los transfiere en paralelo. Es posible encadenar chips según el esquema daisy
chain, incrementando, cada vez en 8, el número de LED-s.

Múltiples salidas digitales con un 74HC595

Tarde o temprano te verás sin suficientes pines en tu placa de Arduino y necesitarás


extenderlos con "shift registers" (registros de desplazamiento ¿?). Este ejemplo se basa en el
74HC595, descrito por su documentación técnica como un registro con entrada serial, con
salida serial o paralela y con interruptores de salida; 3 estados. (“8-bit serial-in, serial or
parallel-out shift register with output latches; 3-state.”) En otras palabras puedes usarlo para
controlar 8 salidas al mismo tiempo pero usando unos pocos pines del Arduino. Y puedes
enlazar varios registros para extender aún más tus salidas.

La forma en que todo esto funciona es a través de algo llamado “comunicación serial
sincrónica” que permite prender y apagar un pin de manera que se transmitan datos al registro
bit por bit. A través de un segundo pin llamado “Reloj” se indican los momentos
correspondientes a cada bit. Este sistema es lo contrario de la “comunicación serial
asincrónica” de la función Serial.begin(), que se basa en que el emisor y el receptor se
establecen de manera independiente sobre una tasa acordada de transmisión de datos. En
nuestro caso, cuando un byte completo se ha transmitido, los pulsos altos y bajos que
corresponden a cada bit se colocan en cada uno de los 8 pines de salida del 74HC595. Esta es
la función de salida paralela, en donde todos los pines hacen lo que tú indicaste al mismo
tiempo.
La función de salida serial del 74HC595 se puede realizar gracias a un pin adicional que
puede pasar la información recibida del Arduino de nuevo y sin cambios. Esto significa que
puedes transmitir 16 bits en fila (2 bytes), de manera que los primeros 8 pasarán de un primer
registro a un segundo y quedarán grabados allí. En el segundo ejemplo de este documento
aprenderás a hacerlo.

“3 estados” hace referencia a que puedes establecer la salida como “High”, “Low”, o “High
impedance”. A diferencia de los estados HIGH o LOW, no se puede colocar cada pin en alta
impedancia por separado, solamente se puede hacer con el chip completo. Esta es una labor
bastante especializada y ningún ejemplo de este cursillo usa esa propiedad y normalmente no
tendrás que preocuparte por obtener un chip que la tenga.

Esta es la representación del registro y una tabla que explica los pines adaptada de la hoja
técnica de Phillips.

PINS 1-7, 15 Q0 – Q7 Pines de salida

PIN 8 GND Tierra, Vss

PIN 9 Q7’ Salida serial

PIN 10 MR Reset Maestro. Activo en LOW

PIN 11 SH_CP Shift register clock pin

PIN 12 ST_CP Storage register clock pin (latch pin)

PIN 13 OE Salida activada. Activo en LOW.

PIN 14 DS Entrada de datos Serial

PIN 16 Vcc Alimentación, voltaje positivo.


1er Ejemplo: Un registro.

1. Instalación

El primer paso es extender tu Arduino con un registro. Para hacer esto realiza las siguientes
conexiones:

 GNG (oin 8) a tierra.


 Vcc (pin 5) a 5V.
 OE (pin 13) a tierra.
 MR (pin 10) a 5V.

Esta configuración hace que todos los pines de salida estén activos y sean accesibles todo el
tiempo. El único problema de esta configuración es que los pines retornan a su estado anterior
o a alguna cosa arbitraria desde que enciendes el circuito hasta que el programa comienza a
andar. Se puede solucionar controlando los pines MR y OE desde tu Arduino, pero así nada
más sirve y gastas menos pines.

2. Conéctalo al Arduino.
 DS (pin 14) al pin digital 11 (cable azul)
 SH_CP (pin 11) al pin digital 11 (cable amarillo)
 ST_CP (pin 12) al pin digital 8 (cable verde)

Desde ahora nos referiremos a ellos como el pinDatos, el pinReloj y el pinCierre,


respectivamente. Observa el condensador de 0.1 µf en el pinCierre, si tienes algo de
parpadeos cuando el pinCierre pulsa puedes usar este condensador para solucionarlo.

3. Agrega 8 LEDs.

En este caso debes conectar el cátodo de cada LED a una tierra en común y el ánodo a su
respectivo pin de salida del registro. Usar el registro así, como origen del poder, se denomina
fuente de corriente. Algunos registros no pueden servir como fuente de poder, solamente
pueden asimilar corriente. Si tienes un registro así, deberás invertir la dirección de los LED,
colocando los ánodos directamente sobre el poder y los cátodos (tierras) en los pines de
salida. Vale la pena aclarar que en este último caso cuando el pin de salida se encuentre
activo el LED se apagará.
4. El código

El código se basa en dos partes de la información de la hoja técnica: el diagrama de tiempos y


la tabla lógica. La tabla lógica es la que te indica básicamente todo lo importante que pasa en
un tiempo. Cuando el pinReloj pasa de LOW hacia HIGH el registro lee el estado del
pinDatos. Cuando los datos son empujados hacia el registro, van siendo salvados en una
memoria interna. Cuando el pinCierre pasa de LOW a HIGH los datos enviados son
traspasados de la memoria interna hacia los pines de salida, prendiendo los LEDs.
He aquí 3 ejemplos de código. El primero es solamente el código “Hola mundo” que enviará
los bytes desde 0 a 255. El segundo programa prende los LEDs uno por uno. El tercero
recorre una pila de datos.

1.1 Hola Mundo


1.1 Uno por uno
1.1 Desde una pila de datos
(en inglés -aún-).

2do Ejemplo: Dos registros.

En este ejemplo añadirás un Segundo registro, doblando así el número de pines de salida
mientras sigues usando el mismo número de pines en tu Arduino.

1. Agrega otro registro.

Comenzando desde el ejemplo anterior, debes añadir un segundo registro en la placa de


prototipos. Debe tener las mismas conexiones de poder y tierra.

2. Conecta los 2 registros.

Dos de estas conexiones simplemente extienden las conexiones Reloj y Cierre del Arduino al
segundo registro (cables amarillo y verde). El cable azul debe ir desde el pin de salida serial
(pin 9) del primer registro a la entrada serial (pin 14) del segundo registro.

3. Agrega otro grupo de LEDs.

En este caso agregaremos LEDs verdes para que cuando leas el códido sea claro cuál Byte
están llegando a cada grupo de LEDs.
4. El código

Nuevamente tenemos 3 ejemplos de código. Si eres curioso, puedes probar los ejemplos del
primer ejercicio con este circuito para ver qué sucede. (En inglés aún).

2.1 Doble contador binario.

Solamente hay una línea adicional de código con respecto al primer ejercicio, que envía un
segundo Byte. Esto fuerza al primer registro, el que está directamente conectado al arduino, a
pasar el primer dato enviado al segundo registro, prendiendo así los LEDs verdes, el segundo
Byte va a ser mostrado en los LEDs rojos.

2.2 Uno por uno.

En comparación al código del primer ejercicio, notarás que este ha cambiado un poco más.
La función parpadeo() ha sido cambiada por la función parpadeo_2Bytes() para reflejar el
hecho de que ahora hay 16 LEDs que controlar. Además en la versión 1 los pulsos del
pinCierre estaban situados dentro de la subfunción desplazarLuzA() y desplazarLuzB()
mientras que ahora se deben ubicar nuevamente en el Loop principal para poder correr cada
función dos veces en línea una para los LEDs verdes y otras para los rojos.

2.3 Pilas de datos dobles

Como en el ejemplo 2.2, el 2.3 también toma provecho de la nueva función


parpadeo_2Bytes(). La gran diferencia con el 1.3 es que en vez de una sola variable llamada
“dato” y una sola pila llamada “pilaDatos” tienes que definir datoRojo, datoVerde,
pilaDatosRojo, pilaDatosVerde desde el principio. Esto significa que las lineas:

dato = pilaDatos[j];

se vuelve:

datoRojo = pilaDatosRojo[j];

datoVerde = pilaDatosVerde[j];

enviarDato(pinDatos, pinReloj, dato);

se vuelve:

enviarDato(pinDatos, pinReloj, datoRojo);

enviarDato(pinDatos, pinReloj, datoVerde);


Detalle del conexionado de un driver Philips 4794
Esquema
Montaje de un driver Philips 4794

El código del ejercicio que sigue a continuación toma el valor almacenado en la variable dato
y lo muestra como un número binario decodificado. Por ejemplo, si la variable dato es 1, sólo
se encendera el primer LED. Si la variable dato es 255, se encenderán todos los LED.

Código fuente

/* Driver Philips 4794

* -------------------
*
* Muestra un byte almacenado en la variable dato
* en una fila de 8 LED-s
*
* (copyleft) 2005 K3, Malmo University
* @author: David Cuartielles, Marcus Hannerstig
* @hardware: David Cuartielles, Marcos Yarza
* @project: made for SMEE - Experiential Vehicles
*/
int data = 9; // PIN-es digitales de la placa
conectados al chip
int strob = 8;
int clock = 10;
int oe = 11;
int count = 0; // Contador
int dato = 0; // Variable dato

void setup() {

beginSerial(9600); // El puerto serie trabajrá a


9600 baudios
pinMode(data, OUTPUT); // Configuración de los PIN-es
digitales
pinMode(clock, OUTPUT);
pinMode(strob, OUTPUT);
pinMode(oe, OUTPUT);

void PulseClock(void) {

digitalWrite(clock, LOW); // Procedimiento que emite un


pulso de reloj
delayMicroseconds(20);
digitalWrite(clock, HIGH);
delayMicroseconds(50);
digitalWrite(clock, LOW);

void loop() {

dato = 5; // 5 en binario es 00000101


for (count = 0; count < 8; count++) {
digitalWrite(data, dato & 01); // Obtiene el bit de más a la
derecha (00000101 AND 00000001 = 00000001) y lo escribe en la entrada serie
del chip
//serialWrite((dato & 01) + 48);
dato>>=1; // Desplaza un bit a la derecha
de la variable dato (00000101 --> 00001010)
if (count == 7){ // Cuando ha enviado los 8 bits
se lo indica al chip
digitalWrite(oe, LOW);
digitalWrite(strob, HIGH);
}
PulseClock(); // Envía un pulso de reloj
digitalWrite(oe, HIGH); // Le indica al chip que le ha
enviado un bit
}
delayMicroseconds(20);
digitalWrite(strob, LOW);
delay(100);
serialWrite(10);
serialWrite(13);
delay(100);

You might also like