Implementación de Inteligencia Artificial IA, Aplicada en...
Transcript of Implementación de Inteligencia Artificial IA, Aplicada en...
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
1
Abstract— The first ideas of creation of artificial intelligence
arose in 1815 fixed in a book of title "The tales of Hoffman"
which takes by author to Ernst Theodor Amadeus Hoffman,
a history of Romance which has Olimpia, a mechanical doll,
as protagonist. in love with the author. Years later thanks
to a computer called deepBlu defeating chess champion
Gary Kasparow, the idea of the existence of an artificial
intelligence is retaken since it is seen that a machine can
become more intelligent than a man. And it was then this
fact that marked the beginning of the development and
fomentation of artificial intelligence. Artificial Intelligence
is the result of research in cognitive psychology and
mathematical logic. It focuses on the explanation of the
work of the mind and the development of algorithms to
solve problems of general interest. Artificial Intelligence is
a combination of computer science, physiology and
philosophy, so general and broad is that it brings together
several fields such as robotics, expert systems, for example,
all of which have in common the creation of machines that
can think. The idea of building a machine that can perform
tasks that are known as human intelligence requirements is
attractive. The tasks that have been studied from this point
of view and include games, language translation, language
comprehension, fault diagnosis, robotics, providing expert
advice on various topics. Intelligence The intelligence of the
human being is defined in its most basic concept; as "the
ability to adapt to an environment, reasoning, and the
capacity of the human being to give a solution to a
problem". In order to have a more central definition of
intelligence, since the general concept does not specify the
environment in which it is unmoved nor the defined
problem, we have to divide it into different types of
intelligence, that is, to each set of tasks that we execute
Attributes a concept of intelligence and uses different
reasoning, such as playing a musical instrument and solving
a math problem, where you can see that different types of
intelligence are applied to the execution of both activities.
INTRODUCCION
En los avances de IA y la interacción del ser humano a las condiciones
tecnológicas del nuevo mundo hace que los desarrollos sean de manera
continua, teniendo acceso a diferentes lugares aumentando la
perspectiva de vida de las naciones. Así mismo la interacción hombre-
máquina hace que la vida sea más simple y practica otorgando, desde
los sistemas de salud pasando incluso a los sistemas educativos.
´´OHMBOT´´ es una IA aplicada en un módulo robótico cuya
características distintivas es la razón de la vida con los humanos,
basados en los principios básicos de la naturaleza. Acercar al hombre
a su sentir vivir con la naturaleza no por el uso de la tecnología sino en
la interacción con ella. El módulo robótico cuenta con componentes
ambientales, sociales y académicos muestra la capacidad de sostener
vida (biótica) en un medio artificial, este módulo es un ayudante
humano cuyo objetivo es prevalecer y responder a estímulos como el
amor, una de las facultades más grandiosas del ser humano. Este
producto muestra el resultado de la aplicación científica a la vida
académica y cotidiana.
LOGARITMO IA PARA RED NEURONAL
Se implementa un software de simulación, en español e inglés,
donde empleamos como método de aprendizaje el Algoritmo
de Retro propagación. Para ello se ha recurrido a la técnica del
Ciclo de Vida, parámetros que nos rodean como variables con
las que interactuamos con nuestros sistemas de vida y actividad
cerebral con un Software artificial, dedicando la etapa inicial a
la investigación y estudio de los primeros parámetros que va
utilizar nuestro Robot OHMBOT, para luego pasar a la etapa de
diseño e implementación. En ésta se optó por dos plataformas
una diseñada en lenguaje C y otra en el lenguaje de
programación orientado a objetos Java en LINUX para el
diseño de nuestra red de neuronas artificiales, por su robustez,
y también por su capacidad de manejar hilos de ejecución y su
arquitectura neutra (multiplataforma) .
Redes Neuronales Artificiales Se describen a continuación los principales componentes de una
red neuronal artificial (RNA). Donde tenemos como concepto
principal de una Neurona o Unidad Procesadora, sobre un
conjunto de nodos N, obtenemos una configuración de tres
Myers E George
Implementación de Inteligencia Artificial IA,
Aplicada en un Módulo Robótico de Interacción
Humana –“OHMBOT” (Octubre 2018)
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
2
varibles (X; f; Y), donde X es un subconjunto de N; Y es un
único nodo de N y f : R → R es una función neuronal (también
llamada de activación) aquí se calcula un valor de salida para
Y basado en una ecuacion lineal de los valores de las
componentes de X, es decir:
Los elementos X; Y y f de denominan grupo de nodos de
entrada, nodo de salida, y función neuronal de la unidad
neuronal, respectivamente.
Red Neuronal Artificial Una Red Neuronal Artificial (RNA) es
un par (N;U), donde N es un subconjunto de nodos y U es un
conjunto de unidades procesadoras sobre N que satisface la
siguiente condición: cada nodo Xi ∈ N tiene que ser un nodo de
entrada o de salida de al menos una unidad procesadora de U.
Donde f(x) es la función neuronal y los pesos wij pueden ser
positivos o negativos, reproduciendo el llamado carácter
excitador o inhibitorio de las sinapsis de las neuronas,
respectivamente. La Figura 1 muestra un ejemplo de una red
neuronal con ocho nodos {x1; ... ; x8 }. Algoritmo de
Aprendizaje: Supervisado Los patrones para el aprendizaje
están formados por parejas, f(ap; bp) p=1;...; r, que constan de
un vector de variables de entrada, a, junto con las salidas
correspondientes b. Por tanto cada valor de salida es la
respuesta deseada a las señales de entrada. En este caso, los
pesos se obtienen minimizando alguna función de error que
mide la diferencia entre los valores de salida deseados y los
calculados por la red neuronal. En este tipo de aprendizaje se
debe tener en cuenta el problema de la convergencia del error.
En general, la función de error resultante puede contener
múltiples mínimos locales y, por lo tanto, el proceso de
aprendizaje puede no converger al mínimo global óptimo.
Figura 1. Validación Una vez que ha terminado el proceso de
aprendizaje y los pesos de la red neuronal han sido calculados,
es importante comprobar la calidad del modelo resultante. Por
ejemplo, en el caso del aprendizaje supervisado, una medida de
la calidad puede darse en términos de los errores entre los
valores de salida deseados y los obtenidos por la red neuronal.
Una medida estándar del error es la suma de los cuadrados de
los errores, definida como: donde bp es la salida de la red para
el vector de entrada ap. Cabe aclarar que en el caso de una única
salida, la función se reduce a la función valor absoluto usual.
También es necesario realizar una validación cruzada para
obtener una medida de la calidad de predicción del modelo. Por
este propósito, los datos obtenidos se pueden dividir en dos
partes, una parte destinada al entrenamiento de la red y otra
parte a la comprobación (testeo o validación). Cuando el error
de comprobación es mucho mayor que el error de
entrenamiento, se produce un problema de sobreajuste durante
el proceso de entrenamiento.
Simulación de Red Neuronal a través de los ojos prototipo
con matriz de leds
Diseñar la expresión de un robot no es tan fácil como se ve, las
expresiones visuales generadas por cualquier ser vivo son dadas
por el movimiento de sus ojos y movimientos de sus parpados,
en nuestro diseño se genera un algoritmo capaz de captar estos
movimientos, implementación dada por medio de sensores de
movimiento, sin red neuronali.
Los elementos que se utilizan fueron:
Matriz de leds 8x8 Adafruitii, una simple pantalla de leds
formada por un mapa de bits, cada matriz solo requiere de
cuatro cables especificados así, alimentación, tierra, y dos
líneas de comunicación al microcontrolador.
Estas pantallas led usan una interfaz de dos hilos hacia el
Arduino (TWI) o I2C, esto nos permite que varios de estos
dispositivos se comuniquen en el mismo bus. Para la conexión
en una placa Arduino se hacen en los pines analógicos (4) para
datos en serie. Las placas Arduino también incluyen don
clavijas SDA y SCL que sirven para las mismas funciones.
Para distinguir entre múltiples dispositivos en el bus de datos, a
cada uno se le debe asignar una dirección numérica única. Hay
una dirección predeterminada (0X70 en notación hexadecimal
que puede ser modificada uniendo o soldando un puente en la
parte posterior de la tarjeta de la matriz.
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
3
En La figura anterior vemos nuestra tarjeta que maneja la
matriz de 16x8 de Adrafruit Industries HT16K33 LEDiii.
Se muestra en un círculo verde las dos conexiones A0,
uniéndolas con un puente esto nos configura la matriz de 0x70
a 0x71, al puentear nos agregara 2 combinaciones, y ambos se
pueden usar en combinación para +3, Esto permite cuatro
direcciones posibles en las matrices pequeñas de 8x8. Las
matrices pequeñas agregan una selección de dirección “A2” que
agrega 4 a la dirección del dispositivo. Esto nos da para
conformar un red neuronal de varias combinaciones de muestra
facial por reacción al algoritmo creado para animar una cara, En
este caso usaremos cinco matrices. Configuradas asi:
Dos matrices
Nuestro diagrama de cableado se vera de la siguiente forma. Se
observa que las cinco pantallas se conectan a los mismos cuatro
puntos de potencia, tierra, reloj serie y datos:
Se realizan pruebas con unas baterías doble AA para su uso
portátil. Se tiene en cuenta que no estamos utilizando el
conector de alimentación de CC en el arduino, Cada una de
estas pantallas puede generar hasta 200 miliamperios cuando
están completamente iluminado.
SOFTWARE
Debemos trabajar con dos librerías importantes para el manejo
de esta matriz Adafruit_GFX y Adafruit_LEDBackpack, para
pruebas usamos en el código (“roboface” y wacface”) para las
expresiones de la cara.
Programación la múltiples Matrices
Ya sea que estemos trabajando con una o varias matrices de
LED se necesitara incluir tres archivos: uno para la biblioteca
Arduino TWI estándar y uno para las bibliotecas de dispositivos
y gráficos de Adafruit.
Bitmaps La cara se dibuja utilizando una serie de mapas de bits
almacenados en lugar de tener un monton de líneas de dibujo
de código, es decir círculos, etc. La única excepción son las
pupilas que tienen movimiento, que son simplemente cuadrados
negros de 2x2 pixeles.
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
4
La notación numérica binaria de Arduino simplifica la tarea de
crear estas formas, prácticamente puedes ver la imagen en el
código.
Hay que tener en cuenta con los Bitmaps: La notación de los
números binarios (los números que comienzan con “B”)
requieren 8 pixeles de ancho ( por ejemplo, 24 en la gráfica
anterior). Se puede rellenar una imagen con ceros adicionales
no utilizados a la derecha para completar la regla de múltiplos
de 8.
Los datos de mapa de bits deben declararse con la directiva
PROGMEN. Esto almacena datos en la memoria del programa
flash de Arduino en lugar de utilizar la RAM escasa.
Nuestro Robot OHMBOT finalmente va tener una cara
digitalizada construida por otro método probando inicialmente
la programación en matrices de LED, para este caso usamos
pantallas LCD donde utilizaremos gráficos definidos para los
ojos., construyendo múltiples algoritmos para formar una red
neuronal principal.
En este caso se diseña una programación compleja para simular
el ojo humano. Creando asi unos ojos animatronic con una
pantalla OLED para simular una pupila dilatada.
Parte necesarias de Adafruit
Microcontrolador PJRC Teensy 3.1 iv, esta placa es la que
controla los ojos.
Pantalla Oled de 1.5”v para cada ojo.
Para generar el efecto de retina en el ojo y dejar la simetría plana
de los dispositivos en este caso las pantallas oled, usamos unos
lentes en forma de gota de agua hechos en vidrio de unos 1.5
pulgadas (38mm) eso les da una forma en 3d, fáciles de
encontrar como objetos tipo pizapapelvi.
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
5
Para nuestros ojos debemos diseñar a medida una cuna para la
pantalla OLED y la retina artificial se realiza un modelo para
impresión en 3D.
Para cada ojo se deben tener cuatro partes principales: una caja
superior e inferior, una lente y la pantalla .
Los ojos deben estar ensamblados en las cajas impresas en 3D
conectados a una placa arduino, inicialmente no se aplica el
algoritmo de red neuronal, en ves de esto se deja con sensores
para la simulación facial.
Nuestro microcontrolador o elemento parte de la red neuronal
que lleva el Robot “OHMBOT”.
Se adiciona un circuito de alimentación alterno por conexión
usb, utilizando una micro tarjeta Lipoy 5V con su conector
táctilvii.
Para nuestro Algoritmo debemos de tener en cuenta los factores
naturales de nuestro alrededor, como interactúan con un ser
vivo, para nuestro Robot “OHMBOT”, se diseña un algoritmo
en su Red Neuronal para la reacción de la pupila no por
programación si no por factores naturales como funciona un ojo
de cualquier ser vivo, como la dilatación por la luz natural o
artificial. Inicialmente se hizo esta reacción con elementos
análogos para la calibración de parámetros de la retina, luego
cambiamos aun elemento electrónico que tomara la incidencia
de la luz para automatizar dicho movimiento con una
fotorresistencia, luego en su programación final le damos
parámetros de medición para una onda de luz y nuestro
microprocesador aprenderá a reaccionar dependiendo de la
intensidad de dicha variable (luz).
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
6
Codigo (algoritmo)
#include <SPI.h>
#include <Adafruit_GFX.h> // Core graphics lib for
Adafruit displays
#include "logo.h" // For screen testing, OK to
comment out
// Enable ONE of these #includes -- HUGE graphics tables for
various eyes:
#include "defaultEye.h" // Standard human-ish hazel eye
//#include "noScleraEye.h" // Large iris, no sclera
//#include "dragonEye.h" // Slit pupil fiery dragon/demon
eye
//#include "goatEye.h" // Horizontal pupil goat/Krampus
eye
//#include "newtEye.h" // Eye of newt
// Then tweak settings below, e.g. change IRIS_MIN/MAX or
disable TRACKING.
// DISPLAY HARDWARE CONFIG -----------------------------
--------------------
#include <Adafruit_SSD1351.h> // OLED display library -
OR-
//#include <Adafruit_ST7735.h> // TFT display library
(enable one only)
#ifdef _ADAFRUIT_ST7735H_
typedef Adafruit_ST7735 displayType; // Using TFT
display(s)
#else
typedef Adafruit_SSD1351 displayType; // Using OLED
display(s)
#endif
#define DISPLAY_DC 7 // Data/command pin for BOTH
displays
#define DISPLAY_RESET 8 // Reset pin for BOTH displays
#define SELECT_L_PIN 9 // LEFT eye chip select pin
#define SELECT_R_PIN 10 // RIGHT eye chip select pin
// INPUT CONFIG (for eye motion -- enable or comment out
as needed) --------
//#define JOYSTICK_X_PIN A0 // Analog pin for eye horiz
pos (else auto)
//#define JOYSTICK_Y_PIN A1 // Analog pin for eye vert
position (")
//#define JOYSTICK_X_FLIP // If set, reverse stick X axis
//#define JOYSTICK_Y_FLIP // If set, reverse stick Y axis
#define TRACKING // If enabled, eyelid tracks pupil
#define IRIS_PIN A2 // Photocell or potentiometer (else
auto iris)
//#define IRIS_PIN_FLIP // If set, reverse reading from
dial/photocell
#define IRIS_SMOOTH // If enabled, filter input from
IRIS_PIN
#define IRIS_MIN 120 // Clip lower analogRead() range
from IRIS_PIN
#define IRIS_MAX 720 // Clip upper "
#define WINK_L_PIN 0 // Pin for LEFT eye wink button
#define BLINK_PIN 1 // Pin for blink button (BOTH
eyes)
#define WINK_R_PIN 2 // Pin for RIGHT eye wink button
#define AUTOBLINK // If enabled, eyes blink
autonomously
// Probably don't need to edit any config below this line, -------
----------
// unless building a single-eye project (pendant, etc.), in which
case one
// of the two elements in the eye[] array further down can be
commented out.
// Eye blinks are a tiny 3-state machine. Per-eye allows winks
+ blinks.
#define NOBLINK 0 // Not currently engaged in a blink
#define ENBLINK 1 // Eyelid is currently closing
#define DEBLINK 2 // Eyelid is currently opening
typedef struct {
int8_t pin; // Optional button here for indiv. wink
uint8_t state; // NOBLINK/ENBLINK/DEBLINK
uint32_t duration; // Duration of blink state (micros)
uint32_t startTime; // Time (micros) of last state change
} eyeBlink;
struct {
displayType display; // OLED/TFT object
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
7
uint8_t cs; // Chip select pin
eyeBlink blink; // Current blink state
} eye[] = { // OK to comment out one of these for single-eye
display:
displayType(SELECT_L_PIN,DISPLAY_DC,0),SELECT_L_
PIN,{WINK_L_PIN,NOBLINK},
displayType(SELECT_R_PIN,DISPLAY_DC,0),SELECT_R
_PIN,{WINK_R_PIN,NOBLINK},
};
#define NUM_EYES (sizeof(eye) / sizeof(eye[0]))
// INITIALIZATION -- runs once at startup ----------------------
------------
void setup(void) {
uint8_t e;
Serial.begin(115200);
randomSeed(analogRead(A3)); // Seed random() from
floating analog input
// Both displays share a common reset line; 0 is passed to
display
// constructor (so no reset in begin()) -- must reset manually
here:
pinMode(DISPLAY_RESET, OUTPUT);
digitalWrite(DISPLAY_RESET, LOW); delay(1);
digitalWrite(DISPLAY_RESET, HIGH); delay(50);
for(e=0; e<NUM_EYES; e++) { // Deselect all
pinMode(eye[e].cs, OUTPUT);
digitalWrite(eye[e].cs, HIGH);
}
for(e=0; e<NUM_EYES; e++) {
digitalWrite(eye[e].cs, LOW); // Select one eye for init
#ifdef _ADAFRUIT_ST7735H_ // TFT
eye[e].display.initR(INITR_144GREENTAB);
#else // OLED
eye[e].display.begin();
#endif
if(eye[e].blink.pin >= 0) pinMode(eye[e].blink.pin,
INPUT_PULLUP);
#ifdef LOGO_TOP_WIDTH
// I noticed lots of folks getting right/left eyes flipped, or
// installing upside-down, etc. Logo split across screens
may help:
eye[e].display.fillScreen(0);
eye[e].display.drawBitmap(NUM_EYES*64 - e*128 - 20,
0, logo_top, LOGO_TOP_WIDTH,
LOGO_TOP_HEIGHT, 0xFFFF);
eye[e].display.drawBitmap(NUM_EYES*64 - e*128 -
LOGO_BOTTOM_WIDTH/2,
LOGO_TOP_HEIGHT, logo_bottom,
LOGO_BOTTOM_WIDTH, LOGO_BOTTOM_HEIGHT,
0xFFFF);
#endif
digitalWrite(eye[e].cs, HIGH); // Deselect
}
#ifdef BLINK_PIN
pinMode(BLINK_PIN, INPUT_PULLUP);
#endif
#ifdef LOGO_TOP_WIDTH
delay(3000); // Pause for screen layout/orientation
#endif
// One of the displays is configured to mirror on the X axis.
Simplifies
// eyelid handling in the drawEye() function -- no need for
distinct
// L-to-R or R-to-L inner loops. Just the X coordinate of the
iris is
// then reversed when drawing this eye, so they move the
same. Magic!
#ifdef _ADAFRUIT_ST7735H_ // TFT
digitalWrite(eye[0].cs , LOW);
digitalWrite(DISPLAY_DC, LOW);
SPI.transfer(ST7735_MADCTL);
digitalWrite(DISPLAY_DC, HIGH);
SPI.transfer(0x88); // MADCTL_MY | MADCTL_BGR
digitalWrite(eye[0].cs , HIGH);
#else // OLED
eye[0].display.writeCommand(SSD1351_CMD_SETREMAP)
;
eye[0].display.writeData(0x76);
#endif
}
// EYE-RENDERING FUNCTION --------------------------------
------------------
SPISettings settings(24000000, MSBFIRST, SPI_MODE3); //
Teensy 3.1 max SPI
void drawEye( // Renders one eye. Inputs must be pre-clipped
& valid.
uint8_t e, // Eye array index; 0 or 1 for left/right
uint32_t iScale, // Scale factor for iris
uint8_t scleraX, // First pixel X offset into sclera image
uint8_t scleraY, // First pixel Y offset into sclera image
uint8_t uT, // Upper eyelid threshold value
uint8_t lT) { // Lower eyelid threshold value
uint8_t screenX, screenY, scleraXsave;
int16_t irisX, irisY;
uint16_t p, a;
uint32_t d;
// Set up raw pixel dump to entire screen. Although such
writes can wrap
// around automatically from end of rect back to beginning,
the region is
// reset on each frame here in case of an SPI glitch.
SPI.beginTransaction(settings);
#ifdef _ADAFRUIT_ST7735H_ // TFT
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
8
eye[e].display.setAddrWindow(0, 0, 127, 127);
#else // OLED
eye[e].display.writeCommand(SSD1351_CMD_SETROW);
// Y range
eye[e].display.writeData(0);
eye[e].display.writeData(SCREEN_HEIGHT - 1);
eye[e].display.writeCommand(SSD1351_CMD_SETCOLUM
N); // X range
eye[e].display.writeData(0);
eye[e].display.writeData(SCREEN_WIDTH - 1);
eye[e].display.writeCommand(SSD1351_CMD_WRITERAM
); // Begin write
#endif
digitalWrite(eye[e].cs, LOW); // Chip select
digitalWrite(DISPLAY_DC, HIGH); // Data
mode
// Now just issue raw 16-bit values for every pixel...
scleraXsave = scleraX; // Save initial X value to reset on each
line
irisY = scleraY - (SCLERA_HEIGHT - IRIS_HEIGHT) /
2;
for(screenY=0; screenY<SCREEN_HEIGHT; screenY++,
scleraY++, irisY++) {
scleraX = scleraXsave;
irisX = scleraXsave - (SCLERA_WIDTH - IRIS_WIDTH)
/ 2;
for(screenX=0; screenX<SCREEN_WIDTH; screenX++,
scleraX++, irisX++) {
if((lower[screenY][screenX] <= lT) ||
(upper[screenY][screenX] <= uT)) { // Covered
by eyelid
p = 0;
} else if((irisY < 0) || (irisY >= IRIS_HEIGHT) ||
(irisX < 0) || (irisX >= IRIS_WIDTH)) { // In sclera
p = sclera[scleraY][scleraX];
} else { // Maybe iris...
p = polar[irisY][irisX]; // Polar angle/dist
d = (iScale * (p & 0x7F)) / 128; // Distance (Y)
if(d < IRIS_MAP_HEIGHT) { // Within
iris area
a = (IRIS_MAP_WIDTH * (p >> 7)) / 512; // Angle
(X)
p = iris[d][a]; // Pixel = iris
} else { // Not in iris
p = sclera[scleraY][scleraX]; // Pixel = sclera
}
}
// SPI FIFO technique from Paul Stoffregen's ILI9341_t3
library:
while(KINETISK_SPI0.SR & 0xC000); // Wait for space
in FIFO
KINETISK_SPI0.PUSHR = p | SPI_PUSHR_CTAS(1) |
SPI_PUSHR_CONT;
}
}
KINETISK_SPI0.SR |= SPI_SR_TCF; // Clear transfer
flag
while((KINETISK_SPI0.SR & 0xF000) || // Wait for SPI
FIFO to drain
!(KINETISK_SPI0.SR & SPI_SR_TCF)); // Wait for last
bit out
digitalWrite(eye[e].cs, HIGH); // Deselect
SPI.endTransaction();
}
// EYE ANIMATION ------------------------------------------------
-----------
const uint8_t ease[] = { // Ease in/out curve for eye
movements 3*t^2-2*t^3
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, // T
3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 10, // h
11, 12, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23,
// x
24, 25, 26, 27, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39,
// 2
40, 41, 42, 44, 45, 46, 47, 48, 50, 51, 52, 53, 54, 56, 57, 58,
// A
60, 61, 62, 63, 65, 66, 67, 69, 70, 72, 73, 74, 76, 77, 78, 80,
// l
81, 83, 84, 85, 87, 88, 90, 91, 93, 94, 96, 97,
98,100,101,103, // e
104,106,107,109,110,112,113,115,116,118,119,121,122,124,1
25,127, // c
128,130,131,133,134,136,137,139,140,142,143,145,146,148,1
49,151, // J
152,154,155,157,158,159,161,162,164,165,167,168,170,171,1
72,174, // a
175,177,178,179,181,182,183,185,186,188,189,190,192,193,1
94,195, // c
197,198,199,201,202,203,204,205,207,208,209,210,211,213,2
14,215, // o
216,217,218,219,220,221,222,224,225,226,227,228,228,229,2
30,231, // b
232,233,234,235,236,237,237,238,239,240,240,241,242,243,2
43,244, // s
245,245,246,246,247,248,248,249,249,250,250,251,251,251,2
52,252, // o
252,253,253,253,254,254,254,254,254,255,255,255,255,255,2
55,255 }; // n
#ifdef AUTOBLINK
uint32_t timeOfLastBlink = 0L, timeToNextBlink = 0L;
#endif
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
9
void frame( // Process motion for a single frame of left or right
eye
uint16_t iScale) { // Iris scale (0-1023) passed in
static uint32_t frames = 0; // Used in frame rate calculation
static uint8_t eyeIndex = 0; // eye[] array counter
int16_t eyeX, eyeY;
uint32_t t = micros(); // Time at start of function
Serial.println((++frames * 1000) / millis()); // Show frame
rate
if(++eyeIndex >= NUM_EYES) eyeIndex = 0; // Cycle
through eyes, 1 per call
// X/Y movement
#if defined(JOYSTICK_X_PIN) && (JOYSTICK_X_PIN >=
0) && \
defined(JOYSTICK_Y_PIN) && (JOYSTICK_Y_PIN >=
0)
// Read X/Y from joystick, constrain to circle
int16_t dx, dy;
int32_t d;
eyeX = analogRead(JOYSTICK_X_PIN); // Raw (unclipped)
X/Y reading
eyeY = analogRead(JOYSTICK_Y_PIN);
#ifdef JOYSTICK_X_FLIP
eyeX = 1023 - eyeX;
#endif
#ifdef JOYSTICK_Y_FLIP
eyeY = 1023 - eyeY;
#endif
dx = (eyeX * 2) - 1023; // A/D exact center is at 511.5. Scale
coords
dy = (eyeY * 2) - 1023; // X2 so range is -1023 to +1023
w/center at 0.
if((d = (dx * dx + dy * dy)) > (1023 * 1023)) { // Outside
circle
d = (int32_t)sqrt((float)d); // Distance from center
eyeX = ((dx * 1023 / d) + 1023) / 2; // Clip to circle
edge,
eyeY = ((dy * 1023 / d) + 1023) / 2; // scale back to 0-
1023
}
#else // Autonomous X/Y eye motion
// Periodically initiates motion to a new random point,
random speed,
// holds there for random period until next motion.
static boolean eyeInMotion = false;
static int16_t eyeOldX=512, eyeOldY=512, eyeNewX=512,
eyeNewY=512;
static uint32_t eyeMoveStartTime = 0L;
static int32_t eyeMoveDuration = 0L;
int32_t dt = t - eyeMoveStartTime; // uS elapsed since last
eye event
if(eyeInMotion) { // Currently moving?
if(dt >= eyeMoveDuration) { // Time up? Destination
reached.
eyeInMotion = false; // Stop moving
eyeMoveDuration = random(3000000); // 0-3 sec stop
eyeMoveStartTime = t; // Save initial time of stop
eyeX = eyeOldX = eyeNewX; // Save position
eyeY = eyeOldY = eyeNewY;
} else { // Move time's not yet fully elapsed -- interpolate
position
int16_t e = ease[255 * dt / eyeMoveDuration] + 1; // Ease
curve
eyeX = eyeOldX + (((eyeNewX - eyeOldX) * e) / 256); //
Interp X
eyeY = eyeOldY + (((eyeNewY - eyeOldY) * e) / 256); //
and Y
}
} else { // Eye stopped
eyeX = eyeOldX;
eyeY = eyeOldY;
if(dt > eyeMoveDuration) { // Time up? Begin new
move.
int16_t dx, dy;
uint32_t d;
do { // Pick new dest in circle
eyeNewX = random(1024);
eyeNewY = random(1024);
dx = (eyeNewX * 2) - 1023;
dy = (eyeNewY * 2) - 1023;
} while((d = (dx * dx + dy * dy)) > (1023 * 1023)); //
Keep trying
eyeMoveDuration = random(72000, 144000); // ~1/14 -
~1/7 sec
eyeMoveStartTime = t; // Save initial time of
move
eyeInMotion = true; // Start move on next frame
}
}
#endif // JOYSTICK_X_PIN etc.
// Blinking
#ifdef AUTOBLINK
// Similar to the autonomous eye movement above -- blink
start times
// and durations are random (within ranges).
if((t - timeOfLastBlink) >= timeToNextBlink) { // Start new
blink?
timeOfLastBlink = t;
uint32_t blinkDuration = random(36000, 72000); // ~1/28 -
~1/14 sec
// Set up durations for both eyes (if not already winking)
for(uint8_t e=0; e<NUM_EYES; e++) {
if(eye[e].blink.state == NOBLINK) {
eye[e].blink.state = ENBLINK;
eye[e].blink.startTime = t;
eye[e].blink.duration = blinkDuration;
}
}
timeToNextBlink = blinkDuration * 3 + random(4000000);
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
10
}
#endif
if(eye[eyeIndex].blink.state) { // Eye currently blinking?
// Check if current blink state time has elapsed
if((t - eye[eyeIndex].blink.startTime) >=
eye[eyeIndex].blink.duration) {
// Yes -- increment blink state, unless...
if((eye[eyeIndex].blink.state == ENBLINK) && //
Enblinking and...
((digitalRead(BLINK_PIN) == LOW) || // blink or
wink held...
digitalRead(eye[eyeIndex].blink.pin) == LOW)) {
// Don't advance state yet -- eye is held closed instead
} else { // No buttons, or other state...
if(++eye[eyeIndex].blink.state > DEBLINK) { //
Deblinking finished?
eye[eyeIndex].blink.state = NOBLINK; // No longer
blinking
} else { // Advancing from ENBLINK to DEBLINK
mode
eye[eyeIndex].blink.duration *= 2; // DEBLINK is 1/2
ENBLINK speed
eye[eyeIndex].blink.startTime = t;
}
}
}
} else { // Not currently blinking...check buttons!
if(digitalRead(BLINK_PIN) == LOW) {
// Manually-initiated blinks have random durations like
auto-blink
uint32_t blinkDuration = random(36000, 72000);
for(uint8_t e=0; e<NUM_EYES; e++) {
if(eye[e].blink.state == NOBLINK) {
eye[e].blink.state = ENBLINK;
eye[e].blink.startTime = t;
eye[e].blink.duration = blinkDuration;
}
}
} else if(digitalRead(eye[eyeIndex].blink.pin) == LOW) { //
Wink!
eye[eyeIndex].blink.state = ENBLINK;
eye[eyeIndex].blink.startTime = t;
eye[eyeIndex].blink.duration = random(45000, 90000);
}
}
// Process motion, blinking and iris scale into renderable
values
// Iris scaling: remap from 0-1023 input to iris map height
pixel units
iScale = ((IRIS_MAP_HEIGHT + 1) * 1024) /
(1024 - (iScale * (IRIS_MAP_HEIGHT - 1) /
IRIS_MAP_HEIGHT));
// Scale eye X/Y positions (0-1023) to pixel units used by
drawEye()
eyeX = map(eyeX, 0, 1023, 0, SCLERA_WIDTH - 128);
eyeY = map(eyeY, 0, 1023, 0, SCLERA_HEIGHT - 128);
if(eyeIndex == 1) eyeX = (SCLERA_WIDTH - 128) - eyeX;
// Mirrored display
// Horizontal position is offset so that eyes are very slightly
crossed
// to appear fixated (converged) at a conversational distance.
Number
// here was extracted from my posterior and not
mathematically based.
// I suppose one could get all clever with a range sensor, but
for now...
eyeX += 4;
if(eyeX > (SCLERA_WIDTH - 128)) eyeX =
(SCLERA_WIDTH - 128);
// Eyelids are rendered using a brightness threshold image.
This same
// map can be used to simplify another problem: making the
upper eyelid
// track the pupil (eyes tend to open only as much as needed -
- e.g. look
// down and the upper eyelid drops). Just sample a point in
the upper
// lid map slightly above the pupil to determine the rendering
threshold.
static uint8_t uThreshold = 128;
uint8_t lThreshold, n;
#ifdef TRACKING
int16_t sampleX = SCLERA_WIDTH / 2 - (eyeX / 2), //
Reduce X influence
sampleY = SCLERA_HEIGHT / 2 - (eyeY +
IRIS_HEIGHT / 4);
// Eyelid is slightly asymmetrical, so two readings are taken,
averaged
if(sampleY < 0) n = 0;
else n = (upper[sampleY][sampleX] +
upper[sampleY][SCREEN_WIDTH - 1 -
sampleX]) / 2;
uThreshold = (uThreshold * 3 + n) / 4; // Filter/soften motion
// Lower eyelid doesn't track the same way, but seems to be
pulled upward
// by tension from the upper lid.
lThreshold = 254 - uThreshold;
#else // No tracking -- eyelids full open unless blink modifies
them
uThreshold = lThreshold = 0;
#endif
// The upper/lower thresholds are then scaled relative to the
current
// blink position so that blinks work together with pupil
tracking.
if(eye[eyeIndex].blink.state) { // Eye currently blinking?
uint32_t s = (t - eye[eyeIndex].blink.startTime);
if(s >= eye[eyeIndex].blink.duration) s = 255; // At or past
blink end
else s = 255 * s / eye[eyeIndex].blink.duration; // Mid-blink
s = (eye[eyeIndex].blink.state == DEBLINK) ? 1 + s :
256 - s;
n = (uThreshold * s + 254 * (257 - s)) / 256;
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
11
lThreshold = (lThreshold * s + 254 * (257 - s)) / 256;
} else {
n = uThreshold;
}
// Pass all the derived values to the eye-rendering function:
drawEye(eyeIndex, iScale, eyeX, eyeY, n, lThreshold);
}
// AUTONOMOUS IRIS SCALING (if no photocell or dial) --
---------------------
#if !defined(IRIS_PIN) || (IRIS_PIN < 0)
// Autonomous iris motion uses a fractal behavior to similate
both the major
// reaction of the eye plus the continuous smaller adjustments
that occur.
uint16_t oldIris = (IRIS_MIN + IRIS_MAX) / 2, newIris;
void split( // Subdivides motion path into two sub-paths
w/randimization
int16_t startValue, // Iris scale value (IRIS_MIN to
IRIS_MAX) at start
int16_t endValue, // Iris scale value at end
uint32_t startTime, // micros() at start
int32_t duration, // Start-to-end time, in microseconds
int16_t range) { // Allowable scale value variance when
subdividing
if(range >= 8) { // Limit subdvision count, because
recursion
range /= 2; // Split range & time in half for subdivision,
duration /= 2; // then pick random center point within
range:
int16_t midValue = (startValue + endValue - range) / 2 +
random(range);
uint32_t midTime = startTime + duration;
split(startValue, midValue, startTime, duration, range); //
First half
split(midValue , endValue, midTime , duration, range); //
Second half
} else { // No more subdivisons, do iris motion...
int32_t dt; // Time (micros) since start of motion
int16_t v; // Interim value
while((dt = (micros() - startTime)) < duration) {
v = startValue + (((endValue - startValue) * dt) / duration);
if(v < IRIS_MIN) v = IRIS_MIN; // Clip just in case
else if(v > IRIS_MAX) v = IRIS_MAX;
frame(v); // Draw frame w/interim iris scale value
}
}
}
#endif // !IRIS_PIN
// MAIN LOOP -- runs continuously after setup() ---------------
-------------
void loop() {
#if defined(IRIS_PIN) && (IRIS_PIN >= 0) // Interactive iris
uint16_t v = analogRead(IRIS_PIN); // Raw
dial/photocell reading
#ifdef IRIS_PIN_FLIP
v = 1023 - v;
#endif
v = map(v, 0, 1023, IRIS_MIN, IRIS_MAX); // Scale to iris
range
#ifdef IRIS_SMOOTH // Filter input (gradual motion)
static uint16_t irisValue = (IRIS_MIN + IRIS_MAX) / 2;
irisValue = ((irisValue * 15) + v) / 16;
frame(irisValue);
#else // Unfiltered (immediate motion)
frame(v);
#endif // IRIS_SMOOTH
#else // Autonomous iris scaling -- invoke recursive function
newIris = random(IRIS_MIN, IRIS_MAX);
split(oldIris, newIris, micros(), 10000000L, IRIS_MAX -
IRIS_MIN);
oldIris = newIris;
#endif // IRIS_PIN
}
IMPLEMENTACION SISTEMA DE VOZ
Para nuestro robot LOVE usaremos un segundo
microprocesador para crear una Red Neuronal independiente
para el procesamiento de palabras, mediante programación en
lenguaje C inicialmente.
Se programara con 250 comandos iniciales con una duración
entre 6 a 7nsegundos para configurar dicha Red Neuronal,
como el primer enlace que tiene un bebe cuando empieza a
interconectar su red neuronal a través de las dendritas.
Para nuestro microprocesador se conecta a través de 2 pines
para la alimentación y 2, TX y Rx, para comunicarse con
nuestro Arduino. Se utiliza la librería Software Serial.
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
12
GRABACION DE COMANDOS Y CONFIGURACION.
Cada vez que queremos grabar o borrar comandos antes de
liberar la red neuronal en el microprocesador tenemos que
visualizar la programación que nos da la librería vr
simple_train, después de cargar el programa, abrimos el
monitor serie y lo configuramos para trabajar a 115.500
baudios. Y nos muestra lo siguiente.
PROGRAMACION FINAL PARA EL
MICROPROCESADOR
int ledDialogo0 = 10;
int ledBodega = 11;
int ledDialogo1 = 12;
int ledDialogo2 = 13;
#define Dialogo0 (0)
#define Bodega (1)
#define Dialogo1 (2)
#define Dialogo2 (3)
#define Encender (4)
#define Apagar (5)
void setup() {
Serial.println("Elechouse Voice Recognition V3 Prueba
Prometec");
pinMode(ledDialogo0, OUTPUT);
pinMode(ledBodega, OUTPUT);
pinMode(ledDialogo1, OUTPUT);
pinMode(ledDialogo2, OUTPUT);
digitalWrite(ledDialogo0, LOW);
digitalWrite(ledBodega, LOW);
digitalWrite(ledDialogo1, LOW);
digitalWrite(ledDialogo2, LOW);
if (myVR.load((uint8_t)Dialogo0) >= 0) {
Serial.println("Dialogo0 loaded");
}
if (myVR.load((uint8_t)Bodega) >= 0) {
Serial.println("Bodega loaded");
}
if (myVR.load((uint8_t)Dialogo1) >= 0) {
Serial.println("Dialogo 1oaded");
}
if (myVR.load((uint8_t)Dialogo2) >= 0) {
Serial.println("Dialogo2 loaded");
}
if (myVR.load((uint8_t)Encender) >= 0) {
Serial.println("Encender loaded");
}
if (myVR.load((uint8_t)Apagar) >= 0) {
Serial.println("Apagar loaded");
}
}
void loop() {
int ret;
ret = myVR.recognize(buf, 50);
if (ret > 0) {
switch (buf[1]) {
case Dialogo0:
digitalWrite(ledDialogo0, !digitalRead(ledDialogo0));
break;
case Bodega:
digitalWrite(ledBodega, !digitalRead(ledBodega));
break;
case Dialogo1:
digitalWrite(ledDialogo1, !digitalRead(ledDialogo1));
break;
case Dialogo2:
digitalWrite(ledDialogo2, !digitalRead(ledDialogo2));
break;
case Encender:
digitalWrite(ledDialogo0, HIGH);
digitalWrite(ledBodega, HIGH);
digitalWrite(ledDialogo1, HIGH);
digitalWrite(ledDialogo2, HIGH);
break;
case Apagar:
digitalWrite(ledDialogo0, LOW);
digitalWrite(ledBodega, LOW);
digitalWrite(ledDialogo1, LOW);
digitalWrite(ledDialogo2, LOW);
break;
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
13
default:
Serial.println("Record function undefined");
break;
}
/** voice recognized */
printVR(buf);
}
}
Microprocesador SOMO14D
Usamos este microviii para nuestro robot, para ampliar su red
neuronal, a medida que el sistema interactúe con su entorno
este se complementara en nuevas redes neuronales.
Nuestro Robot OHMBOT, no solo tendrá que formar nuevas
Redes neuronales si no que deberá de tener la capacidad de
entender su entorno y relacionarlo al cuidado de un elemento
vivo en este caso el cuidado de una planta, tomando y
evaluando condiciones ambientales necesarias para evitar el
daño de nuestra planta a través de sensores acondicionados
para toma de muestras de parámetros ambientales.
Esquema de conexión interna para nuestro Robot
SOFTWARE, PROGRAMACION EN LENGUAJE C
/* SISTEMA DE RIEGO AUTOMÁTICO CON SENSOR DE
HUMEDAD DE SUELO, SENSOR
DE HUMEDAD DE AIRE Y SENSOR DE LUZ */
#include <SimpleDHT.h>
// Librería <SimpleDHT.h> del sensor de temperatura y
humedad relativa
#include <SPI.h>
//Librería <SPI.h> del motor DC compatible con la
minibomba de agua DC
#define humidity_sensor_pin A0
//Se define variable del sensor de humedad en el suelo en el
pin A0
#define ldr_pin A5
//Defino variable del sensor de fotoresistencia LDR en el pin
A5
// for DHT11,
// VCC: 5V or 3V
// GND: GND
// DATA: 2
int pinDHT11 = 2;
// Se declara la variable pinDHT11 y lo asocio al pin 2
SimpleDHT11 dht11;
int ldr_value = 0;
//Se declara la variable ldr_value (fotoresistencia) y
int water_pump_pin = 3;
//Se declara la variable mini bomba de agua y lo asocio al pin
3
int water_pump_speed = 255;
//Velocidad de la minibomba de agua oscila entre 100 como
mínimo y 255 como máximo. Yo he //elegido 255 pero
ustedes pueden elegir la que estimen conveniente. A más
velocidad, mayor //bombeo de agua
void setup() {
Serial.begin(9600);
}
void loop() {
// start working...
// Mide la temperatura y humedad relativa y muestra resultado
Serial.println("*******************************");
Serial.println("Sample DHT11...");
// read with raw sample data.
byte temperature = 0;
byte humidity_in_air = 0;
byte data[40] = {0};
if (dht11.read(pinDHT11, &temperature, &humidity_in_air,
data)) {
Serial.print("Read DHT11 failed");
return;
}
Serial.print("Sample RAW Bits: ");
for (int i = 0; i < 40; i++) {
Serial.print((int)data[i]);
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
14
if (i > 0 && ((i + 1) % 4) == 0) {
Serial.print(' ');
}
}
Serial.println("");
Serial.print("Sample OK: ");
Serial.print("Temperature: ");Serial.print((int)temperature);
Serial.print(" *C, ");
Serial.print("Relative humidity in air:
");Serial.print((int)humidity_in_air); Serial.println(" %");
// DHT11 sampling rate is 1HZ.
// Ground humidity value in %
// Mide la humedad en el suelo en % y muestra el resultado
int ground_humidity_value =
map(analogRead(humidity_sensor_pin), 0, 1023, 100, 0);
Serial.print("Ground humidity: ");
Serial.print(ground_humidity_value);
Serial.println("%");
// Light value in %
// Mide la luminosidad en % y muestra el resultado
int ldr_value = map(analogRead(ldr_pin), 1023, 0, 100, 0);
Serial.print("Light: ");
Serial.print(ldr_value);
Serial.println("%");
Serial.println("*******************************");
//*************************************************
*************
// Condiciones de riego
// Si la humedad en el suelo es igual o inferior al 50%, si la
luminosidad es inferior al 30%,
// Si la temperatura es inferior al 30%, entonces el sistema de
riego riega.
// En caso de que no se cumpla alguno o ninguno de los 3
requisitos anteriores,
// el sistema de riego no riega
//*************************************************
*************
if( ground_humidity_value <= 50 && ldr_value < 30 &&
temperature < 30) {
digitalWrite(water_pump_pin, HIGH);
Serial.println("Irrigate");
analogWrite(water_pump_pin, water_pump_speed);
//El motor de la bomba de agua arranca con la velocidad
elegida anteriormente en el código
}
else{
digitalWrite(water_pump_pin, LOW);
Serial.println("Do not irrigate");
//El motor de la bomba de agua se para y no riega
}
delay (100);
// Ejecuta el código cada 100 milisegundos
ELEMENTOS USADOS EN NUESTRO SISTEMA DE
SOPORTE DE VIDA
Tarjeta microprocesador Arduino
Micro bomba sumergible DC 3V 120L/H Arduino 2,5-6V
Sensores de humedad y luminosidad.
SISTEMA DE LEVITACION DEL ROBOT OHMBOT
Una levitación magnética consta de dos partes, la pieza base y
la pieza flotante.
1.
2. Pieza base
Esta parte está en la parte inferior, que consiste en un imán para
crear un campo magnético redondo y electroimanes para
controlar ese campo magnético.
Cada imán tiene dos polos: el norte y el sur. Los experimentos
muestran que los opuestos se atraen y los mismos polos se
repelen. Cuatro imanes cilíndricos se colocan en un cuadrado y
tienen la misma polaridad, formando un campo magnético
redondo hacia arriba para empujar cualquier imán, que tiene un
mismo polo y entre ellos.
Hay cuatro electroimanes en absoluto, se colocan en un
cuadrado, dos imanes simétricos son un par y su campo
magnético es siempre opuesto.
Controlar un campo magnético entre dos imanes no es sencillo,
es fácil poner dos imanes con polaridad opuesta donde
observamos que se repelen, principio de la levitación, pero solo
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
15
lo podemos hacer sosteniéndolo con las manos pues el propio
imán tratara de invertirse para unirse con su otro polo. Según
cálculos y ensayos podemos manipular dicho campo utilizando
un circuito análogo y sistema digital a través de un
microprocesador
Los sensores de Hall y los circuitos de control controlan los
electroimanes. Crea polos opuestos en los electroimanes al
desviar la corriente a través de ellos.
2. F pieza flotante
Incluye un imán flotando sobre la pieza base
¿Cómo funciona? El imán en la parte superior es elevado por el campo magnético
de los imanes inferiores porque son los mismos polos. Sin
embargo, tiende a voltearse para caer y atraerse el uno al otro.
Para evitar que la parte superior del imán se voltee boca abajo
y caiga, los electroimanes crearán campos magnéticos para
empujar o tirar para equilibrarlo, gracias a los sensores Hall.
Los electroimanes se controlan en dos ejes X e Y, lo que hace
que el imán superior se mantenga equilibrado y flotante.
Controlar los electroimanes no es fácil, esto requiere incluir un
controlador PID.
A QUE LLAMAMOS PID
"Un controlador derivativo proporcional integral (controlador
PID o controlador de tres términos) es un mecanismo de
retroalimentación de bucle de control ampliamente utilizado en
sistemas de control industrial y una variedad de otras
aplicaciones que requieren un control continuamente
modulado. Un controlador PID calcula continuamente un valor
de error {\ displaystyle e (t)} como la diferencia entre un punto
de consigna deseado (SP) y una variable de proceso medida
(PV) y aplica una corrección basada en términos
proporcionales, integrales y derivados (denotados P, I y D,
respectivamente) que da al controlador su nombre ".
De una manera simple de entender: "Un controlador PID
calcula un valor de 'error' como la diferencia entre una [Entrada]
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
16
medida y un punto de ajuste deseado. El controlador intenta
minimizar el error ajustando [una Salida]".
Por lo tanto, le dice al PID qué medir (la "Entrada"), dónde
quiere que sea esa medición (el "Punto de ajuste") y la variable
que ajustar para que eso suceda (el "Resultado").
1. La entrada es el valor actual en tiempo real del sensor Hall,
que se actualiza continuamente porque la posición del imán
flotante cambiará en tiempo real.
2. El punto de ajuste es el valor del sensor Hall, que se mide
cuando el imán flotante está en la posición de equilibrio, en el
centro de la base de los imanes. Este índice es fijo y no cambia
con el tiempo.
3. La salida sería la velocidad para controlar los electroimanes.
Necesitamos agregar una librería en Arduino sobre PID,
investigando en varios foros encontramos una que nos ha
servido, la idea es tener un par de controladores PID en Arduino
para el eje X y otro para el eje Yix.
Componentes que necesitamos para la etapa de levitación
para nuestro Robot “ OHMBOT”.
PUENTE H
Los PUENTE H L298N dobles se usan generalmente
para controlar la velocidad y la dirección de los
motores de dos motores de CC, o controlar un motor
paso a paso bipolar con facilidad. El módulo de puente
en H L298N se puede usar con motores que tienen un
voltaje de entre 5 y 35V DC.
Sensor Hall SS495a
SS495a es un sensor Hall lineal con salida analógica.
Observe la diferencia entre salida analógica y salida
digital, no puede usar un sensor con salida digital en
este proyecto, solo tiene dos estados de 1 o 0, por lo
que no puede medir la salida de los campos
magnéticos.
Un sensor analógico dará como resultado un rango de
voltaje de 250mV a Vcc, que puede leer con la entrada
analógica de Arduino.
Se requieren dos sensores Hall para medir el campo
magnético en los ejes X e Y. Imanes de Neodino
"El neodimio es un metal que es ferromagnético (más
específicamente muestra propiedades anti
ferromagnéticas), lo que significa que, como el hierro,
puede magnetizarse para convertirse en un imán, pero
su temperatura de Curie es de 19 K (-254 ° C), por lo
que en forma pura su magnetismo solo aparece a
temperaturas extremadamente bajas. Sin embargo, los
compuestos de neodimio con metales de transición
como el hierro pueden tener temperaturas de Curie
muy por encima de la temperatura ambiente, y estos se
utilizan para hacer imanes de neodimio ".
FUERTE, esa es la palabra que uso para describir el
imán de Neodimio. No puede usar imanes de ferrita
porque su magnetismo es demasiado débil. Los
imanes de neodimio son mucho más caros que los
imanes de ferrita.
Pequeños imanes se usan para hacer la pieza base,
imanes grandes para hacer la pieza flotante.
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
17
Figura del circuito de los transistores para efecto
HALL.
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
18
PROGRAMACION PARA CONTROL DE CAMPOS
ELECTROMAGNETICOS (LEVITACION ROBOT
OHMBOT.
#include <PID_v1.h>
#define IN1 4
#define IN2 3
#define IN3 7
#define IN4 8
#define ENA 6
#define ENB 5
#define BL 2
double Setpoint_X, Input_X, Output_X,X_plus;
double p_X = 1,i_X = 0,d_X = 0.01;
double Setpoint_Y, Input_Y, Output_Y,Y_plus;
double p_Y = 1,i_Y = 0,d_Y = 0.01;
int i,on_put=1;
unsigned long time;
PID PID_X(&Input_X, &Output_X,
&Setpoint_X,p_X,i_X,d_X, DIRECT);
PID PID_Y(&Input_Y, &Output_Y,
&Setpoint_Y,p_Y,i_Y,d_Y, DIRECT);
char inByte='9',nullByte,run_flag,run_dirict;
float go_step;
void turn_X(int a)
{
if(a>=0)
{
digitalWrite(IN1,1);
digitalWrite(IN2,0);
analogWrite(ENA,a);
}
else
{
a=-a;
digitalWrite(IN1,0);
digitalWrite(IN2,1);
analogWrite(ENA,a);
}
}
void turn_Y(int a)
{
if(a>=0)
{
digitalWrite(IN3,0);
digitalWrite(IN4,1);
analogWrite(ENB,a);
}
else
{
a=-a;
digitalWrite(IN3,1);
digitalWrite(IN4,0);
analogWrite(ENB,a);
}
}
void setup()
{
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
pinMode(IN3,OUTPUT);
pinMode(IN4,OUTPUT);
pinMode(ENA,OUTPUT);
pinMode(ENB,OUTPUT);
pinMode(BL,OUTPUT);
digitalWrite(IN1,0);
digitalWrite(IN2,0);
digitalWrite(IN3,0);
digitalWrite(IN4,0);
analogWrite(ENA,0);
analogWrite(ENB,0);
Setpoint_X = 560;//560;
Setpoint_Y = 560;//560;
PID_X.SetTunings(p_X,i_X,d_X);
PID_Y.SetTunings(p_Y,i_Y,d_Y);
PID_X.SetOutputLimits(-255,255);
PID_Y.SetOutputLimits(-255,255);
PID_X.SetSampleTime(5);
PID_Y.SetSampleTime(5);
PID_X.SetMode(AUTOMATIC);
PID_Y.SetMode(AUTOMATIC);
}
void loop()
{
Input_X = analogRead(A1);
Input_Y = analogRead(A0);
PID_X.Compute();
PID_Y.Compute();
turn_X(Output_X);
turn_Y(Output_Y);
}
> ROBOT OHMBOT-INTELIGENCIA ARTIFICIAL <
19
Myers E. George , Actualmente me
desempeño como docente investigador del
programa de Instrumentación Electrónica
dela Fundación Tecnológica Autónoma
del Pacifico, Miembro del Grupo de
Investigación de informática y electrónica
de la misma institución. Nació en Sevilla –
Colombia , nacionalidad Colom-
Americana, en 1975, graduado en la
Escuela Militar Annapolis –Maryland USA, como Oficial
Naval, Piloto Naval F/A 18 Hornet , Ingeniero Electrónico, de
la Politécnica de España en Barcelona España, Especialidad en
Hidroneumática y Termodinámica – UPC, MBA en ciencias de
Ingeniería mecánica en Kingston University London,
acreditado por la Royal Aeronáutica para Ingeniería
Aeroespacial, Especialidad en Ingeniería Aeroespacial, Centro
de Estudios espaciales – Toulouse –Francia, Aerodinámica y
Estructuras – Centro de Estudios Espaciales- Toulouse-Francia,
Pedagogía Universitaria UNAR-Colombia, Diseño y
mantenimiento protección Catódica-PEMEX, ISO9000,ISO
9001, ISO 14000 – INCONTEC, MBA en Administración y
manejo de recursos marítimos- Instituto de estudios
Internacionales Marítimos, Especialidad En Ingeniería
Biomédica – AUNAR UDENAR , Diplomado Docencia
Universitario-UTAP Miembro de AOPA-Eu..
.
i https://www.researchgate.net/profile/David_Red/publication/228648535_Simulacion_de_Redes_Neuronales_Artificiales_Una_Herramienta_para_la_Docencia_en_Castellano/links/00b49534379983b5a8000000/Simulacion-de-Redes-Neuronales-Artificiales-Una-Herramienta-para-la-Docencia-en-Castellano.pdf?origin=publication_detail ii https://cdn-shop.adafruit.com/datasheets/BL-M07C881.PDF iii https://cdn-shop.adafruit.com/datasheets/ht16K33v110.pdf
iv https://www.adafruit.com/product/1625 v https://www.adafruit.com/product/2088 vi https://www.tapplastics.com/product/plastics/plastic_rods_tubes_shapes/acrylic_cabochons/139 vii https://www.adafruit.com/product/1092 viii https://www.4dsystems.com.au/product/SOMO_14D/ ix