Ontem no laboratório o Leonardo levantou uma questão muito comum quando se utiliza microcontroladores.

Como controlar entradas e saídas ao mesmo tempo usando um microcontrolador sem usar nenhum kernel de multitarefa ?

Um exemplo comum é como piscar 2 leds (um a cada 500 ms e outro a cada 100 ms)
e ao mesmo tempo ficar verificando um botão, que não deve fazer nada quando pressionado, mas quando for solto deve acender um terceiro led por 3 segundos.

Para resolver esse tipo de problema eu costumo usar timers, para simular um ambiente multitarefa.

Cada timer possui o horário que ele foi iniciado (usando data e hora, ou milisegundos após o start da aplicação) e de quanto em quanto tempo ele deve ser resetado.

O timer é verificado de tempos em tempos pela aplicação, e quando existe o estouro do tempo a aplicação chama a função correspondente (task), e reinicia o timer.

Dentro de cada tarefa não se pode utilizar nada que trave o processamento, delays grandes, ou chamada de funções que fiquem aguardando por alguma coisa, caso isso aconteça o sistema multitarefa não vai funcionar corretamente.

Vamos ao código !!!!!

Eu não coloquei todo o código para não ficar muito extenso, os acessos a hardware e as configurações de portas não foram feitas, esse código apenas DEMONSTRA como utilizar timers para simular multitarefa.

O código está voltado para a plataforma ARDUINO.

/*********************************************************
DEFINIÇÔES E FUNÇÔES DE TIMER
*********************************************************/
//Definição da estrutura Timer
typedef struct Timer
{
    unsigned long start;//Armazena o tempo de quando foi iniciado o timer
    unsigned long timeout;//Tempo após o start para o estouro
};

unsigned long Now ( void )
{
    return millis ( );//Retorna os milisegundos depois do reset
}

char TimerExpired ( struct Timer * timer )
{
    //Verifica se o timer estourou
    if ( Now () > timer->start + timer->timeout )
        return true;

    return false;    
}

void TimerStart ( struct Timer * timer )
{
    timer->start = Now ( );//Reseta o timer gravando o horário atual
}

//Definições dos timers utilizados na aplicação
Timer timerLed1 = { 0, 500 }; //Pisca o led1 a cada 500 ms
Timer timerLed2 = { 0, 100 }; //Pisca o led2 a cada 100 ms
Timer timerBotao = { 0, 10 }; //Verifica se o botão foi solto a cada 10 ms
Timer timerLed3 = { 0, 3000 }; //Para temporizar o led 3 por 3000 ms

/*********************************************************
FUNÇÕES DO ARDUINO - LOOP
*********************************************************/
void loop (void)
{
    //Verifica se algum timer estourou - caso positivo chama a função relacionada  
    if ( TimerExpired ( & timerLed1 ) )
    {
        taskLed1 ( );
        TimerStart ( & timerLed1 );
    }

    if ( TimerExpired ( & timerLed2 ) )
    {
        taskLed2 ( );
        TimerStart ( & timerLed2 );
    }

    if ( TimerExpired ( & timerBotao ) )
    {
        taskBotao ( );         
        TimerStart ( & timerBotao );
    }
}

/*********************************************************
                    TASKS  
*********************************************************/
void taskLed1 ( void )
{
    //Liga ou desliga o led1 (não coloquei o código para não ficar extenso!!!)
}

void taskLed2 ( void )
{
    //Liga ou desliga o led2 (não coloquei o código para não ficar extenso!!!)
}

//Indica que o led 3 está ligado
bool led3Aceso = false;

void taskSerial ( void )
{
    //Verifica quando o botão foi solto - (não coloquei o código para não ficar extenso!!!)
    if ( BotaoSolto () )
    {
        //Acende o led3 - (não coloquei o código para não ficar extenso!!!)
        
        //Inicia o timer do led 3, quando o timer estourar o led deve ser apagado !
        TimerStart ( & timerLed3 );
    }
    
    //Caso o led esteja aceso e o timer estourar, o led deverá ser apagado.
    if ( TimerExpired ( & timerLed3 ) && led3Aceso )
    {
        //Apaga o led 3 - (não coloquei o código para não ficar extenso!!!)
        led3Aceso = false;
    }
}

Exibições: 5847

Responder esta

Respostas a este tópico

Seria possivel fazer o upload do codigo atraves de que maneira?
talvez ponteiros e matrizes,elas poderiam dar mais quantidade de codigo em um espaço de memoria reduzida?
eu poderia fazer uma magica para fazer experimentalmente no arduino?
como o codigo seria passado aos microcontroladores,atraves de um dispositivo de rede/internet isso poderia ser possivel?
eu poderia simultaneamente fazer o codigo dentro da memoria ser inicialmente executavel,assim que este chegasse a um limite ele passaria a importar o resultado de um sensor e apos a verificaçao de alguns parametros fazer o upload de um codigo externo que viria da internet por exemplo?
voçe acha que da para fazer um prototipo disso no arduino?
Muito obrigado e me desculpe qualquer erro e ignorancia
;)




Bruno disse:

Guilherme

Existem os chamados CLPs (controladores lógicos programáveis), são microcontroladores programados especificamente para receber um código que deve ser executado.

 

Existem linguagens que são utilizadas para programar um CLP, normalmente na indústria se usa LADDER, mas existem alguns que aceitam C entre outras linguagens.

 

Abraços

 

Guilherme disse:

existe a possibilidade de fazer uma espécie de upload de um código para microcontroladores?

algo como as multitarefas...

como receber este codigo e operar conforme por exemplo os resultados obtidos de um sensor?

Valeu

Guilherme

 

O código (ou comandos) podem ser enviados usando qualquer tipo de meio de comunicação, desde que as duas pontas (PC e microcontrolador) estejam preparados para isso.

 

Aumentar a quantidade de código em memória reduzida é o que geralmente gerentes gostam que o programador faça... rs.... mas é MUITO mais complexo do que parece, é possível otimizar código, fazer compactação, entre outras coisas, mas só se consegue um efeito bom levando em consideração o tipo de informação que vai ser enviada,  se você definir um projeto ai sim será possível verificar se existe otimização para ele ou não (vai depender de MUITASSSSS variáveis) ...

 

Mágica também é o que os gerentes querem que os engenheiros façam,,,,, mas na área de exatas não trabalhamos com mágica AINDA ... hehehehehe .... defina o que é mágica....

 

Não entendi o seu exemplo... poderia explicar melhor ?

 

 

seuahsuahsuahsuahushausa
Entao,na verdade a comunicaçao teria de ser feita entre o microcontrolador um sensor e uma especie de dispositivo que importe os codigos de um local na rede/internet este dispositivo conectado entre o dispositivo central e o dispositivo de rede deveria importar e exportar dados,assim quando uma solicitaçao fosse feita ele enviaria o codigo necessario programada para a funçao ser executada...
Entao a comunicaçao deve ser simultanea e exclusivamente entre os tres dispositivos, o micro o sensor e o importador de codigos que esta conectada a internet, os codigos serao salvos ali de forma que quando necessario eles seriam importados para o microcontrolador gerando assim um loop....
uhdsuihdishdishduishudis
A magica seria se possivel fzer um prototipo disto num arduino...
shuashaishauihsuahisuha
Valeu Bruno! de

Bruno disse:

Guilherme

 

O código (ou comandos) podem ser enviados usando qualquer tipo de meio de comunicação, desde que as duas pontas (PC e microcontrolador) estejam preparados para isso.

 

Aumentar a quantidade de código em memória reduzida é o que geralmente gerentes gostam que o programador faça... rs.... mas é MUITO mais complexo do que parece, é possível otimizar código, fazer compactação, entre outras coisas, mas só se consegue um efeito bom levando em consideração o tipo de informação que vai ser enviada,  se você definir um projeto ai sim será possível verificar se existe otimização para ele ou não (vai depender de MUITASSSSS variáveis) ...

 

Mágica também é o que os gerentes querem que os engenheiros façam,,,,, mas na área de exatas não trabalhamos com mágica AINDA ... hehehehehe .... defina o que é mágica....

 

Não entendi o seu exemplo... poderia explicar melhor ?

 

 

Olá! Alguém já usou esse Kernel?

"ELECTRON KERNEL: ARDUINO MULTI-SKETCH FRAMEWORK"

http://www.eletronlivre.com.br/kernel/learning.jsf

 

 

Bruno sua rotina é muito boa.

Irei fazer testes para serem usadas no Projeto:

http://labdegaragem.com/forum/topics/projeto-alarme-sem-fio-arduino...

Se for usar sua rotina, colocarei o seu nome como colaborador, ok?

Interessante! Vou testar isso, estava precisando de algo assim.... 

Obrigado por compartilhar Bruno!

Bração! 

Uma maneira que eu costumo usar é tipo uma máquina de estado, através de switch case, no caso de funções sincronizadas e dependentes da anterior, ex.:

uchar index_fcn;  // Variavel indexadora da função.

void fcn1(void);

void fcn2(void);

void fcn3(void);

void loop();

    {

           switch(index_fcn)

                {

                      case 0: fcn1();

                                  index_fcn++;

                                  break;

                      case 1: fcn2();

                                  index_fcn++;

                                  break;

                      case 3: fcn3());

                                  index_fcn = 0;

                                  break;

              }

}

A variavel indexadora "index_fcn" ela pode ser sequencial e atemporal, poder temporal aonde uma interrupção do timer

ficaria incrementando ela, pode ser também deterministica, neste caso cada função após o termino aponta para

outra chamada de função que necessáriamente não precisa ser uma sequência.

O objetivo é evitar loops, pois estes podem atrapalhar o seu programa.

boa essa dica

Opa,

Sugiro que dêem uma olhada no video abaixo.

https://www.youtube.com/watch?v=oeP_NiajWME

Abs

Depois de muito tempo, achei mais um exemplo deste código rsrs

http://hwhacks.com/2016/05/08/scheduling-arduino-code-run-every-x-s...

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço