Pin 10 is HIGH. WHY?

So Basically me and my friend developed this code for a cat feeder. The problem that I'm having is that whenever a power source gets hooked up, pin 10 (the one controlling the motor) goes high for a split second and then turns off. The battery supplying the power only lasts about 1.5 days which makes this a big issue. The problem is that within this split second its dispensing food. All my attempts to get rid of this have been futile...
Any suggestions?
Using Arduino Uno

johns_trial.ino (8.05 KB)

SPI.begin() in the RTC_init() function is doing it. I haven't looked into it further, but pin 10 is the hardware SPI SS pin, so that might have something to do with it. Is it possible to connect the motor to another pin?

1 Like

I looked into it further. SPI.begin() drives SS high.

void SPIClass::begin() {
  // Set direction register for SCK and MOSI pin.
  // MISO pin automatically overrides to INPUT.
  // When the SS pin is set as OUTPUT, it can be used as
  // a general purpose output port (it doesn't influence
  // SPI operations).

  pinMode(SCK, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SS, OUTPUT);
  
  digitalWrite(SCK, LOW);
  digitalWrite(MOSI, LOW);
  digitalWrite(SS, HIGH);

  // Warning: if the SS pin ever becomes a LOW INPUT then SPI 
  // automatically switches to Slave, so the data direction of 
  // the SS pin MUST be kept as OUTPUT.
  SPCR |= _BV(MSTR);
  SPCR |= _BV(SPE);
}

void SPIClass::end() {
  SPCR &= ~_BV(SPE);
}

How do you have pin 10 hooked up?
Why do you have

include <SPI.h> when you are not using SPI.transfers at all?

CrossRoads:
How do you have pin 10 hooked up?
Why do you have

include <SPI.h> when you are not using SPI.transfers at all?

There's an RTC function toward the bottom of the code that does SPI transfers. After a bunch of blank lines.

Sadly, I can't wire it to another pin. The product has already made it to the customer and I only have the capability to re-code. Good idea though

vinti6674:
So Basically me and my friend developed this code for a cat feeder. The problem that I'm having is that whenever a power source gets hooked up, pin 10 (the one controlling the motor) goes high for a split second and then turns off. The battery supplying the power only lasts about 1.5 days which makes this a big issue. The problem is that within this split second its dispensing food. All my attempts to get rid of this have been futile...
Any suggestions?
Using Arduino Uno

Are you Dr. Mollendorf's student?

Krupski:

vinti6674:
So Basically me and my friend developed this code for a cat feeder. The problem that I'm having is that whenever a power source gets hooked up, pin 10 (the one controlling the motor) goes high for a split second and then turns off. The battery supplying the power only lasts about 1.5 days which makes this a big issue. The problem is that within this split second its dispensing food. All my attempts to get rid of this have been futile...
Any suggestions?
Using Arduino Uno

Are you Dr. Mollendorf's student?

Yes Mr. Krupski. The product made it to the customer, but sadly this problem has got to be fixed.

You'll have to forgive I'm new to Arduino but I do have a background in C++.
That being said, If I insert this piece of code instead of the SPI.begin() will this prevent pin 10 from going high?

Product? Customer? What's the budget for the fix?

Haha. No budget. It was a senior project. The goal was to help people with disabilities. We made an automatic cat feeder that a client wanted so we gave it to her.

Try a digitalWrite: immediately after SPI.begin():

int RTC_init(){ 
  pinMode(cs,OUTPUT); // chip select
  // start the SPI library:
  SPI.begin();
  digitalWrite(10, LOW);
  ...etc.

That will not eliminate the blip but will significantly reduce it. If that's still not good enough, then I'd make my own version of the SPI library that doesn't pull pin 10 high.

Ok I will try that this Saturday when I visit her to troubleshoot. May I ask why digital write and not analogwrite? we used analogwrite for pin ten thats all.
Thank you for all your help. At least now I know what the problem is.

It's more of a matter of where it is in the code. It needs to be immediately after SPI.begin() to minimize the blip. Instead of digitalWrite(), this will reduce the blip even a little bit more:

int RTC_init(){ 
  pinMode(cs,OUTPUT); // chip select
  // start the SPI library:
  SPI.begin();
  PORTB = PORTB & ~_BV(PORTB2);

vinti6674:
Yes Mr. Krupski. The product made it to the customer, but sadly this problem has got to be fixed.

Unfortunately, the only proper way to fix the problem is to re-arrange the LCD and MOSFET wiring so that you are not using the SPI pins.

Also, of course you need to use a PWM output for the MOSFET (motor controller).

As far as battery life goes, the LCD backlight takes quite a bit of current. You may want to add a bit of hardware and code to turn the backlight on and off - it doesn't need to glow continuously. In fact, aside from when the motor runs, the backlight draws the MOST current of the whole project.

The Arduino board itself only uses something like 30 milliamps and probably 10 to 20 mA for the LCD... the backlight probably draws 1/4 amp (250 mA) or more.

Here's another idea to stop that momentary motor jump: Maybe drive the MOSFET through a small resistor (like around 220 ohm) then connect the GATE side to another Arduino port. The very first thing in the code would be to enable the extra port as an OUTPUT, then do a "digitalWrite(port, LOW)" to "short" the MOSFET gate to ground (which is safe because of the 220 ohm resistor protecting the PWM pin).

Then call the SPI init code, do a small delay to let the "glitch" go by, then set the extra port pin to "pinMode(pin, INPUT)" so that it's basically open circuited.

See what I mean? Use another port to SHORT OUT (disable) the MOSFET gate just long enough for the SPI glitch to go by, then set the port as an input to make it electrically "go away".

The best way to fix the problem is to change the wiring, but what I mentioned above will most likely work.

If there's anything I can help you with, let me know.

-- Roger

His circuit has a parallel LCD, a Sparkfun DS3234 RTC and a MOSFET to drive a DC motor.

The RTC communication is via SPI, but he wired the LCD to most of the other UNO pins and we needed a PWM pin to drive the MOSFET.

Since the only PWM pin that he had not used was pin 10 (which is also an SPI pin), pin 10 was used to control the MOSFET.

Unfortunately, when the SPI code is initialized, it momentarily sets pin 10 high and the motor "jumps" for about 1/10 of a second at full RPM.

The proper solution would be to change a few wires around so that:

(1) Pin 10 was not used at all
(2) A PWM pin is available for the MOSFET

There are several PWM capable pins going to the LCD that don't need to be PWM. Probably switching around just 2 wires (and changing the code accordingly) would solve the problem. Or, hack the SPI code to not talk to pin 10.....

The fast fix is three characters: // right before that digitalWrite, followed by Upload.

Patch the SPI library and you're done. It is not written in stone, nor even in the datasheet, that pin 10 must be used as the slave select, provided that it is initialized as an output, which it safely is.

-br

billroy:
The fast fix is three characters: // right before that digitalWrite, followed by Upload.

Patch the SPI library and you're done. It is not written in stone, nor even in the datasheet, that pin 10 must be used as the slave select, provided that it is initialized as an output, which it safely is.

-br

Agreed. That's the easiest and fastest fix.

Krupski:

billroy:
The fast fix is three characters: // right before that digitalWrite, followed by Upload.

Patch the SPI library and you're done. It is not written in stone, nor even in the datasheet, that pin 10 must be used as the slave select, provided that it is initialized as an output, which it safely is.

-br

Agreed. That's the easiest and fastest fix.

Forgive me if this attempt is totally wrong, I'm still a little new to this. So instead of using #include<SPI.h> I should replace it with this:

void SPIClass::begin() {
  // Set direction register for SCK and MOSI pin.
  // MISO pin automatically overrides to INPUT.
  // When the SS pin is set as OUTPUT, it can be used as
  // a general purpose output port (it doesn't influence
  // SPI operations).

  pinMode(SCK, OUTPUT);
  pinMode(MOSI, OUTPUT);
  pinMode(SS, OUTPUT);
  
  digitalWrite(SCK, LOW);
  digitalWrite(MOSI, LOW);
                //digitalWrite(SS, HIGH);
                      Upload;

  // Warning: if the SS pin ever becomes a LOW INPUT then SPI 
  // automatically switches to Slave, so the data direction of 
  // the SS pin MUST be kept as OUTPUT.
  SPCR |= _BV(MSTR);
  SPCR |= _BV(SPE);
}

void SPIClass::end() {
  SPCR &= ~_BV(SPE);
}

vinti6674:
Forgive me if this attempt is totally wrong, I'm still a little new to this. So instead of using #include<SPI.h> I should replace it with this:

Take the device and MOVE one of the LCD wires that is connected to a PWM pin to a non-PWM pin.

If I recall, you have pin 8 available, but we couldn't use it because it's not PWM. Move one of the LCD wires to pin 8, then use the vacated pin (which must be a PWM pin) and use it to drive the MOSFET. Then of course, change your code accordingly (update the pin numbers).

That should be all you have to do... give the LCD a non-PWM pin, get the MOSFET off of pin 10 and onto a different PWM pin, then update your code.

Make sense?