RTOS, multitarea, o como aprobechar el tiempo de proceso.
4 participantes
Página 1 de 1.
RTOS, multitarea, o como aprobechar el tiempo de proceso.
Es habitual en cualquier programa para micros usar "delays", esperar a que un canal ADC obtenga un dato o a que una linea USART espere ciertos tiempos par enviar o recibir cada bit, de manera que en cuanto ponemos dos o tres tareas a funcionar nos topamos con que eso va cada vez más lento y en muchos casos es imposible mantener la velocidad o frecuencia mínima de operación que nos gustaría para cada tarea. La solución típica es ir a un oscilador más rápido, pero cuando llegamos al máximo parece que hemos llegado al limite de la capacidad del pic, cuando en realidad es muy posible que solo estemos utilizando un 10% util (incluso mucho menos) del tiempo de proceso del micro.
Si viéramos la actividad util del pic, observaríamos que la mayor parte del tiempo no está haciendo nada... solo esperar a que algo termine; para aprovechar mejor el tiempo de proceso del pic se usan los llamados RTOS (Real Time Operating System), de manera que el pic pueda actuar como lo hace cualquiera de nuestros PCs, pareciendo que hace varias cosas al mismo tiempo... en realidad lo único que hace es aprobechar los tiempos de espera para hacer otras cosas.
La base de los RTOS no es más que un control de tiempo, osea implementar algún tipo de "reloj" que controle el tiempo que va pasando, entonces si por ejemplo queremos un led parpadeando cada 500 mS, no usaríamos un delay, sino que se iría mirando cada cierto tiempo a ver si ya han pasado los 500 mS, pero mientras tanto podría hacer otras cosas.
Esto incluso se podría aplicar a una transmision o recepcion USART, dependiendo del baudrate y la frecuencia del pic; en los casos de transmisones no muy rápidas y velocidades altas de oscilador, estos tiempos entre bit y bit son largísimos vistos desde el punto de vista el procesador, perdiendo cientos de ciclos de instrucciones que podrían utilizarse.
Estos cortos periodos de tiempo mientras trabaja el hardware externo al procesador son aprobechables, aunque algo más complicados de implementar, pero realizar tareas cada cierto tiempo sin usar delays o ese tipo de cosas es realmente sencillo y es lo que hacen la mayoría de los llamados RTOS para PIC que se suelen ver por ahí; no es más que implementar un "reloj" con algún timer que provoque una interrupción cada cierto tiempo; en la rutina de interrupciones hay una serie de contadores (uno para cada tarea) que se van incrementando en cada interrupción, si un contador llega al valor establecido para esa tarea, entonces activa un flag de tarea activada, una vez actualizados todos los contadores sale de interrupciones.
La parte principal del programa solo es un bucle infinito que compruebe continuamente esos flags de tarea activada, cuando encuentra un flag en alto salta a la subrutina que realiza la tarea correspondiente.
De esta manera es facil realizar varias tareas "en paralelo", siempre que sean tareas no demasiado largas, y hay que definir cada cuanto tiempo se deben realizar esas tareas.
La ventaja además de permitir una mayor "actividad" del pic, es que por ejemplo se puede decir: lee un canal ADC cada 10 ms, calcula la media de las últimas 10 lecturas cada 100 ms, actualiza pwm según la media de ADC cada 200 ms, manda los datos por UART cada 500 ms... etc.... Tenemos control facilmente de la frecuencia con que se hace cada tarea, cosa que es complicada cuando programamos normalmente, ya que los tiempos cambian cada vez que cambiamos algo en el programa.
Me parece que es algo muy interesante y casi imprescindible si queremos hacer varias tareas cada cierto tiempo sin volvernos locos...
Alguien ha experimentado con estas cosas??... que les parece esto?
Saludos.
Si viéramos la actividad util del pic, observaríamos que la mayor parte del tiempo no está haciendo nada... solo esperar a que algo termine; para aprovechar mejor el tiempo de proceso del pic se usan los llamados RTOS (Real Time Operating System), de manera que el pic pueda actuar como lo hace cualquiera de nuestros PCs, pareciendo que hace varias cosas al mismo tiempo... en realidad lo único que hace es aprobechar los tiempos de espera para hacer otras cosas.
La base de los RTOS no es más que un control de tiempo, osea implementar algún tipo de "reloj" que controle el tiempo que va pasando, entonces si por ejemplo queremos un led parpadeando cada 500 mS, no usaríamos un delay, sino que se iría mirando cada cierto tiempo a ver si ya han pasado los 500 mS, pero mientras tanto podría hacer otras cosas.
Esto incluso se podría aplicar a una transmision o recepcion USART, dependiendo del baudrate y la frecuencia del pic; en los casos de transmisones no muy rápidas y velocidades altas de oscilador, estos tiempos entre bit y bit son largísimos vistos desde el punto de vista el procesador, perdiendo cientos de ciclos de instrucciones que podrían utilizarse.
Estos cortos periodos de tiempo mientras trabaja el hardware externo al procesador son aprobechables, aunque algo más complicados de implementar, pero realizar tareas cada cierto tiempo sin usar delays o ese tipo de cosas es realmente sencillo y es lo que hacen la mayoría de los llamados RTOS para PIC que se suelen ver por ahí; no es más que implementar un "reloj" con algún timer que provoque una interrupción cada cierto tiempo; en la rutina de interrupciones hay una serie de contadores (uno para cada tarea) que se van incrementando en cada interrupción, si un contador llega al valor establecido para esa tarea, entonces activa un flag de tarea activada, una vez actualizados todos los contadores sale de interrupciones.
La parte principal del programa solo es un bucle infinito que compruebe continuamente esos flags de tarea activada, cuando encuentra un flag en alto salta a la subrutina que realiza la tarea correspondiente.
De esta manera es facil realizar varias tareas "en paralelo", siempre que sean tareas no demasiado largas, y hay que definir cada cuanto tiempo se deben realizar esas tareas.
La ventaja además de permitir una mayor "actividad" del pic, es que por ejemplo se puede decir: lee un canal ADC cada 10 ms, calcula la media de las últimas 10 lecturas cada 100 ms, actualiza pwm según la media de ADC cada 200 ms, manda los datos por UART cada 500 ms... etc.... Tenemos control facilmente de la frecuencia con que se hace cada tarea, cosa que es complicada cuando programamos normalmente, ya que los tiempos cambian cada vez que cambiamos algo en el programa.
Me parece que es algo muy interesante y casi imprescindible si queremos hacer varias tareas cada cierto tiempo sin volvernos locos...
Alguien ha experimentado con estas cosas??... que les parece esto?
Saludos.
Última edición por Pikitin el Dom 1 Feb 2009 - 8:30, editado 1 vez
Ejemplo de multitarea en un pic16f876 y GCBasic
Ejemplo básico de multitarea: dos leds parpadeando a distinta velocidad.
Este programita muestra una manera sencilla de afrontar multitareas utilizando el timer0, el "tiempo base del sistema" es de 1ms, aunque seguramente con 500 us o menos es suficiente para realizar varias tareas, pero 1 ms es una base facil de usar para este ejemplo.
Un led parpadea a un ritmo se 2 s , 1s encendido y 1s apagado, el otro a un rimo de 600 ms, 300ms cada estado.
Este es el código en GCBasic:
Este programita muestra una manera sencilla de afrontar multitareas utilizando el timer0, el "tiempo base del sistema" es de 1ms, aunque seguramente con 500 us o menos es suficiente para realizar varias tareas, pero 1 ms es una base facil de usar para este ejemplo.
Un led parpadea a un ritmo se 2 s , 1s encendido y 1s apagado, el otro a un rimo de 600 ms, 300ms cada estado.
Este es el código en GCBasic:
- Código:
'_______________________________________________________________________
'
'
' Multitarea: Dos leds parpadeando a distinta velocidad
'
'_______________________________________________________________________
'------------------------- CONFIGURAR MICRO -----------------------------
'------------------------------------------------------------------------
#chip 16F876, 4 'modelo de pic y velocidad de reloj
#config HS_OSC, WDT_OFF, LVP_OFF, BODEN_OFF, PWRTE_ON
'--------------------------- DEFINICIONES -------------------------------
'------------------------------------------------------------------------
#define LED1 PORTB.0
#define LED2 PORTB.2
'----------------------- CONFIGURAR VARIABLES ---------------------------
'------------------------------------------------------------------------
dim t_led1 as word 'tiempo de parpadeo led1
dim c_led1 as word 'contador led1
f_led1 = 0 'flag led1
dim t_led2 as word 'tiempo de parpadeo led2
dim c_led2 as word 'contador led2
f_led2 = 0 'flag led2
'------------------------- CONFIGURAR PUERTOS ---------------------------
'------------------------------------------------------------------------
TRISA = b'000001'
TRISB = b'00000000'
TRISC = b'10000000'
PORTA = b'000000'
PORTB = b'00000000'
PORTC = b'00000000'
'----------------------------- PRINCIPAL --------------------------------
'------------------------------------------------------------------------
OPTION_REG = b'10000001' 'Timer0 configurado para 1 ms con Fosc=4MHz (prescaler 1/4)
bsf INTCON,T0IE 'Interrupciones Timer0 habilitadas
t_led1 = 1000 'Tiempo de tarea led1
t_led2 = 300 'Tiempo de tarea led2
c_led1 = 0
c_led2 = 0
do
if f_led1 = 1 then call tarea_led1
if f_led2 = 1 then call tarea_led2
loop
'--------------------------- INTERRUPCIONES -----------------------------
'------------------------------------------------------------------------
Sub interrupt
if INTCON.T0IF = 1 then 'si la interrupcion es de timer0
TMR0 = 5 'necesitamos una cuenta de 250: 5 a 255
c_led1 += 1 'incrementar contador de tarea
if c_led1 > t_led1 then 'si ha pasado el tiempo establecido
c_led1 = 0 'borrar contador
f_led1 = 1 'subir flag de tarea
End if
c_led2 += 1
if c_led2 > t_led2 then
c_led2 = 0
f_led2 = 1
End if
End if
INTCON.T0IF = 0
End Sub
'------------------------ SUBRUTINAS DE TAREAS --------------------------
'------------------------------------------------------------------------
Sub tarea_led1
f_led1 = 0
if LED1 = 1 then
LED1 = 0
exit Sub
End if
LED1 = 1
End Sub
Sub tarea_led2
f_led2 = 0
if LED2 = 1 then
LED2 = 0
exit Sub
End if
LED2 = 1
End Sub
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
que tal pikitin, me entusiasma el tema del RTOS, pero no he tenido tiempo para dedicarle.
considero que es una herramienta muy valiosa para desarrollar procesos multitarea, el compilador CCS que uso tiene uno propio puedes ver una muy buena info al respecto aqui.
considero que es una herramienta muy valiosa para desarrollar procesos multitarea, el compilador CCS que uso tiene uno propio puedes ver una muy buena info al respecto aqui.
jpic- Participante Activo
- Mensajes : 34
Fecha de inscripción : 15/12/2008
Localización : Colombia
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
Gracias por el link jpic, muy buena y extensa información la del amigo reinier.
Aunque yo no no uso CSS, el RTOS que trae se vé que tiene muchas posiblidades, pero para dominarlo hay que echarle horas... me había pasado un par de veces que intenté manejar el RTOS de SourceBoost, que al final lo dejaba para otro dia que tubiera más tiempo; pero hace unos días encontré un ejemplo de "multiproceso" muy sencillo y al fin entendí lo que hace basicamente un RTOS, y me dí cuenta que para hacer multiproceso básico no hace falta tener instalado ningún RTOS.
El ejemplo que puse en mi mensaje anterior se podría decir que es el RTOS más simple posible; no es más que establecer una base de tiempo, esto se consigue con un timer y las interrupciones. Solo hay que poner en la subrutina de interrupciones un contador para cada tarea y establecer en que valor del contador se ejecuta esa tarea.
Solo con esto ya se pueden conseguir muchas cosas, por ejemplo dos leds parpadeando simultaneamente a distintas velocidades; lo bueno de esto es que ahora le puedo añadir más tareas sin afectar a las que ya están, por ejemplo podría tranquilamente añadir otros 10 leds parpadeando cada uno a velocidades distintas, luego si quiero le puedo añadir otras tareas.
Por ejemplo el siguiente paso en mis experimentos ha sido añadir una tarea que es mandar una frase por UART, la cual veo por la misma terminal serie (gtkterm) que utilizo para grabar el programa (Bootloader/monitor de Jack-per) .
Pero la tarea de mandar una frase de 30 o 40 caracteres a 9600 baud. ocupa bastantes ms, entonces esto podría retrasarnos otras operaciones que tubieran que ejecutarse cada pocos ms; por ejemplo en una prueba que hice, ajusté el "tiempo base" a 200 us y puse el led2 para que parpadeara cada 1 ms (5 ciclos) y añadí la tarea de mandar una frase larga por uart cada 4 seg; el led2 se debería ver siempre encendido pero a mitad de potencia.. y así es, pero cada 4 seg se vé un parpadeo, que corresponde al momento en que la frase es enviada por uart; osea una tarea larga está afectando a una que se debe ejecutar muy rapidamente.
Entonces podríamos aprobechar nuestro "sistema multiproceso" y dividir esta tarea larga en otras sub-tareas, de manera que solo se use el tiempo de procesador estrictamente necesario, por ejemplo no quedarse esperando a que la linea esté libre, sino cargar el dato a mandar en una variable y añadir una subrutina en las interrupciones que compruebe en cada ciclo si la linea está libre y mande el dato, de esta manera el programa nunca se queda esperando.
Así se pueden añadir tareas largas que en realidad lo que hacen es pasarse la mayor parte del tiempo esperando, por ejemplo ADC, LCD y otras... La limitación (y una diferencia con un verdadero RTOS) es que dos tareas no pueden llamar al mismo recurso a no ser que lo tengamos muy planeado. Por ejemplo, en la tarea led1 añadí una linea para que mandara por uart el tiempo que había pasado desde la última interrupción, pero como las dos tareas coinciden en algunos momentos pues los mensajes quedaban cortados y se producían algunos efectos curiosos que todavía no entiendo, el caso es que las dos tareas estaban accediendo a la linea serie a la vez y se producía un conflicto y un mal funcionamiento.
Hay maneras de solucionar esto, pero por ahora nos quedamos con que solo una tarea manda cosas por uart...
Pues ahí va el mismo ejemplo de antes pero con la tarea "mandar_frase" añadida, ejecutándose a la vez que un led a 1ms sin afectar a este:
Aunque yo no no uso CSS, el RTOS que trae se vé que tiene muchas posiblidades, pero para dominarlo hay que echarle horas... me había pasado un par de veces que intenté manejar el RTOS de SourceBoost, que al final lo dejaba para otro dia que tubiera más tiempo; pero hace unos días encontré un ejemplo de "multiproceso" muy sencillo y al fin entendí lo que hace basicamente un RTOS, y me dí cuenta que para hacer multiproceso básico no hace falta tener instalado ningún RTOS.
El ejemplo que puse en mi mensaje anterior se podría decir que es el RTOS más simple posible; no es más que establecer una base de tiempo, esto se consigue con un timer y las interrupciones. Solo hay que poner en la subrutina de interrupciones un contador para cada tarea y establecer en que valor del contador se ejecuta esa tarea.
Solo con esto ya se pueden conseguir muchas cosas, por ejemplo dos leds parpadeando simultaneamente a distintas velocidades; lo bueno de esto es que ahora le puedo añadir más tareas sin afectar a las que ya están, por ejemplo podría tranquilamente añadir otros 10 leds parpadeando cada uno a velocidades distintas, luego si quiero le puedo añadir otras tareas.
Por ejemplo el siguiente paso en mis experimentos ha sido añadir una tarea que es mandar una frase por UART, la cual veo por la misma terminal serie (gtkterm) que utilizo para grabar el programa (Bootloader/monitor de Jack-per) .
Pero la tarea de mandar una frase de 30 o 40 caracteres a 9600 baud. ocupa bastantes ms, entonces esto podría retrasarnos otras operaciones que tubieran que ejecutarse cada pocos ms; por ejemplo en una prueba que hice, ajusté el "tiempo base" a 200 us y puse el led2 para que parpadeara cada 1 ms (5 ciclos) y añadí la tarea de mandar una frase larga por uart cada 4 seg; el led2 se debería ver siempre encendido pero a mitad de potencia.. y así es, pero cada 4 seg se vé un parpadeo, que corresponde al momento en que la frase es enviada por uart; osea una tarea larga está afectando a una que se debe ejecutar muy rapidamente.
Entonces podríamos aprobechar nuestro "sistema multiproceso" y dividir esta tarea larga en otras sub-tareas, de manera que solo se use el tiempo de procesador estrictamente necesario, por ejemplo no quedarse esperando a que la linea esté libre, sino cargar el dato a mandar en una variable y añadir una subrutina en las interrupciones que compruebe en cada ciclo si la linea está libre y mande el dato, de esta manera el programa nunca se queda esperando.
Así se pueden añadir tareas largas que en realidad lo que hacen es pasarse la mayor parte del tiempo esperando, por ejemplo ADC, LCD y otras... La limitación (y una diferencia con un verdadero RTOS) es que dos tareas no pueden llamar al mismo recurso a no ser que lo tengamos muy planeado. Por ejemplo, en la tarea led1 añadí una linea para que mandara por uart el tiempo que había pasado desde la última interrupción, pero como las dos tareas coinciden en algunos momentos pues los mensajes quedaban cortados y se producían algunos efectos curiosos que todavía no entiendo, el caso es que las dos tareas estaban accediendo a la linea serie a la vez y se producía un conflicto y un mal funcionamiento.
Hay maneras de solucionar esto, pero por ahora nos quedamos con que solo una tarea manda cosas por uart...
Pues ahí va el mismo ejemplo de antes pero con la tarea "mandar_frase" añadida, ejecutándose a la vez que un led a 1ms sin afectar a este:
- Código:
'_______________________________________________________________________
'
'
' Multitarea: Dos leds parpadeando a distinta velocidad
' y una frase enviada por UART
'
'_______________________________________________________________________
'------------------------- CONFIGURAR MICRO -----------------------------
'------------------------------------------------------------------------
#chip 16F876, 4 'modelo de pic y velocidad de reloj
#config HS_OSC, WDT_OFF, LVP_OFF, BODEN_OFF, PWRTE_ON
'--------------------------- DEFINICIONES -------------------------------
'------------------------------------------------------------------------
#define LED1 PORTB.0
#define LED2 PORTB.2
'#define baudrate 9600
'----------------------- CONFIGURAR VARIABLES ---------------------------
'------------------------------------------------------------------------
dim t_led1 as word 'tiempo de parpadeo led1
dim c_led1 as word 'contador led1
f_led1 = 0 'flag led1
dim t_led2 as word 'tiempo de parpadeo led2
dim c_led2 as word 'contador led2
f_led2 = 0 'flag led2
dim t_frase as word 'tiempo de enviar frase
dim c_frase as word 'contador enviar frase
f_frase = 0 'flag enviar frase
'------------------------- CONFIGURAR PUERTOS ---------------------------
'------------------------------------------------------------------------
TRISA = b'000001'
TRISB = b'00000000'
TRISC = b'10000000'
PORTA = b'000000'
PORTB = b'00000000'
PORTC = b'10000000'
'----------------------------- PRINCIPAL --------------------------------
'------------------------------------------------------------------------
dim mensaje(35)
mensaje$ = "esto es una prueba de multitarea"
'InitUSART 'No es necesaria si se usa el Bootloader, usart ya está funcionando
InitTimer0 Osc, PS0_1/2 'Timer0 configurado para 200 us con Fosc=4MHz
TMR0 = 155
set INTCON.T0IE on 'Interrupciones Timer0 habilitadas
t_led1 = 10000 'Tiempo de tarea led1
t_led2 = 5 'Tiempo de tarea led2
t_frase = 20000 'Tiempo de tarea mandar frase
do 'Bucle principal: se comprueban los flags
if f_led1.0 on then call tarea_led1
if f_led2.0 on then call tarea_led2
if f_frase.0 on then call manda_frase mensaje
if f_dato.0 on then call manda_dato
loop
'--------------------------- INTERRUPCIONES -----------------------------
'------------------------------------------------------------------------
Sub interrupt
if INTCON.T0IF on then 'si la interrupcion es de timer0
TMR0 = 155 'necesitamos una cuenta de 100: 155 a 255
c_led1 += 1 'incrementar contador de tarea
if c_led1 > t_led1 then 'si ha pasado el tiempo establecido
c_led1 = 0 'borrar contador
f_led1 = 1 'subir flag de tarea
End if
c_led2 += 1
if c_led2 > t_led2 then
c_led2 = 0
f_led2 = 1
End if
c_frase += 1
if c_frase > t_frase then
c_frase = 0
f_frase = 1
End if
End if
if transmite.0 on then 'transmite un dato por UART si su bandera está activada
if PIR1.TXIF on then 'comprueba linea libre, sinó sale
TXREG = dato
transmite = 0
End if
End if
INTCON.T0IF = 0 'borrar flag Timer0
End Sub
'------------------------ SUBRUTINAS DE TAREAS --------------------------
'------------------------------------------------------------------------
Sub tarea_led1
f_led1 = 0
if LED1 on then
LED1 = 0
exit Sub
End if
LED1 = 1
End Sub
Sub tarea_led2
f_led2 = 0
if LED2 on then
LED2 = 0
exit Sub
End if
LED2 = 1
End Sub
Sub manda_frase (In frase$)
largo = frase(0)
if largo = 0 Then exit Sub
f_dato = 1 'sube flag de tarea manda_dato
caracter = 1
f_frase = 0 'Borra flag de manda_frase
End Sub
Sub manda_dato
if transmite.0 on then exit Sub 'si todavía no ha mandado la letra anterior
if caracter > largo then 'si yá mandó todas las letras
dato = 0x0A 'Retorno de carro
transmite = 1
f_dato = 0 'Borra flag de manda_dato
exit Sub
End if
dato = frase(caracter)
transmite = 1
caracter += 1
End Sub
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
Esta manera de trabajar mediante "banderas" es algo similar a la manera de trabajar de las interrupciones del microcontrolador .
Solo he hecho un par de cosas similares en un HC08 de Freescale, ahora mismo me encuentro planeando cómo implementarlo en la aplicación de mi proyecto, aunque no es lo más urgente .
Gracias por la información .
Solo he hecho un par de cosas similares en un HC08 de Freescale, ahora mismo me encuentro planeando cómo implementarlo en la aplicación de mi proyecto, aunque no es lo más urgente .
Gracias por la información .
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
Si... va todo por banderas, y es lo más complicado, sobre todo cuando tienes varios procesos con sub-procesos que se pueden estar ejecutando a la vez. Las banderas son las que organizan la ejecución de cada tarea y pueden llegar a ser un dolor de cabeza, pero esta manera de programar permite conseguir cosas que es imposible conseguir usando programacion "secuencial", donde cada tarea se ejecuta solo cuando la anterior ha terminado.
Ahora estoy añadiendo unas lecturas ADC, que es otro caso que tiene cierta complicación, porque para leer cada canal hacen falta varios sub-procesos simples: abrir canal, iniciar conversión y leer valor; hay que ir subiendo y bajando banderas según se va realizando cada proceso para que en el siguiente ciclo se sepa donde tiene que seguir... al menos yo lo estoy haciendo así:
if bandera_tarea1 on then
...........if bandera sub_tarea1_1 then
.....................call sub_tarea1_1
.....................goto salir_tarea_1
...........if bandera sub_tarea1_2 then
.....................call sub_tarea1_2
.....................goto salir_tarea_1
...........if bandera sub_tarea1_3 then
.....................call sub_tarea1_3
salir_tarea_1:
De todas formas lo de las banderas es la manera de activar o desactivar tareas en cada ciclo, pero detrás de todo eso tiene que haber una base de tiempo que determine cuando se hace cada cosa, esa es la clave de esta manera de programar: timer + interrupciones para crear una base de tiempo...
Ya nos contarás algo de tus proyectos... no?
Saludos.
Ahora estoy añadiendo unas lecturas ADC, que es otro caso que tiene cierta complicación, porque para leer cada canal hacen falta varios sub-procesos simples: abrir canal, iniciar conversión y leer valor; hay que ir subiendo y bajando banderas según se va realizando cada proceso para que en el siguiente ciclo se sepa donde tiene que seguir... al menos yo lo estoy haciendo así:
if bandera_tarea1 on then
...........if bandera sub_tarea1_1 then
.....................call sub_tarea1_1
.....................goto salir_tarea_1
...........if bandera sub_tarea1_2 then
.....................call sub_tarea1_2
.....................goto salir_tarea_1
...........if bandera sub_tarea1_3 then
.....................call sub_tarea1_3
salir_tarea_1:
De todas formas lo de las banderas es la manera de activar o desactivar tareas en cada ciclo, pero detrás de todo eso tiene que haber una base de tiempo que determine cuando se hace cada cosa, esa es la clave de esta manera de programar: timer + interrupciones para crear una base de tiempo...
Ya nos contarás algo de tus proyectos... no?
Saludos.
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
Pues está interesante esta manera de programar, se gana mucho en flexiblidad; cuesta un poco más poner en marcha el sistema, pero una vez que lo tienes puedes jugar con el tiempo base y las frecuencias de ejecución de cada tarea.
Se puede uno complicar más o menos... por ejemplo lo de dividir las lecturas ADC al final he visto que no vale la pena, ya que todo el proceso se hace muy rápido, sin embargo las transmisiones por UART son muy lentas y se gana un montón haciéndolas por multitarea.
Por ejemplo en las últimas pruebas que hice se leen 3 canales ADC 1000 veces por segundo y se envían los datos por uart a liberlab cada 20 ms, esto con programación "secuencial" sería imposible, ya que cada transmisión de una cadena de datos tarda casi 20 ms, sería imposible hacer esto y a la vez leer 3 canales ADC 1000 veces por segundo.
Liberlab está siendo una herramienta muy util, está pensada para representar datos de ADC, pero en realidad representa cualquier valor que reciba, sean los que sean; así que lo estoy usando para mandarle los tiempos que tardan las tareas en realizarse, de esta forma veo graficamente como está funcionando la cosa.
Como ejemplo aquí podemos ver como con una base de tiempo suficientemente larga todo funciona bien:
Y aquí con una base de tiempo muy corta la cosa cambia, de hecho el pic se "cuelga" de vez en cuando... puede estar funcionando un par de minutos o 30 segundos, pero al final se suele quedar bloqueado... no sé muy bién porqué, pero deja de funcionar:
El proceso azul es la transmisión de datos por uart y el verde la lectura adc, aunque están en escalas distintas, el de uart está medido en ciclos de contador, ya que es mucho más largo y el adc está medido en ciclos del timer, ya que tarda menos de 1 ciclo de contador. la linea blanca es un canal adc conectado a un potenciómetro para comprobar que el adc funciona.
Así puedo experimentar con distintos valores de tiempo base y frecuencias de tareas, así como desfasando las tareas o programando de otra manera y puedo ver graficamente la estabilidad del sistema.
Estaba pensando que incluso podría poner una especie de monitor de "carga" del procesador: si pongo un contador que se incremente cada vez que se realiza una tarea o algo así y con algun cálculo podría ver cual es la carga real del procesador.
Veo que el liberlab tiene la opción de aplicar funciones matemáticas a los valores de entrada... pero todavía no se como vá esto...
Saludos.
Se puede uno complicar más o menos... por ejemplo lo de dividir las lecturas ADC al final he visto que no vale la pena, ya que todo el proceso se hace muy rápido, sin embargo las transmisiones por UART son muy lentas y se gana un montón haciéndolas por multitarea.
Por ejemplo en las últimas pruebas que hice se leen 3 canales ADC 1000 veces por segundo y se envían los datos por uart a liberlab cada 20 ms, esto con programación "secuencial" sería imposible, ya que cada transmisión de una cadena de datos tarda casi 20 ms, sería imposible hacer esto y a la vez leer 3 canales ADC 1000 veces por segundo.
Liberlab está siendo una herramienta muy util, está pensada para representar datos de ADC, pero en realidad representa cualquier valor que reciba, sean los que sean; así que lo estoy usando para mandarle los tiempos que tardan las tareas en realizarse, de esta forma veo graficamente como está funcionando la cosa.
Como ejemplo aquí podemos ver como con una base de tiempo suficientemente larga todo funciona bien:
Y aquí con una base de tiempo muy corta la cosa cambia, de hecho el pic se "cuelga" de vez en cuando... puede estar funcionando un par de minutos o 30 segundos, pero al final se suele quedar bloqueado... no sé muy bién porqué, pero deja de funcionar:
El proceso azul es la transmisión de datos por uart y el verde la lectura adc, aunque están en escalas distintas, el de uart está medido en ciclos de contador, ya que es mucho más largo y el adc está medido en ciclos del timer, ya que tarda menos de 1 ciclo de contador. la linea blanca es un canal adc conectado a un potenciómetro para comprobar que el adc funciona.
Así puedo experimentar con distintos valores de tiempo base y frecuencias de tareas, así como desfasando las tareas o programando de otra manera y puedo ver graficamente la estabilidad del sistema.
Estaba pensando que incluso podría poner una especie de monitor de "carga" del procesador: si pongo un contador que se incremente cada vez que se realiza una tarea o algo así y con algun cálculo podría ver cual es la carga real del procesador.
Veo que el liberlab tiene la opción de aplicar funciones matemáticas a los valores de entrada... pero todavía no se como vá esto...
Saludos.
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
Buenas Pikitin, la verdad muy buena tu explicación de sistema multitarea, sencillo y fácil de entender, como lo comente en mi presentación que hice hace varios minutos....jeje. Todavía no empiezo a programar en forma PIC en Linux pero hoy empiezo....jejeje.
Espero presentar algo pronto, a ver si este fin de semana puedo publicar algo sencillo.
Solo como comentario adicional al los sistemas multitareas en la mayoria de los microntroladores si no es que en todos cuentan con interrupciones para ciertas tareas específicas como lo son: UARTs, ADC, output compare (para hacer PWM), input compare (para medir frecuencia en señales) por mencionar algunas, dependiendo del microcontrolador utilizado tendra más o menos interrupciones de hardware, por lo que se pueden utilizar y asi eliminar unas cuantas banderas, el problema de esto es que nuestro código estará limitado o amarrado a ese procesador específico.
bueno luego sigo comentado mas....ya me tengo que ir....jejeje
atte.
ciccero
Espero presentar algo pronto, a ver si este fin de semana puedo publicar algo sencillo.
Solo como comentario adicional al los sistemas multitareas en la mayoria de los microntroladores si no es que en todos cuentan con interrupciones para ciertas tareas específicas como lo son: UARTs, ADC, output compare (para hacer PWM), input compare (para medir frecuencia en señales) por mencionar algunas, dependiendo del microcontrolador utilizado tendra más o menos interrupciones de hardware, por lo que se pueden utilizar y asi eliminar unas cuantas banderas, el problema de esto es que nuestro código estará limitado o amarrado a ese procesador específico.
bueno luego sigo comentado mas....ya me tengo que ir....jejeje
atte.
ciccero
ciccero- Participante
- Mensajes : 11
Fecha de inscripción : 10/07/2009
Re: RTOS, multitarea, o como aprobechar el tiempo de proceso.
Si... bueno, empecé el tema con el título "Rtos... etc", pero en realidad de lo que hablo no es un verdadero rtos, "multitarea" quizás sea mas conveniente, aunque la verdad no sé cual sería la terminología correcta. Quizás: programar con bases de tiempo...
Si, el hardware del micro ya es en sí un sistema de multitarea pero por hardware, pero esta manera de programar se puede aplicar sobre todo para que ciertos procesos no utilicen tiempo de procesador si no es necesario, por ejemplo delays y ese tipo de cosas; y para ejecutar cada tarea solo con la frecuencia que es necesaria, a veces no hace falta estar repitiendo un proceso continuamente sino ejecutarlo cada x milisegundos o incluso cada x segundos. Aunque la verdad es que ahora casi todo lo hago de esta manera, ya que es muy sencillo añadir o quitar "tareas" sin que esto afecte a las demás, cambiar la frecuencia de ejecución, etc.
Pero al final es un lío de banderas, contadores, etc ; así que me hice una librería que simplifica mucho la cosa.
Ultimamente estoy programando casi todo en GcBasic, así que hice la librería para este compilador:
https://pic-linux.forosactivos.net/gcbasic-f26/librerya-para-multitarea-en-gcbasic-t132.htm
Pues nada, ánimo con tus proyectos, ya nos contarás.
Saludos.
Si, el hardware del micro ya es en sí un sistema de multitarea pero por hardware, pero esta manera de programar se puede aplicar sobre todo para que ciertos procesos no utilicen tiempo de procesador si no es necesario, por ejemplo delays y ese tipo de cosas; y para ejecutar cada tarea solo con la frecuencia que es necesaria, a veces no hace falta estar repitiendo un proceso continuamente sino ejecutarlo cada x milisegundos o incluso cada x segundos. Aunque la verdad es que ahora casi todo lo hago de esta manera, ya que es muy sencillo añadir o quitar "tareas" sin que esto afecte a las demás, cambiar la frecuencia de ejecución, etc.
Pero al final es un lío de banderas, contadores, etc ; así que me hice una librería que simplifica mucho la cosa.
Ultimamente estoy programando casi todo en GcBasic, así que hice la librería para este compilador:
https://pic-linux.forosactivos.net/gcbasic-f26/librerya-para-multitarea-en-gcbasic-t132.htm
Pues nada, ánimo con tus proyectos, ya nos contarás.
Saludos.
Temas similares
» AYUDA CON RTOS
» Librería para multitarea en GCBasic.
» sdcc fallo en el linker
» Como Subo un Archivo al Foro
» AYUDA PARA SOLUCIONAR ERROR
» Librería para multitarea en GCBasic.
» sdcc fallo en el linker
» Como Subo un Archivo al Foro
» AYUDA PARA SOLUCIONAR ERROR
Página 1 de 1.
Permisos de este foro:
No puedes responder a temas en este foro.