Plataforma Robótica

From Qi-Hardware
Jump to: navigation, search
  1. Ivan Mauricio Rodríguez 1
  2. Andrés Mauricio Rodríguez 1
  3. Gerson Darío Piraquive 1


Contents

[edit] Calificación

Porcentaje Presentación 20% Informe 30% Funcionamiento 50%
1 Entrega 10% 1 1 1
2 Entrega 30% 2 2 2
3 Entrega 30% 2 2 2


4 Entrega 30% 5 5 5

[edit] Proyecto

Para el proyecto final de la materia de Sistemas Embebidos, se trabajará con la tarjeta SIE (antes llamada SAKC). Esta tarjeta cuenta principalmente con un SoC de Ingenic Semiconductor Jz4725 y una FPGA Xilinx Spartan 3E XC3S500E, además de varios periféricos que la hacen una solución multimedia ́óptima para productos de MP3, MP4 y dispositivos móiles portables. El procesador del SoC es un XBurst core de 32 bits, el cual utiliza un conjunto de instrucciones SIMD y RISC, en combinación con una unidad de post-procesamiento de video.

[edit] Descripción

El proyecto a realizar es una brazo mecánico que contará con servomotores para controlar el ángulo de posición de cada articulación. Este brazo tendrá tres grados de libertad los cuales se pueden interpretar como hombro, codo y pinza, utilizado para diferentes fines como agarrar objetos, lanzárlos, manipularlos, etc. Como aplicación específica el brazo tomará objetos de una banda transportadora y los colocará en otro lugar. Para poder ubicar el objeto, se colocará un sensor de proximidad en un punto determinado y cuando éste lo detecte, la banda parará su movimiento

Para su funcionamiento, los motores y servomotores necesitan una etapa de potencia, puesto que necesitan mucha corriente. Se usará un convertidor DC-DC y optoacopladores para ponerle protección a los circuitos utilizados. Para el movimiento de la banda transportadora se usarán motores de corriente continua controlados por un puente H.

Con el fin de tener un control más práctico de los servomotores, se colocarán tres potenciómetros para aumentar o reducir la tensión que llega a las entradas análogas en los terminales del ADC. Esta tensión corresponderá a un ciclo útil del PWM.

[edit] Funciones

La plataforma tendrá las siguientes funciones:

  • Tomar un objeto.
  • Arrojar el objeto.
  • Controlar el movimiento de cada articulación del brazo.
  • Tomar objetos de una banda transportadora y desplazarlos.

[edit] Herramientas Hardware

  • Tarjeta SIE
  • Power Driver

Este driver nos permitirá controlar los motores de desplazamiento de la plataforma en las dos direcciones y además nos proporciona una parada rápida, que frena inmediatamente el motor.

  • Convertidores DC-DC

Los convertidores nos servirán para alimentar los motores y los servomotores, haciendo una función de step-up de tensión de 4.5V a 6V. En este caso la corriente de salida es aproximadamente 500 mA. Si se considera que cada motor/servomotor consume un valor máximo 200 mA, es decir, exigiéndolo por completo, estos convertidores nos sirven para nuestro propósito.

  • Servomotores (HiTec 311, Futaba S3006, TowerPro SMG995R)

El rango de ciclos útiles de los servos es 193 a 238 para la base, 222 a 234 para el codo y 216 a 225 para la pinza.

  • Optoacopladores (MOCD213)

[edit] Herramientas Software

  • Lua

Lua es un poderoso lenguaje "embebido". Esto significa que Lua no es un paquete autónmo, sino una librería que puede ser "enlazada" con otras aplicaciones para incorporar facilidades de Lua en estas aplicaciones.

Lua posee también un intérprete autónomo que ejecuta instrucciones (chunks) en tiempo real, interactuando con el usuario. De esta manera se van a controlar los movimientos del brazo mecánico.

  • Xilinx ISE WebPack

Herramienta para crear los módulos hardware en la FPGA de la SIE.

  • KiCAD

Con esta herramienta se diseñó el circuito impreso de montaje superficial.

[edit] Hardware

Para la plataforma robotica el componente de hardware consistira basicamente en:

1. PWM (pulse width modulation). Técnica mendiante la cual se modifica el ciclo de trabajo de una señal periodica para controlar la cantidad de energía que se envia a una carga.

2. Conversor ADC (Analog to digital converter). Conversión de una señal de entrada analogica en valor binario, para poderla manipular en los circuitos digitales. Las señales a convertir son las entregadas por cada uno de los sensores de proximidad (TCRT1000)

3. Controlador del integrado HIP4020 (Full Bridge Power Driver). Driver de potencia especialmente diseñado para motores DC pequeños.

[edit] Comunicación Procesador-Periféricos

Comunicación

[edit] Periféricos

Se usarán 5 periféricos determinados por el componente hardware descrito anteriormente, es decir, 3 módulos PWM, 1 controlador del ADC y 1 controlador del driver de motor.

[edit] PWM como periférico en la FPGA

Este periférico se encarga de controlar los servomotores dispuestos para el brazo.


Diagrama de periférico PWM


Como se observa en la figura anterior, este recibe 8 bits de información del procesador (sram_data) que determinan el ciclo útil de la señal periódica saliente (pwm), el periodo de esta señal esta determinado por un parámetro interno del modulo llamado temp1.

El diagrama de flujo se muestra a continuación en donde se explica el comportamiento del periferico.


Diagrama de flujo PWM

El modulo mostrado a continuación es la segunda versión del controlador de los 3 periféricos de pwm usados para el control de los servomotores.

  1.   `timescale 1ns / 1ps
  2. module pwm(pwm1, pwm2, pwm3, 
  3. wdBus, we, cs,
  4. reset, clk);
  5.   parameter     B = (7);
  6.  
  7.   input            clk, we, reset;
  8.   input [3:0]      cs;
  9.   input [B:0]      wdBus;
  10.  
  11.   output       pwm1, pwm2, pwm3;
  12.  
  13. //PWM
  14.   parameter temp = 500000;
  15.  
  16.   reg [25:0] temp1, temp2, temp3;
  17.   reg [25:0] counter1, counter2, counter3;
  18.   reg ck1, ck2, ck3;
  19.  
  20. //initialize	
  21. initial
  22. begin
  23. counter1 = 26'b0;
  24. counter2 = 26'b0;
  25. counter3 = 26'b0;
  26. temp1 = 26'b0;
  27. temp2 = 26'b0;
  28. temp3 = 26'b0;
  29. ck1=0;
  30. ck2=0;
  31. ck3=0;
  32. end
  33.  
  34.     //--------------------------------------------------------------------------
  35.  
  36. //PWM peripherial1
  37. always @(negedge clk)
  38. begin
  39. 	if (we & cs[1] & wdBus != temp1)     temp1 = wdBus * temp / 256;
  40. end
  41.  
  42.  
  43. always @(posedge clk)
  44. begin
  45. 	counter1 = counter1 + 1;
  46. 	if (counter1 <= temp1)
  47. 		ck1 = 1'b1;
  48. 	else
  49. 		begin
  50. 			if(counter1 == temp)
  51. 			counter1 = 26'b0;
  52. 			else
  53. 			ck1 = 1'b0;
  54. 		end
  55. end
  56.  
  57. //PWM peripherial2
  58. always @(negedge clk)
  59. begin
  60. 	if (we & cs[2] & wdBus != temp2)     temp2 = wdBus * temp / 256;
  61. end
  62.  
  63.  
  64. always @(posedge clk)
  65. begin
  66. 	counter2 = counter2 + 1;
  67. 	if (counter2 <= temp2)
  68. 		ck2 = 1'b1;
  69. 	else
  70. 		begin
  71. 			if(counter2 == temp)
  72. 			counter2 = 26'b0;
  73. 			else
  74. 			ck2 = 1'b0;
  75. 		end
  76. end
  77.  
  78. //PWM peripherial3
  79. always @(negedge clk)
  80. begin
  81. 	if (we & cs[3] & wdBus != temp3)     temp3 = wdBus * temp / 256;	
  82. end
  83.  
  84.  
  85. always @(posedge clk)
  86. begin
  87. 	counter3 = counter3 + 1;
  88. 	if (counter3 <= temp3)
  89. 		ck3 = 1'b1;
  90. 	else
  91. 		begin
  92. 			if(counter3 == temp)
  93. 			counter3 = 26'b0;
  94. 			else
  95. 			ck3 = 1'b0;
  96. 		end
  97. end
  98.  
  99. assign pwm1 = ck1;
  100. assign pwm2 = ck2;
  101. assign pwm3 = ck3;
  102.  
  103. endmodule


La frecuencia de la señal PWM es de 100 Hz. Escogimos esta frecuencia porque al hacer pruebas con los servos, éstos no pedían mucha corriente (alrededor de 400 mA), y si subíamos la frecuencia hasta 150 Hz se cuadruplicaba la corriente necesitada. El ciclo útil de la señal se define por el vector de 8 bits sram_data.

A continuación se muestra la simulación para este módulo,

Simulación modulo PWM

[edit] H_BRIDGE

Para el movimiento de la banda de la plataforma robótica se han dispuesto dos moto-reductores, cada uno es controlado a través de los driver de potencia Hip4020. Para el manejo de estos integrados se ha dispuesto este periférico.

El integrado recibe 3 señales de entrada (Brake, Direction y Enable) con las cuales controla la dirección del motor conectado a este. Estas tres señales son aportadas por el procesador (sram_data).


Diagrama de periférico H_BRIDGE


Aunque el comportamiento de este no es muy complicado, se expresa a continuación a través de un diagrama de flujo.


Diagrama de flujo H_BRIDGE

La descripción de hardware es la siguiente:

  1. `timescale 1ns / 1ps
  2.  
  3. module H_BRIDGE(brake, direction, enableM, wdBus, we, cs,reset, clk
  4.     		);
  5.  
  6. parameter     B = (7);
  7.  
  8. input         clk, we, reset, cs;
  9. input [B:0]   wdBus;
  10.  
  11. output brake, direction, enableM;
  12.  
  13. reg [B:0] temp;
  14. reg brakeB, directionB, enableB;
  15.  
  16. initial
  17. begin
  18. temp = 8'b0;
  19. brakeB = 0;
  20. directionB = 0;
  21. enableB = 0;
  22. end
  23.  
  24. always @(negedge clk)
  25. begin
  26. 	if (we & cs & wdBus != temp)  begin   
  27. 	    temp = wdBus;
  28. 	end			
  29. end
  30.  
  31. always @(posedge clk)
  32. begin
  33. 	brakeB = temp[0];
  34. 	directionB = temp[1];
  35. 	enableB = temp[2];
  36. end
  37.  
  38. assign brake = brakeB;
  39. assign direction = directionB;
  40. assign enableM = enableB;
  41.  
  42. endmodule

[edit] ADC

Se utilizó el controlador del ADC del ejemplo descrito en Scope. Este controlador se basa en el siguiente diagrama de tiempos.


Formas de onda del ADC TLV1548.

[edit] Diagramas de Bloques

Diagrama de bloques.

[edit] Esquemáticos y PCB

[edit] Software

[edit] Usando Lua

Como se mencionó en secciones anteriores, se va a usar Lua para ejecutar las acciones en tiempo real y llamar a las APIs escritas en C. Para comenzar implementamos el controlador del periférico PWM. Se tomó como referencia el ejemplo descrito en Lua_Blink_LED. TODAS las funciones utilizadas se encuentran repartidas en los archivos jz47xx_gpio.c, Control.c, ADCw.c, sram_gpio_wrap.c. jz_adc_peripherial.c es el mismo del usado en el ejemplo de Scope/es que toma el valor del puntero cuando se hace el mapeo de direcciones de la FPGA. En peripherials.lua se encuentran las funciones relacionadas con las rutinas.


Funciones en jz47xx_gpio.c

  1. void
  2. jz_belt (int stop)
  3. {	
  4. 	JZ_REG *virtual4;
  5.  
  6. 	virtual4 = ADCBuffer + 0x700;
  7.  
  8. 	if (stop==1)
  9. 	{
  10. 		virtual4[0]=5;
  11. 		usleep(500000);
  12. 	}
  13. 	else 
  14. 	{
  15. 		virtual4[0]=4;
  16. 		usleep(500000);
  17. 	}
  18. }
  19.  
  20. void
  21. jz_mapping (int duty, int motor)
  22. {
  23.   JZ_REG *virtual2, *virtual3, *virtual1;
  24.  
  25.   switch(motor)
  26. 	{	
  27. 	 case 1:  virtual1 = ADCBuffer + 0x200;
  28. 		  virtual1[0] = duty;
  29. 		  break;
  30. 	 case 2:  virtual2 = ADCBuffer + 0x400;
  31.  	      virtual2[0] = duty;
  32. 		  break;
  33. 	 default: virtual3 = ADCBuffer + 0x600;
  34. 		  virtual3[0]=duty;
  35. 		  break;
  36.  
  37. 	}
  38. }
  • jz_belt() se encarga de escribir en el periférico del puente H un valor alto o un valor bajo para que el motor gire o deje de girar.
  • jz_mmaping() escribe el valor del ciclo útil en el servomotor deseado.

Funciones en Control.c

  1. #define ref 245
  2. #define inc 37
  3. #define inc2 55
  4. #define inc3 70
  5.  
  6.  
  7. int control1(float a)
  8. {
  9. 	int b=215;
  10. 	int a_ant = 0;
  11.  
  12. 	if(a <= a_ant+20) a=a_ant;
  13. 	else if(a<=ref)b=193;
  14. 	else if(a>ref && a<=(ref+inc)) b=195;
  15. 	else if(a>(ref+inc) && a<=(ref+(inc*2))) b=197;
  16. 	else if(a>(ref+inc*2) && a<=(ref+(inc*3))) b=199;
  17. 	else if(a>(ref+inc*3) && a<=(ref+(inc*4))) b=201;
  18. 	else if(a>(ref+inc*4) && a<=(ref+(inc*5))) b=203;
  19. 	else if(a>(ref+inc*5) && a<=(ref+(inc*6))) b=205;
  20. 	else if(a>(ref+inc*6) && a<=(ref+(inc*7))) b=207;
  21. 	else if(a>(ref+inc*7) && a<=(ref+(inc*8))) b=209;
  22. 	else if(a>(ref+inc*8) && a<=(ref+(inc*9))) b=211;
  23. 	else if(a>(ref+inc*9) && a<=(ref+(inc*10))) b=213;
  24. 	else if(a>(ref+inc*10) && a<=(ref+(inc*11))) b=215;
  25. 	else if(a>(ref+inc*11) && a<=(ref+(inc*12))) b=217;
  26. 	else if(a>(ref+inc*12) && a<=(ref+(inc*13))) b=219;
  27. 	else if(a>(ref+inc*13) && a<=(ref+(inc*14))) b=221;
  28. 	else if(a>(ref+inc*14) && a<=(ref+(inc*15))) b=223;
  29. 	else if(a>(ref+inc*15) && a<=(ref+(inc*16))) b=225;
  30. 	else if(a>(ref+inc*16) && a<=(ref+(inc*17))) b=227;
  31. 	else if(a>(ref+inc*17) && a<=(ref+(inc*18))) b=229;
  32. 	else if(a>(ref+inc*18) && a<=(ref+(inc*19))) b=231;
  33. 	else if(a>(ref+inc*19) && a<=(ref+(inc*20))) b=233;
  34. 	else if(a>(ref+inc*20) && a<=(ref+(inc*21))) b=235;
  35. 	else if(a>(ref+inc*21)) b=238;
  36.  
  37. 	a_ant=a;
  38.  
  39. 	return b;
  40. }
  41.  
  42.  
  43. int control2(float a)
  44. {
  45. 	int b=225;
  46. 	int a_ant = 0;
  47.  
  48. 	if(a <= a_ant+inc2) a=a_ant;
  49. 	else if(a<=ref)b=220;
  50. 	else if(a>ref && a<=(ref+inc)) b=221;
  51. 	else if(a>(ref+inc2) && a<=(ref+(inc2*2))) b=222;
  52. 	else if(a>(ref+inc2*2) && a<=(ref+(inc2*3))) b=223;
  53. 	else if(a>(ref+inc2*3) && a<=(ref+(inc2*4))) b=224;
  54. 	else if(a>(ref+inc2*4) && a<=(ref+(inc2*5))) b=225;
  55. 	else if(a>(ref+inc2*5) && a<=(ref+(inc2*6))) b=226;
  56. 	else if(a>(ref+inc2*6) && a<=(ref+(inc2*7))) b=227;
  57. 	else if(a>(ref+inc2*7) && a<=(ref+(inc2*8))) b=228;
  58. 	else if(a>(ref+inc2*8) && a<=(ref+(inc2*9))) b=229;
  59. 	else if(a>(ref+inc2*9) && a<=(ref+(inc2*10))) b=230;
  60. 	else if(a>(ref+inc2*10) && a<=(ref+(inc2*11))) b=231;
  61. 	else if(a>(ref+inc2*11) && a<=(ref+(inc2*12))) b=233;
  62. 	else if(a>(ref+inc2*12) && a<=(ref+(inc2*13))) b=234;
  63. 	else if(a>(ref+inc2*13)) b=235;
  64.  
  65. 	a_ant=a;
  66.  
  67. 	return b;
  68. }
  69.  
  70.  
  71. int control3(float a)
  72. {
  73. 	int b=220;
  74. 	int a_ant = 0;
  75.  
  76. 	if(a <= a_ant+inc3) a=a_ant;
  77. 	else if(a<=ref)b=215;
  78. 	else if(a>ref && a<=(ref+inc)) b=216;
  79. 	else if(a>(ref+inc) && a<=(ref+(inc*2))) b=217;
  80. 	else if(a>(ref+inc*2) && a<=(ref+(inc*3))) b=218;
  81. 	else if(a>(ref+inc*3) && a<=(ref+(inc*4))) b=219;
  82. 	else if(a>(ref+inc*4) && a<=(ref+(inc*5))) b=220;
  83. 	else if(a>(ref+inc*5) && a<=(ref+(inc*6))) b=221;
  84. 	else if(a>(ref+inc*6) && a<=(ref+(inc*7))) b=222;
  85. 	else if(a>(ref+inc*7) && a<=(ref+(inc*8))) b=223;
  86. 	else if(a>(ref+inc*8) && a<=(ref+(inc*9))) b=224;
  87. 	else if(a>(ref+inc*9)) b=225;
  88.  
  89. 	a_ant=a;
  90.  
  91. 	return b;
  92. }
  • control1(), control2() y control3() envían un ciclo útil de acuerdo a una tensión DC que es cambiada por los potenciómetros.

Funciones en ADCw.c

  1. void init()
  2. {
  3. 	BUFFER_OFFSET = 8;		  
  4. 	ADC_SPI_CLKDIV=ADC_SPI_CLKDIV_MAX;
  5. 	BUFFER_LEN=16;
  6. 	MUX_CHANNELS =0;
  7.  
  8. 	ADCBuffer = jz_adc_init();
  9.  
  10. 	for (int i = 0; i < 512; i++)
  11. 	{
  12. 		ADCBuffer[i] = 0x00000000;
  13. 	}
  14.  
  15. 	adcConfig(ADC_CMD_SET_SPI_CLKDIV);
  16. 	adcConfig(ADC_CMD_SET_FAST_CONV);
  17. }
  18.  
  19. float ADC(int servo)
  20. {
  21. 	int a,b,c,d=0;
  22. 	switch (servo)
  23. 	{
  24. 	case 1:		
  25. 		printf("\nTomando muestras potenciometro 1...\n");
  26. 		adcConfig(ADC_CMD_SET_CHANNEL3);
  27. 		adcConfig(ADC_CMD_READ_CHANNEL3);
  28. 		break;
  29. 	case 2:
  30. 		printf("\nTomando muestras potenciometro 2...\n");
  31. 		adcConfig(ADC_CMD_SET_CHANNEL1);
  32. 		adcConfig(ADC_CMD_READ_CHANNEL1);
  33. 		break;
  34. 	case 3:
  35. 		printf("\nTomando muestras potenciometro 3...\n");
  36. 		adcConfig(ADC_CMD_SET_CHANNEL2);
  37. 		adcConfig(ADC_CMD_READ_CHANNEL2);
  38. 		break;
  39. 	case 4:
  40. 		printf("\nTomando muestras del sensor...\n");
  41. 		adcConfig(ADC_CMD_SET_CHANNEL0);
  42. 		adcConfig(ADC_CMD_READ_CHANNEL0);
  43. 		break;
  44. 	default: 
  45. 		printf("\nError...\n");
  46. 	}
  47.  
  48.  
  49. 	for(int i=BUFFER_OFFSET; i< BUFFER_LEN/2+BUFFER_OFFSET; i++)
  50. 	{
  51. 		a=ADCBuffer[i]<<16;
  52. 		b=a>>16;
  53. 		c=ADCBuffer[i]>>16;
  54. 		d=d+b+c;
  55. 	}
  56.  
  57. 	d=d/(BUFFER_LEN/2+BUFFER_OFFSET);
  58.  
  59. 	fflush (stdout);
  60. 	return d;	
  61. }
  62.  
  63.  
  64. void adcConfig(uchar CMD)
  65. {
  66. 	ADCBuffer[0] =  (((MUX_CHANNELS<<6) + CMD)<<24) + \
  67. 					((BUFFER_LEN+BUFFER_OFFSET*2) << 8) + \
  68. 					(ADC_SPI_CLKDIV);
  69. 	while(adcCheckBufferFull()) usleep(10000);
  70. }
  71.  
  72.  
  73.  
  74. int adcCheckBufferFull()
  75. {
  76. 	return ADCBuffer[0]&0x20000000;
  77. }
  • init() inicializa al ADC con un velocidad de reloj mínima (97.65 kHz) y lo configura en conversión rápida.
  • ADC() toma muestras de un determinado canal, que puede corresponder a algún potenciómetro o al sensor de proximidad y saca un valor promedio de esas muestras.
  • adcConfig() selecciona un canal de toma o una configuración del ADC y adcCheckBuffer() revisa la capacidad del Buffer.

El archivo sram_gpio_wrap.c es fundamental para el uso de Lua porque contiene el registro de las funciones descritas anteriormente. Así mismo, en el registro de esas funciones se agregaron algunas líneas de código para ampliar su funcionalidad.

  1. static int init_wrap(lua_State *L){
  2. 	init();	
  3. 	return 0;
  4. }
  5.  
  6. static int take_sample_wrap(lua_State *L){
  7. 	double color=ADC(4); 	
  8.         lua_pushnumber(L, color);
  9. 	return 1;
  10. }
  11.  
  12. static int jz_mmap_wrap(lua_State *L){
  13. 	int duty = luaL_checkint(L, 1);
  14. 	int motor= luaL_checkint(L, 2);
  15. 	jz_mapping(duty,motor);
  16. 	return 0;
  17. }
  18.  
  19. static int usleep_wrap(lua_State *L){
  20. 	usleep(500000);
  21. 	return 0;
  22. 	}
  23.  
  24. static int control_wrap(lua_State *L){
  25. 	int duty1_ant=0;
  26. 	int duty2_ant=0;
  27. 	int duty3_ant=0;
  28.  
  29. 	for(;;){
  30. 	int duty1 = control1(ADC(1));
  31. 	printf("Servo 1 --> %d",duty1);
  32. 	int duty2 = control2(ADC(2));
  33. 	printf("Servo 2 --> %d",duty2);
  34. 	int duty3 = control3(ADC(3));
  35. 	printf("Servo 3 --> %d",duty3);
  36.  
  37. 	usleep(10000);
  38.  
  39. 	if(duty1 != duty1_ant && duty1 < duty1_ant+10)
  40. 	jz_mapping(duty1,1);
  41. 	if(duty2 != duty2_ant)
  42. 	jz_mapping(duty2,2);
  43. 	if(duty3 != duty3_ant)
  44. 	jz_mapping(duty3,3);	
  45.  
  46. 	duty1_ant = duty1;
  47. 	duty2_ant = duty2;
  48. 	duty3_ant = duty3;
  49. 	}
  50.  
  51. return 0;
  52. }
  53.  
  54. static int jz_belt_wrap(lua_State *L){
  55. 	int stop = luaL_checkint(L,1);
  56. 	jz_belt(stop);
  57. 	return 0;
  58. }
  59.  
  60. static const struct luaL_reg functions[] = {  
  61.     {"init",init_wrap},
  62.     {"usleep",usleep_wrap},
  63.     {"control",control_wrap},	
  64.     {"sample",take_sample_wrap},	
  65.     {"mmap",jz_mmap_wrap},
  66.     {"belt",jz_belt_wrap},
  67.     { NULL, NULL}  
  68. };  
  69.  
  70. int luaopen_gpio(lua_State *L) {  
  71.     luaL_newmetatable(L, metaname);  
  72.     luaL_register(L, "gpio", functions);  
  73.     return 1;  
  74. }
  • init_wrap() ejecuta init().
  • take_sample_wrap() toma muestras del sensor de proximidad y retorna el promedio de esas muestras.
  • jz_mmap_wrap() toma los dos argumentos del stack de lua y los ejecuta jz_mmap().
  • usleep_wrap() ejecuta la función usleep() de la librería time.h.
  • control_wrap() se encarga de usar control(1), control(2) y control3() en un ciclo infinito para controlar los servomotores con los potenciómetros.
  • belt_wrap() detiene la banda dependiendo del valor del argumento que se escribe en el stack.
  • luaL_reg registra las funciones con un nombre determinado para poderlas trabajar.
  • luaL_register () crea un identificador "gpio" para llamar las funciones registradas en la estructura.

peripherials.lua se muestra a continuación,

  1. package.cpath = "./?.so"
  2. require "gpio"
  3.  
  4.   function Initial ()
  5.   gpio.mmap(215,1) usleep()
  6.   gpio.mmap(225,2) usleep()
  7.   gpio.mmap(225,3) usleep()
  8.   belt(1)
  9.   end
  10.  
  11.   function init()
  12.   gpio.init()
  13.   end
  14.  
  15.   function PWM (duty,motor)
  16.   gpio.mmap(duty,motor)
  17.   end
  18.  
  19.   function usleep()
  20.   gpio.usleep()
  21.   end
  22.  
  23.   function rutine_white()
  24.   Initial()
  25.   PWM(234,2) usleep() PWM(218,3) usleep()
  26.   PWM(225,2) usleep() PWM(225,1) usleep() PWM(237,1) usleep()
  27.   PWM(234,2) usleep() PWM(223,3) usleep() PWM(225,2) usleep() PWM(225,1)
  28.   end
  29.  
  30.   function rutine_black()
  31.   Initial()
  32.   PWM(234,2) usleep() PWM(218,3) usleep()
  33.   PWM(225,2) usleep() PWM(210,1) usleep() PWM(195,1) usleep()
  34.   PWM(234,2) usleep() PWM(223,3) usleep() PWM(225,2) usleep() PWM(210,1)
  35.   end
  36.  
  37.   function belt(stop)
  38.   gpio.belt(stop)
  39.   end
  40.  
  41.   function rutine()  
  42.   color=gpio.sample()
  43.   print("Taking samples from Lua",color)
  44.   	if color < 7 then 
  45. 	belt(0)
  46. 	elseif color > 70 then
  47. 	belt(1)
  48. 	rutine_white()
  49. 	else
  50. 	belt(1)
  51. 	rutine_black()
  52. 	end
  53.   end
  54.  
  55.   function cycle()
  56. 	for i=1,1000000 do
  57. 	rutine()
  58. 	end
  59.   end
  60.  
  61.   function ctrl()
  62. 	gpio.control()
  63.   end  
  64.  
  65.   init()
  66.   Initial()
  67.   Initial()
  • Initial() coloca los servos en una posición inicial.
  • PWM() escribe el ciclo útil en un servo determinado.
  • cycle() ejecuta en un tiempo casi indefinido la rutina de tomar el objeto de la banda transportadora y dependiendo del color ponerlo en una determinada posición.
  • ctrl() ejecuta el ciclo infinito de escribir la posición en los servos con los potenciómetros.

Primero se hace init() y luego Initial().

Todas estas funciones registradas y descritas en peripherials.lua son llamadas en el modo interactivo de lua con la función dofile("peripherials.lua").

[edit] Driver

El driver creado es para el control de los 3 Servomotores a través de un ciclo útil enviado por este mismo. Este tiene el mismo concepto y en general el mismo funcionamiento que lo hecho en espacio de usuario. Sin embargo hay que tener en cuenta que en este caso no se realizo un mapeo virtual de la memoria física, sino que los datos se envían directamente a esa dirección física (FPGA_BASE = 0xb5000000).

En primera instancia cuando el driver sea cargado se debe configurar el CS2 para el correcto funcionamiento

  1. #define CS2_PIN               JZ_GPIO_PORTB(26)
  1. jz_gpio_set_function(CS2_PIN, JZ_GPIO_FUNC1);

Luego se procede a inicializar cada uno de los servomotores con las posiciones definidas.

  1. outb(215,FPGA_BASE + 0x800);
  2. outb(225,FPGA_BASE + 0x1000);
  3. outb(220,FPGA_BASE + 0x1800);

Después de realizar esto el modulo queda cargado.

La escritura en el mismo consta de ingresar el ciclo útil seguido de una coma y el servomotor al cual enviarle el dato ( 225,1 ). La función de escritura del driver se muestra a continuación:

  1. static ssize_t
  2. device_write(struct file *filp, const char *buff, size_t count, loff_t * off)
  3. {
  4.  
  5. 	int cmd = buff[0]-48;
  6. 	int cmda = buff[1]-48;
  7. 	int cmdb = buff[2]-48;
  8. 	int cmdc = buff[3]-48;
  9. 	int cmdd = buff[4]-48;
  10. 	int cmde = 0;
  11. 	int dir;
  12.  
  13. if(cmdc == -4)
  14. {   
  15.     cmde = cmd*100 + cmda*10 + cmdb;
  16. 	printk(KERN_INFO  "Dutyout %d Servo %d\n", cmde, cmdd);
  17. 	dir = cmdd*0x800;
  18. 	outb( cmde , FPGA_BASE + dir);
  19. }
  20.  
  21. return 1;
  22. }

Se resta el numero 48 debido a que esta función recibe una cadena de caracteres y como se esta enviando un numero, este es tomado en código ASCII. Se usan 5 registros para tomar cada uno de los "numeros" recibidos en la función, si se ingresa correctamente el dato el cuarto registro sera el carácter ',' (44 en ASCII) entrando en el condicional y enviando el ciclo útil al servomotor escogido.

Un ejemplo del uso de esta función se muestra a continuación (el nodo de comunicación debe estar creado mknod /dev/pwm c 252 0)

$ echo '215,1'>/dev/pwm

De este modo se enviara un ciclo útil de 215 al servomotor 1. También es posible enviar datos a cada servo simultáneamente.

$ echo '215,1 230,2 216,3' > /dev/pwm

En este caso se enviara un ciclo util de 215 al servo 1, 230 al servo 2 y 216 al servo 3.

[edit] Cronograma de Actividades

  • Semana 5. Propuesta del Proyecto.
  • Semana 6. Adquisición de la tarjeta SIE y pedido del gripper mecánico. Creación de la imagen del kernel de Linux.
  • Semana 7. Verificación PCB.
  • Semana 8. Verificación de subcircuitos (PWM, Proximidad, Convertidor DC-DC, etc.)
  • Semana 9. Montaje PCB.
  • Semana 10. Driver PWM. Driver SPI. Driver H-Bridge.
  • Semana 13. Comuncación del ADC.
  • Semana 14. Lógica Sensores de Proximidad.
  • Semana 15. Creación API's.
  • Semana 16. Verificación y Pruebas

[edit] Análisis Económico

[edit] Costo de elaboración prototipo

  • Materiales.
    • Sie..........................................$ 200000
    • Pcb.........................................$ 120000
    • Piezas en acrilico.....................$ 45000
    • Servos.....................................$ 80000
    • Gripper más servo....................$ 60000
    • Componentes electrónicos........$ 90000
    • Moto-reductores.......................$ 60000
    • Otros.......................................$ 50000
    • Total Materiales directos............$ 705000
  • Mano de obra.
    • Tiempo semanal de labores.................... 15 Horas
    • Semanas de labores.............................. 12 Semanas
    • Costo hora laboral por desarrollador......... $ 40000
    • Desarrolladores...................................... 3
    • Total Mano de obra directa.......................$ 21´600000
  • Total elaboración del prototipo............$ 22´305000

[edit] Costo de producción en masa (100 dispositivos)

  • Materiales.
    • Pcb.........................................$ 582750
    • Piezas en acrilico.....................$ 2´250000
    • Servos.....................................$ 4´000000
    • Gripper más servo....................$ 3´000000
    • Componentes electrónicos........$ 4´500000
    • Moto-reductores.......................$ 3´000000
    • Otros......................................$ 1´250000
    • Total Materiales directos...........$ 18´582750
  • Costo desarrollo inicial.................... $ 22´305000
  • Costo mano de obra ensamble ........$ 2´000000
  • Total elaboración 100 dispositivos.... $ 42´887750
Personal tools
Namespaces
Variants
Actions
Navigation
interactive
Toolbox
Print/export