miércoles, 31 de diciembre de 2014

Problemas con PICKit2 en MPLAB X?

Estas navidades (a parte de retomar las entradas que me faltan de nuestro Wirelearn Robot Shield), se me ha ocurrido una idea y para llevarla a cabo he tenido que desempolvar mi PICKit2. Después de leer un poco acerca del mundillo de los microcontroladores de Microchip para ponerme al día, he descubierto que MPLAB X IDE ya está en su version 2.26. Además, el compilador Hi-Tech C de la misma casa está en desuso, y lo reemplazan la nueva serie de compiladores XC-x. 


Escenario

Por lo tanto mi escenario es el siguiente:

- Sistema Operativo Linux Ubuntu - Utopic Unicorn (debería dar lo mismo)
- MPLAB X IDE v 2.26
- Compilador XC-8 debidamente instalado y activado en el IDE.
- Programa sencillo (yo hice un blink con un LED en el pin RD4)

Me dispongo a compilar (build) y todo va bien, pero a la hora de programar, obtengo un mensaje de error tal que así:

The programmer could not be started: Could not connect to tool hardware: PICkit2PlatformTool, com.microchip.mplab.mdbcore.pickit2.PICkit2DbgToolManager

Solución

  • Antes de nada, necesitas un PC con windows (a poder ser la versión 7). Descárgate la aplicación PICKit 2 v2.61 aquí.
  • Instala la aplicación en tu PC con Windows 7 (o si eres un valiente intentalo con Wine y nos cuentas).
  • Conecta el PICKit2 y cuando esté reconocido e instalado, abre la aplicación. En la pantalla principal de la aplicación debería mostrar que está conectado.
  • Ahora vamos a Tools > Calibrate VDD and set Unit ID. Damos "next" 3 veces hasta saltarnos la historia del VDD que no nos interesa. Entonces nos aparece una pantalla en la que podemos introducir un "Unit ID". Ponemos lo que nos de la gana, (sin caracteres raros) y finalizamos. Hacemos lo que nos dice de esperar a que el USB esté listo.
  • Reiniciamos MPLAB X y listo. Con esa ID, ya puedes utilizar tu programador en cualquier PC


Al parecer es necesario en MPLAB X que el PICKit2 tenga una ID (los dispositivos antiguos no estan serializados y por defecto vienen sin ID).

Solamente añadir que a mi me aparece el PICKit2 con dos puntitos amarillos en el las propiedades del proyecto para el PIC que utilizo (16F887), y funciona perfectamente con el compilador XC-8, tanto para programar, como para hacer debug.

viernes, 27 de junio de 2014

Depuración hardware en android (Ubuntu)

Esta entrada es de especial importancia para aquellos que os hayáis agenciado un teléfono/tablet con sistema operativo android, de marca no precisamente conocida.


Aquellos que hayáis probado a desarrollar para android pensaréis, igual que el común de los desarrolladores de ésta plataforma, que utilizar dispositivos virtuales, o emuladores, es lento y farragoso. Para ello, el SDK de android nos permite conectar nuestros dispositivos android al PC y utilizarlos como dispositivo de pruebas. Ésto es mucho más rápido y tiene la ventaja de que ves la aplicación funcionando en un terminal de verdad.

Sin embargo no todos los dispositivos se comportan de la misma manera cuando los conectamos a nuestro PC para probar nuestras apps en ellos. En mi caso, hará cosa de un año me compré una tablet china (PiPo Max M1), y cuando la conecto al PC, el adb ni se inmuta. He de decir que con mi teléfono (Xperia Ray) no tengo ningún problema. Es detectado automáticamente por mi PC y sale en la lista de dispositivos.

Después de dar muchas vueltas y probar muchas soluciones, he dado con un método para hacer funcionar (al menos) los dispositivos mencionados. En el caso de la tablet, podemos decir que cualquier dispositivo con chipset RockChip 3066, ya que todos tiene el mismo "vendor id". Dicho método os lo proporciono en forma de script de bash, como buen programador y amante de linux.

Notas adicionales:
  • Activad el modo debug en vuestro teléfono.
  • Ejecutad el script como super usuario.
  • Debeis proporcionar el "vendor id" de vuestro dispositivo al script como único y necesario parámetro. Si no lo conocéis, podéis buscarlo aquí.
  • Para los dispositivos chinos lo tenéis un poco más complicado pero buscando un poco suele aparecer. Para los que tengáis un dispositivo RockChip 3066, el "vendor id" es 0x2207
  • Conectad vuestro dispositivo en modo de almacenamiento antes de ejecutar el script (no es imprescindible, pero al final de la ejecución se muestra la lista de dispositivos conectados y detectados)
  • Es crucial, que si detenéis y arrancais el servidor de adb, lo hagáis como superusuario. De lo contrario el dispositivo podría no aparecer, o como me pasa a mí, poner 20 signos de interrogación y un "no permissions" al listar los dispositivos.
Es posible que al final de la ejecución la lista de dispositivos siga vacía, o invariable. Esperad unos segundos y ejecutad adb devices. Es posible que el comando se ejecute antes de que se detecte el dispositivo.

miércoles, 4 de septiembre de 2013

Motores Paso a paso (steppers)

¿Qué son los motores paso a paso?

Complementando nuestro proyecto Wirelearn Robot Shield (WRS) explicamos en detalle el funcionamiento de los motores paso a paso, y qué circuitería es necesaria para ponerlos en marcha. Esperamos que os ayude!


Los motores paso a paso (E.A. steppers) son motores de corriente contínua (DC) que requieren de cierto grado de lógica digital para funcionar, debido a que son accionados por varias bobinas. De este hecho se derivan dos consecuencias:
  • Los steppers son considerablemente más complejos de utilizar que un motor contínuo común y generalmente son capaces de girar a menos revoluciones por minuto. Además, son mucho más caros debido a los costes de construcción, y a la electrónica externa necesaria.
  • Pueden moverse en fracciones de revolución, lo cual los hace muy precisos y a su vez abre la posibilidad de controlar de forma muy exacta la velocidad a la que giran. Además, es posible forzar una posición magnética, de forma que el motor quede "frenado".
Como podemos observar, los steppers tienen argumentos a su favor, y en su contra. Basándonos en lo visto hasta ahora, no debería ser muy difícil discernir en qué aplicaciones debemos utilizar cada tipo de motor.

Accionamiento

Para ésta explicación utilizaremos nuestro motor unipolar UHD23N01RAZ25 que consta de seis cables. Los cables verdes son comunes. Es decir, que pueden estar conectados a +5 o GND dependiendo del circuito que los acciona. Los demás cables activan cada una de las "4 bobinas" del motor respectivamente. Resumiendo, si conectamos los cables verdes a +V, conectando cada uno de los restantes a masa estaremos cerrando el circuito de su respectiva bobina y con ello orientando el eje del motor en consecuencia. Lo único que hay que hacer para hacerlo girar es activar las bobinas sucesivamente en el orden correcto.

Llegados a este punto, debemos saber que existen diferentes modos de hacer girar un motor paso a paso, dependiendo de la secuencia de activación de las bobinas. Llamemos a los cables por la inicial de su color para simplificar (R)ojo,(N)egro,(A)marillo,(V)ioleta:

  • Modo "Wave Drive": (R, A, N, V) El motor gira en cada paso los grados marcados por el datasheet,  7,5º por paso para el motor citado. Por otra parte, al tener una sola bobina activa en cada momento, el par motor (la fuerza que hace) es más débil de lo que debería. Yo solo lo uso para probar circuitos porque es el más simple.
  • Modo "Full Step": (RA, AN, NV, VA) El par motor es máximo, aproximadamente el doble que en modo el modo anterior. La resolución o angulo de giro sigue siendo la misma.
  • Modo "Half Step" (R, RA, A, AN, N, NV, V, VR) El par motor es aproximadamente el 70% del máximo, pero se multiplica por dos la resolución de giro. Ésto equivale a unos 3,75º por paso.
Evidentemente, nuestro motor rodará en modo half step. He aquí unas imágenes explicativas de ésta secuencia:

Paso 1: R activado, el eje se orienta frente a R

Paso 2: RA activados, el eje se orienta en el punto medio entre las bobinas R y A

Paso 3: A activado, el eje se orienta frente a A
Y así sucesivamente hasta completar la secuencia. :)

Nota: A pesar de que en éste post hablamos de "cuatro bobinas", ésto es solo una simplificación del motor real, que en realidad tiene muchas más. De hecho, nuestro UHD tiene 48. (360º / 7,5º). Lo que sucede es que cuando activamos una de las líneas del motor, en realidad estamos alimentando 12 bobinas distribuidas uniformemente alrededor del eje, pero solo una de ellas está lo suficientemente cerca como para orientarlo. Ésto es una simple aclaración, que no afecta en absoluto la explicación previa ni posterior.

Circuito

Según la hoja de datos, cada bobina presenta una resistencia 30 Ohm. En principio vamos a alimentarlo con 5V, por lo que haciendo un cálculo rápido por la ley de ohm, cada rama del motor llevará una intensidad de 170 mA. Éste cálculo NO es preciso, porque es un motor y no una resistencia. Lo correcto aquí es hablar de impedancia inductiva. Así que podríamos decir que lo calculado se trata de una "media" de la intensidad real.

Como deberíamos saber, Arduino UNO solo puede suministrar 40 mA, con lo cual, estamos ante el problema más común de la electrónica digital aplicada: ¿Cómo puedo mover intensidades grandes, con circuitos que soportan intensidades pequeñas?

Si estás pensando en un relé, no vas mal encaminado, pero te falta mucho camino por andar. Lo correcto aquí es utilizar un transistor. Y la principal ventaja del transistor en éste campo es la velocidad de conmutación. La naturaleza mecánica del relé lo hace miles, o incluso cientos de miles de veces mas lento que un transistor de uso común. Y en nuestro circuito, deberemos alcanzar velocidades de conmutación en torno a los 20 ms.

Como podemos observar en la imagen, de él salen 6 cables. Dos son iguales (verdes), lo cual nos suscita que serán el común, al que aplicaremos GND o +V dependiendo del circuito.

Para evitar combustiones espontáneas pensando cómo accionar 4 líneas de corriente con un sólo transistor y nada más, os adelanto que no es posible. Pero ésto no quiere decir que tengamos que comprarnos 4 transistores y montar 4 circuitos. La solución óptima es hacerse con un array darlington TD62064AP como éste:


Olvidémonos de momento de la circuitería que suele rodear a los transistores, y de bases, colectores y emisores, ya que toda la teoría daría para varias entradas en el blog. De momento nos sirve con saber que éste componente viene en un encapsulado DIP16. En su interior alberga 4 transistores de conmutación, capaces de soportar corrientes de salida de 1,5A y tensiones de hasta 50V. Las patas 4,5,12 y 13 están conectadas entre sí internamente como muestra la imagen anterior, deben conectarse a masa. Por otra parte hay 4 terminales de entrada (I1,I2,I3,I4) y 4 de salida (O1,O2,O3,O4). Olvidémonos de las patas COM.

El funcionamiento es tan simple como, un nivel alto (5V) en I1, conecta O1 con masa. De aquí se deduce, que éste integrado es un sumidero de corriente, lo que quiere decir, que por cada salida del integrado, entrará una corriente que será derivada a masa, cuando la entrada asociada reciba un nivel alto.

Con lo cual, ya sabemos que el común de nuestros motores (recordemos cables verdes) deberán estar conectados al polo positivo de la fuente de tal manera que la corriente salga de dicho polo, atraviese la bobina del motor, entre en nuestro integrado y ahí "se vaya por el sumidero" a masa. Para que ésto sea posible debemos conectar los cables de cada bobina del motor a cada una de las salidas del integrado.

Respecto a los pines de entrada, requieren una I máxima de 20 mA, suficientemente pequeña para poder conectarlos a cuatro pines digitales de nuestro Arduino sin riesgo, y ponernos a mandar secuencias a lo loco.

El circuito completo es éste:

Programa de prueba

Una vez tengas preparado el circuito anterior, puedes flashear éste sketch en tu Arduino UNO:
/* WIRELEARN 2013 - STEPPER TEST4

  This sketch is designed to be flashed to an Arduino UNO board,
  Digital pins 4,5,6 and 7 of arduino board should be connected
  to I1, I2, I3 and I4 pins of TD62064AP DIP16 IC respectively.
  
  See the whole stepper tutorial > wirelearn.blogspot.com
 
  Bugs and suggestions > adm.wirelearn@gmail.com 
  
  #MRGZ#
*/

// DIGITAL PINS
int coil_A = 4;
int coil_B = 5;
int coil_C = 6;
int coil_D = 7;

// MASK FOR EACH PIN
int mask_A = B1000;
int mask_B = B0100;
int mask_C = B0010;
int mask_D = B0001;

// SEQUENCE, TRANSFORM IT TO BINARY NUMBERS MAY MAKE IT EASIER TO UNDESTAND
int sequence[8] = { 8, 12, 4, 6, 2, 3, 1, 9};

int pos;

void setup(){
    pinMode(coil_A, OUTPUT);
    pinMode(coil_B, OUTPUT);
    pinMode(coil_C, OUTPUT);
    pinMode(coil_D, OUTPUT);

    pos = 0;
}

void loop(){
  /*We need 4 bits, one bit per TD62064 input
   first word in sequence is 8, which equates 1000B
   coil_A = 1000 && 1000 >> 3 = 1
   coil_B = 1000 && 0100 >> 2 = 0
   coil_C = 1000 && 0010 >> 2 = 0
   coil_B = 1000 && 0001 = 0
   We just split a four bit number, into single parallel bits :)
   */

  // Finally, let's output our bits
  digitalWrite(coil_A, sequence[pos] && mask_A >> 3);
  digitalWrite(coil_B, sequence[pos] && mask_B >> 2);
  digitalWrite(coil_C, sequence[pos] && mask_C >> 1);
  digitalWrite(coil_D, sequence[pos] && mask_D);
  pos = pos > 7 ? 0 : pos+1;
  delay(100);
  
}
El circuito debería ser similar para cualquier tipo de Stepper unipolar. Muchos de ellos llevan un cableado diferente, con solo dos bobinas y dos cables aparte de los comunes. Ésto solo influiría en la secuencia de activación de los devanados. Pero el principio de funcionamiento y el circuito con array de transistores debería funcionar exactamente igual.

Por último, cada motor es diferente, por lo que algunos permitirán velocidades muy altas, y otros no tanto. Deberéis jugar con el "delay" al final del código para conocer los límites de vuestro motor.

Pronto veremos cómo utilizar un registro de desplazamiento para multiplexar las salidas digitales de Arduino y controlar dos steppers con sólo tres IO Pins. :)

Saludos!

#MRGZ#

domingo, 1 de septiembre de 2013

[PROYECTO] Wirelearn Robot Shield (WRS)

Tras un verano llevando a la práctica una serie de proyectos, desde Wirelearn te traemos una sucesión de entradas explicando paso a paso y desde cero, el proceso completo para crear tu propio robot seguidor de líneas (line follower) a partir de una placa Arduino UNO.

Sugerencia de presentación, como el atún en lata... XD

En las sucesivas entradas veremos cómo afrontar el planteamiento y diseño de la circuitería, la creación de la misma mediante insolado y revelado casero de PCB (printed circuit boards), algunos tips para soldar los componentes, la programación y flasheado del programa, y la construcción del chasis con materiales asequibles.

Nuestros objetivos principales serán los de la mayoría de los aficionados a la electrónica y la robótica. Los factores que más nos preocupan son entre otros el precio, la complejidad y el tiempo. Pero te adelantamos, que si bien ha sido un proyecto duro para nosotros, no lo será tanto para tí, ya que las dificultades propias de cualquier proyecto de este calibre ya han sido tratadas y resueltas.

Como requisitos previos, es recomendable haber trasteado un poco con Arduino y un poco de electrónica no vendría nada mal. Pero la idea es explicarlo todo al máximo y argumentar adecuadamente cada uno de los pasos, para evitar esa sensación que queda a veces de estar haciendo algo sin tener ni p*ta idea sin comprender al máximo todos los detalles subyacentes.

En breve comenzamos con el diseño del circuito, pero para ir adelantando conocimientos, échale un ojete a nuestra entrada sobre Motores paso a paso (steppers) porque incidiremos en ello más adelante.

Un saludo!

MRGZ.

martes, 5 de febrero de 2013

Utilidad para cifrar/descifrar RxBot


Hace un par de días, un amigo me pidió ayuda para descifrar una cadena de texto, con fines que desconozco. Generalmente no me suelo meter en temas de cifrado y seguridad de contraseñas, porque es algo que me aborrece enormemente y sobre lo que no estoy muy al corriente. En éste caso, tras una breve búsqueda en google, fui a parar a un foro en el que un fulano explicaba más o menos la teoría del asunto. Después traté de encontrar una herramienta al uso para solucionar el problema y lo que me encontré un montón de páginas y foros que las proporcionaban, pero requerían registro previo. 

Sin entrar en los intereses que puede tener un foro o página por mis datos personales, preferí no registrarme y como el algoritmo es de risa, traté de hacer un pequeño programa en Java. Un consejo, cuando tengáis que operar a nivel de bit, y realizar operaciones de transformación entre bytes, caracteres y cadenas, huid de este lenguaje.

Tras conseguir una versión cuasi-funcional en java que no me terminaba de convencer, me di por vencido y abrí DevC++. Fue una hermosa regresión al universo de los punteros y los arrays de caracteres que desembocó en las herramientas que más abajo comparto con vosotros.

El algoritmo

Me da mucha pereza explicar en profundidad el algoritmo. No obstante, y para que no penséis que me dediqué al copy-pasting resumo lo importante:

El algoritmo se basa en una tabla de 256 hexadecimales de 8 bits constante. Es (o debería ser) la misma para todas las cadenas cifradas con éste tipo de cifrado. 

Todo lo que hace el algoritmo es coger el primer carácter a cifrar, y hacer un XOR binario con el primer carácter de la tabla maestra, y así sucesivamente. Como todos sabremos, en el sistema de representación de caracteres ASCII a cada letra le corresponde un valor entre 0 y 255, si hablamos de numeración de 8 bits sin signo. A partir del XOR obtenemos ese byte, que representaremos como entero con signo.

De ésta manera, la cadena:
Wirelearn Rulz
Tras el cifrado queda representada como:
{115,69,-120,65,23,-121,-74,35,-13,44,44,-33,66,126,0}

Conclusiones

Lo bueno de utilizar un XOR es que es una operación reversible. Así, si dos personas tienen la misma tabla, la persona A puede escribir y cifrar un mensaje y enviarlo. Y la segunda persona puede descifrarlo de la misma manera. Así si el mensaje es interceptado, al menos llevará un buen rato reventarlo.

Como podréis imaginaros ESTE SISTEMA NO ES SEGURO ya que para empezar, la tabla es pública. Aún cambiando la tabla maestra por una aleatoria es bastante fácil de resolver con tiempo y una caña. Sin embargo, podría servir para que vuestras conversaciones privadas no fuesen escuchadas a primera vista en caso de que alguien esté escuchando la red.

Descarga

Sin ir más lejos, aquí tenéis el paquete descargable para windows

Un saludo.

sábado, 12 de enero de 2013

Un poco de estilo (JAVA)

Imagen tomada de www.xprogramming.com

Supongamos que tenemos una lista de números enteros, y queremos separarlos en dos grupos: Aquellos que cumplen una condición (C) y otros que no cumplen dicha condición (!C). Por ejemplo discriminar de entre todos los numeros de nuestra lista, aquellos que son pares. Lo más inmediato y rápido sin duda sería codificar "a fuego" un algoritmo que recorra la lista y compruebe para cada uno si la condición de la que hablamos se cumple. Éso está bien. Al fin y al cabo, funciona, lo hemos probado muchas veces.

if (numero % 2 == 0)
      imprime("El numero " + numero + " es par);
else
      imprime("El numero " + numero + " no es par);

Pero... ¿Qué pasaría si mañana nos vemos en la obligación de cambiar ese filtro? Imaginemos que mañana no nos interesan los pares sino todos los positivos. Efectivamente, nos vemos obligados a acceder a las tripas del algoritmo, y cambiar un par de cosas para adaptar nuestro código a los requerimientos externos. (Bastante sencillo en éste caso, pero podría no serlo).

Ya de mano, debería preocuparnos el hecho de deshacernos de ése código pero el verdadero problema no está ahí. El supuesto mortal es ¿Y si necesitara filtrar esos números en función de lo que esta pasando?¿Y si necesitara cambiar ese filtro en tiempo de ejecución? A éstas alturas, ya deberíamos saber que es de todo término inviable cambiar el código en tiempo de ejecución.

Además ¿Y si hubiera veinte posibles condiciones?¿Tendríamos veinte bloques IF anidados?¿O un switch enorme? Esa lógica condicional es veneno puro para el mantenimiento y para el rendimiento.

Es en éste punto concreto donde debería saltarnos una alarma dentro, que nos diga "Estoy borrando algo perfectamente funcional, pero hoy ya no me sirve por requerimientos externos". Estamos tirando horas de trabajo a la basura. Es aquí donde deberíamos pensar en la palabra "Delegación".

¿Qué es la delegación?

Delegar es dejar cierta "responsabilidad" en manos de "otro". No es inmediato darse cuenta de cómo encaja la delegación en nuestro proyecto pero ahora veremos una manera mucho mas potente de lidiar con ésta clase de temas.

¿Como encaja eso aquí?

Pongamos algún concepto más avanzado sobre la mesa. ¿Qué tienen en común todos nuestros cambios en el código? Pues que consisten en alterar la condición de filtrado. ¿Que tienen en común todas nuestras condiciones de filtrado? Que evalúan un entero, y que son de carácter booleano. ¿Podríamos decir entonces que una condición en general es algo que tiene un método booleano y un entero de entrada? Pues sí. A eso se le llama TIPO en términos de orientación a objetos, y una de las maneras más potentes de representarlo es mediante Herencia. Pero no cualquier tipo de herencia.

Crearemos una Interfaz llamada "Condicion", que tendra un método

public interface Condicion {
public boolean validar(int numero);
}

Así definimos nuestro tipo <>. Y delegamos en sus hijos la decisión de si un numero nos sirve o no¿Que pasa ahora? Una interfaz por si sola no tiene implementación alguna de cómo validar. Pero permite a nuestro código sustituir nuestra condición grabada a fuego:

for (Integer numero : numeros){
      if (numero % 2 == 0)
            imprime("El numero " + numero + " es par);
      else
            imprime("El numero " + numero + " no es par);
}

Por algo como ésto:

Condicion condicion = .........................;

for (Integer numero : numeros){
      if (condicion.validar(numero))
            imprime("El numero " + numero + " es par);
      else
            imprime("El numero " + numero + " no es par);
}


¿Que?¿No parece haber cambiado mucho no? Además ¿Donde especificamos nuestra condición? Esto es una M...

Demos el último paso. Para filtrar los números de la lista, crearemos dos implementaciones de nuestra condición abstracta que se llamarán por ejemplo "CondicionPositivo", y  "CondicionPar":

public class CondicionPositivo implements Condicion {}

y

public class CondicionPar implements Condicion {}


En seguida el compilador nos obligará a punta de pistola a implementar nuestro método "public boolean validar(int)" en nuestras recién creadas implementaciones. Ahí pondremos nuestras dos formas de filtrar.

Volviendo al código anterior, vemos unos puntos suspensivos que parecen "susceptibles de no compilar bien". Ahí es donde debemos crear una instancia de nuestra clase CondicionPositivo.

Condicion condicion = new CondicionPositivo();

Nuestro código ya funciona. Ahora, ¿qué tendríamos que hacer si mañana nos interesan los números pares en lugar de los positivos? Simplemente tendremos que cambiar la linea anterior a nuestro antojo. Así, el hecho de sustituir una por otra, no es destructiva, y con el tiempo vamos alimentando nuestros recursos de código. Es decir, nuestro árbol de Condiciones crece, y podría sernos útil más adelante.

Ésto esta muy bien, pero dónde está el verdadero potencial de lo que acabamos de construir? 

Sencillo. En nuestro nuevo código nada nos impide sustituir la condición en tiempo de ejecución. Es más, podríamos dejar que la condición dependiera de las acciones del usuario, y en función de qué tecla pulse, la condición varíe. Además, aún teniendo un alto número de condiciones, nuestro código permanecería impecable. Nada de lógica condicional.

Dicho todo ésto, 


¿Sabrías crear un filtro para múltiplos de un numero dado (p.ej: múltiplos de 3)?

Descargate el proyecto de eclipse aquí 

Un saludo!








martes, 4 de septiembre de 2012

Problemas al instalar ADT Plugin para Eclipse

Si os habéis decidido a programar para android en Windows, probablemente habréis optado por utilizar Eclipse para tal fin. También habréis tenido que instalar Android SDK y finalmente el plugin ADT para eclipse. Lo que voy a tratar de resolver a continuación, son los problemas a la hora de instalar éste último plugin...




En mi caso, hace unos meses he instalado el paquete entero que os acabo de mencionar sin problema alguno. Pero ayer, volviendo a instalar todo por segunda vez y de la misma manera, eclipse me dice algo parecido a ésto:

Cannot complete the install because one or more required items could
not be found.
Software currently installed: Shared profile 1.0.0.1316138460759
(SharedProfile_epp.package.java 1.0.0.1316138460759)
Missing requirement: Shared profile 1.0.0.1316138460759
(SharedProfile_epp.package.java 1.0.0.1316138460759) requires
'org.maven.ide.eclipse [1.0.100.20110804-1717]' but it could not be
found

Tras probar varias soluciones disponibles en la red, me quedo con dos.

  • En primer lugar, cerrad eclipse y ejecutadlo de nuevo como administrador (botón dcho > ejecutar como administrador). En mi caso, he alojado el directorio de eclipse en "C:\Program Files". Éste directorio, además de ser famoso por alojar prácticamente todos los programas que instalamos en nuestro PC, lo es también por requerir privilegios elevados para casi todas las operaciones. Una vez ejecutado de ésta manera, no debería poneros ninguna traba a la hora de leer, escribir o ejecutar algo dentro de eclipse.
  • Si aún así seguís obteniendo el mismo error, probad a mover las carpetas "eclipse" y "android" de "C\:Program Files" a "C:\".
 Os aseguro que en mi caso, fue suficiente con el procedimiento descrito en el primer punto, pero el segundo por lo visto, tiene gran aceptación en la comunidad. Supongo que a alguien le funcionaría...

Un saludo, Marcos R.