Ajuda na optimização do meu código

Boas,

Sou completamente novo a programar, o código que vou colocar de seguida é a minha primeira tentativa, depois dos exemplos e tutoriais básicos, de escrever algumas linhas de código para uma função específica.

Pretendo que o Arduino detecte, através de sensores Hall Effect, a passagem de comboios por um determinado ponto na linha e que de seguida execute uma série de funções.

Quando uma locomotiva, com um íman colado no fundo, activa um sensor, o sketch deve fazer o seguinte:

  • Identificar o sensor que foi activado;
  • Saber qual a direcção que o comboio leva;
  • Ligar os leds vermelhos e desligar os verdes, correspondentes aos blocos que estão em utilização
  • Ligar os leds verdes e desligar os vermelhos, correspondentes aos blocos que deixaram de estar em utilização

O sketch que preparei faz o que eu pretendo mas ficou uma "confusão". E como o projecto final vai implicar qualquer coisa como 40 sensores, 80 leds e afins, precisava da vossa ajuda para saber o que posso/devo alterar para ficar com um código mais "limpo".

Obrigado

Miguel

/* Detecção de blocos
  --------------

  Este Sketch faz com que o Arduino detecte, através de sensores Hall Effect, a passagem
  de comboios por um determinado ponto na linha e que de seguida execute uma série de
  funções.

  Quando uma locomotiva, com um íman colado no fundo, activa um sensor, o sketch deve
  fazer o seguinte:
  - Identificar o sensor que foi activado;
  - Saber qual a direcção que o comboio leva;
  - Ligar os leds vermelhos e desligar os verdes, correspondentes aos blocos que estão em utilização
  - Ligar os leds verdes e desligar os vermelhos, correspondentes aos blocos que deixaram de estar em utilização

  O pin 3 dos sensores está ligado ao arduino aos pins 9, 10 e 11
*/


int HallPin [3] = {9, 10, 11};
int HallId[3] = {1, 2, 3};
int LedGreen [3] = {2, 4, 6};
int LedRed [3] = {3, 5, 7};
int i;

int HallPinStatus [3];

int Position;           //Indica qual o sensor que foi activado
int LastPosition;       //Indica qual foi o ultimo sensor a ser activado
int LastLastPosition;   //Indica qual foi o penultimo sensor a ser activado
int Direction;          //Indica qual a direcção. Se passou do sensor 1 para o 2,
//então está a ir no sentido ascendente(2), se passa do
//sensor 2 para o 1, está no sentido descendente(1)


void setup() {
  //Abrir a porta série
  Serial.begin(115200);

  // Definir os PINs dos sensores
  for (i = 0; i < 3; i++) {
    pinMode (HallPin[i], INPUT);
  }

  // Definir os PINs dos leds verdes
  for (i = 0; i < 3; i++) {
    pinMode (LedGreen[i], OUTPUT);
  }

  // Definir os PINs dos leds vermelhos
  for (i = 0; i < 3; i++) {
    pinMode (LedRed[i], OUTPUT);
  }

}

void loop() {


  // Ligar os Leds verdes
  for (i = 0; i < 3; i++) {
    digitalWrite (LedGreen[i], HIGH);
  }

  // Ler o estado dos sensores
  for (i = 0; i < 3; i++) {
    HallPinStatus [i] = digitalRead(HallPin[i]);
    Serial.print(" - Sensor ");
    Serial.print(HallId[i]);
    Serial.print(": ");
    Serial.print(HallPinStatus[i]);
  }

  // O que fazer quando o sensor 1 está Ligado
  if (HallPinStatus[0] == LOW) {
    digitalWrite(LedGreen[0], LOW);
    digitalWrite(LedGreen[1], LOW);
    digitalWrite(LedGreen[2], HIGH);
    digitalWrite(LedRed[0], HIGH);
    digitalWrite(LedRed[1], HIGH);
    digitalWrite(LedRed[2], LOW);
    Position = 1;
  }

  // O que fazer quando o sensor 2 está Ligado
  else if (HallPinStatus[1] == LOW) {
    digitalWrite(LedGreen[1], LOW);
    digitalWrite(LedGreen[2], LOW);
    digitalWrite(LedGreen[0], HIGH);
    digitalWrite(LedRed[1], HIGH);
    digitalWrite(LedRed[2], HIGH);
    digitalWrite(LedRed[0], LOW);
    Position = 2;
  }

  // O que fazer quando o sensor 3 está Ligado
  else if (HallPinStatus[2] == LOW) {
    digitalWrite(LedGreen[2], LOW);
    digitalWrite(LedGreen[0], LOW);
    digitalWrite(LedGreen[1], HIGH);
    digitalWrite(LedRed[2], HIGH);
    digitalWrite(LedRed[0], HIGH);
    digitalWrite(LedRed[1], LOW);
    Position = 3;
  }


  //Estabelecer a direcção seguida
  if (LastLastPosition > LastPosition) {
    Direction = 1;
  }
  else if (LastLastPosition < LastPosition) {
    Direction = 2;
  }
  else {
    Direction = 0;
  }


  //Estabelecer e manter a ultima posição conhecida
  if (Position != LastPosition) {
    LastLastPosition = LastPosition;
    LastPosition = Position;
  }
  else {
    LastPosition = Position;
  }
  Serial.println("");

  Serial.print(" - Last Last Position: ");
  Serial.print(LastLastPosition);

  Serial.print(" - Last Position: ");
  Serial.print(LastPosition);

  Serial.print(" - Position: ");
  Serial.print(Position);

  Serial.print(" - Direction: ");
  Serial.print(LastDirection);

  Serial.println("");
  Serial.println("");



}

Muitas das variáveis não precisam de ser int... podem ser unsigned char.

Que tamanho tem a pista? Existe a possibilidade do mesmo comboio activar dois sensores?

  // O que fazer quando o sensor 2 está Ligado
  else if (HallPinStatus[1] == LOW) {

Aqui apenas testas o sensor 2 se o sensor 1 estiver ligado devido ao else... é isso que pretendes?

Igualmente aqui:

  // O que fazer quando o sensor 3 está Ligado
  else if (HallPinStatus[2] == LOW) {

Não acho que o código tenha ficado feio, uma coisa a fazeres é uma função para substituires por isto:

    digitalWrite(LedGreen[2], LOW);
    digitalWrite(LedGreen[0], LOW);
    digitalWrite(LedGreen[1], HIGH);
    digitalWrite(LedRed[2], HIGH);
    digitalWrite(LedRed[0], HIGH);
    digitalWrite(LedRed[1], LOW);
    Position = 3;

A função receberia o valor dado à variável position e definia o estado dos LED's. Isso tornaria o teu código principal mais curto para ler.

Não percebo porque é que os LED~'s verdes são ligados no inicio do loop. Algum motivo?

Serial.print(" - Direction: ");
Serial.print(LastDirection);

Não encontrei em seu código a declaração desta variável "LastDirection". Seria apenas "Direction"?

Como já foi mencionado, crie um void apenas para o acionamento dos leds, realmente ficaria mais legível.

bubulindo:
Que tamanho tem a pista? Existe a possibilidade do mesmo comboio activar dois sensores?

O modelo actual é só para testes e é pequeno, tem cerca de 10 metros de linha. Estou a preparar o terreno para o modelo definitivo que deverei começar dentro de ano, ano e meio.

Sim, a mesma locomotiva pode actuar 2 sensores antes que a última carruagem passe pelo 1º sensor. Neste momento existe a proibição de circulação no bloco activado e no que se encontra imediatamente a seguir. Mas faltam ainda algumas instruções, como por exemplo, sinalizar a amarelo o bloco anterior ao sensor que esteja activado.

Aqui apenas testas o sensor 2 se o sensor 1 estiver ligado devido ao else... é isso que pretendes?

O que pretendo é que, seja qual for o sensor que seja activado, o arduino execute as tarefas respectivas.
Nos meus limitadíssimos conhecimentos só encontrei esta forma de o fazer.
Pelo que percebi ele testa o sensor 2 e/ou o 3 independentemente do estado do sensor 1.
Mas agora que falas nisto é que percebi que não tentei activar 2 sensores em simultâneo.

Não acho que o código tenha ficado feio, uma coisa a fazeres é uma função para substituires por isto:

    digitalWrite(LedGreen[2], LOW);

digitalWrite(LedGreen[0], LOW);
   digitalWrite(LedGreen[1], HIGH);
   digitalWrite(LedRed[2], HIGH);
   digitalWrite(LedRed[0], HIGH);
   digitalWrite(LedRed[1], LOW);
   Position = 3;




A função receberia o valor dado à variável position e definia o estado dos LED's. Isso tornaria o teu código principal mais curto para ler.

Obrigado pela dica, já tinha pensado em tentar usar funções mas não sabia por onde lhe "pegar".

Não percebo porque é que os LED~'s verdes são ligados no inicio do loop. Algum motivo?

De cada vez que ligava o arduino toda a sinalização ficava desligada e esta foi a maneira que encontrei de resolver o assunto. E, agora mesmo, fez-se luz na minha cabeça... esta instrução tem de passar para o setup :slight_smile:

Obrigado pela ajuda

Miguel

yago4xd:
Não encontrei em seu código a declaração desta variável "LastDirection". Seria apenas "Direction"?

Como já foi mencionado, crie um void apenas para o acionamento dos leds, realmente ficaria mais legível.

Quando criei o post reparei que o nome da variável LastDirection não estava correcto e alterei aqui directamente. Realmente é só Direction. Já corrigi no sketch.

Obrigado pela atenção

Miguel

miguelcarmor:
O modelo actual é só para testes e é pequeno, tem cerca de 10 metros de linha. Estou a preparar o terreno para o modelo definitivo que deverei começar dentro de ano, ano e meio.

Porra... quem me dera viver numa casa como a tua se 10 metros de linha é pequeno. :stuck_out_tongue: A única pista que tive tinha 3 metros.

miguelcarmor:
Sim, a mesma locomotiva pode actuar 2 sensores antes que a última carruagem passe pelo 1º sensor. Neste momento existe a proibição de circulação no bloco activado e no que se encontra imediatamente a seguir. Mas faltam ainda algumas instruções, como por exemplo, sinalizar a amarelo o bloco anterior ao sensor que esteja activado.

O que deves ter é os sensores de detecção de sentido (e possível velocidade :wink: ) perto uns dos outros por forma a que apenas lides com esses dois sensores em bloco.
Esta seria mais uma função que poderias ter. No inicio do ciclo, lias todas as entradas para um array e vias se houve alterações e se o sentido está correcto.

miguelcarmor:
O que pretendo é que, seja qual for o sensor que seja activado, o arduino execute as tarefas respectivas.
Nos meus limitadíssimos conhecimentos só encontrei esta forma de o fazer.
Pelo que percebi ele testa o sensor 2 e/ou o 3 independentemente do estado do sensor 1.
Mas agora que falas nisto é que percebi que não tentei activar 2 sensores em simultâneo.

O teu código testa o sensor 2 dependendo do estado do sensor 1 e testa o estado do sensor 3 dependendo do sensor 2.

Não és obrigado a usar a instrução if... e podes agrupar condições dentro da condição if com && e || (and e or respectivamente).

Tendo a linha montada, vê as condições que vais ter nas linhas de cruzamentos, entroncamentos, intersecções e lista-as todas.
Depois em projectos separados cria código para lidar com cada uma delas. Tenta agrupar em funções esse código.

Depois mais tarde apenas tens de adicionar funções para cada uma dessas situações e mapear as entradas/saídas correctamente.

Não tentes fazer tudo de uma vez.

bubulindo:
Porra... quem me dera viver numa casa como a tua se 10 metros de linha é pequeno. :stuck_out_tongue: A única pista que tive tinha 3 metros.

Os 10 metros são de linha linear, não é o tamanho do layout:)
Quando digo que é pequeno é porque tenho 3 vias num espaço de 2x1,5mt. O definitivo (a ver vamos) deverá ter mais de 30 metros de linha linear porque vou ampliar um pouco o espaço total e porque vou passar para a escala N.

bubulindo:
O teu código testa o sensor 2 dependendo do estado do sensor 1 e testa o estado do sensor 3 dependendo do sensor 2.

Não és obrigado a usar a instrução if... e podes agrupar condições dentro da condição if com && e || (and e or respectivamente).

Pois... Já percebi o que querias dizer no post original. Da forma como estava (e ainda está) ele só detecta o sensor 3 se não tiver já detectado o sensor 1...

Não tentes fazer tudo de uma vez.

Não, não tento... Aliás já dei vários nós cegos na minha cabeça.

Tenho de aprender mais. O que sei nem sequer chega para fazer perguntas

Percebi os conceitos e objectivos do teu último post mas ainda vou ter de "comer muita sopa" para perceber como é que transformo ideias em código :slight_smile:

Obrigado pela tua disponibilidade e voltarei à carga quando souber mais qualquer coisinha.

Miguel

Desculpa, num dos posts acima queria dizer que não tens de usar a instrução else num bloco de if. O if é uma das mais, se não a mais importante instrução numa linguagem de programação.

Quando precisares, é só dizer.