tacômetro com pulseIn

Olá pessoal! Estou começando a usar o Arduíno e preciso escrever um código para ler a informação recebida por um sensor óptico acoplado a um motor, que retorne a frequência em Hz a ser exibida em 3 displays catodo comum. O código que criei gera 3 saídas BCD a serem decodificadas por CIs 4511. Estou simulando o sinal do sensor com um botão, porem todos os displays ficam na função default alguns segundos após o programa começar a rodar, e quando ligo o monitor serial não vejo alteração no número que deveria estar variando conforme a função pulseIn. Atualmente sei que mesmo resolvido este problema, o único display que funcionaria corretamente seria o que representa a maior unidade a ser expressa, transformando 31,4 em 30,0 (por exemplo). Seria possível resolver isto controlando o tamanho da variável "frequency" fazendo com que o resultado da expressão ((1/duration)*100000000) nunca superasse os 100, valor máximo programado a ser exibido no display dos décimos de Hz, mas não sei como, nem se é possível fazer isto. Não sei se fui claro, atualmente preciso resolver estes dois problemas, porem, qualquer ideia de como fazer a mesma coisa de outro jeito é bem vinda.

unsigned long duration = 1; //declara a variável "duration" e a inicia com valor 1
unsigned long frequency = 1; //declara a variável "frequency" e a inicia com valor 1
byte Saidas[] = {2,3,4,5,6,7,8,9,10,11,12,13}; //vetor com os pinos usados como OUTPUTs

void setup() {
    pinMode(14, INPUT); //seta o pino 14 ou A0 como INPUT
  for(int pino=0;pino <= 12;pino++) //seta os pino 2-13 como OUTPUTs
    pinMode(Saidas[pino],OUTPUT);
  for(int pino=0;pino <= 12;pino++) //inicia os pinos 2-13 em estado lógico baixo
    digitalWrite(Saidas[pino],LOW);
  Serial.begin(9600); //inicia a comunicação serial com velocidade de 9600
}

void loop() {
  duration = pulseIn(14, HIGH); //armazena em "duration" o tempo em que um botão esteve em estado lógico alto
  frequency = (1/(duration/1000000)); //armazena em "frequency" a frequência em Hz
  switch(((1/duration)*1000000)) //puxa o valor da frequência em micro segundos 6 casas decimais, dando 10 + 1 diferentes respostas em BCD para um display catodo comum representando as dezenas de Hz 
  {
  default: (digitalWrite(2, HIGH),digitalWrite(3, HIGH),digitalWrite(4, HIGH),digitalWrite(5, HIGH)); break;
  case 0 ... 9: (digitalWrite(2, LOW),digitalWrite(3, LOW),digitalWrite(4, LOW),digitalWrite(5, LOW)); break;
  case 10 ... 19: (digitalWrite(2, LOW),digitalWrite(3, LOW),digitalWrite(4, LOW),digitalWrite(5, HIGH)); break;
  case 20 ... 29: (digitalWrite(2, LOW),digitalWrite(3, LOW),digitalWrite(4, HIGH),digitalWrite(5, LOW)); break;
  case 30 ... 39: (digitalWrite(2, LOW),digitalWrite(3, LOW),digitalWrite(4, HIGH),digitalWrite(5, HIGH)); break;
  case 40 ... 49: (digitalWrite(2, LOW),digitalWrite(3, HIGH),digitalWrite(4, LOW),digitalWrite(5, LOW)); break;
  case 50 ... 59: (digitalWrite(2, LOW),digitalWrite(3, HIGH),digitalWrite(4, LOW),digitalWrite(5, HIGH)); break;
  case 60 ... 69: (digitalWrite(2, LOW),digitalWrite(3, HIGH),digitalWrite(4, HIGH),digitalWrite(5, LOW)); break;
  case 70 ... 79: (digitalWrite(2, LOW),digitalWrite(3, HIGH),digitalWrite(4, HIGH),digitalWrite(5, HIGH)); break;
  case 80 ... 89: (digitalWrite(2, HIGH),digitalWrite(3, LOW),digitalWrite(4, LOW),digitalWrite(5, LOW)); break;
  case 90 ... 99: (digitalWrite(2, HIGH),digitalWrite(3, LOW),digitalWrite(4, LOW),digitalWrite(5, HIGH)); break;
  }
  switch(((1/duration)*100000000)) //puxa o valor da frequência em micro segundos 7 casas decimais, dando 10 + 1 diferentes respostas em BCD para um display catodo comum representando as unidades de Hz
  {
  default: (digitalWrite(6, HIGH),digitalWrite(7, HIGH),digitalWrite(8, HIGH),digitalWrite(9, HIGH)); break;
  case 0 ... 9: (digitalWrite(6, LOW),digitalWrite(7, LOW),digitalWrite(8, LOW),digitalWrite(9, LOW)); break;
  case 10 ... 19: (digitalWrite(6, LOW),digitalWrite(7, LOW),digitalWrite(8, LOW),digitalWrite(9, HIGH)); break;
  case 20 ... 29: (digitalWrite(6, LOW),digitalWrite(7, LOW),digitalWrite(8, HIGH),digitalWrite(9, LOW)); break;
  case 30 ... 39: (digitalWrite(6, LOW),digitalWrite(7, LOW),digitalWrite(8, HIGH),digitalWrite(9, HIGH)); break;
  case 40 ... 49: (digitalWrite(6, LOW),digitalWrite(7, HIGH),digitalWrite(8, LOW),digitalWrite(9, LOW)); break;
  case 50 ... 59: (digitalWrite(6, LOW),digitalWrite(7, HIGH),digitalWrite(8, LOW),digitalWrite(9, HIGH)); break;
  case 60 ... 69: (digitalWrite(6, LOW),digitalWrite(7, HIGH),digitalWrite(8, HIGH),digitalWrite(9, LOW)); break;
  case 70 ... 79: (digitalWrite(6, LOW),digitalWrite(7, HIGH),digitalWrite(8, HIGH),digitalWrite(9, HIGH)); break;
  case 80 ... 89: (digitalWrite(6, HIGH),digitalWrite(7, LOW),digitalWrite(8, LOW),digitalWrite(9, LOW)); break;
  case 90 ... 99: (digitalWrite(6, HIGH),digitalWrite(7, LOW),digitalWrite(8, LOW),digitalWrite(9, HIGH)); break;
  }
  switch(((1/duration)*10000000000)) //puxa o valor da frequência em micro segundos 8 casas decimais, dando 10 + 1 diferentes respostas em BCD para um display catodo comum representando os décimos de Hz
  {
  default: (digitalWrite(10, HIGH),digitalWrite(11, HIGH),digitalWrite(12, HIGH),digitalWrite(13, HIGH)); break;
  case 0 ... 9: (digitalWrite(10, LOW),digitalWrite(11, LOW),digitalWrite(12, LOW),digitalWrite(13, LOW)); break;
  case 10 ... 19: (digitalWrite(10, LOW),digitalWrite(11, LOW),digitalWrite(12, LOW),digitalWrite(13, HIGH)); break;
  case 20 ... 29: (digitalWrite(10, LOW),digitalWrite(11, LOW),digitalWrite(12, HIGH),digitalWrite(13, LOW)); break;
  case 30 ... 39: (digitalWrite(10, LOW),digitalWrite(11, LOW),digitalWrite(12, HIGH),digitalWrite(13, HIGH)); break;
  case 40 ... 49: (digitalWrite(10, LOW),digitalWrite(11, HIGH),digitalWrite(12, LOW),digitalWrite(13, LOW)); break;
  case 50 ... 59: (digitalWrite(10, LOW),digitalWrite(11, HIGH),digitalWrite(12, LOW),digitalWrite(13, HIGH)); break;
  case 60 ... 69: (digitalWrite(10, LOW),digitalWrite(11, HIGH),digitalWrite(12, HIGH),digitalWrite(13, LOW)); break;
  case 70 ... 79: (digitalWrite(10, LOW),digitalWrite(11, HIGH),digitalWrite(12, HIGH),digitalWrite(13, HIGH)); break;
  case 80 ... 89: (digitalWrite(10, HIGH),digitalWrite(11, LOW),digitalWrite(12, LOW),digitalWrite(13, LOW)); break;
  case 90 ... 99: (digitalWrite(10, HIGH),digitalWrite(11, LOW),digitalWrite(12, LOW),digitalWrite(13, HIGH)); break;
  }
  Serial.print("A frequência do motor é  "); //escreve no monitor serial "a frequência do motor é"
  Serial.println(frequency); //completa a frase com a frequência em Hz
  delay(1000);
}

Porque é que o default é a primeira opção?

Este código não compila... já experimentaste ver isso?

As fórmulas usadas no switch, não batem com a fórmula usada para calcular a frequência. Qual delas está correcta?

Esse delay está a mais....

A função pulseIn pode retornar 0.... não seria pior ver o que ela retorna antes de a usares numa divisão.

Não sabia que a posição do default influenciava em alguma coisa, mudei ele de lugar e o erro persiste.

Aqui em casa o código compilou adequadamente.

Cada um dos switches controla um dos displays, a variação na fórmula serve para variar a "sensibilidade" ao tamanho do pulseIn, sendo o display dos décimos de Hz (pinos 10, 11, 12, 13) o mais sensível, variando muito mais que os outros. Seria a mesma coisa usar "frequency" em todos os switches porém no primeiro ter uma saída zero (0000) entre 0-999, no segundo ter um zero entre 0-99 e no terceiro um zero entre 0-9. Como já disse, mesmo que o erro do pulseIn (seja ele qual for) fosse consertado, acredito que que caso a frequência seja mais alta que o maior número representado em cada switch, este entraria na função default, transformando uma frequência qualquer em um único dígito, Ex: "76,9" em "7-,-". Este problema poderia ser resolvido colocando uma variável para cada switch, e fazendo com que ela "cortasse" parte do número, transformando 8675 em 75, ou em 675 dependendo do display a ser programado (o problema é que não tenho ideia de como fazer isto).

Coloquei isso para o mostrador atualizar a cada um segundo somente. Pode ser isto que esta afetando a função pulseIn?

Como que a função pode retornar 0 se a variável "duration" foi iniciada com 1 e a partir dai espera um nível lógico alto para começar a contar (pelo que entendi)?

Description

Reads a pulse (either HIGH or LOW) on a pin. For example, if value is HIGH, pulseIn() waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW and stops timing. Returns the length of the pulse in microseconds. Gives up and returns 0 if no pulse starts within a specified time out.

Logo existe a possibilidade de retornar zero. O timeout de default é de 1 segundo.

Sendo assim... porque não começas pelo início, não te preocupes com o display de 7 segmentos. Vê se o sistema está a mandar dados pelo Serial Port. Inicializa a variavel duration a zero.

Dentro do loop, se a variável duration for diferente de zero, envia o valor que foi lido pelo Serial Port. Vê qual é o valor e se essa parte está a funcionar.