Show Posts
Pages: [1] 2
1  International / Español / Re: ciclos anidados? saltos??... ayuda on: December 12, 2012, 11:39:44 am
Creo que haría falta una descripción mucho más detallada tanto del código como del hardware.

En principio, un servo puede estar en su estado original o "trucado" de dos formas diferentes.

Un servo normal de fábrica está formado por un motor que mueve el mecanismo y un sensor que mide la posición del mecanismo. El sensor que mide la posición viene a ser un potenciómetro y la posición se mide midiendo la resistencia. Este potenciómetro suele tener una carrera mecánica (el ángulo de giro que abarca) de unos 240º grados y una carreta eléctrica de unos 220º. Así que el mecanismo puede moverse hasta 240º antes de dar en el tope mecánico pero la resistencia solo cambia y la posición solo puede medirse en los 220º centrales.

El control del servo suele estar ajustado para que cuando la señal de control va de extremo a extremo el servo se mueva unos 90º.

Si se truca este potenciómetro la amplitud del movimiento se puede ampliar hasta 200 o 220º.

Otro "truco" consiste en suprimir y los topes mecánicos y entonces el servo se convierte en un "servo de rotación continua", que puede dar, por ejemplo, 12 vueltas en un sentido y luego 16 en el otro. El problema es que con este "truco" deja de ser posible conocer la posición en que está el servo y el servo, en realidad, deja de ser un servomotor.

El código típico para una cosa de estas podría tener esta pinta general:

Vamos a suponer que la posición del servo (pos) puede moverse desde 0 (extremo izquierda) hasta 255 (derecha), que y que el valor medido en la fotoresistencia (val) crece cuando el servo se mueve hacia la derecha y que queremos pararnos el el valor de fotoresistencia TARGET.

Necesitamos una función, o unas líneas de código que ordenen al servo una nueva posición, lo llamaremos servo_pos() y otra función o lineas de código que miden el valor de la resistencia, lo llamaremos mide_val()

Code:
#define MIN_SERVO    0
#define MAX_SERVO   255

#define T_INICIAL     1500
#define T_PASO         15

#define TARGET         1000

servo_pos(MIN_SERVO);
delay(T_INICIAL);              // Damos tiempo al servo a llegar al extremo izquierdo

for(n = MIN_SERVO; n<= MAX_SERVO; n++){
       if(mide_val()>TARGET) break;
       servo_pos(n);
       delay(T_PASO);
       }

if(TARGET<mide_val()) Serial.printnl(Error: El target no ha sido alcanzado);

La instrucción break; hace que la ejecución "salte fuera" del bucle y continúe, el problema es que no sabemos si hemos salido del bucle porque val ha alcanzado el target  o porque se ha alcanzado el extremo izquierdo de las posiciones del servo.

Con "while" se puede emplear break; o hacer falsa la condición del while


Code:
#define MIN_SERVO    0
#define MAX_SERVO   255

#define T_INICIAL     1500
#define T_PASO         15

#define TARGET         1000

servo_pos(MIN_SERVO);
delay(T_INICIAL);              // Damos tiempo al servo a llegar al extremo izquierdo

int continua = 1;
int posicion = MIN_SERVO;

while(continua==1){
       if(mide_val()>TARGET)        continua=2;

       servo_pos(posicion);
       posicion++;
       if(posicion>MAX_SERVO)      continua=3;

       delay(T_PASO);
       }

if(continua==2) Serial.printnl(Target alcanzado);
if(continua==3) Serial.printnl(Error: Target no alcanzado);
2  International / Español / Re: Problema com "goto" on: November 30, 2012, 07:24:15 am
La instrucción “goto” no debería ser nunca necesaria.

Los corchetes {} crean un bloque de código que se ejecuta como un conjunto, de arriba abajo.
Una estructura de control, como por ejemplo un if() puede hacer que se ejecute una instrucción
suelta o un bloque de código entre corchetes. Cuando solo se ejecuta una instrucción, no son necesarios los corchetes.

Por ejemplo:

Code:
if (val =='2') digitalWrite(ledPin2, HIGH);

o, un bloque

Code:
if (val =='2')
{
digitalWrite(ledPin2, HIGH);
Serial.println("LedPin2 activo");
}

Los grupos if..else anidados pueden dar lugar a un código muy confuso y que puede contener errores fácilmente. Creo que eso es
lo que le pasa a tu código. Se trata de identificar a que if corresponde cada else y eso suele ser complicado.

Como los diferentes valores de "val" son mutuamente excluyentes (solo se ejecuta uno de los if), creo que el código podría funcionar como sigue:

Code:
void loop()
{
   val= Serial.read()-48;

   if(val =='1') digitalWrite(ledPin1, HIGH);
   if(val =='2') digitalWrite(ledPin2, HIGH);
   if(val =='3') digitalWrite(ledPin3, HIGH);
   if(val =='4') digitalWrite(ledPin4, HIGH);

    digitalWrite(ledPin1, HIGH);
    digitalWrite(ledPin2, HIGH);
    digitalWrite(ledPin3, HIGH);
    digitalWrite(ledPin4, HIGH);
   
    delay(500);
   
    digitalWrite(ledPin1, LOW);
    digitalWrite(ledPin2, LOW);
    digitalWrite(ledPin3, LOW);
    digitalWrite(ledPin4, LOW);
}

Para este tipo de estructuras en las que hay varios comportamientos posibles según el "caso" suele emplearse la instrucción switch...case

El código quedaría asi:

Code:
void loop()
{
   val= Serial.read()-48;
   
   switch(val)
    {
    case '1': digitalWrite(ledPin1, HIGH); break;
   
    case '2':
    digitalWrite(ledPin2, HIGH);
    Serial.println("ledPin2 activado"); // Instrucciones hipotéticas
    delay(10);
    break;
   
    case '3': digitalWrite(ledPin3, HIGH); break;
   
    case '4': digitalWrite(ledPin4, HIGH); break;   
   
    default: Serial.println("Valor de val ilegal");
    }

escribe4Pines(HIGH);
   
    delay(500);
   
escribe4Pines(LOW);
}

void escribe4Pines(int valor)
{
digitalWrite(ledPin1, valor);
    digitalWrite(ledPin2, valor);
    digitalWrite(ledPin3, valor);
    digitalWrite(ledPin4, valor);
}

(He incluido la función escribe4Pines() para ilustrar cómo se definen y usan funciones)   
3  International / Español / Re: problemas para programar arduino mega 2560 on: November 24, 2012, 06:21:02 am
Ni Avrdude ni el bootloader analizan el código que se transmite así que por muy disfuncional que sea el código que se intenta transmitir no debería ocurrir ningún problema durante la transmisión.

Si el código contuviese construcciones o instrucciones ilegales se produciría un error cuando el Arduino intenta ejecutar ese código pero no durante la fase previa de transmisión.

Debe ser un problema de sintaxis, de los símbolos que contiene el código y no de lo que esos símbolos signifiquen, de las instrucciones que están codificadas en ellos. Se trataría de encontrar "una letra" equivocada y no una instrucción equivocada.

El método más rápido es comentar o suprimir grandes bloques de código hasta aislar la linea concreta que crea el problema.

Un ejemplo de símbolo que atasca el sistema de transmisión en la mega es "!!!". Si hay una string literal como "Sobrecalentamiento !!!" en el código, las 3 exclamaciones seguidas impiden la transmisión del programa.

http://arduino.cc/forum/index.php/topic,126778.0.html

4  International / Español / Re: Uso de motor DC como cuasi Servo, proyecto avanzado, para sugerencias on: November 22, 2012, 02:45:40 pm
El problema que le veo yo a una aproximación tan matemática es que, aunque sobre el papel, puede ser muy exacta, supone una enorme sobrecarga de cálculo para el procesador. Estos microcontroladores son potentes cuando trabajan con números enteros pequeños pero extremadamente ineficientes cuando trabajan con números en coma flotante.

En una aplicación en la que el procesador, además de controlar 4 o 5 servos, tenga que hacer muchas otras cosas a la vez y en tiempo real, este enfoque puede fácilmente desbordar la capacidad de cómputo en coma flotante del controlador.

Una aproximación, menos académica, pero más eficiente con este tipo de controladores es tener las funciones pre-calculadas y almacenadas en una tabla. Como estas tablas son constantes, pueden ser de "solo lectura" y almacenarse en la "memoria de programa", mucho más abundante, en lugar de en la RAM donde habitan las variables.

El proceso de construir el algoritmo de control, en esencia, consiste en "dibujar" la función de respuesta que se quiere.

Una función básica es "estática", esto es, supone que el sistema no tiene inercia, y además, supone que las fuerzas de resistencia son constantes.

En este esquema básico, se mide la posición del servo (y el error) pero no la velocidad con que se mueve el servo (ni la velocidad con que varía el error). Así que el bucle de control está cerrado en un grado (el de la posición) pero abierto en los grados superiores (la velocidad)

De esta forma, damos por hecho que si ordenamos al motor que se mueva a velocidad V, con un digitalWrite(V) el motor pasará instantáneamente a moverse con velocidad V (este bucle está abierto). Esto implica que las fuerzas que puedan estar oponiéndose al movimiento del servo (si ese servo mueve el alerón de un avión, por ejemplo) no son tenidas en cuenta y tampoco se tiene en cuenta la energía cinética que tenga acumulada el sistema: cuando ordenamos al motor que se pare (Velocidad=0) nos conformamos con que los rozamientos pasivos absorban la energía y detengan el sistema un "poco más allá"

Para sistemas pequeños y sencillos, esta primera aproximación puede funcionar. En esta aproximación suponemos que las velocidades del motor serán proporcionales a la energía que le enviemos (bucle abierto) y la energía que enviemos al servo será solo una función del error instantáneo (de la distancia que tiene que moverse hasta anular el error)

Así que podemos "dibujar" una tabla pre-calculada o ajustada mediante tanteos, de energías a enviar al servo en función del error actual. En un sistema pequeño bastan muy pocos valores para definir la forma de esa curva porque las inercias del sistema promedian los "escalones"

Si la posición del joystick y del servo están definidas con 10 bits (1024 valores), el acceso a una tabla de energías-error de 32 valores podría ser así:

Code:
byte tabla_energía[32] = {7, 16, 19, 23, ...}

digitalWrite(motor, tabla_energía[error >> 5]);

Para sistemas más grandes, el bucle de la "energía-velocidad" debe cerrarse. No solo hay un error de posición, sino también un error de variación de posición (de velocidad)

La posición, el error actual requiere programar cierta velocidad pero cosas como la inercia, o perturbaciones externas pueden hacer que la velocidad que se consiga no sea "la esperada" y la diferencia es un error de segundo grado, un error de velocidad.

Si miramos al servo a intervalos de tiempo conocidos, la lectura de su potenciómetro nos dice la posición en que se encuentra, si restamos la posición actual de la que tenía la última vez que lo medimos y conocemos cuanto tiempo ha pasado, sabemos también la velocidad.

Esto nos permite compensar fuerzas externas desconocidas (el error de velocidad que vemos nos permite conocerlas) y hacer que el motor frene activamente enviándole energía en "la dirección equivocada"

Para esto podemos usar el método anterior pero con una tabla de dos dimensiones que defina qué energía debe enviarse al servo en función del error actual y de la velocidad a que se está corrigiendo ese error. Una tabla de 16x8 bastaría para casos bastante complicados y una tabla de 32x16 permite controlar el vuelo de un cohete Ariane. 

Dibujar estas tablas es una mezcla de cálculo y arte.

Una hoja de cálculo, como OpenOffice, sirve perfectamente y yo creo que un Arduino basta para calcular estos valores en "tiempo diferido"

Luego, los datos provisionales se someten a experimentos: ver si es capaz de frenar en seco o se pasa del semáforo, la aceleración máxima que puede alcanzar pero de forma que el sistema tenga tiempo de frenar luego o si resiste bien a las fuerzas externas.

Como las hojas de cálculo permiten hacer gráficos de estas funciones contenidas en las tablas, y como podemos ver cuando el sistema se excede o se queda corto, con un poco de práctica, el último ajuste puede hacerse puramente a ojo.

Los cohetes que pusieron en órbita a los primeros astronautas, Semiorka y Atlas-Mercury, no es que tuviesen ordenadores incapaces de calcular en coma flotante, es que no tenían ordenador alguno.



5  International / Español / Re: 4-20ma a 0-5v con rcv420 on: November 21, 2012, 02:34:11 pm
Dibujar un sistema de pistas a partir del esquema del datasheet es bastante sencillo, solo hay que entender lo que significa cada signo y traducir a la placa las conexiones con un poco de paciencia y revisándolo todo para no liarla.

Sin embargo no tengo claro que vayas a mejorar demasiado la resolución con este circuito y este chip requiere una fuente de alimentación doble bastante engorrosa. Quizás deberías explicar con más detalle en qué punto echas de menos el tener más resolución o cuál es la aplicación concreta.

Vayamos con el esquema.

En la figura “PIN CONFIGURATION” página 3, está la “foto” del chip visto desde arriba con el número y nombre de cada pin. Hay que asignar 2 filas de 8 agujeros para esos 16 pines.

Pasemos a la figura 1 de la página 5, que es la configuración para una aplicación básica.

Hay que establecer la típica pista gorda de “masa” (También llamada 0V, o GND)

El Pin 2 del chip (retorno del bucle) el Pin 5 (0V de la referencia de tensión) y Pin 13 (los 0V del propio chip) van todos ellos conectados a esta pista “masa”

Además, tendríamos que sacar otras 5 conexiones más de esta pista “masa”.

Una para cerrar el bucle de corriente conectándola al GND del sensor de presión.
Otra para los 0V de la fuente de alimentación doble  para el chip.

Una tercera para el GND del Arduino.

Y dos conexiones más para los condensadores anti-ruido.

Los pines 1, 7 y 8 no se usan en esta configuración y quedarían “en el aire”

Hay una pista que une los pines 14, 15 y la tensión analógica que se envía a Arduino

Hay otra pista que une los Pines 10, 11 y 12 entre sí.

Veamos ahora la alimentación del chip que es la parte más confusa. El Pin 16 (V+) es la alimentación positiva del chip y el Pin 4 (V-) es la alimentación negativa. En el dibujo, debajo de los pines 4 y 16 tenemos dibujados 4 objetos. Los dos que están marcados con 1 uF, son dos condensadores. Los otros dos, dibujados como una serie de líneas apiladas, son “pilas” o fuentes de alimentación.

Este chip, para dar 0 V en la salida, necesita alimentarse de una tensión negativa, por debajo de 0V y eso obliga a suministrarle como alimentación una tensión negativa además de la positiva normal.

Para aclarar conceptos, supongamos que tenemos una fuente de alimentación doble que suministra +15V y - 15V (referidos a un hilo de 0V). Esta fuente de alimentación vendrá con 3 hilos, el de tensión positiva (+ 15V) el de tensión negativa (- 15V) y un hilo GND (0V o “masa”). El hilo +15V tenemos que conectarlo al Pin 16, el hilo -15 V, al Pin 4 y el hilo GND a la pista general de masa del circuito.

Con eso el chip queda alimentado pero hay un problema: incluso aunque la fuente entregase tensiones libres de ruido, los cables que van desde la fuente hasta el chip podrían capturar ruido por el camino, haciendo de antenas de radio, por ejemplo. Así que, por decirlo de algún modo, tenemos que descontaminar de ruido, a pié de obra, las entradas de alimentación del chip.

Para eso, ponemos un condensador que conecte el Pin 4 con “masa” y otro que conecte el Pin 16 con “masa”. Estos condensadores son “opacos” a la corriente continua que llega a los pines 4 y 16 y la corriente de alimentación no puede atravesarlos. Sin embargo, el ruido, que está formado por corriente alterna, si los atraviesa fácilmente y ese ruido es desechado a “masa”.

Estos condensadores que son como aire para la corriente (continua) de alimentación, son como un cortocircuito para el ruido, y el ruido que pueda llegar a 4 o 16 es derivado a través de ellos a masa y eliminado. Estos condensadores deben conectarse físicamente lo más cerca que se pueda de los pines 4 y 16 que hay que descontaminar y las conexiones de los condensadores a los pines y a masa ser lo más cortas posibles, o harán de antenas y capturarán nuevo ruido.

Estos son dos condensadores de tántalo de 1 microFaradio. Los condensadores de tántalo, y los condensadores grandes en general, van polarizados, tienen una pata + y otra - y deben conectarse en el sentido correcto si no se quiere que exploten.

En el esquema está indicada esa polarización, que sería la siguiente. Hemos llevado +15V al Pin16, ahora conectamos el + de uno se los tántalos al Pin 16. En el Pin 4 tenemos el hilo -15V de la fuente y tenemos que conectar también la pata - del otro tántalo. Los extremos que nos han quedado libres de los tántalos van a “masa”, que es donde depositan el ruido que extraen de 4 y 16.

Así que como resumen, tendríamos: el chip con los pines correspondientes conectados y luego podemos imaginar tres bornas.

La “borna del sensor”, con el terminal “4-20 mA” conectado al Pin 3 y el terminal GND, conectado a la pista “masa”

La “borna Arduino” con el terminal “Salida analógica” conectado a los pines 14 y 15, y el terminal GND, conectado a la pista “masa”

La “borna alimentación”, con el terminal “+15V” (Pin 16), el terminal “-15V” (Pin 4) y el terminal GND (pista “masa”)

Existen apaños para alimentar uno de estos circuitos con una fuente “normal”, por ejemplo de GND y 24V, a base de inventar una masa virtual a medio camino por ahí, pero son bastante engorrosos. Me parace que hay en Texas alguna hoja de aplicaciones en la que se detalla la forma de usar este chip con una alimentación sencilla. Creo que si expones con más detalle el problema con el que tropiezas se podría inventar alguna solución más simple.
6  International / Español / Re: variaciones en la senyal del potenciometro al servo on: November 21, 2012, 11:54:19 am
Tiene pinta de ser un problema de hardware, probablemente porque aparece una realimentación positiva parásita.

El sistema lee una tensión en el potenciómetro. Esa tensión es función de la posición del potenciómetro y de la tensión con que se alimente ese potenciómetro. Si el servo no está en la posición correcta, el sistema ordena moverse al servo. Cuando el servo se activa, su motor consume corriente de la misma alimentación que alimenta el potenciómetro y eso hace que la tensión que genera el potenciómetro cambie, aunque la posición del potenciómetro no cambie. Hay que desacoplar el conjunto de forma que los cambios de consumo del servo no modifiquen la tensión con que se alimenta el potenciómetro.
7  International / Español / Re: Uso de motor DC como cuasi Servo, proyecto avanzado, para sugerencias on: November 21, 2012, 11:19:16 am
No entiendo el código muy bien pero la intensidad del ajuste, o del movimiento, debería ser de algún modo proporcional al error que se trata de corregir. El joystick se mueve por su cuenta y el motor debe seguirle y copiar la posición del joystick. Si la posición del motor no corresponde con la del joystick aparece un desfase o error y se trata de corregir ese error.

Por ejemplo: si el joystick está en la posición 650 y el motor en la posición 512 (en el centro), el error, el desfase, que hay que corregir es 138. Si el joystick está en la posición 650 y el motor en la posición 660, el desfase a corregir sería de -10. En este segundo caso, para corregir el desfase, el motor tiene que moverse en la dirección opuesta, ya que el signo es negativo, y además una distancia mucho menor.

La velocidad a que se mueve el motor tiene que ser grande cuando está muy lejos de donde debería estar, cuando el desfase a corregir es elevado, y el motor debe ir reduciendo esa velocidad según se acerque a donde debería estar: según el error a corregir se vaya haciendo cero.

He escrito un ejemplo de código que no funciona directamente sino que sirve para ilustrar el principio.

Code:
#define MIN_AJUSTE 50
#define PAR_A 0.25F
#define PAR_B 20
#define DERECHA 1
#define IZQUIERDA 0

void loop(){
int error;

error = leeError();
corrige(error);
}

int leeError(){
int motor, joystick, err;

joystick = analogRead(pot2);
motor = analogRead(A3);
error = joystick – motor;

return(err);
}

void corrige(int err){
byte dir = DERECHA;
int velocidad;

if(err==0) { parada(); return; } // (1)

if(err<0) { dir = IZQUIERDA; err = -err; } // (2)

if(err<MIN_AJUSTE) {parada(); return; } // (3)

velocidad = PAR_A * err; // (4)
velocidad = velocidad + PAR_B;
if(velocidad>255) velocidad = 255;

if(dir == DERECHA) giraDerecha(velocidad);
else giraIzquierda(velocidad);
}

void parada(){
digitalWrite(right,LOW); 
    digitalWrite(left, LOW); 
    analogWrite(enable, 0);
}

void giraDerecha(int vel){
digitalWrite(right,LOW); 
    digitalWrite(left, HIGH); 
    analogWrite(enable, (byte) vel);
}

void giraIzquierda(int vel){
digitalWrite(right,HIGH); 
    digitalWrite(left, LOW); 
    analogWrite(enable, (byte) vel);
}

El código está muy descompuesto en funciones y hay muchas líneas innecesarias pero creo que así se ven mejor lo que hace cada parte.

Supondremos que medimos la posición del joystick y del motor con dos entradas analógicas y que esa posición de cada uno puede ir desde 0 hasta 1023.

leeError() simplemente calcula la distancia o desfase que hay actualmente entre la posición que tiene el motor y la posición que debería tener, que es la misma posición que tenga el joystick.

parada(), giraDerecha() y giraIzquierda(), detienen el motor o lo mueven en un sentido o el otro a cierta velocidad.

corrige(error) es la parte  donde realmente se define el comportamiento.

Si el error a corregir es demasiado pequeño, si el motor está lo bastante bien posicionado con respecto al joystick, paramos el motor y damos el ajuste por bueno, incluso aunque no sea un ajuste perfecto. Esto se hace para evitar que el motor se ponga a oscilar a derecha e izquierda tratando de corregir un error muy pequeño.

Hay definir una “banda muerta” en la que el error no se intentará corregir por ser demasiado pequeño (y para evitar el peligro de oscilación). La anchura de esta “banda muerta” la definimos con MIN_AJUSTE. En este ejemplo, si el desfase del motor con respecto al joystick es menor que 50 en cualquier dirección el sistema no intenta corregir el desfase. Las líneas (1) y (3) se encargan de cancelar ajustes demasiado pequeños.

La línea (2) se encarga de determinar en qué dirección debe girar el motor. El código asume en principio que el error tendrá signo positivo y la corrección será a la derecha, en caso de que el error tuviera signo negativo, la línea (2) se encarga de cambiar la dirección.

A partir de la línea (4) definimos cuál será la velocidad de corrección en función de lo lejos que esté el motor de donde debería, en función de lo grande que sea el error. Para calcular una velocidad que sea proporcional al error, multiplicamos el error por un parámetro que hemos llamado PAR_A. En este ejemplo PAR_A es un número en coma flotante de valor 0.25 que hará que si el error es 400 la velocidad sea 100 o si el error ha bajado ya a 80 la velocidad sea 20.

Si hacemos este PAR_A mayor, el sistema tendrá mayor velocidad de respuesta y el motor seguirá al joystick con reflejos más rápidos pero existe el peligro de que el motor no pueda luego frenar a tiempo. Cuando el motor se lanza a corregir el error, la inercia hace que el mecanismo acumule energía mecánica que hay que disipar para que el motor se pare. Este PAR_A hay que ajustarlo con tanteos al mismo tiempo que MIN_AJUSTE. Si le pedimos al motor que sea rápido debemos dejarle luego una “banda muerta” más ancha donde pueda frenar. Si movemos el motor muy despacio el ajuste final puede ser más fino.

Tenemos luego el parámetro PAR_B que es algo así como una “potencia mínima”.  Esto se pone para vencer rozamientos que pueda haber. Si no lo ponemos, tenemos el peligro de que el motor se pare antes de haber corregido el error por sus rozamientos mecánicos. La función giraDerecha() podría estar ordenándole al motor que se mueva a una velocidad 12 y el motor ser simplemente incapaz de moverse con tan poca potencia, así que añadimos esta potencia mínima para ayudarle.

MIN_AJUSTE, PAR_A y PAR_B hay que ajustarlos a base de experimentos, comenzando por una banda muerta grande y velocidades pequeñas.

Lo que sea derecha o izquierda con relación a lo que sea un signo + o - en el error es arbitrario y el motor podría tratar de corregir el error en la dirección equivocada. En ese caso hay que invertir la polaridad del motor o los potenciómetros o cambiar el significado de derecha o izquierda.

Este código de ejemplo, tal como está escrito, es muy poco eficiente por muchos motivos pero sobre todo por esa multiplicación en coma flotante que es muy costosa para el controlador. En un código más realista emplearíamos una “multiplicación entera” y PAR_A sería un número entero.
La línea (4) y siguientes tendrían un aspecto del estilo de:

#define PAR_A 16

velocidad = ((err * PAR_A) >> 6) + PAR_B;
if(velocidad>255) velocidad = 255;
8  International / Español / Re: Consejos para hacer un shield on: November 21, 2012, 08:30:58 am
Quote
respecto a crear la PCB, aun no me he atrevido, mas que nada porque no tengo el material ni el diseño hecho, pero creo que me animare con algo pequeño e intentare ir a mas. probare lo de llevar el circuito a imprimir ya que no tengo impresora laser, necesito que esta placa este construida en plan profesional así que tengo que ponerme las pilas.

En esto puedes encontrarte con una dificultad técnica: es necesario imprimir la máscara que formará el circuito con un toner "barato" o "antiguo".

La máscara impresa debe tener el mejor contraste posible, o sea, ser lo bastante transparente a los ultravioleta en las partes blancas y lo más opaca posible a los UV en las partes negras. El problema es que los toner modernos, que se emplean para impresiones de muy alta resolución, no son opacos a los UV.

Los toner antiguos, o los modernos baratos, suficientes para impresoras baja resolucón (150-300-600 ppp) se hacían/hacen de "negro de humo", el mismo polvo negro que recubre el interior del tubo de escape de un coche y que viene a ser carbono puro. Este polvo de carbono absorbe de forma extrema casi cualquier tipo de radiación y hace que las manchas impresas sean muy opacas a los UV.

Las impresoras modernas de alta resolución requieren un toner formado por partículas más finas y de un tamaño más regular y están hechos de partículas de "plástico". Este toner no es lo bastante opaco.

La solución suele ser utilizar una laser "antigua", de resolución moderada, y cargarla con "toner pirata", hecho de carbono a la vieja usanza. 
9  International / Español / Re: problema creando array multidimensional on: November 20, 2012, 11:15:03 am
Este es un problema bastante fundamental. Ocurre porque ese array está definida como una "variable global"

Una "variable global" es una variable definida fuera de cualquier función y accesible desde cualquier punto del código, desde el interior de cualquier función. Para el compilador, estas variables son simplemente lugares (direcciones) en la memoria RAM y para compilar el programa necesita saber cuánto espacio debe reservar y en qué sitio está cada variable.

Una posibilidad es usar "asignación dinámica de memoria" con la función malloc() pero se rumorea que el C de Arduino no maneja bien la función free()

Otra posibilidad es declarar esa variable dentro de una función, lo que crea esa variable en el stack, en "tiempo de ejecución". La declaración, por ejemplo int tabla[h][v]; tendría que estar, por ejemplo, dentro de loop()

Code:
loop()
{
int tabla[h][v];
...
...
}

pero eso impediría el acceso directo a ese array por parte de otras funciones y loop() tendría que proporcionarles ese acceso. Por ejemplo:

Code:

funcionJ(int valor)
{
....
}

loop(){
int tabla[h][v];
...
...
funcionJ(tabla[3][5]);

}

Otra posibilidad es usar un array (global) lo bastante grande que cubra el peor de los casos y luego utilizar algún tipo de índice que indique qué parte de la capacidad total del array se está empleando actualmente.



10  International / Español / Re: ¿Alguien sabe por que esta tontería de codigo no funciona? on: November 20, 2012, 10:35:36 am
El flujo de programa solo "entra" en un bucle como:

Code:
    while(lectura == HIGH)
    {
      digitalWrite(O5, HIGH);
    }

si la condición es verdadera, en este caso si "lectura" es HIGH. Una vez atrapado dentro del bucle while, el flujo de programa solo puede escapar si "la condición" deja de ser verdadera. Esto implica que algo que se ejecute dentro del bucle while tiene que cambiar en algún momento la "verdad" de la condición o el flujo quedará atrapado para siempre en un "bucle eterno". En este caso, salvo que haya por ahí algún código invisible, como el servicio de una interrupción, el código dentro del bucle while no cambia ni el valor de "lectura", ni el valor de HIGH lo que condena al bucle a ser un bucle infinito.

El compilador debería dar un warning en este caso porque se puede determinar que este es un bucle infinito en "tiempo de compilación"

Offtopic: Las etiquetas empleadas en los #define deberían ser palabras largas e improbables, como Pin_entrada_driver_05, para evitar que puedan aparecer accidentalmente en el código. Por ejemplo: si escribimos

#define er 456

y luego en el código

Serial.print(vv);

el preprocesador del compilador nos cambiará esa linea por:

S456ial.print(vv);
11  International / Español / Re: Que sensor usar para posicionamiento en el espacio on: November 20, 2012, 10:01:35 am
Yo creo que es más preciso utilizar el "tiempo de llegada" o el ángulo que la potencia de señal pero me temo que eso requeriría un sistema más complicado. Una posibilidad sería usar un par de "transponder" de ultrasonidos. 

El helicóptero podría emitir un pulso de sonido, un simple pitido o una de esas firmas pseudoaleatorias. Cuando un transponder recibe ese pulso, espera (pongamos) 5 milisegundos y emite un pulso de respuesta. El helicóptero tiene que cronometrar el tiempo en que tarda en recibir la respuesta. Para definir un punto en un plano hacen falta 2 de estos transponders. Para distinguir entre el eco de los dos "transponders" cada transponder puede tener un tiempo de espera diferente, de forma que se obtengan dos ecos bien separados. Para obtener una resolución de 10 cm todo el sistema debe tener una precisión de reloj de 200 microsegundos. Se pueden alcanzar resoluciones mayores utilizando, además del tiempo de llegada, la fase del ultrasonido pero eso es bastante más complicado.

Para utilizar ángulos hacen falta emisores y/o receptores muy direccionales. Las piezas fijas podrían ser LED que emitiesen destellos, como las luces de un aeropuerto o un faro costero y el helicóptero necesitaría alguna clase de "sextante" que pudiese determinar la dirección visual del destello del faro. Este sextante es similar a una cámara con unos pocos pixeles (1, 2, 4), un objetivo formado por una lente, que proporcione la direccionalidad y la ganancia óptica y algún motor que permita apuntarla en diferentes direcciones o hacer que vaya dando vueltas. 
12  International / Español / Re: Mega 2560 no carga los sketch grandes... SOLUCIONADO on: November 20, 2012, 09:36:06 am
Sí, la secuencia de bytes que representan "!!!" (no sé si son 2 o 3) tienen un significado especial en el mecanismo de transmisión serie y cuando durante la transferencia del programa intentan pasar esos 3 "!" la otra parte en la linea serie lo interpreta como alguna "secuencia escape" especial.
13  International / Español / Re: Ayuda con alimetacion de Arduino UNO on: November 20, 2012, 08:06:28 am
Yo creo que el regulador interno de la placa Arduino debería dar corriente suficiente para el LCD y los giróscopos, además de para el propio Arduino, pero eso es algo que nunca está muy claro.

La placa Arduino tiene una "linea externa" de alimentación no regulada que es "Vin". Esta linea Vin va conectada al pin "Vin" y al jack de alimentación externo. En esta linea podemos inyectar por ejemplo 9V no regulados.

La placa Arduino tiene un regulador interno de 5 V que se alimenta de esa linea "Vin" genera una tensión regulada de 5V y la coloca en la linea "5V". De esa linea "5V" es desde donde se alimenta el microcontrolador y esa linea aparece como el pin "5V"

Cualquier otro periférico que necesite tensión regulada a 5V y no consuma muchos miliamperios puede alimentarse de este pin 5V que vendría a ser la salida regulada del regulador interno.

El problema es que no está nada claro cuántos miliamperios se pueden extraer razonablemente de este pin "5V". Esta parte está mal documentada porque depende de demasiados factores.

El factor limitante es la cantidad de calor que genere el regulador y que pueda disiparse: si se sobrecarga el sistema el regulador se recalienta y con el tiempo deteriora la placa.

La cantidad de calor que desprende el regulador depende del "salto de tensión" que haya entre la linea "Vin" y la linea "5V" y de los miliamperios que consuma el conjunto conectado a "5V". Lo ideal es una batería que alimente "Vin" con 7 o 8 V ya que esto produce un "salto" de solo 2 o 3 V. Alimentar "Vin" con 12V está en el límite máximo recomendado y produce un salto de 7 V (12-5)

La corriente que puede sacarse de "5V" depende tanto de este "salto" como de la corriente que consuma el propio Arduino y eso es algo que depende por completo de qué cosas haya conectadas a sus pines de salida. Por ejemplo: cada pin digital puede alimentar hasta 30 mA (creo recordar). Si tenemos activos al mismo tiempo 6 pines conectados a 6 dispositivos que consumen 30 mA, estas 6 lineas consumirán y cargarán al regulador con un consumo de 180 mA. Si solo tenemos 4 pines gobernando dispositivos que consumen 2 mA, estas lineas consumirán solo 8 mA y la linea "5V" podrá suministrar 170 mA más que antes.

Para probarlo, se pueden ir conectando cosas y ver si la temperatura del regulador no sube de forma alarmante.

Encendemos el Arduino desnudo unos minutos y tocamos con el dedo el regulador para tener una temperatura base de referencia. Luego montamos el giróscopo y conectamos el conjunto durante 3 o 4 segundos. Si la temperatura del regulador no ha subido alarmantemente dejamos el conjunto conectado durante tiempos más largos para certificar que la cosa funciona. Después desconectamos el giróscopo, conectamos el LCD y repetimos el stress test "basado en dedo"

Es un método primitivo pero que funciona en la práctica, siempre que estemos hablando de dispositivos de bajo consumo: 50, 100 o 150 mA en total.
14  International / Español / Re: Pantalla LCD 128x64 imprime datos "basura" con el Serial.print on: November 20, 2012, 07:28:20 am
Yo no veo nada mal en el código pero si las frases se imprimen bien y los floats no, una solución de emergencia podría ser convertir el float en una frase y luego imprimir la frase.

Por ejemplo, imprimir "litros" con 2 decimales
Code:
float litros = 425.63;
long  a;
String ss;

a = (long) litros;
ss = String(a, DEC);

Serial.print(ss);
Serial.write('.');

a = (long) (litros*100.0);
a %=100;
ss = String(a, DEC)

Serial.print(ss);

15  Using Arduino / Project Guidance / Re: Is ASM possible with Arduino? on: November 10, 2012, 01:16:21 pm
If you know how to write assembler files, the simplest method to include those ".S" files in your project is the "iard" method.

You must use the GCC assembler syntax that is a bit different from the AVR assembler syntax. 

A minor problem is that the ". S" files should be placed in a subdirectory of "libraries". "\arduino-1.0.1\libraries\AssemblerFiles" for example. You can use as many assembler libraries subdirectories as you wish but must reside in "libraries" directory, not in your projects/sketches directory.

http://arduino.cc/forum/index.php/topic,37588.0.html

Note: the syntax, general estructure and philosophy of inline assembly, asm(), __asm__(), and so on, is a real nightmare  designed by sadists computer scientists
Pages: [1] 2