Contador em horas...

Boas,

No projecto que tou a elaborar gostava de ter uma informação da soma de horas de funcionamento de uma bomba ou seja o tempo total em horas em que o rele esteve em high...

Cumprimentos

Tou a seguir este topico penso q ira ajudar Ajuda na contagem de tempo - Português - Arduino Forum

Podes usar o millis... Ou um rtc.

Quando o rele passa a high, guardas o valor do millis. Quando passa a low, guardas esse valor.

Um menos o outro a dividir por 1000 dá-te um numero em segundos e daí calculas horas. Convém ter em atenção se o relé vai estar ligado durante mais de uns dias, mas dee ser pacifico.

Um menos o outro a dividir por 1000 dá-te um numero em segundos e daí calculas horas.

A uns tempos num programa que tambem necessitava de algo semelhante fiz assim:

#define  MILISECONDS_IN_DAY  86400000UL // 86400000 milliseconds in a day
#define  MILISECONDS_IN_HOUR  3600000UL // 3600000 milliseconds in an hour
#define  MILISECONDS_IN_MINUTE  60000UL // 60000 milliseconds in a minute
#define  MILISECONDS_IN_SECOND   1000UL // 1000 milliseconds in a second
// o teu programa ...
void printTime(long val)
{  
 uint8_t days = val / MILISECONDS_IN_DAY ;                               
 uint8_t hours = (val % MILISECONDS_IN_DAY) / MILISECONDS_IN_HOUR;                     
 uint8_t minutes = ((val % MILISECONDS_IN_DAY) % MILISECONDS_IN_HOUR) / MILISECONDS_IN_MINUTE ;         
 uint8_t seconds = (((val % MILISECONDS_IN_DAY) % MILISECONDS_IN_HOUR) % MILISECONDS_IN_MINUTE) / MILISECONDS_IN_SECOND;
 
  // digital clock display of current time
  Serial.print(days,DEC);  
  printDigits(hours);  
  printDigits(minutes);
  printDigits(seconds);
  Serial.println();  

  
}
void printDigits(byte digits){
  // utility function for digital clock display: prints colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits,DEC);   
}

Obtento o numero de segundos com a funçao millis() , passas esse valor na funçao printTime() e sera impresso na consola na forma de tempo 00:00:00

tecnisol:
Boas,

No projecto que tou a elaborar gostava de ter uma informação da soma de horas de funcionamento de uma bomba ou seja o tempo total em horas em que o rele esteve em high...

Cumprimentos

Não estou a perceber. Isto é um contador com o numero de horas da última (ou actual se a bomba ainda estiver ligada), ou é a utilização desde sempre?
Qualquer que seja a resposta, a implementação é a sugerida nos outros dois posts, mas se for desde sempre, vai ter que ir guardando o valor, por exemplo, na EEPROM.

Isto quer dizer que a questão dos sensores de temperatura está resolvida?

boas,

Luis,

Um das minhas duvidas é a que tu perguntaste pois necessito que guarde os valores para q dê a soma desde o 1º dia da instalação por dai em diante...

Em relação as sondas ando a espera de receber material para fazer uma board nova e testar c novo material...

Assim que tiver tudo pronto volto a mencionar o anterior topico tb ando a ponderar colocar 2 arduino a comunicar um com o outro assim resolveria o problema das sondas tb.

Se utilizar o RTC como o Bubulino refere não será a melhor opção?

Hugo,

O programa q referes é para usar com um RTC?

Ainda não tenho os codigos para usar o RTC que recebi hoje

OK. O programa do HugoPT, praticamente, implementa um RTC através da função millis(). A vantagem do RTC é que normalmente, funciona com uma pilha externa que permite manter a data e hora certas, mesmo depois de uma fala de energia. Outra vantagem do RTC é que ao contrário do contador de milissegundo, sabe-se que chega a zero à meia-noite. O contador de milissegundo, também chega a zero, mas não se sabe quando (ou melhor, não é todos os dias à mesma hora) e assim, o código vai ter que verificar constantemente, se o contador já chegou (ou ultrapassou, desde a última verificação) o zero e se sim, actuar em conformidade. Por estas razões, penso que talvez seja mais fácil implementar a sua aplicação com RTC. A partir daí quando liga o relé deve guardar a data e hora (atenção que se ao passar da meia-noite o relé estiver activo o programa deve saber e deve conseguir fazer os cálculos, por isso, penso que deve ser melhor guardar a data também) e quando desliga o relé, deve guardar também os valores, fazer os cálculos do tempo que o relé esteve activo e deve guardar o valor do "tempo acumulado" em memória não volátil (EEPROM). Normalmente os módulos RTC trazem também (na mesma placa) uma memória EEPROM.

o que tenho é este:
http://www.ebay.com/itm/RTC-I2C-DS1307-AT24C32-Real-Time-Clock-Module-For-Arduino-AVR-ARM-PIC-51-ARM-M2/151485918454?_trksid=p2045573.c100034.m2102&_trkparms=aid%3D555012%26algo%3DPW.MBE%26ao%3D1%26asc%3D20131003150253%26meid%3D33bb258c7550477dbe25eb6357694e31%26pid%3D100034%26prg%3D20131003150253%26rk%3D4%26rkt%3D8%26sd%3D310959068263

Eu tenho por aqui um par deles igual a esse. Não é grande coisa (desacerta bastante), mas por esse preço, também não se pode pedir muito mais. Se não precisar de muita precisão (e não houver problema em perder um par de minutos por mês) é suficiente. Esse é uma das tais placas que já trazem uma memória EEPROM incorporada (é o chip AT24C32 - que se vê na descrição). O RTC propriamente dito é o DS1307. É fácil encontrar na net exemplos de código para fazer esse RTC funcionar.

Encontrei este codigo mas ainda n testei

//Arduino 1.0+ Only
//Arduino 1.0+ Only

#include "Wire.h"
#define DS1307_ADDRESS 0x68
byte zero = 0x00; //workaround for issue #527


void setup(){
  Wire.begin();
  Serial.begin(9600);
  setDateTime(); //MUST CONFIGURE IN FUNCTION
}

void loop(){
  printDate();
  delay(1000);
}

void setDateTime(){

  byte second =      45; //0-59
  byte minute =      40; //0-59
  byte hour =        0; //0-23
  byte weekDay =     2; //1-7
  byte monthDay =    1; //1-31
  byte month =       3; //1-12
  byte year  =       11; //0-99

  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero); //stop Oscillator

  Wire.write(decToBcd(second));
  Wire.write(decToBcd(minute));
  Wire.write(decToBcd(hour));
  Wire.write(decToBcd(weekDay));
  Wire.write(decToBcd(monthDay));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));

  Wire.write(zero); //start 

  Wire.endTransmission();

}

byte decToBcd(byte val){
// Convert normal decimal numbers to binary coded decimal
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)  {
// Convert binary coded decimal to normal decimal numbers
  return ( (val/16*10) + (val%16) );
}

void printDate(){

  // Reset the register pointer
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.write(zero);
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  int second = bcdToDec(Wire.read());
  int minute = bcdToDec(Wire.read());
  int hour = bcdToDec(Wire.read() & 0b111111); //24 hour time
  int weekDay = bcdToDec(Wire.read()); //0-6 -> sunday - Saturday
  int monthDay = bcdToDec(Wire.read());
  int month = bcdToDec(Wire.read());
  int year = bcdToDec(Wire.read());

  //print the date EG   3/1/11 23:59:59
  Serial.print(month);
  Serial.print("/");
  Serial.print(monthDay);
  Serial.print("/");
  Serial.print(year);
  Serial.print(" ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(minute);
  Serial.print(":");
  Serial.println(second);

}

mas tb encontrei muita coisa a falar o que referes qual seria a melhor opção RTC para n vir a ter problemas no futuro?

Não gosto desse código! Pela simples razão que não usa uma biblioteca para implementar as funções de comunicação com o RTC. O que isso vai originar é uma de duas coisas:

  • ou esse código fica no ficheiro do programa, o que vai gerar uma "confusão" desnecessária;
  • ou vai ter que pegar nele e criar a sua própria biblioteca de comunicação com o RTC.

Há várias bibliotecas que implementam a comunicação com esse RTC e que têm tudo o que é necessário. Se pesquisar nesta secção do fórum, vai encontrar muita informação sobre esse tema, pois já foi várias vezes discutido nos últimos meses.

Em relação a qual é o melhor RTC, não sei dizer de cabeça. Teria que ir pesquisar os vários módulos RTC que existem e ver as características deles. Normalmente os que falam de "compensação de temperatura" são muito superiores aos outros. No entanto, penso que esse que tem dá perfeitamente para começar e fazer algo minimamente funcional.

OK vou fazer novas buscas e encontrar outros codigos

O rtc não é necessariamente mais preciso ou melhor.

O ds1307 costuma desviar bastante por dia também. O ds1307 não garante que as leituras são guardadas em caso de falha de energia.

Logo a não ser que o rtc seja usado para mais alguma coisa ou o processador tenha algo que interfira com o millis, não me parece que seja melhor.

Mas isto depende do sistema como um todo.

Bubulino,

fazendo da forma q referes perde a memoria os o n de horas se ficar sem corrente electrica certo? eu ja fiz o teste e no meu caso perdeu a contagem e pretendia algo que mantesse a soma total mesmo com falta de corrente.

O facto de perder a contagem não está relacionado com a forma como é feita a contagem do tempo, mas sim com o local onde é armazenada essa contagem. No caso, para que a contagem não seja perdida tem que ser armazenada na EEPROM.
Pode procurar alguns exemplos na net sobre esse assunto. Aqui no site estão estes dois exemplos (um programa escreve e o outro lê):

Mesmoi Assim tou a ter problema e não estou a ver o porque, quero q comece a contar quando o diferencial for 7ºC e pare de contar aos 3ªC mas o que acontece com este codigo é: começa logo a contar depois para de contar quando for superior a 5ºC e volta a contar abaixo dos 3.

Acerca do Eprom como posso juntar a este codigo? não o estou a entender bem.

// Load RTD library and create new instance
//----------------------------------------------------------------------------
#include <Wire.h>

#include "RTDModule.h"
RTDModule rtd;
String SB1;

int Rele1 = 6;

//----------------------------------------------------------------------------
// Temperature variables
//----------------------------------------------------------------------------
double CYLB,CYLT,COL;

double Sen1 = 0;
double Sen2 = 0;

int Dif1=0;

unsigned char flagHIGH=0;
unsigned long temp1;
unsigned long temp2;
unsigned long tempHL;


//----------------------------------------------------------------------------
// Setup
//----------------------------------------------------------------------------
void setup()

{
  
  rtd.setPins(4,5,2);                                //RTD PT1000 pins 4,5 are digital pins for multiplexer, 2 is analog input
  
  //rtd.calibration( input number, scaler, offset )
  rtd.calibration(0, 0.120270927, -15.066198679);   //INPUT 0 pin 12
  rtd.calibration(1, 0.120821076, -13.824162893);   //INPUT 1 pin 14
  rtd.calibration(2, 0.120400012, -14.91327759);    //INPUT 2 pin 15
      
  analogReference(INTERNAL);                        //Set reference to 1.1V ready for RTD measurements

  Serial.begin(9600);
  pinMode (6, OUTPUT);
}

//----------------------------------------------------------------------------
// Main loop
//----------------------------------------------------------------------------
void loop()
{
  delay(1000);
  //Get temperatures and pass through digital low pass filter
  
  COL = digitalLowPass(COL, rtd.getTemperature(0) ,0.90);
  CYLB = digitalLowPass(CYLB, rtd.getTemperature(1) ,0.90);
  CYLT = digitalLowPass(CYLT, rtd.getTemperature(2) ,0.90);
  
  //Print temperatures out to serial
  Serial.print ("Sensor 1: ");
  Serial.println(COL);
  Serial.print("Sensor 2: ");
  Serial.println(CYLB);
  //Serial.print("Sensor 2: ");
  //Serial.println(CYLT);
  
  lcd.clear(); 
  
  Sen1=COL;
  Sen2=CYLB;
  
  Dif1=int(Sen1-Sen2);
  
  if(Dif1 <= 3){Bomba1_Off();}else if (Dif1 >=7){Bomba1_On();}
  
  
Displaybomba();

}

void Bomba1_On(){
  
digitalWrite(Rele1, LOW); 
SB1="ON";
     temp1=millis();
     flagHIGH=1;  
}
 
void Bomba1_Off(){
digitalWrite(Rele1, HIGH);
SB1="OFF";
          temp2=millis();
          tempHL=(temp2-temp1)/1000;
          flagHIGH=0;
          Serial.println(tempHL);
  }

  //----------------------------------------------------------------------------

//Digital low pass filter
double digitalLowPass(double last_smoothed, double new_value, double filterVal)
{
  double smoothed = (new_value * (1 - filterVal)) + (last_smoothed * filterVal);
  return smoothed;
}

Como sabes a que temperaturas liga e desliga?
Estas a fazer print das temperaturas e do diferencial para confirmar o que estas a dizer?
Consegues simular as temperaturas com alguma precisao de forma a que a activacao da bomba nao interfira com as leituras?

Bubulino sim tou a fazer o print das leituras e o que vejo n me esta a dar o que pretendo possivelmente porque tou a fazer algo errado dai colocar aqui o codigo

Ok... mas sem vermos algo mais, não é fácil de detectar o que se passa.

Os prints que eu vejo são sim das temperaturas, mas a bomba liga e desliga com base no diferencial. Estás a imprimir o diferencial? Isso não aparece no código que colocaste, daí estar a perguntar.

Estás a fazer isto com temperatura ou com resistências de modo a poderes simular?

Este bocado de código tem coisas que podem causar coisas estranhas.

//isto está aqui a mais, podes fazer a conta com as variáveis COL e CYLB. 
  Sen1=COL;
  Sen2=CYLB;
  
  Dif1=int(Sen1-Sen2);
  Serial.println(Dif1); // faz um print aqui... 
  
  if(Dif1 <= 3)
     Bomba1_Off();
  if (Dif1 >=7)
     Bomba1_On();

Pode também ser o filtro, mas sem saber como estás a simular as temperaturas é impossível de ter a certeza.

sim tens razao vou verificar tudo eu so tou a fazer o print das temperaturas n dos diferenciais mas vou analizar depois informo obrigado