Alterando o código para usar dois servo motores aleatoriamente

Bom dia Fórum,

Estou tentando fazer um estacionamento com duas cancelas (uma contando a entrada e outra contando a saída de carros.

Estou seguindo um tutorial que ensina a fazer a contagem de vagas disponíveis apenas com uma cancela, no meu projeto eu quero usar duas cancelas. Uma cancela de entrada, o carro irá entrar e será subtraída uma vaga disponível no estacionamento, na outra cancela de saída o carro irá sair e será somada uma vaga disponível no estacionamento. Alguém pode me ajudar e mostrar para mim onde eu devo alterar o código para fazer as contagem com os dois servo motores simultaneamente? Porquê eu só consegui fazer a cancela de entrada contar até 9, só depois disso a cancela de saída funciona.

Segue o código:

/*ParkingL02.pde
Arduining.com 08 JUL 2012
Code used in the production of the Youtube material.
*/

#include <Servo.h>
Servo myservo1;  // criar o objeto servo motor de entrada
Servo myservo2;
#define ServoM    12        //Connected to the servo motor.
#define ServoN    13
#define Bright    11        //servo library disable PWM on pins 9 and 10.
#define Exit      9         //Pin connected to the EXIT button.
#define In        8         //Pin connected to the IN button.

#define BarLow    177       //Low position of the barrier.
#define BarUp     95        //Up position of the barrier.
#define CAPACITY  8         //Capacity of the parking lot.
#define INTEN     80        //Display intensity %

//Pins conections to segments (cathodes).
#define  segA  0
#define  segB  1
#define  segC  2
#define  segD  3
#define  segE  4
#define  segF  5
#define  segG  6

//Array with the segments to represent the decimal numbers (0-9).
byte segments[10] = {
// pgfedcba  <--- segments
  B00111111, // number 0
  B00000110, // number 1
  B01011011, // number 2
  B01001111, // number 3
  B01100110, // number 4
  B01101101, // number 5
  B01111101, // number 6
  B00000111, // number 7
  B01111111, // number 8
  B01101111  // number 9
};

void setup(){
  myservo1.attach(ServoM);          // anexa o servo
  myservo2.attach(ServoN);
  pinMode(Exit, INPUT);           // setar botão EXIT no pino de entrada
  pinMode(In, INPUT);             // setar botão IN no pino de entrada
  digitalWrite(Exit, HIGH);       // Connect Pull-Up resistor.
  digitalWrite(In, HIGH);         // Connect Pull-Up resistor.
  pinMode(segA,OUTPUT);
  pinMode(segB,OUTPUT);
  pinMode(segC,OUTPUT);
  pinMode(segD,OUTPUT);
  pinMode(segE,OUTPUT);
  pinMode(segF,OUTPUT);
  pinMode(segG,OUTPUT);
  pinMode(Bright,OUTPUT);
  analogWrite(Bright,255*INTEN/100);
  myservo1.write(BarLow);          //Barrier in the low position
  myservo2.write(BarLow);
//  delay(1000);
}

int  Available= 9;                    // Number of places available.

//================================================================
void loop(){
Display(Available);
if(digitalRead(In)==0)
{
  if(Available != 0){
    Available--;
    myservo1.write(BarUp);
    delay(3000);
    myservo1.write(BarLow);
    }
  }
if(digitalRead(Exit)==0)
{
  if(Available != CAPACITY){
    Available++;
    myservo2.write(BarUp);
    delay(3000);
    myservo2.write(BarLow);
    }
  }
}

/*-------------------------------------------------------------------
Put the segments according to the number.
--------------------------------------------------------------------*/
void Display(int number){
byte segs =  ~segments[number];        //"~" is used for commom anode.

digitalWrite(segA, bitRead(segs, 0) );
digitalWrite(segB, bitRead(segs, 1) );
digitalWrite(segC, bitRead(segs, 2) );
digitalWrite(segD, bitRead(segs, 3) );
digitalWrite(segE, bitRead(segs, 4) );
digitalWrite(segF, bitRead(segs, 5) );
digitalWrite(segG, bitRead(segs, 6) );
}

wmazoni: (...) Porquê eu só consegui fazer a cancela de entrada contar até 9, só depois disso a cancela de saída funciona. (...)

Não percebo o que significa isto. Podia explicar melhor? Já agora, não é visto com muito bons olhos publicar a mesma questão em 2 locais diferentes do fórum, por isso, o meu conselho é que apague um dos dois posts.

Para alguem que "fez" o codigo...

Estas linhas parecem-me responder a tua pergunta, nao achas??

#define CAPACITY  8         //Capacity of the parking lot.
int  Available= 9;                    // Number of places available.

@bubulindo:

wmazoni:
(…)Estou seguindo um tutorial que ensina a fazer a contagem de vagas disponíveis (…)

Por isso, não foi ele que escreveu o código. De qualquer forma, também não acho que seja por aí. No início o parque começa vazio, sendo assim a linha:

int  Available= 9;                    // Number of places available.

parece-me correcta.

Talvez fosse melhor fazer qualquer coisa como:

#define CAPACITY  9         //Capacity of the parking lot.
int  Available= CAPACITY;                    // Number of places available.
  if(Available > 0){
  if(Available < CAPACITY){

mas parece-me que não é por isso que não está a funcionar. (ou talvez seja eu que ainda não percebi o que é que não funciona).

Ja experimentaste apagar os delays do codigo?

Se abrires uma cancela (imagina a de entrada), durante 3 segundos o Arduino nao vai ligar puto ao que a outra cancela vai estar a fazer.

Desculpe pelo dublo post, como faço para excluir? Pessoal existe algum problema eu pegar o código disponível na internet para fazer uma pequena alteração apenas para meu início no conhecimento do arduino? Eu estou começando agora por isso que estou pegando exemplos disponíveis na internet e tentando modifica-los.

Eu não sei como eu coloco no código para que as duas cancelas funcionem simultaneamente. No código está funcionando da seguinte forma: Primeiro eu tenho que colocar os 9 carros para dentro do estacionamento, então só depois disso consigo usar a cancela de saída para remover os carros.

Gostaria que funcionasse da seguinte forma: simultaneamente as duas cancelas, tanto a de saída como de entra devem funcionar, enquanto a cancela de entrada diminuísse as vagas disponíveis a cancela de saída aumentava as vagas disponíveis no display 7 segmentos.

O erro está aqui. só não sei como arrumar, primeiro ele faz o loop com a entrada "In", para só depois quando terminar as vagas disponíveis entrar no lop da entrada "Exit", enquanto o loop estiver analisando a entrada "Exit" ele não analisa a entrada "In" e vice-versa. Quero que isso aconteça no mesmo if, que verifique a entrada "In" e "Exit" ao mesmo tempo =(

void loop(){
Display(Available);
if(digitalRead(In)==0)
{
  if(Available != 0){
    Available--;
    myservo1.write(BarUp);
    delay(3000);
    myservo1.write(BarLow);
    }
  }
if(digitalRead(Exit)==0)
{
  if(Available != CAPACITY){
    Available++;
    myservo2.write(BarUp);
    delay(3000);
    myservo2.write(BarLow);
    }
  }
}

Como experimentaste?

Tentaste colocar um carro, abrir a cancela, esperar 3 segundos, fechar a cancela, tentar tirar o carro de la de dentro? Ou tentaste logo tirar e meter ao mesmo tempo?

O erro esta no uso da funcao delay(). Basicamente a funcao delay bloqueia o arduino durante o tempo especificado. Logo, enquanto a cancela esta aberta e ainda nao terminou de fechar, o Arduino nao faz mais nada.

Para aprenderes uma forma de nao usar delay para temporizacoes olha para a funcao millis() e o exemplo blink without delay para aprenderes a mecanica.

So por curiosidade, testaste o codigo ou estas a interpretar o codigo? Isto porque o codigo nao parece ter o erro que dizes ter e a forma como o descreves e muito semelhante a forma como alguem o descreveria se nao tiver nocao da velocidade a que o programa corre (sem as funcoes de delay()). Entao, ja tens isto tudo ligado com um display de 7 segmentos? Nota que tu nem tao pouco colocaste um Serial.Print no codigo... o que e o primeiro passo para se resolver um problema em microcontroladores.

Eu estou testando com o arduino Uno R3, com display 7 segmentos, dois servo motores e dois contatos. O problema não é no delay, o delay está configurando para fechar a cancela após 3 segundos, e isto está certo. O problema é que eu não consigo abrir a cancela de saída sem antes não lotar meu estacionamento. Quero controlar as cancelas simultaneamente, quando entra um carro e quando sai um carro. No código, primeiro ele verifica o if da condição do contato "In", para só depois quando terminar essa condição ele verificar o contato "Exit". E é isso que eu não quero que aconteça, quero que tanto o contato "In" como o "Exit" sejam verificados a qualquer momento, e é justo isso que não estou sabendo alterar. Compreendeu?

Nesse código ele faz essa condição por completo, fecha o contato "In", para que os 9 carros entrem no estacionamento, enquanto a variável for diferente de 0 essa condição irá se repetir. Apenas sai dessa condição quando não possuir mais vagas disponíveis nesse estacionamento: OK! Isto está funcionando.

if(Available != 0){
    Available--;
    myservo1.write(BarUp);
    delay(3000);
    myservo1.write(BarLow);
    }

Nessa outra condição quando o contato "Exit" fechar, a cancela irá liberar os carros e contar a capacidade do estacionamento até chegar a 9 que é o valor de Avaliable, quando o estacionamento estiver vazio a condição termina: Isto também esta ok!

if(Available != CAPACITY){
    Available++;
    myservo2.write(BarUp);
    delay(3000);
    myservo2.write(BarLow);
    }

Agora como eu faço para tirar um carro do estacionamento quando o estacionamento ainda não estiver lotado? Compreendeu o problema? É isto que o programa não esta fazendo.

Acho que nao estamos a falar a mesma linguagem ou tu nao queres entender o que eu estou a dizer.

Anteriormente perguntei como funciona o sinal de In e de exit… e um pulso? De quanto tempo?

O Arduino tem um processador… logo so corre um programa ao mesmo tempo. Logo o que tu pretendes fazer de correr duas coisas em simultaneo e impossivel.

No entanto, o processador corre tao depressa que para mim e para ti, a sensacao com que vais ficar e que as coisas acontecem ao mesmo tempo.

Para tal acontecer, tens de garantir que o teu programa nao tem sitios onde a execucao possa ficar presa.
As unicas instrucoes que bloqueiam a execucao dum programa sao ciclos for e while. O delay que tens ai e um ciclo While que ocupa o processador durante 3 segundos.

Mas adiante… Porque nao fazes o que o comum dos mortais faz para ver se um programa tem erros e colocas Serial.println para debug?

/*ParkingL02.pde
Arduining.com 08 JUL 2012
Code used in the production of the Youtube material.
*/

#include <Servo.h>
Servo myservo1;  // criar o objeto servo motor de entrada
Servo myservo2;
#define ServoM    12        //Connected to the servo motor.
#define ServoN    13
#define Bright    11        //servo library disable PWM on pins 9 and 10.
#define Exit      9         //Pin connected to the EXIT button.
#define In        8         //Pin connected to the IN button.

#define BarLow    177       //Low position of the barrier.
#define BarUp     95        //Up position of the barrier.
#define CAPACITY  8         //Capacity of the parking lot.
#define INTEN     80        //Display intensity %

//Pins conections to segments (cathodes).
#define  segA  0
#define  segB  1
#define  segC  2
#define  segD  3
#define  segE  4
#define  segF  5
#define  segG  6

//Array with the segments to represent the decimal numbers (0-9).
byte segments[10] = {
// pgfedcba  <--- segments
  B00111111, // number 0
  B00000110, // number 1
  B01011011, // number 2
  B01001111, // number 3
  B01100110, // number 4
  B01101101, // number 5
  B01111101, // number 6
  B00000111, // number 7
  B01111111, // number 8
  B01101111  // number 9
};

void setup(){
  myservo1.attach(ServoM);          // anexa o servo
  myservo2.attach(ServoN);
  pinMode(Exit, INPUT);           // setar botão EXIT no pino de entrada
  pinMode(In, INPUT);             // setar botão IN no pino de entrada
  digitalWrite(Exit, HIGH);       // Connect Pull-Up resistor.
  digitalWrite(In, HIGH);         // Connect Pull-Up resistor.
  pinMode(segA,OUTPUT);
  pinMode(segB,OUTPUT);
  pinMode(segC,OUTPUT);
  pinMode(segD,OUTPUT);
  pinMode(segE,OUTPUT);
  pinMode(segF,OUTPUT);
  pinMode(segG,OUTPUT);
  pinMode(Bright,OUTPUT);
  analogWrite(Bright,255*INTEN/100);
  myservo1.write(BarLow);          //Barrier in the low position
  myservo2.write(BarLow);
  Serial.begin(19200);
//  delay(1000);
}

int  Available= 9;                    // Number of places available.

//================================================================
void loop(){
Display(Available);

if(digitalRead(In)==0)
{
  Serial.println("exit");
  if(Available != 0){
    Available--;
    Serial.print("Down: ");
    Serial.println(Available);
    myservo1.write(BarUp);
    delay(3000);
    myservo1.write(BarLow);
    }
  }
if(digitalRead(Exit)==0)
{
  Serial.println("exit");
  if(Available != CAPACITY){
    Available++;

    Serial.print("Up: ");
    Serial.println(Available);

    myservo2.write(BarUp);
    delay(3000);
    myservo2.write(BarLow);
    }
  }
}

/*-------------------------------------------------------------------
Put the segments according to the number.
--------------------------------------------------------------------*/
void Display(int number){
byte segs =  ~segments[number];        //"~" is used for commom anode.

digitalWrite(segA, bitRead(segs, 0) );
digitalWrite(segB, bitRead(segs, 1) );
digitalWrite(segC, bitRead(segs, 2) );
digitalWrite(segD, bitRead(segs, 3) );
digitalWrite(segE, bitRead(segs, 4) );
digitalWrite(segF, bitRead(segs, 5) );
digitalWrite(segG, bitRead(segs, 6) );
}

Experimenta assim, liga o Serial Monitor com velocidade 19200 e testa o teu programa… Ve se a variavel available varia… depois coloca aqui o que encontraste.

Entretanto, ja foste ver como funciona a funcao millis()?

wmazoni:
Eu estou testando com o arduino Uno R3, com display 7 segmentos, dois servo motores e dois contatos. O problema não é no delay, o delay está configurando para fechar a cancela após 3 segundos, e isto está certo. O problema é que eu não consigo abrir a cancela de saída sem antes não lotar meu estacionamento. Quero controlar as cancelas simultaneamente, quando entra um carro e quando sai um carro. No código, primeiro ele verifica o if da condição do contato “In”, para só depois quando terminar essa condição ele verificar o contato “Exit”. E é isso que eu não quero que aconteça, quero que tanto o contato “In” como o “Exit” sejam verificados a qualquer momento, e é justo isso que não estou sabendo alterar. Compreendeu?

Experimenta fazer este programa:

Serial.println(millis(), DEC);
if(digitalRead(In)==0)
{
  if(Available != 0){
    Available--;
    myservo1.write(BarUp);
    delay(3000);
    myservo1.write(BarLow);
    }
  }
if(digitalRead(Exit)==0)
{
  if(Available != CAPACITY){
    Available++;
    myservo2.write(BarUp);
    delay(3000);
    myservo2.write(BarLow);
    }
  }
Serial.println(millis(), DEC);
}

Nao actives nenhum sinal de entrada para que o codigo que corre a funcao delay() nao execute. 
A diferenca entre dois valores contiguos que aparecem no Serial Port e o tempo que demorou a correr o pedaco de codigo entre as instrucoes de print. 
Diz-me sinceramente, consegues determinar se passou esse tempo ou se passou o dobro do tempo? e quatro vezes?? 
Conseguirias distinguir entre duas accoes que acontecem ao mesmo tempo ou accoes que acontecem com esse tempo de intervalo?

wmazoni:
Nesse código ele faz essa condição por completo, fecha o contato “In”, para que os 9 carros entrem no estacionamento, enquanto a variável for diferente de 0 essa condição irá se repetir. Apenas sai dessa condição quando não possuir mais vagas disponíveis nesse estacionamento: OK! Isto está funcionando.

Nao… nao esta a funcionar. O teu contacto deve ligar e desligar dentro de 3 segundos para que o ciclo nao continue a repetir.

Se quiseres evitar isto, tens de fazer o codigo de forma a detectar um flanco. Ou seja:

unsigned char In = digitalRead(_in);
unsigned char PreviousIn = 1;
if (In < PreviousIn) { // In = 0 e PreviousIn = 1
   //chegou um carro. 
   DoorIn = 1;
}


PreviousIn = In:

if (DoorIn == 1){
   Available--;
   Display(Available);
   DoorIn = 0;
   //mexe cancela
}

Isto que esta aqui em cima e um encravamento… ou seja, quando o sinal muda de estado, inicia um ciclo e so quando o sinal voltar a variar (ou seja, o carro saiu do sitio e chegou outro) e que podes voltar a entrar.

Essa alterações não surtiu diferença no funcionamento. Então o arduino não consegue fazer o que estou tentando fazer?

Define

wmazoni:
Essa alterações não surtiu diferença no funcionamento.

Isto pode ter mil e um significados e causas. Sem ver o codigo final e impossivel de ver se houve algum erro.
Alem do mais, um dos posts atras pedia para colocares um Serial.println para fazer debug.

Eu creio ter ja deixado explicacoes que chegue para entenderes o que se esta a passar, mas a verdade e que ainda nao respondeste a nenhuma das perguntas colocadas anteriormente e assim e literalmente imposivel de ajudar a nao ser que eu faca esse projecto e te de o codigo.

Está funcionando do mesmo jeito que antes. Primeiro o estacionamento deve ficar sem vagas disponíveis para depois deixar os carros saírem do estacionamento.

Mudando de assunto no código estou usando apenas contatos para abrir a cancela. Caso eu usasse um sensor de proximidade iria mudar alguma coisa no código?

Desculpa ser insistente, mas importas-te de responder as perguntas que estao em baixo, por favor? Dizes que nao funciona e que tem problemas, mas sem responderes a isto nao te posso ajudar muito mais.

bubulindo: Como experimentaste?

Tentaste colocar um carro, abrir a cancela, esperar 3 segundos, fechar a cancela, tentar tirar o carro de la de dentro? Ou tentaste logo tirar e meter ao mesmo tempo?

bubulindo: Anteriormente perguntei como funciona o sinal de In e de exit... e um pulso? De quanto tempo?

Mas adiante... Porque nao fazes o que o comum dos mortais faz para ver se um programa tem erros e colocas Serial.println para debug?

Demos varias ideias para resolver o problema, mas dizes na mesma que nao funciona, sem mais indicacao do que esta a acontecer de errado ou qualquer outra informacao. Achas que somos bruxos e temos uma bola de cristal?

Repetiste o funcionamento que aparece no video da pessoa que escreveu esse codigo? Ou ligaste tudo e esperavas que funcionasse como TU queres e nao como alguem projectou?

Terias de usar uma deteccao de flanco ou enquanto o sensor estivesse activado, nao fechar a cancela.

Como experimentaste?

Tentaste colocar um carro, abrir a cancela, esperar 3 segundos, fechar a cancela, tentar tirar o carro de la de dentro?
Ou tentaste logo tirar e meter ao mesmo tempo?

Eu tentei tirar um carro após o3 segundos, assim que a cancela fechou.

Anteriormente perguntei como funciona o sinal de In e de exit… e um pulso? De quanto tempo?

Mas adiante… Porque nao fazes o que o comum dos mortais faz para ver se um programa tem erros e colocas Serial.println para debug?

O sinal de In e Exit são apenas pulso.

O que é detecção de flanco? Tentei usar um sensor de presença sem alterar o código mais não funcionou.

Deteccao de flanco e quando estas a ver se um sinal mudou de estado em vez dum estado especifico.

Parece-me estranho que tanta gente tenha comentado que o projecto funciona como no video e a ti nao funciona.

Quanto tempo deixas esse pulso activado?

Mais o código funcionou. Do mesmo jeito que funcionou no vídeo. Só que primeiro você deve colocar 9 carros no estacionamento pra depois começar a retirar os carros. Ele não deixa você retirar algum carro sem antes colocar 9 carros na garagem.

Eu não é isso que vejo no código. A menos que os sensores de entrada e saída estejam trocados. Nesse caso sim, terá que "tirar" todos os carros do parque para poder receber mais. Será que é este o problema?