Arduino Mega. Puertos I/O Digitales.


Click en la imagen para mayor detalle.

Me he decidido a hacer el robot hexápodo con un AVR para ver si consigo aprender algo de estos micros, al ser un proyecto grande y complejo se tocarán la mayoría de las posibilidades de los micros por lo que es ideal para aprender. Para ello voy a usar la placa de Arduino Mega que me parece lo mejor que se puede conseguir en características/coste, esta placa me ha cambiado todos los proyectos que tenía pensados para estos meses... Resumiré todos los avances que haga aquí para mantenerlos ordenados y a mano cuando los necesite recordar, si no suelo perderlos y olvidar. Voy desde cero por lo que será largo y nada de lo que escriba tiene que estar bien.. lo único que puedo hacer es verificar el correcto funcionamiento de los pasos que vaya dando, si alguien quema su Arduino que no me eche la culpa x_x.

Lo primero es identificar los puertos que tenemos disponibles en los conectores de la placa, y por tanto los puertos que podemos usar. Los puertos con un punto en el dibujo son los que tienen conexión al mundo exterior a través de los distintos conectores de la placa, los puntos azules son los puertos que van conectados al integrado FTDI, es decir el RX y TX para la comunicación en serie, van conectados mediante una resistencia de 1K en serie por lo que los podemos usar para nuestros fines, aunque teniendo la conexión usb montada en la placa mejor dejarlos para lo que están. Los puntos dobles  tienen dos conectores distintos en la placa del arduino (accesibles desde dos sitios).



Los pines de los puertos, su situación en la placa del Arduino y sus funciones alternativas:

PA0: Pin Micro 78. Pin Arduino: conector digital, pin 22. Funciones: AD0 (External memory interface address and data bit 0).
PA1: Pin Micro 77. Pin Arduino: conector digital, pin 23. Funciones: AD1.
PA2: Pin Micro 76. Pin Arduino: conector digital, pin 24. Funciones: AD2.
PA3: Pin Micro 75. Pin Arduino: conector digital, pin 25. Funciones: AD3.
PA4: Pin Micro 74. Pin Arduino: conector digital, pin 26. Funciones: AD4.
PA5: Pin Micro 73. Pin Arduino: conector digital, pin 27. Funciones: AD5.
PA6: Pin Micro 72. Pin Arduino: conector digital, pin 28. Funciones: AD6.
PA7: Pin Micro 71. Pin Arduino: conector digital, pin 29. Funciones: AD7.

PB0: Pin Micro 19. Pin Arduino: conector digital, pin 53. Funciones: SS/PCINT0.
PB1: Pin Micro 20. Pin Arduino: conector digital, pin 52. Conector ICSP, pin 3. Funciones: SCK/PCINT1.
PB2: Pin Micro 21. Pin Arduino: conector digital, pin 51. Conector ICSP, pin 4. Funciones: MOSI/PCINT2.
PB3: Pin Micro 22. Pin Arduino: conector digital, pin 50. Conector ICSP, pin 1. Funciones: MISO/PCINT3.
PB4: Pin Micro 23. Pin Arduino: conector PWM, pin 10. Funciones: OC2A/PCINT4.
PB5: Pin Micro 24. Pin Arduino: conector PWM, pin 11. Funciones: OC1A/PCINT5.
PB6: Pin Micro 25. Pin Arduino: conector PWM, pin 12. Funciones: OC1B/PCINT6.
PB7: Pin Micro 26. Pin Arduino: conector PWM, pin 13. Funciones: OC0A/OC1C/PCINT7.

PC0: Pin Micro 53. Pin Arduino: conector digital, pin 37. Funciones: A8(External Memory interface address bit 8).
PC1: Pin Micro 54. Pin Arduino: conector digital, pin 36. Funciones: A9.
PC2: Pin Micro 55. Pin Arduino: conector digital, pin 35. Funciones: A10.
PC3: Pin Micro 56. Pin Arduino: conector digital, pin 34. Funciones: A11.
PC4: Pin Micro 57. Pin Arduino: conector digital, pin 33. Funciones: A12.
PC5: Pin Micro 58. Pin Arduino: conector digital, pin 32. Funciones: A13.
PC6: Pin Micro 59. Pin Arduino: conector digital, pin 31. Funciones: A14.
PC7: Pin Micro 60. Pin Arduino: conector digital, pin 30. Funciones: A15.

PD0: Pin Micro 43. Pin Arduino: conector Communication, pin 21. Funciones: INT0/SCL.
PD1: Pin Micro 44. Pin Arduino: conector Communication, pin 20. Funciones: INT1/SDA.
PD2: Pin Micro 45. Pin Arduino: conector Communication, pin 19. Funciones: INT2/RXD1.
PD3: Pin Micro 46. Pin Arduino: conector Communication, pin 18. Funciones: INT3/TXD1.
PD4: Pin Micro 47. Pin Arduino: Sin conexión. Funciones: ICP1.
PD5: Pin Micro 48. Pin Arduino: Sin conexión. Funciones: XCK1.
PD6: Pin Micro 49. Pin Arduino: Sin conexión. Funciones: T1 (Timer/Counter1 Clock Input).
PD7: Pin Micro 50. Pin Arduino: conector digital, pin 38. Funciones:T0 (Timer/Counter0 Clock Input).

PE0: Pin Micro 2. Pin Arduino: conector PWM, pin 0. RX0 FTDI R de 1K en serie. Funciones: PDI/RXD0/PCINT8.
PE1: Pin Micro 3. Pin Arduino: conector PWM, pin 1. TX0 FTDI, R de 1K en serie. Funciones: PDO)/TXD0.
PE2: Pin Micro 4. Pin Arduino: Sin conexión. Funciones: AIN0/XCK0.
PE3: Pin Micro 5. Pin Arduino: conector PWM, pin 5. Funciones: AIN1/OC3A.
PE4: Pin Micro 6. Pin Arduino: conector PWM, pin 2. Funciones: INT4/OC3B.
PE5: Pin Micro 7. Pin Arduino: conector PWM, pin 3. Funciones: INT5/OC3C.
PE6: Pin Micro 8. Pin Arduino: Sin conexión. Funciones: INT6/ T3.
PE7: Pin Micro 9. Pin Arduino: Sin conexión. Funciones: INT7/ICP3/CLK0.

PF0: Pin Micro 97. Pin Arduino: conector Analog In, pin 0. Funciones: ADC0 (ADC input channel 0).
PF1: Pin Micro 96. Pin Arduino: conector Analog In, pin 1 Funciones: ADC1.
PF2: Pin Micro 95. Pin Arduino: conector Analog In, pin 2. Funciones: ADC2.
PF3: Pin Micro 94. Pin Arduino: conector Analog In, pin 3. Funciones: ADC3.
PF4: Pin Micro 93. Pin Arduino: conector Analog In, pin 4. Funciones: ADC4/TCK.
PF5: Pin Micro 92. Pin Arduino: conector Analog In, pin 5. Funciones: ADC5/TMS.
PF6: Pin Micro 91. Pin Arduino: conector Analog In, pin 6. Funciones: ADC6/TDO.
PF7: Pin Micro 90. Pin Arduino: conector Analog In, pin 7. Funciones: ADC7/TDI.

PG0: Pin Micro 51. Pin Arduino: conector digital, pin 41. Funciones: WR (Write strobe to external memory).
PG1: Pin Micro 52. Pin Arduino: conector digital, pin 40. Funciones: RD (Read strobe to external memory).
PG2: Pin Micro 70. Pin Arduino: conector digital, pin 39. Funciones: ALE (Address Latch Enable to external memory).
PG3: Pin Micro 28. Pin Arduino: Sin conexión. Funciones: TOSC2 (RTC Oscillator Timer/Counter2).
PG4: Pin Micro 29. Pin Arduino: Sin conexión. Funciones: TOSC1 (RTC Oscillator Timer/Counter2).
PG5: Pin Micro 1.   Pin Arduino: conector PWM, pin 4. Funciones: OC0B.
PG6: No implementado
PG7: No implementado

PH0: Pin Micro 12. Pin Arduino: conector Communication, pin 17. Funciones: RXD2.
PH1: Pin Micro 13. Pin Arduino: conector Communication, pin 16. Funciones: TXD2.
PH2: Pin Micro 14. Pin Arduino: Sin conexión. Funciones: XCK2.
PH3: Pin Micro 15. Pin Arduino: conector PWM, pin 6. Funciones: OC4A.
PH4: Pin Micro 16. Pin Arduino: conector PWM, pin 7. Funciones: OC4B.
PH5: Pin Micro 17. Pin Arduino: conector PWM, pin 8. Funciones: OC4C.
PH6: Pin Micro 18. Pin Arduino: conector PWM, pin 9. Funciones: OC2B.
PH7: Pin Micro  27. Pin Arduino: Sin conexión. Funciones: T4(Timer/Counter4 Clock Input).

PJ0: Pin Micro 63. Pin Arduino: conector Communication, pin 15. Funciones: RXD3/PCINT9.
PJ1: Pin Micro 64. Pin Arduino: conector Communication, pin 14. Funciones: TXD3/PCINT10.
PJ2: Pin Micro 65. Pin Arduino: Sin conexión. Funciones: XCK3/PCINT11.
PJ3: Pin Micro 66. Pin Arduino: Sin conexión. Funciones: PCINT12.
PJ4: Pin Micro 67. Pin Arduino: Sin conexión. Funciones: PCINT13.
PJ5: Pin Micro 68. Pin Arduino: Sin conexión. Funciones: PCINT14.
PJ6: Pin Micro 69. Pin Arduino: Sin conexión. Funciones :PCINT15
PJ7: Pin Micro 79. Pin Arduino: Sin conexión. Funciones: Ninguna.

PK0: Pin Micro 89. Pin Arduino: conector Analog In, pin 8. Funciones: ADC8 /PCINT16.
PK1: Pin Micro 88. Pin Arduino: conector Analog In, pin 9. Funciones: ADC9/PCINT17.
PK2: Pin Micro 87. Pin Arduino: conector Analog In, pin 10. Funciones: ADC10/PCINT18.
PK3: Pin Micro 86. Pin Arduino: conector Analog In, pin 11. Funciones: ADC11/PCINT19.
PK4: Pin Micro 85. Pin Arduino: conector Analog In, pin 12. Funciones: ADC12/PCINT20.
PK5: Pin Micro 84. Pin Arduino: conector Analog In, pin 13. Funciones: ADC13/PCINT21.
PK6: Pin Micro 83. Pin Arduino: conector Analog In, pin 14. Funciones: ADC14/PCINT22.
PK7: Pin Micro 82. Pin Arduino: conector Analog In, pin 15. Funciones: ADC15/PCINT23.

PL0: Pin Micro 35. Pin Arduino: conector digital, pin 49. Funciones: ICP4.
PL1: Pin Micro 36. Pin Arduino: conector digital, pin 48. Funciones: ICP5.
PL2: Pin Micro 37. Pin Arduino: conector digital, pin 47. Funciones: T5.
PL3: Pin Micro 38. Pin Arduino: conector digital, pin 46. Funciones: OC5A.
PL4: Pin Micro 39. Pin Arduino: conector digital, pin 45. Funciones: OC5B.
PL5: Pin Micro 40. Pin Arduino: conector digital, pin 44. Funciones: OC5C
PL6: Pin Micro 41. Pin Arduino: conector digital, pin 43. Funciones: Ninguna.
PL7: Pin Micro 42. Pin Arduino: conector digital, pin 42. Funciones: Ninguna.

En total tenemos unos 70 pines de entrada/salida accesibles desde el mundo exterior, de los que16 los podemos usar como adc, 14 como salidas pwm,  tenemos 4 USART,  un I2C o TWI,  y un SPI, conexión USB para el PC y el botón de Reset. Y más funciones que todavía desconozco y no puedo evaluar, junto a  una buena cantidad de memoria hace que en principio parezca una placa ideal para el proyecto del Hexápodo.


Puertos de entrada salida. Fuente Datasheet.

En los microcontroladores los puertos se pueden configurar como entrada/salida digital, la mayoría de ellos además llevan otras funciones alternativas multiplexadas que requieren de hardware adicional integrado en el propio puerto, éste lo iré viendo según vaya necesitando esas funciones. Los puertos son capaces de suministrar o absorber una corriente máxima de 40 mA @ 5V, que nunca se deberá sobrepasar ya que podemos quemar el puerto o el microcontrolador, y este micro suelto sale por unos 25 euros, además de las 100 patas que hay que soldar para cambiarlo.

El esquema equivalente de entrada para el puerto digital es el siguiente:




Se pueden ver un par de diodos de protección, la capacitancia del pin y una resistencia de pull-up que podemos activar o desactivar cuando configuremos el puerto como entrada, lo que en algunos casos nos ahorrará poner una resistencia externa.

Por cada puerto tenemos en la memoria tres registros de ocho bits para su uso y configuración, DDRx, PORTx, y PINx



PORTx: es usado para escribir datos en el puerto.
DDRx: sirve para configurar el puentro como entrada (0) o salida (1), al revés que en los pic.
PINx: es usado para leer datos en el puerto.

Poniendo 0 en el bit DDA7 del registro DDRA, configuraríamos el pin 7 del puerto A como entrada, si en el registro PORTA, en su bit PORTA7 ponemos un 0 desactivamos la resistencia de pull-up del pin7 del puerto A (PA7), si ponemos un 1 en lugar del 0 activamos esta resistencia. El bit PUD del registro MCUCR hábilita (0) o deshábilita (1) todas las resistencias de pull-up independientemente del valor de los bits en PORTx (x: designa el puerto). Para leer el valor que tenemos en la entra del pin7 los hacemos en el bit PINA7 del registro PINA.

Si queremos configurar este mismo pin como salida debemos de poner un 1 en el bit DDA7 del registro DDRA, y para poner a uno (suministra corriente) o cero (absorbe corriente) la salida lo hacemos en el bit PORTA7 del registro PORTA. Si el pin está configurado como entrada PORTA activa o desactiva las resistencias de pull-up, y si  el puerto está configurado como salida PORTA asigna el valor de los pines de salida.


x: designa el puerto.
n: designa el pin.

El esquema digital del puerto donde entran los bits de configuración anteriores es el siguiente:


Hello World!

Un primer programa para comprobar el funcionamiengo dle Arduino Mega desde el AVR Studio y la configuración y funcionamiento de lo anterior. Para programar el Arduino se va a usar un programador externo directamente conectado al conector que trae de ICSP y no el Bootloader con el que podemos programar el micro a través de su USB que viene grabado en la placa de Arduino. En lugar de usar el entorno de programación de Arduino se usa el AVR Studio con el WinAVR de compilador, aunque estoy planteandome usar uno comercial, CodevisionAVR (160 euros) que por lo poco que he visto me gusta más que el WinAVR.


Primer código para AVR..

/****************************************************************************************
*Configuración puertos digitales.
*PORTA0: entrada, pulsador, pull-up off.
*PORTA1: entrada, pulsador, pull-up on.
*PORTA2: salida, diodos led.
*PORTA3: salida, diodo led.
*PORTA4: salida, osciloscopio
*Funcionamiento: PA2=PA0, PA3=PA1, PA4 cambia valor en cada iteracción.
*
******************************************************************************************/
#include <avr/io.h> 
void inicializar_puertos(void);

int main(void)
{
   inicializar_puertos();
   char leer_pin=0;

   while(1)
   {
    PORTA ^= 0x10; //0001 0000. 0^1=1 no afecta el pull-up de PA1
      
//Si PA0=1 activamos la salida PA2, si no la desactivamos
    leer_pin= PINA & (1<<PINA0);
    if(leer_pin)
        PORTA |= (1<<PORTA2); //Rojo
    else
        PORTA &= ~(1<<PORTA2); //Verde

//Si PA1=1 activamos la salida PA3, si no la desactivamos   
    leer_pin= PINA & (1<<PINA1);  
    if(leer_pin)
        PORTA |= (1<<PORTA3); //Amarillo ON
    else
        PORTA &= ~(1<<PORTA3); //Amarillo OFF    
   }
}

// Funciones
void inicializar_puertos(void)
{
   DDRA=0x1C;     //0001 1100 2,3,4 Salidas.
   PORTA=0x02;    //0000 0010 Resistencia de pull-up activada en PA1            
}


Tenemos dos pulsadores y 3 diodos led, un pulsador conectado mediante la resistencia de Pull-up interna del micro activa y apaga un diodo led, el otro pulsador enciende o apaga los otros dos diodos led, un diodo led se enciende cuando el microcontrolador proporciona corriente (salida a 5V) y el otro cuando absorbe corriente (salida a 0V). Una tercera salida cambia su estado en cada iteracción del búcle, de esta forma podemos ver a que frecuencia se ejecuta el programa en el micro.

Lo primero y que no sé como se puede hacer, es acceder a los pines de cada puerto de forma directa como se hace con otros compiladores, aquí tenemos que usar operaciones OR o AND para leer o escribir un sólo bit sin afectar a los demás, por ejemplo leer_pin= PINA & (1<<PINA1);, haría la operación AND del valor del puerto A con (1<<PINA0). PINA0=0, PINA1=1, etc.. son valores que tenemos definidos en las librerias del micro, por lo que haríamos una operación de desplazamiento a la izquierda sobre el valor 1 (00000001) de 1 bit en este caso obteniendo (00000010). Lo que nos da la siguiente operación: PINA (xxxxxxxx)&(00000010) = (000000X0), sacando el 1 o el 0 del puerto que queremos leer, pasandolo por el if(leer_pin) si éste es distinto de cero tenemos un 1 en el pin que hemos leído. En fin, con lo fácil que sería hacer if(PORTA.1) en lugar de todo eso. Y lo mismo para asignar una salida, tenemos que hacer la operación de OR sobre el puerto con los bits que queramos activar puestos a 1 en el Byte, y si queremos poner a cero pues la operación de AND sobre el puerto con los bits que queramos desactivar puestos a cero en el byte y el resto a 1. Si queremos desactivar sólo un pin por ejemplo en: ~(1<<PORTA2); obtendríamos el valor (11111011) el operador ~ invierte, lo que pondría a cero ese pin al hacer la AND con el puerto dejando el resto como estaban.

Con PORTA ^= 0x10;  hacemos que el bit4 del byte cambie en cada iterración, 0^0 = 0, 0^1=1, 1^0=1, 1^1=1, ya que hacemos la operación con 00010000, dejando los demás bytes del bit sin afectar a hacer su operación con un 0, 0^X=X.


Esquema electrónica conectada a Arduino. (Los nombres de las parejas están cambiado en la protoboard).



Video del funcionamiento:


El funcionamiento no ha sido del todo correcto, la resistencia de Pull-up me hacía una cosa rara y no sé porque, tengo que buscar de cuanto es el valor de esta R y sus detalles.. Los pulsadores y los leds funcionan de la manera esperada como se puede ver en el video, pero cuando pulsaba el pulsador del los leds rojo y verde, metiendo un cero al pin del micro y por tanto poniendo un cero en su correspondiente salida, en la otra salida (led amarillo) podía apreciar como el brillo del led era menor encontrando la siguiente salida:



La razón ni idea, no sé si el error está en el código o donde, no veo que en ningún momento desactive la resistencia de pull-up en PORTA, además tiene una frecuancia de 50Hz por lo no creo que sea el código. Poniendo una resistencia externa en el pulsador se soluciona el problema.

En el pin 4 (el que cambia en cada paso por el búcle) aparece la siguiente señal:





La frecuencia del programa es de 148.1 KHz, el reloj de la placa es de 16MHz pero en los fuses a la hora de seleccionar el reloj sólo me parece opciones de 8 MHz, por lo que no sé si lo tengo bien configurado, y una Vpp de 8.72V.

Me queda mucho que  leer y estudiar para empezar a manejar estos micros, la primera impresión del WinAVR no ha sido satisfactoria, he visto código del CodeVision AVR y me parece más amigable, sobretodo porque te permite hacer operaciones a nivel de pin en los puertos de salida sin tener que estar usando ANDs y ORs y demás operadores de bits, su precio es de 160 euros y dadas las horas que voy a dedicar a este proyecto que van a ser muchas puede que me merezca la pena la ineversión, así que voy a ver si me informo bien. Si alguien tiene experiencia con estos micros, conoce varios compiladores y me puede aconsejar se lo agradezco, porque acabo de empezar con ellos y ando muy perdido. Cualquier recomendación de libros o manuales también vienen bien (de momento estoy empezando a leer todo lo que encuentro por internet).

Para cualquier comentario más abajo, gracias, saludos.
blog comments powered by Disqus