LusoRobótica - Robótica em Português
Sistemas específicos => Arduino / AVR => Tópico iniciado por: duaron em 21 de Novembro de 2014, 12:36
-
Boas pessoal,
Alterei o meu codigo antigo que tinha no contador para usar o millis() com o while para mais ou menos colocar um cronometro a rolar.
O que acontece é que apos 26segundos bloqueia. Aqui deixo video com o exemplo do que acontece.
Alguem sabe porque acontece isto?
http://youtu.be/0rLvR81UciE (http://youtu.be/0rLvR81UciE)
//arduino 4 digit 7 segment project
#define DIGIT_ON HIGH
#define DIGIT_OFF LOW
int time = 3;
int x=100;
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int f = 6;
int g = 7;
//segments
char seg[]= {a,b,c,d,e,f,g};
//numbers and others
int num[10][7] = {{1,1,1,1,1,1,0}, //0
{0,0,1,1,0,0,0}, //1
{1,1,0,1,1,0,1}, //2
{0,1,1,1,1,0,1}, //3
{0,0,1,1,0,1,1}, //4
{0,1,1,0,1,1,1}, //5
{1,1,1,0,1,1,1}, //6
{0,0,1,1,1,0,0}, //7
{1,1,1,1,1,1,1}, //8
{0,0,1,1,1,1,1}};//9
int hifen[] = {0,0,0,0,0,0,1}; //-
int o[] = {1,1,1,0,0,0,1}; //o
int t,t2; //time of numbers
void setup(){
pinMode(13, OUTPUT);// 4 digit
pinMode(12, OUTPUT);// 3 digit
pinMode(11, OUTPUT);// 2 digit
pinMode(10, OUTPUT);// 1 digit
pinMode(g, OUTPUT);
pinMode(f, OUTPUT);
pinMode(e, OUTPUT);
pinMode(d, OUTPUT);
pinMode(c, OUTPUT);
pinMode(b, OUTPUT);
pinMode(a, OUTPUT);
}
void loop(){
//counter
for(int i=0; i<10; i++){
for(int j=0; j<10; j++){
for(int k=0; k<10; k++){
for(int l=0; l<10; l++){
t=millis();
while(t2<(t+10)){ //10ms, podem colocar o contador a correr à velocidade que quiserem
printNumber(i,3);
delay(time);
printNumber(j,2);
delay(time);
printNumber(k,1);
delay(time);
printNumber(l,0);
delay(time);
t2=millis();
}
}
}
}
}
//loop
/*
for(int i =0 ; i<8 ; i++){
lightNumber(o);
digitalWrite((10),LOW);
delay(200);
lightNumber(hifen);
digitalWrite((11),LOW);
delay(200);
lightNumber(hifen);
digitalWrite((12),LOW);
delay(200);
lightNumber(o);
digitalWrite((13),LOW);
delay(200);
lightNumber(hifen);
digitalWrite((12),LOW);
delay(200);
lightNumber(hifen);
digitalWrite((11),LOW);
delay(200);
} */
}
void lightNumber(int c[]){
clearLeds();
for(int i=0; i<7; i++){
if(c[i]==1){
digitalWrite(seg[i], HIGH);
}
}
}
void printNumber(int n, int index){
clearLeds();
if(n>=0 && n<=9){
lightNumber(num[n]);
}
digitalWrite((10+index),LOW);
}
void clearLeds(){
for(int i=0; i<7; i++){
digitalWrite(seg[i], LOW);
}
digitalWrite(13, HIGH);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
digitalWrite(10, HIGH);
}
cumprimentos
-
Isso é um overflow em algum lado, 4 for's uns dentro dos outros faz-me uma confusão tremenda.
Aconselho-te a ver o exemplo blink without delay e entender como funciona.
Uma variavel int tem 16 bits, logo a gama de valores que suporta é de -32768 a 32767, o milis usa uma variavel de 64 bits, se não tens overflow em meia duzia de horas ou minutos.
-
Um aparte: tens um erro temporal no contador, pelo teste que fiz, quando o teu contador diz que passaram 22segundos na realidade já passaram 27 segundos.
-
Eu suspeito que alguma variavel está a dar a volta aos 32767 dado os delays e incrementações e loops dentro de loops.
-
O erro temporal vem de estares a colocar um delay entre actualização do valor no lcd.
-
Outra boa prática é iniciares as variveis antes de as usares numa condição como é o caso do t2. Por acaso não sei como é que o avr-gcc trata disto mas há muitos casos em que os compiladores não inicializam as variáveis e esta condição while(t2<(t+10)){ poderia nunca acontecer.
O erro poderá tambem estar aqui pois estás a igual a varial t2 e t a mills e como o senso disse mills é de 64bits por isso vais ter aqui problemas.
Acho que se confirma, olhando para o video o teu código corre entre o segundo 0:06 e 0:38 o que dá nada mais nada menos que 32 segundos de execução :) Uma variavel int tem 16 bits, logo a gama de valores que suporta é de -32768 a 32767, o milis usa uma variavel de 64 bits, se não tens overflow em meia duzia de horas ou minutos.
-
Obrigado pelas respostas, realmente o problema estava na variavel do t, devia ser long para conseguir aguentar tudo.
Quanto ao tempo real, alterei o delay para DelayMicroseconds e já ficou muito idêntico ao normal.
-
Se usares algo assim, o tempo perdido no meio do loop é "compensado" por assim dizer.
if(getMilis() - fMilis>= 1000){
//código aqui
fMilis= getMilis();
}