novo projeto - ajuda

Ola pessoal.
Sou iniciante no arduino e estou a tentar executar um projeto, mas gostava da vossa ajuda para afinar aqui algumas coisas.
o objectivo é utilizar o arduino para medir a carga que uma bateria gasta num pequeno carro electrico, medir a velocidade dele, a tensão da bateria, e a distância percorrida.
para a medição da carga estou a usar um shunt resistivo, que conforme o sentido a medir, carga ou descarga da bateria, é o pino do arduino que eu uso e o sentido que faço a ligação ao shunt, visto a corrente ter sentido contrario na carga e descarga e logo troca-me os sinais da tensão.
para medir a tensão da bateria, apenas liguei a entrada analogica com um divisor de tensão aos terminais da bateria.
o problema começou a surgir quando tentei medir a velocidade e distancia. devo ter baralhado alguma coisa no codigo relativamente ao tipo de variáveis, pois o que me aparece no LCD não é muito estável. ora aparece o resultado com casas decimais, ora começa a aparecer caracteres aleatorios e estranhos ppelo LCD todo.
bem, sem mais demora vou colocar aqui o resumo do projeto e o codigo que já fiz.
-Arduino UNO
-LCD Keypad Shield for Arduino SKU:DFR0009
-sensor indutivo de 10v com divisor tensão no sinal para 5v

  • A5 carga corrente
  • A4 consumo corrente
  • A3 tensão bateria
  • D2 sinal do sensor indutivo

codigo:
"
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

unsigned long tepTimer ;
const int pinoA = 12 ;
const int pinoB = 11;
const int pinoC = 3;
const int pinoD = 2;
const int pinoE = 1;
int estadobotaoA = 0 ;
int estadobotaoB = 0 ;
int estadobotaoC = 0 ;
int estadobotaoD = 0 ;
int estadobotaoE = 0 ;
double dataE = 0;
double dataG = 0;
unsigned long velocidadeA = 0;
unsigned long velocidadeB = 0;
double contador_totalA = 0;

volatile int contador_total=0;
unsigned long ultima_contagem = 0;
unsigned long intervalo = 0;
unsigned long intervaloB = 0;

void setup(){
lcd.begin(16, 2);
pinMode(pinoA, INPUT);
pinMode(pinoB, INPUT);
pinMode(pinoC, INPUT);
pinMode(pinoD, INPUT); //pino para velocidade e conta quilometros
pinMode(pinoE, INPUT);

attachInterrupt(0,contador,RISING);
}

void loop(){
lcd.setCursor(0, 0);
int valA;
int valB;
int valC;
double dataA;
double dataB;
double dataC;
double dataD;
double dataF;

valA=analogRead(4); // amperes para descarga
valB=analogRead (5); // amperes para carga
valC=analogRead (3); // tensao da bateria

dataD= (double) valC * 0.00488 * 11,1; //conversao para tensao real

dataB = (double) valB * 0.00488 * 1666 * 1.7; // conversao para watt para carga
dataC = (double) dataB / 3600 ;
dataE = (double) dataE + dataC;

dataA = (double) valA * 0.00488 * 1666 * 1.7; // conversao para watt para descarga
dataF = (double) dataA / 3600;
dataG = (double) dataG + dataF;
delay(1000);

lcd.setCursor(0,0);
lcd.print(dataE); //LCD para carga

lcd.setCursor(10,0);
lcd.print(dataG); //LCD para descarga

lcd.setCursor(0,1);
lcd.print(dataD); //LCD para tensão

// intervaloB = intervalo / 1000;
float velocidadeA = 1 / (float)intervalo;
velocidadeB = velocidadeA * 1000 * 60 * 1.78 / 100;
lcd.setCursor(6,1);
lcd.print(velocidadeB); //LCD para velocidade

contador_totalA = contador_total * 1.78 ;
lcd.setCursor(12,1);
lcd.print(contador_totalA); // LCD para quilometros

}

void contador(){
contador_total = contador_total + 1;
intervalo = millis() - ultima_contagem;
ultima_contagem = millis();

}
"
alguem dá alguma dica?
obrigado. :wink:

Qual e a diferenca entre o pino A4 e A5?

Porque e que colocaste um divisor resistivo para medir a tensao da bateria? Isso nao te da precisao nenhuma, nao seria melhor um amplificador operacional? A bateria e de quanto?

O delay(1000) esta a mais no programa...

Os pinos estao so como INPUT, dependendo de como os ligaste, isto pode ser a explicacao dos resultados estupidos de velocidade, etc...

A variavel intervalo e igual a 0 e o seu valor nunca muda... afinal de contas a funcao contador nunca e chamada... nota tambem que a funcao contador nao e propriamente aquilo que se pretende com funcoes.

a diferença entre o A4 e o A5 é que "imprimem" em posições diferentes do LCD, conforme se está a medir a carga da bateria ou a descarga (utilização) da bateria. a bateria é vai de 24V até 80V. estamos a testar diferentes. o delay(1000) foi para conseguir converter os amperes que mede. a forumula está feita de maneira que os amperes que mede a cada segundo ( daí o delay ) vão se acumulando. por exemplo durante 25 minutos sei que a bateria recebeu 12A de carga.

os pinos estão só como INPUT? só estou a ler.. não percebi, desculpa.

a variavel intervalo = 0? tenho no void setup : attachInterrupt(0,contador,RISING); quando o pino 2 passa de 0 para 1 ele executa a função contador. ou não? ???

O delay de 1 segundo não te dá um segundo... Dá um segundo mais o tempo de ciclo. Se já usas o millis porque é que não calculas tudo com millis? A pergunta do A4 e A5 tem a ver com que circuito tens lá ligado, já que me parece estares a medir a mesma coisa... Se não meteres uma resistência de pullup, definires os pinos como inpu vai deixar o pino a flutuar. Se não tens pullup, define os pinos como input_pullup. Que numeros vês no LCD? Um lcd.clear() não ficaria mal ai no programa....

estou a fazer um esquema eletrico para colocar aqui.
entretanto, não ves nenhum conflito nos tipos de definição das variaveis e o fato de terem operações de soma ou multiplicação entre elas? tipo unsigned com float ou int?
já agora o lcd.clear() não estar sempre a limpar o LCD e não deixa mostrar nada?

aqui está o esquema.
penso ser mais facil perceber. alguns componentes tive de improvisar. por exemplo o sensor indutivo é um da Omron, que só trabalha com pelo menos 10V, logo tive de lá por uma alimentação à parte para ele.

já agora, obrigado pela ajuda até agora dada.

ainda em relação ao estar a medir a mesma coisa no A4 e A5, de fato estou a medir a mesma coisa, mas como a carregar a bateria, a corrente vai em sentido contrario ao da bateria em descarga(uso) ia colocar-me tensão inversa no arduino ( do ponto de vista do shunt de corrente).

Actuar um motor DC directamente do arduino pode causar isto.... Pode até queimar o arduino. Não tens um transistor ou algo do género? O mesmo se aplica ao sensor... U divisor de tensão não é ideal e pode queimar o arduino. Acerca de carregar a bateria, depende do lado onde ligas o carregador... Mais uma vez deveria estar isolado do arduino e apenas medirias a tensão da bateria a subir. É provável que o programa tenha algum problema de cálculo, mas eu não vi e não simulei. Quanto ao LCD Clear, se escreveres 999 e depois escreveres 10 sem fazeres um lcd.clear, vais ver 109. Isto pode explicar o teu problema, mais acima eu pedi exemplos dos numeros precisamente para avaliar se seria algo assim. Sempre que vais actualizar o lcd, limpas o lcd e actualizas tudo ao mesmo tempo... Não é muito dificil de fazer.

em relação ao lcd.clear, já percebi. sim, realmente acontecia a situação de escrever 999, depois 10 e fica 109. mas tinha a ideia de ter colocado um lcd.clear e o lcd ficava sempre limpo. vou voltar a tentar.

relativamente ao actuar o motor DC atraves do arduino… não sei se percebi.
baseei-me neste conceito : Measuring Current with the Arduino

fica aqui outra maneira de mostrar o esquema.
achas que o divisor de tensão não é ideal para o sensor? :frowning:

tambem ando a tentar descobrir como gravar a leitura do consumo na EEPROM para não se perder quando o desligo. mas já sei que a gravação é um pouco limitada ( 100.000 vezes), o que é muito pouco dado que está sempre a medir e não posso gravar em tempo real. a minha ideia era de gravar na EEPROM somente quando a leitura da tensão do shunt no A5 fosse 0mV, e quando ligasse o arduino, ou seja, no primeiro ciclo ele fosse ler esse valor, mas tenho tido dificuldade em perceber como gravar por ser vários digitos, 7 ou 8.

vi estes exemplos:
http://playground.arduino.cc/Code/EEPROMLoadAndSaveSettings
http://playground.arduino.cc/Code/EEPROMWriteAnything

mas ainda não consegui atinar…

desculpem lá estas duvidas, mas principiantes tem disto. mas tenho pesquisado muito sozinho, não estou a querer que me façam o trabalho todo.

Ja percebemos isso... esta descansado que ninguem te esta a chamar preguicoso. :)

Eu tinha ideia que era o Arduino que actuava o motor, se esta so a monitorizar, isso devia tambem ser isolado do Arduino. Como sabes que o Arduino nao vai queimar quando ligares o carregador? Como desligas o motor se o carregador fica ligado no mesmo sitio?

O que acontece se a resistencia queimar e abrir? ;) Nota que o site que tu meteste no teu post tem a mesma preocupacao que eu... dai referir um amplificador operacional que serve tambem para isolar (ate certo ponto) os circuitos. Para correntes, o ideal e sempre um sensor externo... mas isso e carote.

EEPROM para guardar dados nao e boa ideia... a EEPROM serve principalmente para guardar definicoes.

Para o teu sensor, poderias ver um isolador optico... tendo em atencao a frequencia maxima que o sensor vai medir e a frequencia maxima que o isolador consegue deitar para fora.

Relativamente ao codigo, se conseguires mostrar exactamente qual e o problema que aparece no LCD, e muito mais simples (embora por vezes nao seja suficiente) de determinar o que pode ter causado isso. Outro metodo e atraves de mensagens de debug... ou simulacao.

O teu LCD deve ser actualizado de segundo a segundo, mas o programa deve estar sempre a funcionar, para isso podes fazer algo assim:

unsigned long tempo = 0; 
#define REFRESH 1000

loop() {
...

if (millis() - tempo > REFRESH) { //actualiza
    lcd.clear(); // limpa primeiro... 
    lcd.goto(0,0);
    lcd.print(valorA);
    lcd.goto(10,0);
    lcd.print(valorB);
    lcd.goto(1,0);
    lcd.print(valorC);
    lcd.goto(1,10);
    lcd.print(valorD);
    }   
}

Outra coisa que pode estar a acontecer e a precisao do calculo.... assim sendo eu aconselharia a calcular a velocidade com base em intervalos e nao com base na mudanca de estado do sensor. Ou seja:

float calv_vel() {

static double _cont = 0; //valor inicial
static long time_int = 0; //valor inicial... 

float vel = (contador_total-_cont)/(millis()-time_int); //cont por milisegundo... 

//static usado... prepara o proximo calculo. 
time_int = millis();
_cont = contador_total; 
}

Podias entao chamar esta funcao dentro do if que actualiza o LCD e assim a velocidade seria contada de segundo a segundo... mais ou menos, mas seria mais estavel uma vez que era uma media e nao baseada em no tempo que demora um pulso a ser feito.

Nota que as interrupcoes devem ser o mais rapido possiveis... nesse sentido, o que deves fazer e:

void contador(){
  contador_total++;  
}

Poderias olhar para os pinos do Arduino que podem ser usados como um contador (os que ligam ao Timer1 para poderes continuar a usar o millis) e ficavas com um contador por hardware capaz de contar ate 65535... definindo uma interrupcao sempre que a contagem passar desse valor podias incrementar uma variavel que contaria 65535 interrupcoes... depois era uma questao de aritmetica para calcular o numero total de impulsos. O beneficio deste metodo seria haver menos processamento por parte do Arduino... mas nao e tao simples assim de conseguir.

Como sabes que o Arduino nao vai queimar quando ligares o carregador?

  • não sei.. :(

Como desligas o motor se o carregador fica ligado no mesmo sitio?

não exemplifiquei, mas a bateria ( bateria + shunt ) estão ligados a uma ficha. ou seja desligo a ficha do circuito do motor e ligo à ficha do carregador.

Para correntes, o ideal e sempre um sensor externo... mas isso e carote

-pois..

estamos numa fase de testes de um veiculo pequeno 100% eletrico e daí precisarmos de algumas medições para valiar e estudar o sistema, mas são fundos proprios e o dinheiro é escasso(muito). e claro o espirito de DIY.

EEPROM para guardar dados nao e boa ideia... a EEPROM serve principalmente para guardar definicoes.

  • o problema é que preciso nesta fase, antes de desligar o carro que fique guardado o consumo dos amperes.. e não me convem gastar $$ em adaptador SD.. daí ter pensado em usar o momento em que o carro para ( V do shunt = 0) como trigger para fazer o save na EEPROM.

apesar de já ter visto alguns exemplo e a sintaxe do "static" ainda não percebi a sua vantagem..

Como vais alimentar o arduino se a tensão é zero?

lol

era só pra ver se tavas atento. :smiley: