multitarea

Muy buenas, soy Alex!

Os cuento, tras adquirir una impresora 3d, y sufrir de lo lindo para su configuracion, aprendi ciertos criterios sobre arduino, y me he tirado a la piscina para realizar un programa para el control de una estufa.

Estoy usando una lcd 20x4, un rotary encoder, 2 ventiladores a 220 (usando placa triac) 3 motores paso a paso...etc

Bueno, la historia es, que todo de forma independiente, soy capaz a moverlo, o hacer lo que mas o menos quiero....la historia viene cuando los uno...

Si en mi void loop, hago una llamada a un void para temperaturas...un void para ventiladores etc, como puedo ejecutar todos simltaneamente?

poder leer constantemente la temperatura, a la vez que el ventilador hace una secuencia de aceleracion, y a la vez que el motor paso a paso da un numero de vueltas determinado.

Ahora mismo, consigo una sola lectura de temperatura, no se vuelve a repetir, consigo que el ventilador se ponga la velocidad de inicio, pero no que continue su incremento, y que el motor paso a paso, de vueltas, pero no a la velocidad que lo hace si ejecuto solamente su void.

que ejemplo podria seguir para llevar esto a cabo?

si a google le pregunto sobre el multitarea, solmamente me hace referencia a usar la funcion milis en lugar de delay.

Espero haberme explicado mas menos bien!

Gracias, un saludo!

No existe la multitarea en Arduino.
Este tema se ha respondido muchas veces. Yo mismo lo he hecho.
Y claro que millis() es la respuesta pero no como te imaginas.
El tema es que en cualquiera de las cosas que describes no puedes usar delay(XXXX) si lo que pretendes es que todo el código fluja como si fuera multitarea.

Plantea lo que quieres hacer, pero no como lo has descripto, sino desde la interacción entre ellos.
Esta claro que tienes un arduino con un LCD.
Esta claro que tienes un sensor de temperatura.. hasta ahi todo junto no tiene problema alguno.
El ventilador da una aceleración basado en que?
El motor paso a paso se mueve de que modo en relación a temperatura u otro parámetro?

NOTA: lee las normas del foro y si vas a insertar códigos, imágenes y enlaces no termines agregado fotos adjuntas, ni copiar y pegar enlaces.

Muy buenas de nuevo.
En primer lugar agradecer la rapida repuesta.

te cuento mas extenso, como entradas contare:

4 termopares con mx6625
2 termistores

el rotary encoder que viene intergrado en la lcd y sus botones

salidas:

-dos ventiladores que extreran aire caliente segun como este un cajon
-dos motores paso a paso para el movimiento de los tiros de la estufa
-un motor paso a paso para crear una valvula alveolar y que mueva la aliemtacion de la estufa.

El programa, contara con un sistema de menus, en el que seleccionaremos el modo manual o el automatico.

Mis pruebas por ahora, las he realizado con la libreria menubackend.

El menu automatico no me tendre que molestar mas que asignar parametros y el trabajara (esto llegara mas adelante)

Desde el modo manual, queria visualizar en todo momento la temperatura y poder mover desde cada submenu correspondiente los motores ventiladores etc.

Por ejemplo, entrar en modo manual, ir a ventilador, ponerlo al 50% (a traves del rotary encoder), salir, ir al submenu del tiro, y mover el motor paso a paso los incrementos necesarios, siempre, viendo en una esquina la temperatura que hay en cada momento.

La complejidad del programa, o las ideas desorganizadas de mi cabeza, hace que me cueste explicarlo, pero el ejemplo es sencillo, en la impresora 3d, en la pantalla siempre veo la temp del extrusor, a la vez que manda trabajar a varios motores de manera simultanea y con pequeños pasos.

Preciso, puesto que creo que desde el primer momento lo entendiste, que me lances ese gancho que haga que pueda investigar, ese ejemplo, al cual yo le llamo multitarea, pero posiblemte se le designe d otra manera.

Gracias, un saludo

Mira es MUY FACIL para el nivel de lo que estas haciendo o has hecho.
Premisa número uno. NO USES UN SOLO DELAY (salvo los que tu no controlas que esten en una librería).
Si puedes controlar eso.. lo demas funcionará perfectamente.
Organiza tu programa de este modo

  1. incluir librerías
  2. Definición de variables globales, objetos, etc.
  3. Setup: inicializar objetos que asi lo requieran.
  4. tu loop debe tener
    4.1 llamados a rutina de menú (a travez del rotaty encoder)
    4.2 llamado cada x milisegundos a actualizar sensores
    4.3 Actuar según los sensores para controlar los dispositivos Externos : Ventiladores, motor paso a paso etc.
  5. Rutina de menu
  6. Rutina de sensores
  7. Rutina de control de dispositivos Externos

En todo esto si necesitas tiempos que deben completarse usas millis()
ej. Defines timer = millis()+1000UL; // esto hace que timer se cargue con el valor del cronómetro mas 1000 mseg
Esto sirve para hacer que algo muestre datos cada 1 seguno, entonces

if (millis() > timer) {
   displayLCD();    // llamas al display LCD 
   timer = millis()+1000UL; // recargas la variable de comparación
}

supongamos que quieres actualizar cada 100 mseg los sensors o 250 pues haces algo similar y llamas a la rutina sensores()
Se entiende?

Gracias de nuevo por tu ayuda.
Puesto que el programa esta "encajado" de manera compleja, podria mandarte el archivo comprimido por correo, o compartirlo en formato comprimido por esta via (no se si se puede hacer)?

Todo lo que quieras hacer canalízalo por este foro.
Si me contactas por privado para mi se transforma en trabajo y obviamente funciona de otro modo.
Los archivos que excedent 9000 caracteres deben adjuntarse usando compresión zip.

Vale, me parece totalmente logico lo que me comentas.

He buscado, incluso preguntado a google...como adjunto para todo el mundo un zip en uno de mis comentarios?

No obstante, estoy manos a la obra en la estructuracion que me comentas, pero estoy segurisimo de que estoy pecando en mas cosas...

Todas tus dudas respecto al foro, serán reveladas cuando leas las Normas del Foro. Muy simple. Ahi dice absolutamente como manejarte en todo sentido, incluido los adjuntos comprimidos o zippeados.

Buenas noches!, Aqui vuelvo al ataque.

Despues de seguir tu consejo, y comenzar la casa por el tejado(leer las normas del foro), ya se como colgar el archivo con el programa.

Para cualquier otra persona que quiera descargarlo, saber que la funcion de movimiento por el menu funciona perfecta, y que los programas anidados de lectura de termistor, aceleracion de ventilador o control del motor paso a paso, tambien funciona, el problema surge al unirlo todo.

Espero podais ayudarme con esta "multitarea", en el void loop, hago una llamada a proposito para el arranque del ventilador, motor paso a paso y temperatura, para que podais ver el error que tiene, si eliminais la funcion TERMISTOR(); del loop, el programa trabaja de manera muy distinta.

Gracias, un saludo

A_general.zip (11.5 KB)

Este es tu error?

menuUsed.ino: In function 'void menuUsed(MenuUseEvent)':
menuUsed.ino:10:8: error: 'class MenuBackend' has no member named 'toRoot'
Error de compilación

No existe un miembro denominado toRoot en la clase correspondiente.
Mira el ejemplo
usan

#include <MenuBackend.h>
/*
	This is the structure of the modelled menu
	
	Settings
		Pin
		Debug
	Options
		Delay (D)
			100 ms
			200 ms
			300 ms
			400 ms
*/
//this controls the menu backend and the event generation
MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);
	//beneath is list of menu items needed to build the menu
	MenuItem settings = MenuItem("Settings");
		MenuItem pin = MenuItem("Pin");
		MenuItem debug = MenuItem("Debug");
	MenuItem options = MenuItem("Options");
		MenuItem setDelay = MenuItem("Delay",'D');
			MenuItem d100 = MenuItem("100 ms");
			MenuItem d200 = MenuItem("200 ms");
			MenuItem d300 = MenuItem("300 ms");
			MenuItem d400 = MenuItem("400 ms");
	
//this function builds the menu and connects the correct items together
void menuSetup()
{
	Serial.println("Setting up menu...");
	//add the file menu to the menu root
	menu.getRoot().add(settings); 
		//setup the settings menu item
		settings.addRight(pin);
			//we want looping both up and down
			pin.addBefore(debug);
			pin.addAfter(debug);
			debug.addAfter(pin);
			//we want a left movement to pint to settings from anywhere
			debug.addLeft(settings);
			pin.addLeft(settings);
	settings.addBefore(options);
	settings.addAfter(options);
		options.addRight(setDelay);
			setDelay.addLeft(options);
			setDelay.addRight(d100);
				d100.addBefore(d100); //loop to d400 
				d100.addAfter(d200);
				d200.addAfter(d300);
				d300.addAfter(d400);
				d400.addAfter(d100); //loop back to d100
				//we want left to always be bak to delay
				d100.addLeft(setDelay);
				d200.addLeft(setDelay);
				d300.addLeft(setDelay);
				d400.addLeft(setDelay);
	options.addAfter(options);
}
/*
	This is an important function
	Here all use events are handled
	
	This is where you define a behaviour for a menu item
*/
void menuUseEvent(MenuUseEvent used)
{
	Serial.print("Menu use ");
	Serial.println(used.item.getName());
	if (used.item == setDelay) //comparison agains a known item
	{
		Serial.println("menuUseEvent found Dealy (D)");
	}
}
/*
	This is an important function
	Here we get a notification whenever the user changes the menu
	That is, when the menu is navigated
*/
void menuChangeEvent(MenuChangeEvent changed)
{
	Serial.print("Menu change ");
	Serial.print(changed.from.getName());
	Serial.print(" ");
	Serial.println(changed.to.getName());
}
void setup()
{
	Serial.begin(9600);
	
	menuSetup();
	Serial.println("Starting navigation:\r\nUp: w   Down: s   Left: a   Right: d   Use: e");
}
void loop()
{
	if (Serial.available()) {
		byte read = Serial.read();
		switch (read) {
			case 'w': menu.moveUp(); break;
			case 's': menu.moveDown(); break;
			case 'd': menu.moveRight(); break;
			case 'a': menu.moveLeft(); break;
			case 'e': menu.use(); break;
		}
	}
}

copie todo el ejemplo para que se vea como debe usarse.

No,ese no es mi error,eso es debido al software de ardyino,para poder hacer uso de la librería backend tuve que volver a una versión anterior de arduino...1.05...

Es más...mi sketch llega a compilar,él error viene en el multitarea..hacer trabajar al void loop..

Cómo?
Entonces deberías haber comenzado diciendo que librería estas usando y qué IDE.
Repasa por favor las Normas del Foro donde dice que debes presentar todo tu panorama con todos los detalles involucrados.
Si me tomo el trabajo de descargar tu programa, bajar la librería backend para que luego me digas que debo bajarme el IDE 1.0.5 y una librería que tiene 4 o 5 años de antigüedad como he visto, realmente no lo hubiera hecho.

No se como ayudarte entonces. Si no puedo reproducir con un IDE 1.6.0 como el que uso. Para mi no tiene mucho sentido.
Tal vez alguien mas pueda o te estoy malentendiendo.. tu dirás.

ESTUFA AIRE CALIENTE

madre mia!lo dificil que resulta eso de la programacion! :o :o

software: Arduino IDE, v1.0.6

hardware:

  • 1 Arduino mega 2560
  • 1 Ramps 1.4
  • 3 pololus drv8825
  • 3 motores nema 17
  • 2 placas casera control triac para ventiladores
  • 2 ventiladores 220v
  • ReprapDiscount Smart controller (lcd+rotary encoder+button)
  • 2 termistores 100k
  • 4 termopares con driver max6625

Las librerias utilizadas

  • AccelStepper-master (motor paso a paso)
  • MenuBackend

Por que uso esta version de IDE de arduino, por que al añadir esta libreria (MenuBackend) no compilaba, me daba el error que a ti, y despues de mucho leer, vi que lo comun era que a todos los que les funcionaba, usaban esta version de arduino, probe, funciono y me despreocupe, segui al siguiente nivel...

Ahora viene lo que quiero hacer, con el archivo zip que visteis antes, claro antes, si me puedes decir porque no funciono la libreria con un sistema de software mayor... y asi me puedo poner a tu nivel...mientras probare lo que has puesto antes...

Estufa aire caliente:

El programa, esta destinado a el control en modo manual y en modo automatico de una estufa.
La estufa usa combustibles tipo pellet, cascara de almedra, etc.
La estufa esta alojada en el interior de un cajon, en el cual se acumulara calor.
La tolva esta por la parte superior del hogar, y a medida que va consumiendo, por peso cae la alimentacion al hogar.

Cuenta con dos tiros,movidos por motores paso a paso, uno en el hogar y otro en la chimenea, segun la regulacion de estos, conseguiremos variar la temperatura en el interior del cajon, la temperatura antes de la chimenea y posterior a la chimenea. Las temperaturas mencionadas, seran las que se midan con los termopares

El cajon cuenta con una salida de 200m de diametro, por la cual saldra el aire caliente del interior del cajon, movido por los ventiladores a 220v,asi que tambien tendremos en cuenta la temperatura del aire que expulsa.

Para garantizar la alimentacion de combustible, se dotara a la tolva de una valvula alveolar movida por un motor paso a paso.

Ahora que mas menos esta todo expuesto, lo que quiero ir probando es lo siguiente:

Por ahora, me olvido absolutamente del modo autocatico
Modo manual:

  • Por deplazamiento en menu de lcd, a traves del rotary encoder, poder arrancar al tanto por ciento los ventiladores mediante el uso del rotary encoder.
  • En otra pantalla visualizar las temperaturas, e incluso, ajustar el set point que luego usare en el modo auto.
    -En otro, poder avanzar el paso de la valvula alveolar
    -Posicionar los tiros

Ahora que creo que no dejo nada en el tintero
-Lo primero que debo de hacer para poder usar la version 1.6, en que estoy fallando, hay librerias compatibles unicamente con una version?
-Lo segundo, es correcto el entorno de organizacion creado en el sketch que mande ayer?
-Tercero, empiezo de 0 con el programa y me olvido de lo realizado hasta ahora?

Toda esta parrafada viene al bloqueo mental que tengo en no poder continuar avanzando en el proyecto.

Nuevamente gracias, por tu ayuda y paciencia

Porque la librería esta desactualizada. Tiene 4 o 5 años.
Jamás hubiera comenzado siquiera con algo tan viejo habiendo opciones mas actuales.
Pero veamos si puede resolverse.

Soy de Leon....somo muy brutos...le dare la vuelta a la tortilla!!

Reemplaza MenuBackEnd.h por esto que te adjunto

Resuelto!!
Compilé con IDE 1.6.0 tu código.

C:\Program Files (x86)\Arduino/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/arm-none-eabi-gcc -Os -Wl,--gc-sections -mcpu=cortex-m3 -TC:\Program Files (x86)\Arduino\hardware\arduino\sam\variants\arduino_due_x/linker_scripts/gcc/flash.ld -Wl,-Map,C:\Users\Ricardo\Documents\Arduino\Output/A_general.cpp.map -o C:\Users\Ricardo\Documents\Arduino\Output/A_general.cpp.elf -LC:\Users\Ricardo\Documents\Arduino\Output -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols -Wl,--start-group C:\Users\Ricardo\Documents\Arduino\Output/syscalls_sam3.c.o C:\Users\Ricardo\Documents\Arduino\Output\A_general.cpp.o C:\Users\Ricardo\Documents\Arduino\Output\Wire\Wire.cpp.o C:\Users\Ricardo\Documents\Arduino\Output\LiquidCrystal\LiquidCrystal.cpp.o C:\Users\Ricardo\Documents\Arduino\Output\AccelStepper\AccelStepper.cpp.o C:\Users\Ricardo\Documents\Arduino\Output\AccelStepper\MultiStepper.cpp.o C:\Users\Ricardo\Documents\Arduino\Output\variant.cpp.o C:\Program Files (x86)\Arduino\hardware\arduino\sam\variants\arduino_due_x/libsam_sam3x8e_gcc_rel.a C:\Users\Ricardo\Documents\Arduino\Output/core.a -Wl,--end-group -lm -gcc 
C:\Program Files (x86)\Arduino/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/arm-none-eabi-objcopy -O binary C:\Users\Ricardo\Documents\Arduino\Output/A_general.cpp.elf C:\Users\Ricardo\Documents\Arduino\Output/A_general.cpp.bin 

Sketch uses 43.476 bytes (8%) of program storage space. Maximum is 524.288 bytes.

MenuBackend.h (6.11 KB)

Bueno, deciros que la version del IDE a cambiado, ahora uso la 1.6.7, he descargado la supuesta actualizacion de la libreria backend, la cual esta dentro de una archivo llamado wiring, el cual incluye mas librerias..
Con el ejemplo usado por surbyte lineas mas arriba, tampoco funciona, da el siguiente error:

Arduino:1.6.7 (Windows 8), Placa:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"

HelloMenu:21: error: 'menuUseEvent' was not declared in this scope

 MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);

                                ^

HelloMenu:21: error: 'menuChangeEvent' was not declared in this scope

 MenuBackend menu = MenuBackend(menuUseEvent,menuChangeEvent);

                                             ^

exit status 1
'menuUseEvent' was not declared in this scope

  Este informe podría tener más información con
  "Mostrar salida detallada durante la compilación"
  activala desde Archivo > Preferencias

Por eso exactamente pase a usar una version anterior de IDE.
Seguire en pruebas! Gracias

Perdona, coincidimos antes en espacio tiempo en el envio del mensaje y no lo vi.

IDE 1.6.7 eliminado e instalado la V1.6.0.

Cambiado la libreria de menubackend por la que tu has mandado, ya estamos en lugares comunes...

Y funciona?

Funciona...funciona lo mismo que me funcionaba en la version 1.0.6, lo unico que ahora lo cargo desde la version 1.6, que no es poco, pero no es por lo que pregunte al incio.
El resto...sigo con la misma duda que en el incio, Sistema Multitarea

Donde debo de incorporar la lectura de las temperaturas, que son las que me dan la impresion de que me paraliza todo?

Ejemplo, me meto en uno de los submenus que he creado, y en el hago la llamada a un void que ejecuta la accion de poner en marcha el motor paso a paso, como la libreria utilizada para esto, lo que hace es mandar pulsos al driver pololu, para que avance la posicion, si mientras esta alcanzando esa posicion, se ejecuta la lectura de la temperatura, este no se mueve como debe.

Alguien a entendido, la duda con la que llevo desde el inicio, sistema multitarea, leer temperatura mientras hago otras cosas.

Cierto es, que surbyte al inico me dijo "Y claro que millis() es la respuesta pero no como te imaginas."
Pues aqui sigo, hechando imaginacion, pero sin salir del bache..

Nuevamente, gracias por la ayuda prestada.