SPI settings and sleep current

I am using 2 SPI devices - a micro SD card and an CUI absolute encoder (to change valve positions) on a MEGA 1280. Everything is working except that when I put the MEGA to sleep, the encoder is drawing 8mA even if the pin used to power it is put LOW. I’m guessing it might have to do with possible SPI settings conflicts. I set the settings for the encoder but I don’t know how they interact with the settings in the SPI and SD libraries. Any suggestions? Thanks. Parts of the code are shown below.

#include <SPI.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <avr/sleep.h>

#define sdChipSelectPin 10 // SDcard SPI chip select pin
#define cuiChipSelectPin 53 // CUI encoder SPI chip select pin
#define cuiPin 26 // Pin to power CUI Encoder

void setup() {

Wire.begin();
SPI.begin();
delay(1000);

pinMode(cuiPin,OUTPUT);
pinMode(cuiChipSelectPin, OUTPUT);
digitalWrite(cuiPin, HIGH);
digitalWrite(cuiChipSelectPin, HIGH);

Serial.begin(9600);

if (!RTC.begin()) error(“RTC failed”);

SdFile::dateTimeCallback(dateTime);

if (!sd.begin(sdChipSelectPin, SPI_HALF_SPEED)) sd.initErrorHalt();

logfile.open(fname, O_CREAT | O_APPEND | O_WRITE);
if (!logfile.is_open())
error(“file.open”);
else {
logfile << dbuf;
logfile.close();
}

digitalWrite(cuiChipSelectPin, LOW);
digitalWrite(cuiPin, LOW);

void loop() {

Serial1.begin(9600);

// subroutine to command CUI encoder and return encoder position
int GetPosition( byte value) {
byte result;
int iresult;
int MSB;
int LSB;

result=CUIRead(CUIReadByte);

do
{
result=CUIRead(CUINOPByte);

} while (result != CUIReadByte);

result = CUIRead(CUINOPByte);

result = CUIRead(CUINOPByte);
LSB = int(result);

iresult=256*MSB+LSB;
return(iresult);
}

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

// Subroutine to send commands to CUI encoder
byte CUIRead(byte CUICmd) {
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV16);
delay(100); // Ginger added 9/10/13

byte result;
digitalWrite(cuiChipSelectPin, LOW);
result=SPI.transfer(CUICmd);
delayMicroseconds(20);
digitalWrite(cuiChipSelectPin, HIGH);

return(result);
}

// Save data to file
logfile.open(fname, O_CREAT | O_APPEND | O_WRITE);
if (!logfile.is_open())
error(“file.open”);
else {
logfile << dbuf;
logfile.close();
}

// sleep function
void sleep_sec(uint8_t x) {
while (x–)
{
// set the WDT to wake us up!
WDTCSR |= (1 << WDCE) | (1 << WDE); // enable watchdog & enable changing it
WDTCSR = (1<< WDE) | (1 <<WDP2) | (1 << WDP1);
WDTCSR |= (1<< WDIE);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
sleep_disable();
}
}

the encoder is drawing 8mA even if the pin used to power it is put LOW.

How did you determine that?

If the SPI pins are high, it seems possible that current could be flowing through them to the encoder. Set them low before sleep().

There is much more you can do to reduce power consumption in sleep mode. See this excellent guide.

tunabird: Everything is working except that when I put the MEGA to sleep, the encoder is drawing 8mA even if the pin used to power it is put LOW.

jremington: How did you determine that?

If the SPI pins are high, it seems possible that current could be flowing through them to the encoder. Set them low before sleep().

There is much more you can do to reduce power consumption in sleep mode. See this excellent guide.

I agree with Jremington, Look at your data sheet for the encoder. I bet is specifies High level in reference to VCC. When you Drop Vcc, and still drive the SPI interface with High (5V) you are exceeding the maximum allowed voltage on the SPI port pins, The internal Protection diodes are shorting the SCK. MOSI to the VCC pin of the device, which you are driving LOW. So, basically your are connecting SCK,MOSI (both High) to your VCC pin which is LOW, Your AVR chip has two pins HIGH, connected to one pin LOW with a couple of diodes inbetween. BAD design!

Chuck.

Thanks for your comments. The way I determined it was to simply unplug the cable to the encoder when it was sleeping. The power supply indicates 8mA less current draw when I do that.

Hello,
I have the same problem, but I can’t remove the SPI partner when it is powering off.
I “just” have to set the sck pin to low.
I try to force the pin state by using

digitalWrite(SCK, LOW);
or 
digitalWrite(52, LOW);

But unfortunatli it doesn’t work !
I try another way by using a “fake” transaction:

SPI_Settings = SPISettings(16000000/4, MSBFIRST, SPI_MODE3);
SPI.begin();
SPI.beginTransaction(SPI_Settings);
SPI.transfer(BYTE_FULL); //0xFF
SPI.endTransaction();

But the sck pin remain high.
Can you explain me why and tell me how can I put this line to low ?

Best regards

Thierry

Vorms: Hello, I have the same problem, but I can't remove the SPI partner when it is powering off. I "just" have to set the sck pin to low. I try to force the pin state by using

digitalWrite(SCK, LOW);
or 
digitalWrite(52, LOW);

But unfortunatli it doesn't work ! I try another way by using a "fake" transaction:

SPI_Settings = SPISettings(16000000/4, MSBFIRST, SPI_MODE3);
SPI.begin();
SPI.beginTransaction(SPI_Settings);
SPI.transfer(BYTE_FULL); //0xFF
SPI.endTransaction();

But the sck pin remain high. Can you explain me why and tell me how can I put this line to low ?

Best regards

Thierry

When the SPI interface is active, digitalWrite() cannot effect MISO,MOSI,SCK. You must shutdown the SPI interface before you can directly control the pins.

SPI.end(); // shutdown the SPI interface
pinMode(SCK,INPUT);
digitalWrite(SCK,LOW); // shut off pullup resistor
pinMode(MOSI,INPUT);
digitalWrite(MOSI,LOW); // shut off pullup resistor
pinMode(MISO,INPUT);
digitalWrite(MISO,LOW); // shut off pullup resistor

digitalWrite(devicePower,LOW); // power off SPI device
pinMode(sensorCS,INPUT);
digitalWrite(sensorCS,LOW); // shut off pullup resistor

All of the other devices on the SPI bus need their CS pins driven High.

When you power the device back up, reverse the shutdown order.

digitalWrite(sensorCS,HIGH);
pinMode(sensorCS,OUTPUT); 
digitalWrite(DevicePower,HIGH);

SPI.begin(); // the SPI library will configure the pinMode for SCK,MOSI,MISO
// reinit your device and all of your SPI setting.

Chuck.

Hello, Many thanks for your help, I will try ! I don't see the spi.end() method !

Best regards

Thierry