Finalmente, en lo que se refiere a las pruebas experimentales, se anulo el sistema de control y se hicieron más pruebas para definir cuál debería ser el ciclo de trabajo
dependiendo de la velocidad recibida al inicio. En el eje ‘Y’ aparecen valores
entre 0 y 255, los cuales determinan el ciclo de trabajo que irá a los drivers
para que la velocidad corresponda con las pruebas realizadas a través de la
ecuación que proporciona Excel con la línea de tendencia (esta ecuación se
incluyó en la programación).
lunes, 18 de mayo de 2015
Esquemático
Para la conexión física,
además del Teensy++, se utilizaron algunos módulos adicionales que ayudan al
control de los motores del robot. En el esquemático que se presenta a
continuación se pueden apreciar todas las conexiones del microcontrolador y en
la tabla se
describe cada entrada o salida utilizada del Teensy.
|
PIN
|
Tipo de Señal
|
Descripción
|
|
PB7
PD0
|
Salida
|
Este pin manda una
señal al Driver que controla el motor izquierdo/derecho la señal de PWM que
determina la velocidad del motor correspondiente.
|
|
PC3
PD6
|
Entrada
|
Este pin recibe
una señal cuadrada proveniente del Encoder indicado a través de su
frecuencia, la velocidad de giro del motor izquierdo/derecho. Para controlar
los picos de voltaje positivos y negativos se agregó una configuración de
seguridad con un transistor que funciona como switch en serie con un buffer
que conecta al Teensy.
|
|
PD2
|
Entrada
|
Es el pin de
recepción (RX) del Teensy, que se conecta al pin de TX de la RaspBerry a través
de un convertidor de voltaje (5v a 3.3v) para hacer una interfaz confiable
entre ambos dispositivos.
|
|
PD3
|
Salida
|
Es el pin de
transmisión (TX) del Teensy, que se conecta al pin de RX de la RaspBerry a
través de un convertidor de voltaje (3.3v a 5v) para hacer una interfaz confiable
entre ambos dispositivos.
|
|
PF0
|
Salida
|
Este pin se
conecta al pin A del driver del motor izquierdo para controlar su dirección
de giro.
|
|
PF1
|
Salida
|
Este pin se
conecta al pin B del driver del motor izquierdo para controlar su dirección
de giro.
|
|
PF2
|
Salida
|
Este pin se
conecta al pin B del driver del motor derecho para controlar su dirección de
giro.
|
|
PF3
|
Salida
|
Este pin se
conecta al pin A del driver del motor derecho para controlar su dirección de
giro.
|
|
PF4
|
Salida
|
Se conecta al pin
de Trigger del sensor ultrasónico para comenzar la medición.
|
|
PF5
|
Entrada
|
Se conecta al
pin de Echo del sensor ultrasónico para recibir la señal y hacer las mediciones.
|
Diseño de la página web y comunicación serial.
Para crear el archivo
.html se utilizó el editor de texto Brackets (http://brackets.io/)
y el framework Bootstrap (http://getbootstrap.com/),
el archivo .zip con todo el proyecto se encuentra en el blog con el nombre de Página web. A continuación se presenta el diara de flujo y se explica el
código más importante (Javascript) que permite la comunicación serial.
Encabezado
Declaración del formato
de codificación de caracteres, librerías de Bootstrap, íconos, estilos y
scripts en Javascript.
<head>
<!-- Basic Page Needs
================================================== -->
<meta charset="utf-8">
<!--[if IE]><meta http-equiv="x-ua-compatible"
content="IE=9" /><![endif]-->
<meta name="viewport" content="width=device-width,
initial-scale=1">
<title>Destructinador</title>
<!-- Favicons
================================================== -->
<link rel="shortcut icon" href="img/favicon.ico"
type="image/x-icon">
<link rel="apple-touch-icon"
href="img/apple-touch-icon.png">
<link rel="apple-touch-icon" sizes="72x72"
href="img/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="114x114"
href="img/apple-touch-icon-114x114.png">
<!-- Bootstrap -->
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<link rel="stylesheet" type="text/css"
href="fonts/font-awesome/css/font-awesome.css">
<!-- Slider
================================================== -->
<link href="css/owl.carousel.css" rel="stylesheet"
media="screen">
<link href="css/owl.theme.css" rel="stylesheet"
media="screen">
<!-- Stylesheet
================================================== -->
<link rel="stylesheet" type="text/css" href="css/style.css">
<link rel="stylesheet" type="text/css" href="css/styles.css">
<link rel="stylesheet" type="text/css"
href="css/responsive.css">
<link href='http://fonts.googleapis.com/css?family=Lato:100,300,400,700,900,100italic,300italic,400italic,700italic,900italic'
rel='stylesheet' type='text/css'>
<link
href='http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,700,300,600,800,400'
rel='stylesheet' type='text/css'>
<link
href="https://gitcdn.github.io/bootstrap-toggle/2.2.0/css/bootstrap-toggle.min.css"
rel="stylesheet">
<script
src="https://gitcdn.github.io/bootstrap-toggle/2.2.0/js/bootstrap-toggle.min.js"></script>
<script type="text/javascript" src="js/modernizr.custom.js"></script>
<script type="text/javascript"
src="/webiopi.js"></script>
<script
type="text/javascript">
Declaración del script en
javascript principal que será usado para la validación de datos y el envío
de datos de forma serial en la Raspberry.
La variable modo indicará si se encuentra en modo Manual o en
Coordenadas.
var
modo = 0; // 0 = Modo manual-normal.
La función checkManual() revisa si actualmente se encuentra en modo
Manual, regresa un tipo de dato bool.
function checkManual(){
var manual =
document.getElementById('manual').checked;
return manual;
}
La función checkModo() revisa si actualmente el manejo se encuentra en Manual
o Demon del modo Manual.
function
checkModo(){
if
(modo == 0) {
return
true; // Modo normal
}
else {
return
false; // Modo Demon
}
}
La función changeToNormal() cambia el tipo manejo en modo Manual a
Normal.
function
changeToNormal(){
if
(checkManual()) {
modo
= 0;
}
}
La función changeToNormal() cambia el tipo manejo en modo Manual a Demon.
function
changeToDemon(){
if
(checkManual()) {
modo
= 1;
}
}
La función verify() revisa si los valores introducidos en modo de
búsqueda de coordenadas cumplen con las siguientes características:
§ X<500 y X>-500
§ Y<500 y Y>-500
§ Velocidad>10cm/s y
Vel<104 cm/s
function
verify(){
if (!checkManual()) {
var X =
document.getElementById("X").value;
var Y =
document.getElementById("Y").value;
var vel =
document.getElementById("vel").value;
if ((X == "") || (Y ==
"") || (vel == "")){
alert("Favor de
introducir todos los datos requeridos");
return
false;
} else if ( (X > 500) || (X
< -500)) {
alert("El valor de la coordenada X debe de
encontrarse en un rango entre -500 y 500 cm.");
return
false;
} else if ( (Y > 500) ||
(Y < -500)) {
alert("El valor de la coordenada Y debe de
encontrarse en un rango entre -500 y 500 cm.");
return
false;
} else if ( (vel > 104) ||
(vel < 10) ) {
alert("El valor de la velocidad debe de ser estar
en un rango de 10 a 104 cm/s.");
return
false;
} else {
return true;
}
} else {
alert("Favor de desactivar
el modo manual antes de enviar algún dato");
return false;
}
}
En esta función se hace la llamada a la aplicación WebIOPi que nos
permitirá enviar datos de manera serial al Raspberry, es necesario mencionar que
esta parte del código solo funcionará (se verá reflejada) cuando el archivo
.html sea cargado al Raspberry, ya que de probarlo en un ordenador portátil no
desplegará nada. La razón de esto es que el WebIOPi únicamente se encuentra
cargado en la Raspberry.
webiopi().ready(function()
{
Acción de presionar la flecha superior con su validación de entrada.
$("#up").mousedown(function(event){
if
(checkManual()) {
webiopi().Serial("serial0").write("2");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n")
if
(checkModo()) {
webiopi().Serial("serial0").write("3");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
else {
webiopi().Serial("serial0").write("4");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
webiopi().Serial("serial0").write("5");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write("10");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
});
Acción de presionar la flecha derecha con su validación de entrada.
$("#right").mousedown(function(event){
if
(checkManual()) {
webiopi().Serial("serial0").write("2");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n")
if
(checkModo()) {
webiopi().Serial("serial0").write("3");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
else {
webiopi().Serial("serial0").write("4");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
webiopi().Serial("serial0").write("6");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write("10");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
});
Acción de presionar la flecha izquierda con su validación de entrada.
$("#left").mousedown(function(event){
if
(checkManual()) {
webiopi().Serial("serial0").write("2");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n")
if
(checkModo()) {
webiopi().Serial("serial0").write("3");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
else {
webiopi().Serial("serial0").write("4");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
webiopi().Serial("serial0").write("7");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write("10");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
});
Acción de presionar la flecha inferior con su validación de entrada.
$("#down").mousedown(function(event){
if
(checkManual()) {
webiopi().Serial("serial0").write("2");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n")
if
(checkModo()) {
webiopi().Serial("serial0").write("3");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
else {
webiopi().Serial("serial0").write("4");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
webiopi().Serial("serial0").write("8");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write("10");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
});
Acción de presionar el botón de Alto con su validación de entrada.
$("#stop").mousedown(function(event){
if
(checkManual()) {
webiopi().Serial("serial0").write("2");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n")
if
(checkModo()) {
webiopi().Serial("serial0").write("3");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
else {
webiopi().Serial("serial0").write("4");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
webiopi().Serial("serial0").write("9");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write("10");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
});
Acción de presionar el botón de modo Normal con su validación de
entrada.
$("#normal").mousedown(function(event){
changeToNormal();
});
$("#demon").mousedown(function(event){
changeToDemon();
});
Acción de presionar el botón de Enviar comando con las coordenadas
requeridas y con su validación de entrada.
$("#command").mousedown(function(event){
var X = $('#X').val();
var Y =
$('#Y').val();
var vel = $('#vel').val();
if
(verify()){
webiopi().Serial("serial0").write("1");
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write(X);
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write(Y);
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
webiopi().Serial("serial0").write(vel);
webiopi().Serial("serial0").write("\r");
webiopi().Serial("serial0").write("\n");
}
return false;
});
$("#inputText").keyup(function(event){
if(event.keyCode == 13){
sendData();
}
});
$.get("/devices/*", function(data) {
var devices =
$("#devices");
var added = false;
for (i in data) {
if
(data[i].type=="Serial") {
added = true;
devices.append($("<option>" + data[i].name +
"</option>"))
}
}
if (added) {
readData();
}
});
});
Función para leer información externa a las Raspberry.
function readData() {
webiopi().Serial($("#devices").val()).read(function(data) {
if (data.length > 0) {
var d =
$("#output").text() + data;
$("#output").text(d);
}
});
setTimeout(readData, 500);
}
Función para enviar información desde Raspberry.
function sendData() {
var data = $("#inputText").val() + "\n";
webiopi().Serial($("#devices").val()).write(data);
$("#inputText").val("");
}
Indica el estado del dispositivo.
function deviceChanged()
{
$("#output").text("");
}
</script>
Cuerpo.
En el cuerpo del archivo HTML se hace la definición de
cada sección de la página, barras de navegación, imágenes, texto y efectos de
diseño. En caso de tener alguna duda acerca de la sintaxis de esta sección se recomienda
visitar las siguientes ligas y revisar la sección de Referencia o de
Tutoriales.
Enseguida se
muestran algunas capturas de la página web funcionando:
Suscribirse a:
Comentarios (Atom)


