Welcome to the fifth and final part of the "Sleeping Arduino" series, where we will cover how to wake the Arduino from sleep mode using the Watchdog Timer (WDT). When waking your Arduino from sleep, you could use one of the standard internal timers of an Arduino as I have detailed in Part 4, but if you are looking for the maximum sleep time and/or minimum sleep power consumption, you have the use the WDT;
As I have mentioned in this table, the WDT can give us a sleep time of 8 seconds, whereas the 'longest' 8/18bit timer will only give us a sleep time of ~4 seconds.
Watchdog Timer (WDT)
The Watchdog Timer on the Arduino's microprocessor only has one source to drive it: it's own separate internal 128kHz oscillator (as opposed to the 8/16bit internal timers, which can use either the 16Mhz system clock or an external clock). It is this separate oscillator that enables the WDT to function in the lowest power mode: SLEEP_MODE_PWR_DOWN (see here for more detailed info on the Arduino's power modes).
The WDT also has a prescaler, which is used to configure the timeout period. It supports timeout periods from 16ms to 8 seconds:
Also it has three modes of operation:
- Interrupt - The WDT_vect interrupt sub-routing will be called when the WDT times out. Can be used to wake the micro from sleep modes, including the lowest power sleep mode (SLEEP_MODE_PWR_DOWN), where other timers are not available.
- System Reset - A watchdog time-out reset will occur, i.e. the micro-controller will be restarted. For use in handling code lockups.
- Interrupt and System Reset - First the WDT_vect interrupt sub-routing will be called, when completed a watchdog time-out reset will occur.
Please refer to my post here for the other operation modes of the WDT. The post is for the Atmega1281, but the functionality is pretty much the same.
Code
So, we will be using interrupt mode in our code to wake the Arduino from sleep every 8 seconds to toggle the state of the LED:
/* * Sketch for testing sleep mode with wake up on WDT. * Donal Morrissey - 2011. * */ #include <avr/sleep.h> #include <avr/power.h> #include <avr/wdt.h> #define LED_PIN (13) volatile int f_wdt=1; /*************************************************** * Name: ISR(WDT_vect) * * Returns: Nothing. * * Parameters: None. * * Description: Watchdog Interrupt Service. This * is executed when watchdog timed out. * ***************************************************/ ISR(WDT_vect) { if(f_wdt == 0) { f_wdt=1; } else { Serial.println("WDT Overrun!!!"); } } /*************************************************** * Name: enterSleep * * Returns: Nothing. * * Parameters: None. * * Description: Enters the arduino into sleep mode. * ***************************************************/ void enterSleep(void) { set_sleep_mode(SLEEP_MODE_PWR_SAVE);
/* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
sleep_enable(); /* Now enter sleep mode. */ sleep_mode(); /* The program will continue from here after the WDT timeout*/ sleep_disable(); /* First thing to do is disable sleep. */ /* Re-enable the peripherals. */ power_all_enable(); } /*************************************************** * Name: setup * * Returns: Nothing. * * Parameters: None. * * Description: Setup for the serial comms and the * Watch dog timeout. * ***************************************************/ void setup() { Serial.begin(9600); Serial.println("Initialising..."); delay(100); //Allow for serial print to complete. pinMode(LED_PIN,OUTPUT); /*** Setup the WDT ***/ /* Clear the reset flag. */ MCUSR &= ~(1<<WDRF); /* In order to change WDE or the prescaler, we need to * set WDCE (This will allow updates for 4 clock cycles). */ WDTCSR |= (1<<WDCE) | (1<<WDE); /* set new watchdog timeout prescaler value */ WDTCSR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */ /* Enable the WD interrupt (note no reset). */ WDTCSR |= _BV(WDIE); Serial.println("Initialisation complete."); delay(100); //Allow for serial print to complete. } /*************************************************** * Name: enterSleep * * Returns: Nothing. * * Parameters: None. * * Description: Main application loop. * ***************************************************/ void loop() { if(f_wdt == 1) { /* Toggle the LED */ digitalWrite(LED_PIN, !digitalRead(LED_PIN)); /* Don't forget to clear the flag. */ f_wdt = 0; /* Re-enter sleep mode. */ enterSleep(); } else { /* Do nothing. */ } }
All parts of this series:
- Part 1 Overview Of Arduino Sleep Modes
- Part 2 Wake Up Via An External Interrupt
- Part 3 Wake Up Via the UART
- Part 4 Wake Up Via Internal Timer
- Part 5 Wake Up Via The Watchdog Timer
References
thanks for this
ReplyDeleteHi, thanks for your articles first.
ReplyDeleteDoes it work only for Arduino Diecimila?
I'm trying to run it on my Arduino UNO but the sketch returns me some strange characters
C¡ªËë šÙ•±¥½…<0> instead of a simple test print i wrote.
void loop()
{
if(f_wdt == 1)
{
/* Toggle the LED */
Serial.println("Hello!");
/* Don't forget to clear the flag. */
f_wdt = 0;
/* Re-enter sleep mode. */
enterSleep();
}
else
{
/* Do nothing. */
}
}
Thanks
Hi NicolaG,
ReplyDeleteYes, the code should work on your UNO. The strange characters could be because of your serial port settings aren't correct.
Check the baud rade that you have set in the Arduino pc software and check the value you have set in code using the Serial.begin(...) function.
Donal
First of all thanks a lot for the article, I'm newbe but i understand a lot of thinks... i think :-)
ReplyDeleteI just want to ask ... is possible to put the arduino in sleep mode and also use an interrupt pulse counter ?
But what i need is a timer that tell me how much time
is between pulses...
Thanks a lot again
Denis
Hi Denis,
ReplyDeleteYou probably will be able to do this a sleep mode, but not the lowest power sleep mode (power-down).
If you have a look at the excerpt from the datasheet here:
http://2.bp.blogspot.com/_9WOJMofzxU0/S9PyagiuISI/AAAAAAAAHY8/tGlOUPRmano/s400/Picture+1.png
You can see the different sleep modes and what hardware modules are supported within it.
I think you will need to wake the board from sleep using the external interrupt(count the pulses) You could then use one of the timers to check the time between interrupt pulses.
Hope this helps.
Donal
Thanks a lot Donal,
ReplyDeletegreat think all this timers on the tabel.
I think i'll try using an external crystal (32MHz)
This weekend i'll play :-)
Thanks again
Denis
Thanks for this, very good.
ReplyDeleteHow about if I just want to wake the arduino every hour?
How can I set that?
Thanks, great article!
Joao, Portugal
Hi Joao,
ReplyDeleteThank you for the feedback. If you want a very long sleep time: several minutes or hours, I'd suggest using an external real-time clock, such as:
http://proto-pic.co.uk/deadon-rtc-ds3234-breakout/
Something like this could generate an external interrupt to wakeup the Arduino.
Best Regards,
Donal
Hey, great tutorials, keep up the neat work.
ReplyDeleteDo you know if it is possible to combine the wake from interrupt and the watchdog ? I'm asking because I would like to build a low power board that transmits temp data every 5 minutes, but should also wake up on a PIR interrupt.
Thanks in advance,
Eric
This is really great, thanks! I wasn't able to get anywhere with the use of sleep modes by following the threads on the Arduino forums, but you've made it much more clear. I'm going to be using these concepts in the code for a project I'm writing up for MAKE magazine.
ReplyDeleteCan you tell me, is there a way to put an Arduino to seep so that it won't wake up until the power is cycled (or it is reset)?
I have a gizmo that counts down for several minutes (or even hours) before it performs a single action, and then it doesn't do anything else until it is restarted. I would like it to essentially shut itself off after it performs the action, but the issue is complicated because I am using the watch dog timer with an 8s delay to preserve power during the initial count-down phase.
Of course, after the action is complete, I can just make it go right back to sleep every time it wakes up, but I'm looking for a more elegant solution. Is there a way to switch from an 8s watch dog to _no_ watch dog once the code is already looping?
Thanks again for this great site, and for any other suggestions you may be able to give me.
Hi Tom,
ReplyDeleteThank you for the feedback, always good to hear that people are finding the site helpful.
I think it would be as straight forward as disabling the watchdog interrupt before entering the SLEEP_MODE_PWR_DOWN sleep mode.
I don't have access to my Arduino at the moment to test this, so if you get to test this before I do, please let me know if it works :-)
Cheers,
Donal
Thanks for work on Power Save, this has saved me many hours.
ReplyDeleteHow do I change the test PIN from 13 to 4 ?
Just changing #define LED_PIN (13) to (4) doesn't do the trick?
I have a WiFiRedback and am trying very hard to teach it and me how to make it sleep since battery operation is essential.
Any chance you have info on how to make the WiFi part (MRF24WBOMA) sleep using DTIM beacon, then though SPI from the Arduino (Nano) wake up the WiFi? I'm completly stumped.
thanks,
Hi Jerry,
ReplyDeleteI've plenty of experience with XBee modules, but unfortunately I have no experience with the MRF24WBOMA radio module or the WiFiRedback.
Sorry I can't be of more help.
Cheers,
Donal
How about how to change froom PIN 13 to PIN 4 ?
DeleteThanks, your work here is very helpful.
Hi Jerry,
DeleteIf you want to control an LED from PIN 4, you will need to configure the mode of the pin to be an output. You will need to do this in your setup() function.
pinMode(LED_PIN, OUTPUT);
Hope that helps,
Cheers,
Donal
Again, thanks! That did the trick. Hum didn't understand where PIN 13 was made an OUTPUT. Must have been in one of the headers.
DeleteThanks for the article.
ReplyDeleteWhen running the code it appears to put the arduino into a lower power mode for execution - ie the LED is only dimly lit. How would I modify the code so that the board runs at full power when not in sleep? I'm using an Uno (AtMega 328P), don't know if that may be causing problems?
What is the current consumption under SLEEP_MODE_PWR_DOWN mode for wdt enabled? and wdt disabled?
ReplyDeleteHi I'm trying to use this code in my arduino uno, but it doesn't works, the serial show a different character "III" the baud rate is correct, the led doesn't change the state. Maybe you can help me.
ReplyDeleteThanks for now
luis
Hi I have a similar problem that luis with arduino uno, it doesn't write anything in the serial monitor at (9600 bauds)and the led is always "on". Any suggestion?
ReplyDeleteHi Guys,
ReplyDeleteI will get my hands on an Arduino Uno and test the software.
Donal
This comment has been removed by the author.
ReplyDeleteI solved the problem with arduino UNO: pinMode(LED_PIN, OUTPUT); into SETUP LOOP solves the led problem.
ReplyDeletethe problem of communication is due to the microcontroller has a small delay in initialization, and it goes to sleep too faster before to finish the transmission (or something like that), a delay(50); solves this problem.
Regards
Excellent Emos,
DeleteI'm due to receive my UNO tomorrow, I will update the source code during the weekend.
Best Regards,
Donal
Donal,
ReplyDeletecould you explain how to use a RTC to sleep the arduino and wake it up? Thanks
Does anyone use the watchdog timer on the Geogram One to extend the battery life?
Deletehttp://dsscircuits.com/geogram-one.html
Hi Woodmate,
DeleteI have one of these Arduino data logging shields http://learn.adafruit.com/adafruit-data-logger-shield - which has a real time clock. Only problem is I can't find the shield! I'll search again and if I find it write a post on using it to wake the Arduino.
Best Regards,
Donal
That'd be great Donal
DeleteI have tried code,sleeping-arduino-part-3-wake-up-via uart and this is works ! mm but If I want to awake arduino with serial data which I choose (ex: just send character "A" and then arduino wake up ) /not receiving any serial data ? I really2 confuse,, I start depressed because that, can you help me ?? plis T___T
ReplyDeleteHi yuliaRetno,
DeleteI don't think it is possible to wake up via a particular character. As far as I know, the wake up is triggered on either a logical 1 or 0 on one of the serial uart lines.
Cheers,
Donal
hmm, ok sir, can you help me sir ?mm,I find a difficulty from my final project, particularly with wake up sleep arduino with tag rfid (mifare) ,my tag rfid communication with SPI,So I decided wake up with serial uart,
ReplyDeleteActually, it can wake up, but I want to wake up with particularly tag (not all of tag )I confuse in what way I must try to wake up ?
Can I wake up with internal timer or watchdog ?
void sleepNow(){
uint32_t idc ;
idc = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A);// triger
from tag rfid ,,is like serial.available()
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
sleep_disable();}
Hi Yulia,
DeleteI don't think you will be able to wake up via serial uart on a particular tag. What you could do is wake up the microcontroller on all tags, but check the tag immediately and if the tag in not the particular one you want, put the microcontroller back to sleep.
Hope that helps,
Donal
hi, this code seems not to work if i just look on the indicators (Serial and LED toggle).
ReplyDeletePut a delay of 100ms after each serial print and initialize the LED_PIn as output in the setup.
Then its showing what it should (on arduino UNO).
I was searching for a bug in the WDT and Sleep setup for hours.... until i found this simple bug of just initializing the pin.. ;-(..
Hi saperlot,
DeleteCheers for finding that, I have updated the code.
Donal
Hi in my case I'm not able to see the message "WDT Overrun!".
ReplyDeleteI've also added the delay(100) after the Serial.println.
In addition I've moved the MCU on a breadboard but the LED is always on (pin 13 arduino -> pin 19 atmega328p).
Hi Anto,
DeleteThe "WDT Overrun!" is an error message that you will see if your application doesn't clear the f_wdt correctly.
Was the LED flashing correctly if you run the code with your MCU on your Arduino board? If so, then perhaps it is an issue with your circuit on the breadboard? Have you checked you are wiring the LED correctly?
Cheers,
Donal
I've integrated this code with a ZigBee transmission and it doesn't work. The ZigBee transmission works without the watchdog timer and it requires some delay time (5 secs) to work properly. Is the program restarted from the last row executed before the WatchDog interrupt ?
ReplyDeleteHi Anto,
ReplyDeleteThe code is designed to be a basic example that can be extended by the reader if necessary, not a piece of code that will work with all scenarios, so I'm not surprised that you are having issues.
The first line of C code executed when the micro wakes from sleep is 'sleep_disable();' in the'void enterSleep(void)' function.
Can you please post your code so I can have a better idea of what you are trying to do?
Cheers,
Donal
You're right. Thanks in advance for your help.
ReplyDeleteThis is the sketch: http://pastebin.com/Zn2htthL
I've disabled the power saving options to be sure the problem wasn't there.
The transmission is now working. This is the sketch: pastebin.com/tFt2vJRm It's using some power saving options, the power hibernation of the xBee pin and the power_done mode. The problem is that I need to wait for a really long time (about 10 seconds) before I can send a packet. Where am i wrong?
ReplyDeleteHi Anto,
DeleteWill have a look this evening when I get home from work.
Donal
Hi Ando,
DeleteI suspect it is taking 10 seconds for your xBee module to connect to the network once it has exited sleep.
First of all disable the watchdog sleep stuff and test enabling & disabling the xbee sleep.
Also, keep an eye on the Association LED connected to your xbee module. Does it take several seconds to illuminate after the xbee has been taken out of sleep?
Donal
Hello,
ReplyDeleteFirst, I'm sorry about my english, I'm french!
I'm trying to do a datalogger with low power to economise the battery. You say before that if we want 15 minutes of sleeping, we have to use the RTC ds3234. I want to know if it's possible to do it with the DS1307 that I have yet or if I have to buy this one particular? And if it's possible do you some tutorial to do it?
Thanks
Cécile
Hi Cecile,
DeleteI don't think you can use the DS1307 to wake your microcontroller as it doesn't have an alarm feature, whereas the DS3224 does:
DS3224 Features:
...
* Two Time-of-Day Alarms
...
"The clock provides two programmable time-of-day
alarms and a programmable square-wave output. The
INT/SQW pin either generates an interrupt due to alarm
condition or outputs a square-wave signal and the
selection is controlled by the bit INTCN."
I recently got a DS3234 and will try to complete the tutorial for using it this weekend.
Hope that helps!
Donal
Thank you very much for the information!
DeleteSo I will follow with interest your next article!
The informations you give on your diferents posts were very helpful to put my arduino in sleep mode! Now I have to try to reduce more the consumption with a RBBB instead of my arduino!
thanks a lot!
Cécile
Hi Cécile,
DeleteYou can find here Feature Comparison of the DS323x Real-Time Clocks.
Hi donal!
Deletedo you know when you will publish your article about DS3234? I'm very interested on it! I'm trying to program it and I have some dificulties! I hope you can help me!
thanks
Cécile
Hi Donal,
ReplyDeleteThanks for the code that you provided. Very useful!
I created a blog posing using your code, where I measure the current of an Arduino Uno R3 board. It's nice to see how current draw & power consumption changes as you put the microcontroller to sleep. Check out my post: http://www.dossant.com/projects/arduino-low-power/
Thanks,
Igor
Using the code from above, my arduino diecimila only seems to sleep for about 4 seconds, any idea why this might be?
ReplyDeleteHi,
ReplyDeleteI have discovered a possible major problem with - Part 5 Wake Up Via The Watchdog Timer.
I used this code as a test on the Leonardo R3 and now cannot access the board.
I had no problems installing the code to my board, but now whenever I connect the board to the PC the Port tab in Device manager disappears after the first 8 second sleep cycle and does not re-apear.
I have no access to any port information in either the PC or Arduino 1.5.2 Sketchbook.
I have tested my other Arduino boards and they work perfectly.
My Leonardo usually access Ports 11 to 14, but all I have available with the Leonardo now is Ports 3 to 5 (which are already in use)
Do you have any ideas why the sleep cycle cuts off communication to the PC ports (I am assuming it cuts USB communication)?
Do you have any ideas on how I might be able to re-gain access to my Leonardo???
Any help will be appreciated.
Lance.
Hi Lance,
DeleteCan you hold down the reset button until the 'uploading sketch' message appears in the IDE then release it? Please let me know if you can program it that way.
BR,
Donal
Many thanks for that Donal.
DeleteIt took a couple of attempts, but it eventually allowed the IDE to sync with the correct Port and let me upload the blink sketch and has given me full control of the board again (I shall remember this trick for future similar lock ups).
I like the Wakeup with Watchdog Timer, so it would be good to figure out why it severed USB control and find a code fix for this (plus maybe add a loop counter or interrupt to end the Timer).
Thanks again for your great tutorial on Sleep and Wakeups, these have been very educational and useful. I will certainly be using these in my future projects to reduce power usage.
I am soon to start using some ATtiny85 chips in my small projects. Do you foresee any conflicts with this code? (I have not used AT85 chips before. I have the Digispark Tiny 1.04 IDE).
Lance.
Hi Lance,
DeleteGlad you got your board back up and running again! I must get my hands on a Leonardo to see why is it causing a lock-up!
Hmm, I've no experience with the ATtiny85 chips, please share if the code works.
Cheers,
Donal
Hi Donal,
ReplyDeleteThanks for the excellent article.
I have a suggestion for an enhancement.
Instead of delay(100) to wait for the serial transport to finish, you can also use:
Serial.flush();
Older arduino versions would clear the transmit buffers, but > 1.0 will really wait for the transmit to finish.
hi sir
ReplyDeletethank's for this great article !
I tried your sleep wakeup by wdg timer and it works great . now I try to add my own stuff to this and I get surprise
I just begin a SOftwareSerial with a GPS in the setup part I sent few config string to GPS and for now I do nothing in loop part
the result is that it sleep for few ms and stay awake for almost 8sec I dont understand I mad the test several time and if I do not initiate my SoftSerial it works as soon as I do the begin function it fails
do you have any idea ??
thank's for your help
Hi Olivier,
DeleteWhat Arduino are you using? What is the interface with your GPS module?
Can you share your startup code?
Cheers,
Donal
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteHi donal
ReplyDeletethank's for your fast answer
I'm using an arduino NANO 328
I've connected GPS serial on pin 7 and 6 ( https://www.adafruit.com/products/746 )
I' ve also a gsm module connected but I dont care for now
I just copy my source code below
thank's for your kind help
#include
#include
#include
#include
//#include
//#include
//#include
#define GPS_TX_PIN 7
#define GPS_RX_PIN 6
#define GPS_EN_PIN 5
#define GSM_TX_PIN 3
#define GSM_RX_PIN 2
#define GSM_KEY_PIN 8
#define GSM_PS_PIN 9
#define GSM_RST_PIN 4
#define LED_PIN 13
SoftwareSerial myGPSSerial(GPS_TX_PIN, GPS_RX_PIN);
//SoftwareSerial myGSMSerial(GSM_TX_PIN, GSM_RX_PIN);
//Adafruit_GPS GPS(&myGPSSerial);
//Adafruit_FONA FONA(&myGSMSerial,GSM_RST_PIN);
volatile int f_wdt=1; // sleep status ( must always be 0 on wakeup
ISR(WDT_vect) // watch dog interrupt executed just before wakeup
{
if(f_wdt == 0)
{
f_wdt=1;
}
else
{
Serial.println("WDT Overrun!!!");
}
}
void enterSleep(void)
{
Serial.print("SLEEP ... ");delay(100);digitalWrite(LED_PIN,LOW);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* EDIT: could also use SLEEP_MODE_PWR_DOWN for lowest power consumption. */
sleep_enable();
/* Now enter sleep mode. */
sleep_mode();
/* The program will continue from here after the WDT timeout*/
sleep_disable(); /* First thing to do is disable sleep. */
/* Re-enable the peripherals. */
power_all_enable();
Serial.println("WAKEUP");delay(100);digitalWrite(LED_PIN,HIGH);
}
void setup()
{
Serial.begin(115200);
pinMode(LED_PIN,OUTPUT);
Serial.print("Init GPS ...");
delay(100); //Allow for serial print to complete.
myGPSSerial.begin(9600);
Serial.print("Init Watchdog ... ");
delay(100); //Allow for serial print to complete.
MCUSR &= ~(1<<WDRF); // Clear the reset flag.
WDTCSR |= (1<<WDCE) | (1<<WDE); // In order to change WDE or the prescaler, we need to set WDCE (This will allow updates for 4 clock cycles).
WDTCSR = 1<<WDP0 | 1<<WDP3; // set new watchdog timeout prescaler value 8.0 seconds
WDTCSR |= _BV(WDIE); // Enable the WD interrupt (note no reset).
Serial.println("OK");
delay(100);
}
void loop()
{
if(f_wdt == 1)
{
f_wdt = 0;
enterSleep();
}
}
I start to figure out what happends
ReplyDeleteI got the feeling that somthing in soft serial keeps me awake while not resetting the flag (but what ? only WDG INT0 or INT1 can wakeup from deep powerdown mode)
it keeps me awake until wdg interrupt falls reseting flag and allowing loop to go sleeping witch wakes up immediatly again ...
i read softserial lib and see that it register one if of PCINT0 to PCINT3 ididnt understand wicth one but in my case it looks to be PCINT2 that falls and keep me awake
I tried to call softserial.end() that mask RX it :
void SoftwareSerial::end()
{
if (digitalPinToPCMSK(_receivePin))
*digitalPinToPCMSK(_receivePin) &= ~_BV(digitalPinToPCMSKbit(_receivePin));
}
and it works
all what i have to do is to call begin() after wakeup and end() just before
thank's
Hi Olivier,
DeleteSorry for the delay in getting back to you.
Glad to hear you got it sorted! Looking at the official documentation here: http://www.arduino.cc/en/Reference/SoftwareSerial it doesn't mention the end() function, but looking at the github repo, I can see it is there.
Thanks for sharing!
BR,
Donal
hi donal !
Delete(sorry for my late answer too I get stuck on other things)
I have a last question about Watchdog
if I well understand it decrease a counter and send the it whenn reaching 0 and reload the counter for next countdown
I configured it to get approx 8sec as you explain in your article but how can I reset the counter ?? I whant to do it right before entering in sleep to be sure to have 8 sec of sleep not regarding on time I spend in wake up phase
(sory if my english is not understandable if you dont see what I mean let me know)
hello, and congrat for the great article.Also , i want to use an arduino mini pro and a gsm module.I want to sleep , ad once per day , wake up and verify an analog imput(baterry).Can i do this using WTD?(lucky2004alex@yahoo.com)THX
ReplyDeleteThanks for the informative article.
ReplyDeleteI have an Arduino application where I want to run at low power, wake up ca. every eight hours to make a brief reading, then return to the low power mode. Also, I do not want to use interrupts, if possible.
Any suggestions?
hi, can you please help i want to put arduino to sleep for like 20mins. how can i increase it time . which sleep mode should i use.
ReplyDeleteany help would be appreciated.