Sleepmode / energiebesparing atmega 328p

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Nocturno
  • Registratie: September 2001
  • Laatst online: 04-07 07:36
Hoi allemaal,

ik ben bezig mijn huis van een aantal sensoren te voorzien , die via RF om de X minuten b.v. de temperatuur moeten gaan doorsturen naar een ontvanger in de meterkast.
de ontvanger (een arduino met rf ontvang module) lees ik via serial met wat java code weer uit, en de data wordt in een mysql db opgeslagen ,waarna ik er allerhande leuke grafiekjes mee kan maken ;)
Deze configuratie heb ik werkend gehad, met een arduino nano + sensor + rf zend module als "zender" aan een usb hub.

het probleem is alleen , de sensoren moeten eigenlijk een tijdje mee kunnen gaan op batterijen.
ik ben daarom aan het onderzoeken hoe een atmega328p zo energie zuinig als mogelijk te laten draaien.

ik heb aan de hand van deze link al een hoop geleerd over wat te doen, zaak is het dus de arduino te lozen en een minimale configuratie te maken rondom de atmega , en deze op zijn interne klok te laten draaien .
ik heb een breadboard versie met een standaard "blink" sketch aan de gang gekregen , met een 8 mhz bootloader via de tutorial hier , ik heb zelf wel wat aanpassingen moeten doen om het werkend te krijgen in avrdude , maar ik denk dat het gelukt is.

mijn vraag is eigenlijk de volgende , ik denk dat ik de temp sensors ( ofwel een onewire DS18B20 , ofwel een DHT11) wel via de atmega van stroom kunnen worden voorzien, als de atmega uit de slaapmode gehaald wordt.
Alleen de rf zender zal vermoed ik wel teveel stroom verbruiken. Die zal denk ik via een transistor achtige schakeling powered moeten worden direct vanaf de batterijen, maar alleen als de atmega "wakker" is .
iemand enig idee wat voor een schakeling ik daar ongeveer voor nodig heb?
de rf zender is er een van het type dat niels bij samenkopen verkoopt , dus het exacte verbruik weet ik niet.

mijn electronica kennis is helaas niet van het nivo om dit op te lossen, maar ik wil het wel graag aan de gang krijgen.
Mocht ik het werkend krijgen deel ik uiteraard mijn ervaringen en code weer met jullie. ;)

Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Waarschijnlijk verbruiken die niet heel veel. Makkelijkste is een zender met gewoon een sleep pin, maar waarschijnlijk doet die het ook wel als je gewoon voeding met een PMOS schakelt, of aarde met een NMOS. Bijvoorbeeld dan gewoon een BS170, met gate naar pin van atmega, source naar aarde, drain naar aarde connectie van de zender. Maak de pin hoog en hij staat aan, en bij laag staat hij uit. Hoe lang het duurt voordat hij aan gaat nadat je die pin hoog maakt is een andere vraag.

Acties:
  • 0 Henk 'm!

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 21:55

Infant

It's a floating Dino!

Zoiets:
RF Aan uit

Als je de TO_ATMEGA pin hoog maakt, staat het device uit. Als je hem laag maakt, staat het device aan.

Als de Atmega in sleep mode gaat, gaan de pinnen mits correct uitgezet, floaten en blijft het device achter de mosfet ook uit.

De twee condensatoren zijn niet echt nodig, en de weerstanden mogen ook een wat hogere waarde hebben.

[ Voor 4% gewijzigd door Infant op 01-01-2013 13:05 ]


Acties:
  • 0 Henk 'm!

  • Megamind
  • Registratie: Augustus 2002
  • Laatst online: 28-02 01:01
Maar die zenders gebruiken toch niet meer dan 20mA? Dan kan je de 5V direct op een pin hangen. Als ik in de datasheet van die dingen kijk gebruiken ze maar 5mA.

[ Voor 25% gewijzigd door Megamind op 01-01-2013 13:28 ]


Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Infant schreef op dinsdag 01 januari 2013 @ 13:03:
Zoiets:
[afbeelding]

Als je de TO_ATMEGA pin hoog maakt, staat het device uit. Als je hem laag maakt, staat het device aan.

Als de Atmega in sleep mode gaat, gaan de pinnen mits correct uitgezet, floaten en blijft het device achter de mosfet ook uit.

De twee condensatoren zijn niet echt nodig, en de weerstanden mogen ook een wat hogere waarde hebben.
Als pinnen gaan floaten heb je je Atmega incorrect in sleep modus gezet. Granted uit mijn hoofd worden de input buffers van nieuwere atmegas uitgeschakeld in sleep modus, tenzij ze als interrupt input worden gebruikt. Maar het blijft beter om te zorgen dat je pinnen altijd gedefinieerd zijn en niet ergens rondfloaten.

Kan dan trouwens nog wel goed idee zijn er pull-ups bij te zetten zoals in dat schema, maar floating is niet wat je wilt.


Als ze maar 5mA gebruiken mag je ze idd rechtstreeks aan een pin hangen van atmega. Maar ik kan dat enkel van de ontvanger vinden, de zender kan ik niet zomaar vinden. Je kan het met een multimeter nameten.

[ Voor 9% gewijzigd door Sissors op 01-01-2013 14:19 ]


Acties:
  • 0 Henk 'm!

  • Infant
  • Registratie: Januari 2008
  • Laatst online: 21:55

Infant

It's a floating Dino!

furby-killer schreef op dinsdag 01 januari 2013 @ 14:16:
[...]
Als pinnen gaan floaten heb je je Atmega incorrect in sleep modus gezet.
In sleep modus wil je zo min mogelijk stroom gebruiken, lijkt mij.

Als je de DDR en PORT registers in de correcte volgorde op 0 zet, gedragen de pinnen zich als tri-state. Als er extern een pull op of down is, is dat wat hun niveau definieert.

Wat is daar mis mee?

Acties:
  • 0 Henk 'm!

  • memphis
  • Registratie: Oktober 2000
  • Laatst online: 20:53

memphis

48k was toen meer dan genoeg.

Als je de hele meetschakeling zelfstartend zou kunnen maken zou je ook via een simpele CMOS logica een timer kunnen maken die het geheel inschakelt, de meeting doet en doorstuurt en weer uitschakelt.

Er zijn mensen die mij een GOD vinden


Acties:
  • 0 Henk 'm!

Anoniem: 83328

die zendmodules trekken geen stroom als de "data" pin niet hoog is. Ze trekken ruim 40mA bij 5V als de "data" pin wel hoog is.

Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Wat is geen stroom? Want daar zit ook nog wel wat verschil in, dus dat zou ik dan even doormeten (als TS).

@Infant, probleem is dat als je input buffers wel aan staan (wat bij oudere atmels volgens mij het geval is, en bij nieuwere hangt het af van de instellingen), en je uitgang zweegt ergens halverwege, dan verbruiken die input buffers hoop stroom (zijn gewoon inverters).

Als je externe pull-ups hebt kan je ook gewoon interne pull-ups aan zetten. Je kan ze ook gewoon hard hoog/laag maken zolang er verder geen weerstand/soortgelijks aanhangt: Als je een led bijvoorbeeld eraan hebt zitten moet je uiteraard niet hem hoog maken in slaapstand, maar als er niks aan zit, of in jouw schema een PMOS gate, dan verbruikt hij niks als je hem hoog zet.

Acties:
  • 0 Henk 'm!

  • SA007
  • Registratie: Oktober 2002
  • Laatst online: 00:01

SA007

Moderator Tweaking
Wat dan een goed idee is bij de zender.
Waarschijnlijk heb je met een zender en een tempsensor en een atmega veel pinnen over.

Als je dan pinnen bij elkaar trekt kan je meer mA aan dan de maximale 20.
Als ik me niet vergis mag de volledige chip 200mA trekken.

Dus als je een complete poort pakt (of minder, maar is misschien lastig) en dan alle pinnen aan elkaar koppelt kan je 160mA trekken.
Moet je wel in je software goed opletten dat je de hele poort als geheel aanstuurt, maar dat werkt prima.
Heb zelf verschillende opstellingen zo om bijv relais te schakelen zonder extra transistor.

Hele poort tegelijk doe je simpelweg met:
DDRx = 0xFF; // Alles output (in je init)
PORTx = 0xFF; // Alles aan
PORTx = 0; // Alles uit

En zorgen dat je nergens anders die poort adresseert.

Acties:
  • 0 Henk 'm!

  • Nocturno
  • Registratie: September 2001
  • Laatst online: 04-07 07:36
ik heb de volgende sketch geprobeerd , maar ik krijg de sensor niet uitgelezen als ik hem power over een van de uitgangen van de atmega.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <OneWire.h>
#include <DallasTemperature.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
#define SENSOR_POWER 8
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// watchdog interrupt
ISR (WDT_vect) 
{
  wdt_disable();  // disable watchdog
}

void myWatchdogEnable() 
{
  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset
  WDTCSR = _BV (WDCE) | _BV (WDE);
  // set interrupt mode and an interval 
  WDTCSR = _BV (WDIE) | _BV (WDP3) | _BV (WDP0);    // set WDIE, and 8 seconds delay
  wdt_reset();  // pat the dog

  // disable ADC
  ADCSRA = 0;  

  // ready to sleep
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();

  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);
  MCUCR = _BV (BODS); 
  sleep_cpu ();  

  // cancel sleep as a precaution
  sleep_disable();
} 


void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // Start up the library
  sensors.begin();
}

void loop(void)
{ 
 
  // power up sensor chip
  digitalWrite (SENSOR_POWER, HIGH);
  pinMode (SENSOR_POWER, OUTPUT);
  delay(1500);
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  //Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  //Serial.println("DONE");
  
  //Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));  
  delay(1000);
  // finished with sensor
  pinMode (SENSOR_POWER, INPUT);  
  digitalWrite (SENSOR_POWER, LOW);
   // sleep for a total of 64 seconds (8 x 8)
  for (int i = 0; i < 1; i++)
    myWatchdogEnable (); 
}


ik upload de code via een ftdi breakout board, en als ik de power daarvandaan haal krijg ik netjes de temperatuur te zien.
als ik pin 14 van de atmega meet , wordt die ook netjes 5v voor een aantal seconden ( heb ik de code met deplays geprobeerd de sensor wat meer tijd te geven). de sensor geeft "85" terug, wat een foutstatus is , dus hij doet wel iets.
switch ik de power naar de 5v van de ftdi krijg ik netjes de temperatuur terug.
de sensor is een ds1820.

ik lees op microcontroller forums wel iets over dat de temp conversie meer power kost of zoiets ,maar dat kon ik niet helemaal volgen.

Acties:
  • 0 Henk 'm!

  • Nocturno
  • Registratie: September 2001
  • Laatst online: 04-07 07:36
hmzz , het lijkt erop dat de gettempbyindex de boosdoener is , ik heb nu de sketch aangepast zodat ik in de setup al het adres van de sensor bepaal, waarna ik rechstreeks de temp kan lezen, dat lijkt beter te gaan.

volgende stap.. de zender er aan.

[ Voor 7% gewijzigd door Nocturno op 04-01-2013 19:35 ]


Acties:
  • 0 Henk 'm!

  • jeroen3
  • Registratie: Mei 2010
  • Laatst online: 06:37
@furby killer, 9.10.6 in de user manual.
In sleep modes where both the I/O clock (clkI/O) and the ADC clock (clkADC) are stopped, the input buffers of the device will be disabled.
Het is even de moeite waard om de manual goed door te lezen.

Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
jeroen3 schreef op vrijdag 04 januari 2013 @ 21:14:
@furby killer, 9.10.6 in de user manual.

[...]

Het is even de moeite waard om de manual goed door te lezen.
Oftewel exact wat ik zei: Standaard staan ze uit, al hangt het van je instellingen af (en in welke sleep modus je gaat).

Acties:
  • 0 Henk 'm!

  • Tarquin
  • Registratie: Januari 2002
  • Laatst online: 26-06 23:50
Je gebruikt de 18B20 temperatuur sensor. Je kunt er een dozijn van op een meterslange twee-aderige kabel zetten. Met als gevolg dat je Arduino die het zaakje aanstuurt ergens in de buurt van een stopcontact kan uitkomen.
Zelfs als dat niet lukt is het goedkoper op één Atmega 10 sensors uit te laten lezen dan elke sensor zijn eigen atmega te geven.

Acties:
  • 0 Henk 'm!

  • Nocturno
  • Registratie: September 2001
  • Laatst online: 04-07 07:36
@Tarquin , dat begrijp ik wel , maar ik wil er een in het tuinhuis , 1 boven en 1 beneden hebben. Er kunnen ook nog andere sensoren aan komen. daarbij vind ik het overbodig om adapters 24/7 te laten draaien om 5v te leveren voor de arduino.Dan gebruik ik liever oplaadbare batterijen.


en het is natuurlijk een leuk project om eens wat meer te leren over microcontrollers ,sleepmode enz ;)

[ Voor 14% gewijzigd door Nocturno op 08-01-2013 07:24 ]


Acties:
  • 0 Henk 'm!

  • Nocturno
  • Registratie: September 2001
  • Laatst online: 04-07 07:36
even een updateje , ik heb het werkend, ik heb de power voor de zender gewoon aan een ander poortje gehangen, en geprobeerd, dat lijkt te werken, voor de sensor heb ik een 2.2k weerstand gebruikt ipv de 4.7k die er normaal aan hangt, omdat hij op 3.3v niet goed meer wou meten anders.
zal mij benieuwen hoe lang de batterij meegaat.
hij logt nu om het kwartier.

Acties:
  • 0 Henk 'm!

  • Sissors
  • Registratie: Mei 2005
  • Niet online
Gooi eens je multimeter ertussen om de stroom te meten als hij in sleep-mode staat.

Acties:
  • 0 Henk 'm!

  • Mikey NL
  • Registratie: Februari 2004
  • Laatst online: 02-07 09:04
@Nacturno, is de sketch die je gebruikt nog steeds bovenstaande? Wil zelf binnenkort ook wat spullen gaan bestellen hiervoor (vorige week een Arduino gekocht om mee te testen), zodat ik zelf sensoren kan maken voor m'n NinjaBlock...

Edit: Net trouwens dit gevonden, deze gast heeft het inmiddels zo ver dat hij 1,5 jaar op een CR2032 kan draaien. Hij gebruikt echter geen atmega328, maar een ATTiny... http://mchr3k-arduino.blo...s-sensor-node-part-9.html

[ Voor 34% gewijzigd door Mikey NL op 09-01-2013 16:31 ]


Acties:
  • 0 Henk 'm!

  • Nocturno
  • Registratie: September 2001
  • Laatst online: 04-07 07:36
@Mikey
ik gebruik nu de volgende sketch (iets aangepast).
Let niet op de waarschijnlijk stomme manier van Strings gebruiken, ik ben nu eenmaal java ontwikkelaar ;)
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <VirtualWire.h>

#include <OneWire.h>
#include <DallasTemperature.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include<stdlib.h>

// Data wire is plugged into port 2 on the Atmega
#define ONE_WIRE_BUS 2
// Sensor power from port 8 on the atmega
#define SENSOR_POWER 8
// Transmitter power from port 6 on the atmega
#define TRANS_POWER 6
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
DeviceAddress insideThermometer;
String stringOne, stringTwo,stringTot;
// watchdog interrupt
ISR (WDT_vect) 
{
  wdt_disable();  // disable watchdog
}

void myWatchdogEnable() 
{
  // clear various "reset" flags
  MCUSR = 0;     
  // allow changes, disable reset
  WDTCSR = _BV (WDCE) | _BV (WDE);
  // set interrupt mode and an interval 
  WDTCSR = _BV (WDIE) | _BV (WDP3) | _BV (WDP0);    // set WDIE, and 8 seconds delay
  wdt_reset();  // pat the dog

  // disable ADC
  ADCSRA = 0;  

  // ready to sleep
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  
  sleep_enable();

  // turn off brown-out enable in software
  MCUCR = _BV (BODS) | _BV (BODSE);
  MCUCR = _BV (BODS); 
  sleep_cpu ();  

  // cancel sleep as a precaution
  sleep_disable();
} 


void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
//power up sensor first time , to get adress
  digitalWrite (SENSOR_POWER, HIGH);
  pinMode (SENSOR_POWER, OUTPUT);
  delay(500);
  // Start up the library
  sensors.begin();
  if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0");

stringOne = String("SN1:");  //length4
stringTwo = String("TEM:"); //length4
stringTot = String();

//setup rf communication
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);  // Bits per sec
    vw_set_tx_pin(7);
}

void loop(void)
{ 
 
  // power up sensor +transmitter
  digitalWrite (SENSOR_POWER, HIGH);
  pinMode (SENSOR_POWER, OUTPUT);
  digitalWrite (TRANS_POWER, HIGH);
  pinMode (TRANS_POWER, OUTPUT);
  delay(500);

  sensors.requestTemperatures(); // Send the command to get temperatures
  float tempC = sensors.getTempC(insideThermometer);
  char x[8];
    stringTot = stringOne+stringTwo;
    stringTot = stringTot+dtostrf(tempC, 2, 2, x);
    char s[32];
  //Serial.println(stringTot);

    stringTot.toCharArray(s, 32);
    vw_send((uint8_t *)s, strlen(s));
    vw_wait_tx();
  delay(500);
  // finished with sensor and transmitter
  pinMode (SENSOR_POWER, INPUT);  
  digitalWrite (SENSOR_POWER, LOW);
  pinMode (TRANS_POWER, INPUT);  
  digitalWrite (TRANS_POWER, LOW);
   // sleep for a total of 112X8 seconds 
  for (int i = 0; i < 112; i++)
    myWatchdogEnable (); 
}
Pagina: 1