Economia de Energia e Cálculo de Consumo

Boa tarde a todos. Gostaria da ajuda dos mais experientes quanto ao que se refere a economia de energia no arduino.

Tenho um projeto que pretendo deixar funcionando a pilhas (atualmente: 18650 - 3.7V, 4Ah).

Neste projeto, uso os seguintes componentes :

  • RTC 1307
  • LCD 1602
  • Arduino Nano
  • Resistores e componentes diversos

Acredito que o LCD 1602 é o que me consome mais energia, para tanto, coloquei um LDR na porta analógica A7 e determinei que enquanto a luminosidade for baixa, o backlight do LCD apaga (O display fica em sua maior parte do tempo no escuro, dentro de uma caixa, e só precisa ser aberto quando alguém for programar algo)

Outro detalhe é que enquanto a luminosidade é baixa, além de apagar o LCD, coloquei também a seguinte linha:
Narcoleptic.delay(1500);

Mas as baterias não aguentaram muito tempo mesmo assim, e gostaria de saber como posso calcular o consumo de todo o circuito. Fiz o seguinte:

Coloquei um resistor de 300R entre o positivo das baterias e o restante do circuito (em série), e medi a queda de tensão sobre ele, obtendo 6,15V com o LCD apagado e 7,1V com o LCD aceso.
A partir daí, calculei a corrente, sendo elas respectivamente: 21,6mA e 24,9mA. Uma diferença muito pequena, por isso a dúvida, se fiz corretamente ou não...

Mas, se o cálculo está correto, gostaria de saber então, como calcular a autonomia dessas baterias de 3.7V 4Ah (usei duas de 8,8Ah e uma de 4Ah, e as duas de 8,8Ah foram as que descarregaram pra 0, enquanto de de 4Ah manteve a tensão em 3,7V)

Em último caso, se tudo acima estiver correto ou então o sistema estiver consumindo mais energia, gostaria de saber como posso economizar mais, visto que o Narcoleptic.delay(1500); não teria sido muito eficiente.

Obrigado a todos.

Sabendo o consumo, a autonomia é calculada facilmente. Neste caso, com um consumo de 21,6mA e uma capacidade de 4Ah (este valor precisa de ser convertido para mAh e isso dá 4000mAh) deverá ter uma autonomia de 183h, aproximadamente.
Deve estar a explicar mal alguma coisa, pois quando eu faço os cálculos (a partir dos valores que forneceu) do consumo obtenho outros valores. Penso que a resistência tem um valor muito alto (e consequentemente uma queda de tensão muito elevada também), o que pode interferir nos valores medidos. O meu conselho é que obtenha uma resistência de precisão e com um valor bastante mais baixo e um bom aparelho de medida (que lhe permita medições com precisão de valores de tensão na ordem dos milivolt). Repare que a medição não deve interferir nos valores que estão a ser medidos (e não me parece que isso esteja a acontecer com quedas de tensão de 6V).

Estranho mesmo é que no datasheet do display (http://www.oarduino.com/download/arquivos/datasheets/Datasheet_DisplayLCD%20HD44780.pdf) diz que o led pode variar de 100 a 200mA... Qual seria a autonomia de uma bateria de 4200mAh pra esse led?

Isso não é o datasheet do módulo que está a utilizar. Isso é um documento genérico que descreve o protocolo de comunicação deste tipo de módulos e pouco mais. Por outro lado esses valores de corrente estão relacionados com a tensão de alimentação. Ao retirar 6V à tensão de alimentação, também a corrente vai ser muito inferior. Se tiver uma bateria com uma capacidade de 4200mAh e consumir 200mA, "é só fazer as contas"! Neste caso teria uma autonomia de 21h (e nem é necessário usar calculadora).

Quando fui pesquisar cálculos de autonomia de bateria, dizia a potência ser um parâmetro conhecido para o cálculo. Eu calculei 21h mas não achei que fosse realmente dessa facilidade.

Mas prosseguindo, não tenho um voltímetro preciso comigo, nem uma resistência pequena, portanto, utilizei um de 45R (valor real) e medi uma queda de 1,25V, obtendo 27,8mA (LCD aceso) e 20mA (LCD apagado) Porém, a bateria já tinha descarregado para 6,78V.

Enfim, não estou conseguindo tempo satisfatório, e gostaria de saber como posso consumir menos energia possível. O display já está programado para apagar quando o sistema estiver fechado, e o arduino "dorme" enquanto isso (Narcoleptic). Alguma sugestão?

Caso alguém precise do código para analisar possíveis gastos desnecessários:

Update do código (Coloquei toda a rotina do loop dentro da condição 'Luz Acesa', ou seja, tudo só será executado se o LCD estiver em claro, caso contrário, não irá ler nada, exceto as saídas programadas)

Timer.ino (14.8 KB)

TimerUpdate.ino (14.6 KB)

#1 - Nao uses um Arduino... ou tira-lhe os LEDs.

#2 - Usa um transistor para regular a iluminacao do LCD... e desliga-lo completamente quando precisares.

#3 - Desliga o que nao estas a usar. Se nao usas timers, desliga-os. Se nao usas o ADC ou SPI, desliga-os.

#4 - Se nao estas a usar alguns pinos, coloca-os num estado conhecido (activar o pull-up por exemplo).

#5 - Pesquisa como parar o timer0 (e por consequencia o millis) e como ligar de volta e adapta o codigo para funcionar correctamente.

#6 - Aprende a ler os portos sem usar a digitalRead/digitalWrite. simplesmente porque essas funcoes demoram bastante mais a processar e e tempo que o processador come bateria.

#7 - NUNCA USES A FUNCAO DELAY!!!!! Isso e literalmente contar carneirinhos.

#8 - Ao usar modos sleep, pesquisa qual e o que consome menos bateria e vai por esse. Teras de adaptar o teu codigo e usar watchdog, etc... mas consegues muito mais rendimento.

#9 - Se estas apenas a usar a porta serie para debug, faz uma versao de codigo sem ela para testes de consumos.

#10 - Se nao usares um Arduino, usa uma frequencia de clock inferior.

#11 - Se nao usares o Arduino, nao tens o conversor da UART apra USB a consumir.

#12 - Se nao usares um Arduino podes encontrar um conversor de tensao que seja mais eficiente e poupe mais a bateria...

Ve este site:

http://jeelabs.org/2011/06/26/current-measurements/
http://jeelabs.org/book/1449d/
http://jeelabs.org/tag/lowpower/

Obrigado Bubulindo! Referente aos itens citado, poderia me dar uma mão nos marcados com *?

#1 - Ok, removerei.

*2 - Fazendo um digitalWrite(6,LOW) não estarei desligando o LCD completamente?

#3 e #5 - OK! (ArduinoProg: Como economizar o consumo de energia do Arduino)

#4 - OK! (Usei pull-down)

*6 - Não entendi como realizar mudança ou leitura de estado de outra forma. (Pesquisei como ler portas digitais no arduino e todos usavam a mesma forma)

#7 - Já retirei do código.

#8 - Verei se consigo usar o modo SLEEP_MODE_PWR_DOWN.

#9 - Ok, removerei.

O item #8 será o mais complicado para mim (Relógio digital no Arduino, com interrupções e uso do maior modo de economia de energia) mas vou me esforçar a tentar.

Novamente obrigado.

PS: Item #8 -> Preciso acordar o arduino em duas ocasiões (1: LDR > 0; 2: Horário programado == Horário Real + Timer programado;), mas não consegui ainda.

Se não me engano esse RTC tem uma saída de interrupção que pode ser utilizada para acordar o Arduino (isto pode ser usado para a situação 2). A outra situação também poderia ser ligada a uma entrada de interrupção.

Estou tentando esse aqui (ATmega328P wakeup from sleep via interrupt - heliosoph), mas não consigo entender como usar esse Square Wave Output..

Estou me baseando nessas fontes:

http://combustory.com/wiki/index.php/RTC1307_-_Real_Time_Clock
http://forum.arduino.cc/index.php?topic=228079.0
http://www.glacialwanderer.com/hobbyrobotics/?p=12

Mas não está fácil não kkk. Vou ver o que consigo.

2 - Para fazeres esse digitalWrite, vais ter de meter um transistor. Se tens um transistor, porque nao usar PWM e ajustar a luminosidade com PWM em vez de ser com queima de energia atraves de resistencias? Uma coisas e ligares e desligares, outra e ligares, desligares e ajustares luminosidade (poupando energia).

6 - tens de pesquisar por ler/escrever portos em AVR, ou pesquisar por uma biblioteca FastWrite ou algo do genero.

8 - Podes usar o watchdog do microcontrolador.

Estou quase conseguindo o #6, mas não consigo transcrever isso:

digitalWrite(6, LOW);
digitalWrite(6, HIGH);

para isso:

PORTD &= ~(6 << PORTD6);
PORTD |= (6 << PORTB6);

Ele simplesmente não torna sinal baixo ou alto.

Só consigo sinal alto desta forma
PORTD = PORTD | B01000000; //D6 como HIGH; Restante como LOW ("digitalWrite(6, HIGH);")

Sinal baixo desta forma não funciona também
PORTD = PORTD | B00000000;

PS: Percebi que se tirar o delay no final do loop, o cursor do lcd fica quase apagado, pouco visível. Para tentar amenizar, coloquei o menor delay necessário para tornar o cursor visível (50).

yago4xd:
Estou quase conseguindo o #6, mas não consigo transcrever isso:

digitalWrite(6, LOW);
digitalWrite(6, HIGH);

para isso:

PORTD &= ~(6 << PORTD6);
PORTD |= (6 << PORTB6);

Ele simplesmente não torna sinal baixo ou alto.

Só consigo sinal alto desta forma
PORTD = PORTD | B01000000; //D6 como HIGH; Restante como LOW ("digitalWrite(6, HIGH);")

Sinal baixo desta forma não funciona também
PORTD = PORTD | B00000000;

PS: Percebi que se tirar o delay no final do loop, o cursor do lcd fica quase apagado, pouco visível. Para tentar amenizar, coloquei o menor delay necessário para tornar o cursor visível (50).

Se funciona assim:

PORTD = PORTD | B01000000;

Também tem que funcionar assim:

PORTD |= B01000000;

e tamém tem que funcionar assim:

PORTD |= PORTD6;

certo?

Onde foi buscar isto?

PORTD |= (6 << PORTB6);

Assim:
PORTD = PORTD | B01000000;
e assim:
PORTD |= B01000000;
Funcionam...

Mas assim:
PORTD |= (6 << PORTB6);
e assim:
PORTD |= PORTD6;
Não funcionam...

Então tente:

PORTD |= (1 << PORTD6);

e

PORTD &= ~(1 << PORTD6);

Repare também nas notas das páginas: "Para acompanhar esse tutorial é necessário algum conhecimento de lógica digital."

Funcionou kk.

Obrigado. Tive a infelicidade de associar o exemplo da fonte incorretamente. Ele utilizou o pino digital 9, cujo a porta é PORTB1, aí pensei que esse 1 fosse referente ao pino desejado, mas aí li essa frase com mais atenção:

"Para definir um pino como alto devemos setar seu respectivo bit do registrador PORT como 1 e para defini-lo como baixo seta-lo para 0."

E entendi agora.
Vlw. Agora vou tentar voltar ao modo economia de energia/wake RTC e LDR

TimerUpdate.ino (15 KB)

Boa tarde. Estava dando uma lida em WatchDog para poder implementar o modo econômico de energia e vi que sua função é resetar o sistema após passado o tempo definido (WDTO_2S ou WDTO_8S, por exemplo).

Porém, esse reset não é interessante para o meu sistema, pois desta forma eu perco a programação realizada pelo usuário (O usuário pode programar três horários diferentes via botão para que a saída seja acionada).

Ao fazer o reset, ele perde as três programações. Por acaso não existe um meio de salvar as programações pelo usuário né (hora, minuto, segundo , timer; hora2, minuto2, segundo2, timer2; hora3, minuto3, segundo3, timer3 --> São nestas variáveis que ficam armazenadas a programação do usuário).

TimerUpdate.ino (14.1 KB)

Tu tens uma memoria EEPROM no chip. Usa-a.

O watchdog reset pode apenas gerar uma interrupcao e nao fazer reset ao chip... Se calhar e essa a opcao que te interessa.

Ok. Obrigado pela direção. Vou rumar nesse trilho.

Só um parênteses fora do assunto em questão. É possível que uma condição if/else seja executada simultaneaente?

if (hour == hora && minute == minuto && second >= segundo && second < segundo + timer)  {
    PORTD |= (1 << motor);
    saida = 1;
  } else {
    if (saida2 == 0 && saida3 == 0) {
      PORTD &= ~(1 << motor);
      if (saida == 1) {
        saida = 0;
        retorna();
      }
    }
  }

Quando o horário atinge o programado, o motor fica em um estado intermitente, até que passe o timer programado, ou seja, ele lê o if e depois (logo em seguida) o else. Já ocorreu algo assim antes em outros casos?

Quanto ao EEPROM, já consegui realizar as adaptações de escrita e leitura. Agora irei adaptar o modo SLEEP_MODE_PWR_DOWN