Pedido de Ajuda sobre organização e programação no Arduino

Boa tarde Senhores

Sou iniciante em programação e ainda não compreendo com clareza a estrutura e sintaxe da linguagem estou naquele inicio de capturar conhecimento das bases básicas da programação . . . ,

e geralmente compilo os programas básicos para testes

da própria Ide em uma única pagina na Ide do Arduino . . .

sendo que por mais que inclua comentários as vezes o programa ficando grande

fico naquele desce e sobe na pagina...

para reverificar possíveis alterações, melhorias e correção nos códigos que posso fazer . . .

foi então que decidi pesquisar sobre a opção Tab na ide do Arduino

mas encontrei pouca informação a respeito ( talvez esteja procurando errado ...)

e o que encontrei  foi um exemplo usando o blink mantendo na pagina inicial as variáveis globais e a função setup() e jogando em uma nova Tab a função loop e assim dividindo o programa em duas partes . . .

minhas duvidas são:

Vale a pena usar Tabs ?

quais são os:

pontos positivos e

negativos

em se fazer um programa com esta opção usando as Tabs

é possível dividir meus programas em diversas tabs como por exemplo:

| principal | sensores | motores | calculos | dados |

vale a pena em pensar neste tipo de organização ?

Desde já agradeço a sua ajuda.

Exibições: 4299

Responder esta

Respostas a este tópico

Acho que isso vai da organização de cada um.

Um fonte meu, que seria imenso, fiz dessa forma. Dividi em tabs e ficou bem organizado. Mas não me acostumei a usar essas tabs no arduino.

Mas, funciona!

Abraços!

Também sou aprendiz de Sketch.

Tento formatar o maximo durante a edição do programa, para ficar mais fácil a compreensão

Veja essa dica para formatar a edição:

http://labdegaragem.com/forum/topics/sublimetext-como-ide-para-arduino

Organizacao sempre eh bom, principalmente quando existe a possibilidade que o projeto aumente.

Vantagens? Organizacao. Desvantagens? Desorganizacao se nao for organizado  { (O.o) WHAT?! }

Cabe ao programador manter tudo em ordem, se voce eh desorganizado, nao vai ser dividir em arquivos que vai te salvar.

Pessoalmente, gosto bastante de dividir em arquivos, facilita identificar erros (mistureba de codigos confunde), realizar testes isolados para cada "modulo", reutilizar codigo, duas pessoas trabalhem cada uma em um arquivo (extremamente importante em projetos colaborativos).

No comeco eh meio dificil/estranho, mas depois que pega o jeito fica facil.

Não sei o que são essas tabs que vc se refere, mas falando como programador, não consigo imaginar um programa com mais de 200 linhas em um arquivo só, isso é pedir por problemas, fica tudo misturado, especialmente se vc usa variáveis globais, acaba interferindo no código, fica difícil de achar os erros e isso é ainda mais crítico em um ambiente onde os recursos de debug são bem precários como é o caso dos microcontroladores em geral.

Não tem pontos negativos em dividir o programa em módulos, a partir de certo tamanho isso é uma necessidade, não uma opção. Tente fazer com que os módulos sejam bem independentes entre si, isso evita que os erros se propaguem de um módulo pra outro.

Francesco, como dividir um Sketch em módulos?

Eu não sei fazer isso. Poderia explicar?

Ou você queria  dizer dividir em rotinas? 

Obrigado.

Olá Jose,

Eu quis dizer módulos mesmo, conforme a linguagem isso significa algo ligeiramente diferente. No caso do arduíno a linguagem é C/C++, pelo menos a versão que eu uso. Cada módulo seria então um arquivo .cpp (ou .c) com o seu header correspondente .h. Esses arquivos podem ser incluídos no programa principal usando o comando #include. Tem duas maneiras de fazer isso: colocando esses arquivos na pasta libraries da instalação do arduino, isso é bom quando vc quer que várias aplicações compartilhem esses arquivos. Nesse caso vc usa o comando include com o arquivo header entre < >. A outra maneira é deixar esses arquivos na mesma pasta da aplicação. Aí vc usa o include com aspas duplas. Depois vou pegar um exemplo do arduino e posto aqui pra vcs.

Ah ok ! Eu já conhecia esse arquivos CPP e H . Não sabia que se chamavam módulos.

Mas sinceramente não gosto. Acho um saco ter que ficar abrindo vários arquivos para entender o programa. 

Aprendi programação estruturada com Turbo Pascal, a vinte anos atrás.

E tenho feito os meus programas Sketch usando rotinas ( similares a Procedures em Turbo Pascal) 

No momento tenho estudado Programação orientada a objeto. Mas ainda não entendi direito.

Preciso estudar mais.

Estou vendo que o tópico esta rendendo bons conhecimentos.

Muito obrigado !

Aqui está um exemplo de como uma aplicação pode evoluir quando começa a ficar maiorzinha.

O programa abaixo é uma adaptação do programa de exemplo AnalogInOutSerial e faz o seguinte: tem dois pinos de gatilho, para entrada e para saída e tem dois pinos analógicos, um para entrada e outro para saída.

Quando o gatilho de entrada muda de estado é feita uma leitura no pino de entrada e o valor lido é armazenado em um buffer circular (é acrescentado no final do buffer). Esse buffer tem 100 posições, então o programa consegue armazenar até 100 valores.

Quando o pino associado ao gatilho de saída muda de estado, o primeiro valor no buffer é retirado e enviado ao pino de saída.

É só um programa de exemplo, não cheguei a fazer um circuito pra testar, mas compilou certinho aqui.

Abaixo o que seria a primeira versão deste programa usando um único arquivo:

+-----------------------------------------------------------------------------------+

// Implementa um buffer circular de inteiros

// Capacidade do buffer
#define bufSize 100

// buffer
int buf[bufSize];

// variáveis de controle do buffer
int first   =0; // primeiro na lista
int nextFree=0; // próxima posição livre
int items   =0; // quantidade atual de items na lista

///////////////////////////////////////////////////////////
// Adiciona um item no buffer
//
boolean addItem(int item)
{
  // Verifica se tem espaço disponível no buffer
  if(items >= bufSize)
    return false;
    
  // Agora adiciona o item
  buf[nextFree]= item;
  nextFree= (nextFree+1)%bufSize;
  items++;
  return true;
}

///////////////////////////////////////////////////////////
// Retira um item do buffer
//
int getItem()
{  int item=0;

  // Verifica se tem algum item para retirar
  if(items > 0){
    // Agora retira o item
    item = buf[first];
    first= (first+1)%bufSize;
    items--;
  }
  return item;
}

///////////////////////////////////////////////////////////
// informa se existe algum item esperando no buffer
//
boolean itemWaiting()
{
  return items > 0;
}

///////////////////////////////////////////////////////////
// informa a quantidade de posições livres no buffer
//
int freePos()
{
  return bufSize - items;
}

//////////////////////////////////////////////////////////////
// Código abaixo baseado no programa exemplo AnalogInOutSerial

// These constants won't change.  They're used to give names
// to the pins used:
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

// gatilhos de entrada e saída
const int triggInPin  = 7; // dispara entrada quando muda de estado
const int triggOutPin = 8; // dispara saída quando muda de estado

// controle dos gatilhos
boolean lastIn, lastOut;

int outputValue = 0;        // value output to the PWM (analog out)

void setup() {
  // comunicação serial retirada do código

  // inicializa controle dos gatilhos
  pinMode(triggInPin, INPUT);      
  pinMode(triggOutPin, INPUT);
  lastIn= digitalRead(triggInPin);
  lastOut= digitalRead(triggOutPin);
}

void loop() {

  if(digitalRead(triggInPin) != lastIn) // dispara entrada
  {
    // lê e armazena o valor lido no buffer
    addItem(analogRead(analogInPin));
    lastIn= digitalRead(triggInPin);
    // wait 2 milliseconds before the next loop
    // for the analog-to-digital converter to settle
    // after the last reading:
    delay(2);                     
  }
 
  if(digitalRead(triggOutPin) != lastOut) // dispara saída
  {
    // remove um item do buffer e mapeia para pwm
    outputValue = map(getItem(), 0, 1023, 0, 255);  
    // change the analog out value:
    analogWrite(analogOutPin, outputValue);           
    lastOut= digitalRead(triggOutPin);
  }
 
}// loop

+-----------------------------------------------------------------------------------+

Apesar de pequeno, o programa acima tem alguns problemas. Ele define uma estrutura que precisa ser controlada. As variáveis de controle dessa estrutura estão globais e acessíveis pelo resto do programa. Isso é péssimo. Esse é um programa pequeno, tem apenas uma estrutura sendo controlada, mesmo assim já declara 3 variáveis de controle além da própria estrutura. Imaginem um programa bem maior, com várias estruturas sendo controladas, a profusão de variáveis de controle que esse programa teria, todas elas globais e acessíveis pelo programa inteiro. Um erro de atribuição em alguma dessas variáveis provocaria erros que poderiam afetar qualquer parte do código, mesmo as partes não relacionadas com a estrutura controlada pela variável. Como resolver isso? Modularizando. No próximo post a versão modular deste programa.

Nesta versão do programa, o buffer e todas as funções e variáveis de controle dele foram movidos pra outro arquivo e foi criado o arquivo header correspondente. O programa principal continua podendo acessar as funções de controle para usar o buffer, mas o buffer propriamente dito e as variáveis de controle dele agora estão escondidos do programa principal e só são visíveis dentro do arquivo que implementa o buffer.

Isso torna o programa mais estável, menos sujeito a erros e quando eles ocorrem, é muito mais fácil descobrir onde estão. Os erros em um módulo ficam limitados a esse módulo, não se propagam pelo resto do programa.

Só uma correção, em outro post eu disse que poderiam ser usados arquivos .c mas aparentemente o arduino só aceita arquivos .cpp.

Arquivo header. Deve ser colocado na mesma pasta que a aplicação (programa principal).

+--------------------- CircBuf.h -------------------------------------------------+

// Implementa um buffer circular de inteiros
//
#ifndef CircBuf_h
#define CircBuf_h

#include<arduino.h>

// Capacidade do buffer
#define bufSize 100

boolean addItem(int item); // Adiciona um item no buffer
int getItem();                      // Retira um item do buffer
boolean itemWaiting();      // informa se existe algum item esperando no buffer
int freePos();                     // informa a quantidade de posições livres no buffer

#endif

+-----------------------------------------------------------------------------------+

Aqui o arquivo com a implementação do buffer. Também deve ficar na pasta da aplicação.

+--------------------- CircBuf.cpp ------------------------------------------------+

// Implementa um buffer circular de inteiros
#include "CircBuf.h"

// buffer
int buf[bufSize];

// variáveis de controle do buffer
int first   =0;      // primeiro na lista
int nextFree=0; // próxima posição livre
int items   =0;   // quantidade atual de items na lista

///////////////////////////////////////////////////////////
// Adiciona um item no buffer
//
boolean addItem(int item)
{
  // Verifica se tem espaço disponível no buffer
  if(items >= bufSize)
    return false;
    
  // Agora adiciona o item
  buf[nextFree]= item;
  nextFree= (nextFree+1)%bufSize;
  items++;
  return true;
}

///////////////////////////////////////////////////////////
// Retira um item do buffer
//
int getItem()
{  int item=0;

  // Verifica se tem algum item para retirar
  if(items > 0){
    // Agora retira o item
    item = buf[first];
    first= (first+1)%bufSize;
    items--;
  }
  return item;
}

///////////////////////////////////////////////////////////
// informa se existe algum item esperando no buffer
//
boolean itemWaiting()
{
  return items > 0;
}

///////////////////////////////////////////////////////////
// informa a quantidade de posições livres no buffer
//
int freePos()
{
  return bufSize - items;
}

+-----------------------------------------------------------------------------------+

E finalmente o programa principal. Veja que acrescenta um comando #include na primeira linha para o arquivo de header acima.

+-----------------------------------------------------------------------------------+

#include "CircBuf.h"

//////////////////////////////////////////////////////////////
// Código abaixo baseado no programa exemplo AnalogInOutSerial

// These constants won't change.  They're used to give names
// to the pins used:
const int analogInPin = A0;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

// gatilhos de entrada e saída
const int triggInPin  = 7; // dispara entrada quando muda de estado
const int triggOutPin = 8; // dispara saída quando muda de estado

// controle dos gatilhos
boolean lastIn, lastOut;

int outputValue = 0;        // value output to the PWM (analog out)

void setup() {
  // comunicação serial retirada do código

  // inicializa controle dos gatilhos
  pinMode(triggInPin, INPUT);      
  pinMode(triggOutPin, INPUT);
  lastIn= digitalRead(triggInPin);
  lastOut= digitalRead(triggOutPin);
}

void loop() {

  if(digitalRead(triggInPin) != lastIn) // dispara entrada
  {
    // lê e armazena o valor lido no buffer
    addItem(analogRead(analogInPin));
    lastIn= digitalRead(triggInPin);
    // wait 2 milliseconds before the next loop
    // for the analog-to-digital converter to settle
    // after the last reading:
    delay(2);                     
  }
 
  if(digitalRead(triggOutPin) != lastOut) // dispara saída
  {
    // remove um item do buffer e mapeia para pwm
    outputValue = map(getItem(), 0, 1023, 0, 255);  
    // change the analog out value:
    analogWrite(analogOutPin, outputValue);           
    lastOut= digitalRead(triggOutPin);
  }
 
}// loop
+-----------------------------------------------------------------------------------+

Bom exemplo Francesco.

So acrescentando: em C++ nao é obrigatoria a existencia do .h, é perfeitamente possivel que tudo esteja em um .cpp e no arquivo principal faça-se apenas

#include "file.cpp"

Entretanto a utilizacao do .h é a forma habitual e consagrada, alem de possuir como vantagens a separaçao entre as interfaces e a implementaçao.

Não sou muito experiente em C++, mas imagino que incluir diretamente arquivos .cpp seja mais usado para arquivos que definem classes, assim a classe pode decidir o que é público e o que não é. No caso de funções "soltas", acho que usar o header seria mais indicado por que assim é possível decidir o que esconder e o que publicar.

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço