Pages: 1 [2] 3   Go Down
Author Topic: Gadget para desconectar un ascensor  (Read 4831 times)
0 Members and 1 Guest are viewing this topic.
Madrid
Offline Offline
Sr. Member
****
Karma: 5
Posts: 481
Life isn't about finding yourself, life is about creating yourself!!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

En la misma linea de lo que enseñan en el libro de TTE Systems mencionado por IgorR,
El siguiente articulo (ingles) presenta un microkernel para sistemas embebidos también en "C"
http://www.scirp.org/journal/PaperDownload.aspx?FileName=JSEA_2013013009475515.pdf&paperID=27477
Logged

Engineering is the art of
making what you want from
things you can get.

     

[SOLUCIONADO]

0
Offline Offline
Edison Member
*
Karma: 16
Posts: 1579
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Tiene buena pinta ese artículo, yOPERO!! smiley-wink

Lo único que yo aconsejaría ir empezando poco a poco para "entender" los problemas y saber "identificar" tus necesidades.
Necesitas pelearte con interrupciones primero, para poder entender que puedes estar en tu rutina de mostrar algo por pantalla, y que de repente entres a tu interrupción y empieces a tener problemas....
O que eliges leer tus botones por interrupción, y un día falla la conexión (eléctricamente) siendo intermitente y estás entrando todo el rato a dicha rutina, no dejando ejecutarse el código principal si no has previsto este modo de fallo en tu código.
O entender el problema de manipular variables no atómicas => http://arduino.cc/forum/index.php?topic=73838.0
etc.

Luego así aprendes a evitar usarlas o tener mucho cuidadín...je,je,je


 smiley-twist
« Last Edit: January 30, 2013, 03:26:41 pm by Igor R » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Muy buenas,

Me he estado mirando el tema de las máquinas de estado y lo que he "sacado" es el archivo adjunto. no se si lo que he hecho es una maquina de estados, o me lo he inventado smiley-razz.

Para programarla lo estoy haciendo con switch (que no se si es correcto o no)

Agradeceria que me dijerais si estoy por bueno camino o no he entendido nada de lo que me habeis dicho.

Muchas gracias por la ayuda y un saludo


* maquina estadov2.jpg (227.58 KB, 1950x1997 - viewed 26 times.)
« Last Edit: February 27, 2013, 03:37:50 am by erikcrane » Logged

0
Offline Offline
Edison Member
*
Karma: 16
Posts: 1579
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Lo he mirado rápido, pero tiene pinta que no hace lo que originalmente querías, no??

Si estás en el menu (y/o siguientes estados) no hay transición para que si es la hora XXhXX,dia D,etc haga tus acciones de desactivar,etc.
Es decir, se te quedaría bloqueado en dicho estado de muestra menu,etc sin poder desactivar o hacer lo que tienes en otras ramas.

Yo diría que te faltan transiciones en ese flujograma....no crees?

Un consejo, puedes crearte nombre de eventos cortos, para poner en tus transiciones y luego en un lateral describes lo que hace cada uno. Es más fácil de seguirlo, dibujar el diagrama y queda más limpio.
Por ejemplo: ev_pulsacion1, ev_pulsacion2, ev_alarm1,.... (ev=evento).
Y describes la lógica de cada evento en otro sitio que no sea sobre las transiciones:
ev_pulsacion1= pulsación de la tecla 1 (entrada digital 7)
ev_alarma1= Hora 7h30 && laborable && Stop
etc.

Es más, si lo programas así.... luego puedes sustituir lo que genera tu evento muy fácil!!! Yo lo hago así en mi programación, y esto me permite, por ejemplo, que mi evento pulsación tecla confirmar (ev_confirmar), pueda venir de una tecla o de un comando serie.
Para que me entiendas por dónde voy... de forma sencillísima, hago que mi programa se controle por comandos serie, por entradas digitales, o por ambos!!
Es un ejemplo, pero es para que entiendas la ventaja de pensarlo/programarlo así, que luego tus eventos son fáciles de cambiar las condiciones que lo generan, y si te has preparado el código, pues te resulta inmediato hacerlo.

Lo digo para que no hagas tu programación repetitiva con IF (RTC.hora...&& digitalread(x) { bla,bla}
Si no que leas todas tus entradas que generen eventos (RTC, entradas analógicas/digitales, serie,etc) y generes el evento/s que corresponda.
Luego en tu código sólo tienes, si estoy en (estado==5 && ev_alarma1), hago tal y cual.... Y tu ev_alarma=(RTC.hora==  && digitalRead...etc.).
A parte que el mismo evento, puede ser utilizado en varias transiciones y no tienes que repetir código.
Espero que me entiedas por donde voy...


smiley-wink



« Last Edit: February 27, 2013, 03:25:40 pm by Igor R » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Primero de todo muchas gracias por tus consejos. Entiendo por donde vas y ya estaba pensando en que el codigo que estoy escribiendo es muy chapucero (basicamente vos escribiendo codigo segun las necesidades) y mi idea era reescribirlo para que no fuera tan chapucero. Con esto que me dices quedará mejor y mas entendible. Gracias de nuevo  smiley-lol

En lo referente al dibujo, está mal. Con lo que me has dicho me he puesto a revisar el dibujo con el codigo y he visto que he representado mal graficamente el codigo que tengo escrito.

En el loop tengo dos switchs. Un switch es el que se encarga de mirar la hora y el dia, y dependiendo de estos dos valores hace una u otra acción. Y el otro siwtch es el del menu, que segun la tecla apretada vas a una opcion u otra.

En el primer caso (el case 0 en mi codigo) del switch (que es cuando mira la hora y el dia) tambien se controla si se aprieta la tecla # (que es la que sirve para ir al menu). Si esa tecla se aprieta el siwtch del menu pasa al case encargado de mostrar el menu. (el primer case del switch del menu es de reposo, que no hace nada)

El codigo seria mas o menos asi:

Code:
void loop(){
  switch (a){
   case 0:
     leo hora y dia
     controlo si se aprieta # - si se aprieta # b = 1 sino b continua valiendo 0
     segun hora y dia cambio asigno a variable a los diferentes case
     break;
  case 1:
     cuando es la hora 7.30 y dia laborable desactivo stop
     break;
  .......
  }
  switch (b){
    case 0:
      break;
    case 1:
      muestro menu
      segun opcion me voy a un case o otro
      break;
    case 2:
      configuro hora y fecha
      break;
    .....
   }

Muchas gracias por los comentarios y por el tiempo dedicado a responder

Un saludo
« Last Edit: February 28, 2013, 06:13:13 am by erikcrane » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Esto es lo que he echo con lo me has dicho de los eventos, no lo acabo de ver claro, me parece que lo programo demasiado enrevesado:

Code:
#define E_INICIO 1


#define E_IDLE 1
#define E_MENU 2
#define E_CTIME 3
#define E_CCALENDAR 4
#define E_EXTRAERSD 5

void setup(){}
void loop(){
leer_hora_fecha();
key = leer_tecla();

switch (desconexion){
case E_INICIO:
/* aqui quiero poner:
si el menu esta en en el estado de espera (E_IDLE) y aprieto la tecla # entonces
se limpia la pantalla y se cambia el estado del menu a estado menu (E_MENU)<--es decir que entro en el menu

tambien tengo que tener en cuenta que la pantalla de inicio solo se muestre cuando el menu esta en estado de espera (E_IDLE)
*/
if(menu == E_IDLE){
if(ev_teclaHash89){
lcd.clearDisplay();
menu = E_MENU;
}
pantalla_inicio(); //Pantalla que se muestra siempre (menos cuando se esta dentro del menu) que muestra la hora y la fecha
}
break;
}
switch (menu){
case E_IDLE:
//Aqui no hago nada
break;
case E_MENU:
//Se muestra el menu y se pasa a los siguientes estados segun la tecla apretada
//No se si he entendido bien lo que me has dicho sobre los eventos, pero esto es lo que se me ocurre de como ponerlo
//También he pensado que en vez de los if se podria poner un switch y dependiendo del ev_tecla se envia un estado o a otro

if(ev_tecla1()){
lcd.clearDisplay();
menu = E_CTIME;
}
if(ev_tecla2()){
lcd.clearDisplay();
menu = E_CCALENDAR;
}
if(ev_tecla3()){
lcd.clearDisplay();
menu = E_EXTRAERSD;
}
break;
case E_CTIME:
//Se configura la hora y la fecha del RTC
break;
case E_CCALENDAR:
//Se configura los dias festivos
break;
case E_EXTRAERSD
//Se extrae la SD
break;
}
}

Si me pudieras dar algun consejo te lo agradeceria muchismo

Un saludo
Logged

0
Offline Offline
Edison Member
*
Karma: 16
Posts: 1579
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola,

Hay muchas maneras de hacerlo. La manera que yo elegí (que no es para nada como te pongo aquí abajo), la puedes ver en el código de mi librería y ejemplos....https://github.com/IgorReal/SECUduino/tree/master/FSM%20Library

Lo hagas como lo hagas, quieres que en tu loop se este haciendo todo el rato (hablando de una máquina sencilla):
1) Leer eventos (transiciones)
2) Actualizar estados
3) Realizar la función que corresponda a dicho estado.

Por ejemplo, una muy básica pero que tiene el problema de gastar mucha RAM por las variables utilizadas(ya que tienes una variable por cada evento), podría ser:


//EVENTOS
if (Serial.available()>0)   myReceivedByte=Serial.read();
ev_botonOK=digitalRead(5) || myReceivedByte=="O";
ev_botonUP=digitalRead(1) || myReceivedByte=="U";
if (RTC.Hora==13 && RTC.Minutos>=30)  
{
    ev_alarma1=1;
}else
    ev_alarma1=0;
}

//MAQUINA DE ESTADOS
switch(estado)
{
  case st_Menu:
    //Muestro por pantalla cosas, activo salidas, etc
    if (ev_botonOK) estado=st_Pantalla1;
  break;
  case st_Pantalla1;
    //muestro por pantalla cosas
    if (ev_botonUP)
    {
        estado=st_MENU;
    }else if (ev_alarma1)
    {
      estado=st_Alarma;
    }
    break;
  case st_Alarma:
     ....
   break;
   etc.
}


Y a partir de esto básico, pues seguro que ves como puedes mejorar y hacerla más efectiva (en cuanto a código).
Para botones, al leer tus entradas, puedes crearte un byte (o del tamaño que necesites) que cada bit sea una de ellas. Es decir, el bit0 es botonUP, el bit1 es botonOK, etc...Incluso si te lo montas bien en tu código, puedes conectarlo al mismo puerto(hardware), y leer el puerto de una vez.Cosa que será más rápida que digitalRead() de Arduino.
Bueno, en realidad podrías tener una variable evento, y que cada bit tiene un significado (según su posición, indica el estado de los eventos).

Luego usas máscaras para saber si está activo o no.

Pero poco a poco!! smiley-wink

Saludos,


Igor R.


[1] Manejo de puertos => http://arduino.cc/es/Reference/PortManipulation
[2] Máscaras y operaciones con bits => http://arduino.cc/es/Tutorial/BitMask
« Last Edit: February 28, 2013, 03:00:51 pm by Igor R » Logged


Málaga, Spain
Offline Offline
Edison Member
*
Karma: 41
Posts: 2182
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

En estas lineas, hace mucho tiempo diseñé una pequeña librería de co-rutinas o proto-threads la mar de maja para un proyecto con PICs que debería ser portable a Arduino sin muchas historias.

Si la encuentro, abro un hilo con ella.

Muy útil para algunas cosas.
Logged

   

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Muchas gracias fm  smiley-lol

Igor, gracias a ti tambien smiley-lol. Estoy haciendo otro proyecto (un cronometro cuenta atras, que cuando llega a 0 activa un rele) que tambien lo he hecho por maquina de estados. Como es mucho mas corto que el del ascensor, intentare programarlo segun dices y segun vea en el codigo del link. De momento no me entero mucho, he entendido el usar solo codigo no bloqueante para poder hacer "multi-tarea", pero aun me queda para escribir un codigo decente.

Lo dicho, seguire mirando sobre fsm y el codigo que has posteado, muchas gracias

Edit: Acabo de leerme el pdf de la FSM Library y me ha gustado. Muy sencillo todo, con un par de sentencias creas una maquina de estado y la manipulas. Ahora me miraré el código a ver si entiendo algo smiley-razz
« Last Edit: March 07, 2013, 02:42:01 am by erikcrane » Logged

Lorca
Offline Offline
Newbie
*
Karma: 0
Posts: 5
El Primer Paso es Intentarlo
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola erikcrane.

Oye, una cosilla que no me ha quedado clara. ¿Qué pasa si llega el momento de la desconexión y el ascensor está siendo utilizado por un pasajero? ¿Y si alguien lo está esperando en planta?

Creo que es un punto conflictivo de este montaje.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hola erikcrane.

Oye, una cosilla que no me ha quedado clara. ¿Qué pasa si llega el momento de la desconexión y el ascensor está siendo utilizado por un pasajero? ¿Y si alguien lo está esperando en planta?

Creo que es un punto conflictivo de este montaje.

Muy buenas y gracias por tu comentario.

Es un montacargas donde las personas no pueden subir, es solo para material. Y se para cuando se acaba la jornada laboral. Por tanto nadie lo estará usando.

Igualmente para situaciones puntuales en que se necesite fuera de un horario laboral voy a implementar un interruptor para desconectar este sistema y que pueda funcionar normalmente. Luego cuando se acabe de usar se vuelve a conectar y el sistema ya se encarga de comprobar que el montacargas este en la 4 planta y el boton de stop este apretado.

Logged

Cordoba
Offline Offline
God Member
*****
Karma: 40
Posts: 686
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@erikcrane, para eso agrega una excepcion por medio de una clave, y se transforma en un estado nuevo, cuando llega arriba pierde el estado y si quieres que baje vuelves a acargar la clave.

@Igor R, es excelente tu trabajo voy a usarlo en mi proyecto domotico y si me permite lo voy a mencionar en arduino playground de linkedin donde hay una persona que esta desarrollando un plc con arduino mega
Logged

El que pregunta aprende, el que responde aprende a responder.

0
Offline Offline
Edison Member
*
Karma: 16
Posts: 1579
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Gracias @maxid.

He subido un video del invento...Así ves como se puede cambiar menus, mientras se están haciendo otras cosas... smiley-wink



Eso por dentro tiene un Arduino core... smiley-twist
Y usando la librería que he comentado en anteriores post (FSM).

Saludos,


Igor R.
« Last Edit: March 23, 2013, 06:13:17 pm by Igor R » Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 17
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Pero esto no son pruebas caseras, no? esto son pruebas de rendimiento de motores en algun curro. Me mola mucho smiley-grin, no solo la maquina de estados sino el centro de trabajo smiley-grin

Le voy pillando el tranquillo ha hacer una maquina de estados sencillita a traves de switch e ifs. Antes de empezar con la del ascensor he hecho una para un cronometro cuenta atras, que cuando empieza la cuenta atras se activa un rele y cuando acaba se desactiva. Creo que he seguido la filosofia de la maquina de estados y no hay codigo bloqueante, pero no se si lo he hecho todo bien (el progama hac elo que tiene que hacer)

Te dejo el setup y el loop por si quieres hecharle un ojo, sino ningún problema porque queria ponerme a leer algun libro sobre maquinas de estado ahora que ya he ido asimilando mejor en que consisten

Code:
#include "Wire.h"
#include "lcd_i2c.h"
#include "Bounce.h"

#define RELE 12
#define LED 10
#define START 4
#define RESET 5
#define SEG_UP 6
#define SEG_DOWN 7
#define MIN_UP 8
#define MIN_DOWN 9

#define INTERVAL_MILLIS 5

#define E_INICIAL 0
#define E_CONFIG_TIME 1
#define E_CUENTA_ATRAS 2
#define E_RELE_ACTIVADO 3

#define REBOUNCE_TIME 250

LCD_I2C lcd(0x38);

uint8_t state = E_CONFIG_TIME;

Bounce buttonStart = Bounce(START, INTERVAL_MILLIS);
Bounce buttonReset = Bounce(RESET, INTERVAL_MILLIS);
Bounce buttonSegUp = Bounce(SEG_UP, INTERVAL_MILLIS);
Bounce buttonSegDown = Bounce(SEG_DOWN, INTERVAL_MILLIS);
Bounce buttonMinUp = Bounce(MIN_UP, INTERVAL_MILLIS);
Bounce buttonMinDown = Bounce(MIN_DOWN, INTERVAL_MILLIS);

struct tiempo{
  uint8_t horas;
  uint8_t minutos;
  uint8_t segundos;
  uint8_t decimas;
}cuenta = {0,0,0,0};

long milisegundos;

void setup(){
  pinMode(RELE, OUTPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(RELE, LOW);
  digitalWrite(LED, LOW);
 
  for(int i=4; i<10; i++){
    pinMode(i, INPUT_PULLUP);
  }

  lcd.init(0x38);
}
void loop(){
  switch(state){
    case E_INICIAL:{
      imprimirTiempo();    //Escribir en pantalla el tiempo que en este caso como es el inicial es 0. Este estado se podria eliminar porque la   
                                    //funcion configTiempo() tambien llama a imprimirTiempo()
      state = E_CONFIG_TIME;
    }break;
    case E_CONFIG_TIME:{
      configTiempo();     //con unos botones configuo los segundos y minutos
      if(ev_reset()){         //ev_reset comprueba si se ha apretado el boton reset
        resetTiempo();        //Pongo minutos, segundos y decimas a 0
        state = E_INICIAL;
      }
      if(ev_start()){     //ev_start comprueba si se ha apretado el boton start
        activarRele();    //activa el rele y un led indicador
        state = E_CUENTA_ATRAS;
      }
    }break;
    case E_CUENTA_ATRAS:{
      if(!ev_fin_cuenta_atras() && !ev_reset()){   //ev_fin_cuenta_atras devuelve true cuando los minutos, segundos y decimas son igual a
                                                                   //0
        cuentaAtras();
      }else{
        desactivarRele();
        resetTiempo();
        state = E_INICIAL;
      }
    }break;
  }
}
Logged

0
Offline Offline
Edison Member
*
Karma: 17
Posts: 1413
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Gracias @maxid.

He subido un video del invento...Así ves como se puede cambiar menus, mientras se están haciendo otras cosas... smiley-wink



Eso por dentro tiene un Arduino core... smiley-twist
Y usando la librería que he comentado en anteriores post (FSM).

Saludos,


Igor R.

Muy bueno Igor ! Gracias por compartirlo.

El problema que yo tengo en uno de mis proyectos es que una de las tareas requiere hacer un bucle que tarda unos 200 a 250 ms, por lo que aunque para la pantalla no es problema, si que afecta cuando intentas navegar por el menu. No quiero usar interrupciones para tener control total del programa. Tu no utilizas interrupciones,no? el loop es muy rapido para permitir moverte así por los menus.
Logged

* Si preguntas, pon el código de tu programa, hace mucho mas fácil ayudarte. Y me ahorro un mensaje pidiendo que lo hagas.
* Si consigues solucionar tu problema, dedica unos minutos a explicar en tu post como lo conseguiste para beneficio de todos.
* Cambia el 'Subject' de tu hilo y añade 'SOLUCIONADO' cuando hayas llegado a una solución al problema que planteaste.
* Utiliza un 'Subject' para tu hilo que explique de que va el hilo.
Si estas empezando:
* Comienza a usar Arduino
* Guías de iniciación a Arduino
* Ejemplos
* Referencia del Lenguaje
* Conceptos básicos
Guia de usuario de arduino
Tutoriales en Ingles
Si necesitas que alguien te escriba el código: http://www.freelancer.com/  o esta  http://www.guru.com/

Pages: 1 [2] 3   Go Up
Jump to: