I see two issues in this code.
The first is that you are trying to send data through an UART that has
been powered off. Serial.print()
doesn't wait for the data to get out,
it merely stores it into a memory buffer. You should wait until
everything gets out before switching the UART off. This can be done by
calling either Serial.flush()
or Serial.end()
. I would use the
latter, as it feels safer to stop the UART before switching if off. But
then you have to Serial.begin()
again on wakeup.
To avoid the garbled characters in the serial stream, you could try to
either pinMode(1, INPUT_PULLUP);
or digitalWrite(1, HIGH);
. This way
you ensure that the TX line stays HIGH
(which is its normal idle
state) when the UART goes off.
The second issue is your use of the Arduino timekeeping functions
millis()
and delay()
. These functions rely on an interrupt triggered
by Timer 0. If you power off that timer, millis()
and delay()
won't work. If you don't, SLEEP_MODE_PWR_SAVE
does it for you while
sleeping. Then those function will work while awake, but millis()
will
not count the time you spent sleeping.
Edit: There are two interrupts related to the UART that are enabled
by Serial.begin()
:
USART_UDRE
, "Data Register Empty", is used for transmission. It fires when the hardware transmit buffer is ready to receive new data. The corresponding ISR's job is to copy one byte from the transmit memory buffer (the oneSerial.print()
writes into) into the hardware transmit buffer.USART_RX
, "Receive Complete", is used for reception. It fires when a byte is received. The corresponding ISR copies this byte into receive memory buffer (the oneSerial.read()
reads from).
The first one fires when transmitting. Once you wait for the end of the
transmission (say with Serial.flush()
), you shouldn't see this
interrupt firing anymore.
The second one fires only when receiving. If you are not receiving anything, this interrupt shouldn't fire. If the RX pin is floating, the interrupt could be triggered by external noise. This can be prevented by enabling the internal pullup on the RX pin. Alternatively, you can disable the receiver part of the UART:
UCSR0B &= ~_BV(RXEN0); // disable the UART receiver
Note that if you stop the UART with Serial.end()
, both the transmitter
and the receiver are disabled, and you don't get UART-related interrupts
anymore.
I see two issues in this code.
The first is that you are trying to send data through an UART that has
been powered off. Serial.print()
doesn't wait for the data to get out,
it merely stores it into a memory buffer. You should wait until
everything gets out before switching the UART off. This can be done by
calling either Serial.flush()
or Serial.end()
. I would use the
latter, as it feels safer to stop the UART before switching if off. But
then you have to Serial.begin()
again on wakeup.
To avoid the garbled characters in the serial stream, you could try to
either pinMode(1, INPUT_PULLUP);
or digitalWrite(1, HIGH);
. This way
you ensure that the TX line stays HIGH
(which is its normal idle
state) when the UART goes off.
The second issue is your use of the Arduino timekeeping functions
millis()
and delay()
. These functions rely on an interrupt triggered
by Timer 0. If you power off that timer, millis()
and delay()
won't work. If you don't, SLEEP_MODE_PWR_SAVE
does it for you while
sleeping. Then those function will work while awake, but millis()
will
not count the time you spent sleeping.
I see two issues in this code.
The first is that you are trying to send data through an UART that has
been powered off. Serial.print()
doesn't wait for the data to get out,
it merely stores it into a memory buffer. You should wait until
everything gets out before switching the UART off. This can be done by
calling either Serial.flush()
or Serial.end()
. I would use the
latter, as it feels safer to stop the UART before switching if off. But
then you have to Serial.begin()
again on wakeup.
To avoid the garbled characters in the serial stream, you could try to
either pinMode(1, INPUT_PULLUP);
or digitalWrite(1, HIGH);
. This way
you ensure that the TX line stays HIGH
(which is its normal idle
state) when the UART goes off.
The second issue is your use of the Arduino timekeeping functions
millis()
and delay()
. These functions rely on an interrupt triggered
by Timer 0. If you power off that timer, millis()
and delay()
won't work. If you don't, SLEEP_MODE_PWR_SAVE
does it for you while
sleeping. Then those function will work while awake, but millis()
will
not count the time you spent sleeping.
Edit: There are two interrupts related to the UART that are enabled
by Serial.begin()
:
USART_UDRE
, "Data Register Empty", is used for transmission. It fires when the hardware transmit buffer is ready to receive new data. The corresponding ISR's job is to copy one byte from the transmit memory buffer (the oneSerial.print()
writes into) into the hardware transmit buffer.USART_RX
, "Receive Complete", is used for reception. It fires when a byte is received. The corresponding ISR copies this byte into receive memory buffer (the oneSerial.read()
reads from).
The first one fires when transmitting. Once you wait for the end of the
transmission (say with Serial.flush()
), you shouldn't see this
interrupt firing anymore.
The second one fires only when receiving. If you are not receiving anything, this interrupt shouldn't fire. If the RX pin is floating, the interrupt could be triggered by external noise. This can be prevented by enabling the internal pullup on the RX pin. Alternatively, you can disable the receiver part of the UART:
UCSR0B &= ~_BV(RXEN0); // disable the UART receiver
Note that if you stop the UART with Serial.end()
, both the transmitter
and the receiver are disabled, and you don't get UART-related interrupts
anymore.
I see two issues in this code.
The first is that you are trying to send data through an UART that has
been powered off. Serial.print()
doesn't wait for the data to get out,
it merely stores it into a memory buffer. You should wait until
everything gets out before switching the UART off. This can be done by
calling either Serial.flush()
or Serial.end()
. I would use the
latter, as it feels safer to stop the UART before switching if off. But
then you have to Serial.begin()
again on wakeup.
To avoid the garbled characters in the serial stream, you could try to
either pinMode(1, INPUT_PULLUP);
or digitalWrite(1, HIGH);
. This way
you ensure that the TX line stays HIGH
(which is its normal idle
state) when the UART goes off.
The second issue is your use of the Arduino timekeeping functions
millis()
and delay()
. These functions rely on an interrupt triggered
by Timer 0. If you power off that timer, millis()
and delay()
won't work. If you don't, SLEEP_MODE_PWR_SAVE
does it for you while
sleeping. Then those function will work while awake, but millis()
will
not count the time you spent sleeping.