6

I am working on a simple project using an Arduino Mega 2560 that involves reading a 12-bit binary encoder signal and which is used to cycle a digital pin high and low (depending on the angular location of the encoder).

My problem is that when the digital output pin is told to go low, it only goes down to about 4V. I also noticed that it would occasionally dip down to ground, instead of just 4V. Much to my surprise, when I unplug the Arduino, the digital output pin is still reading 4V. When I turned off power to my encoder which is connected up the the Arduino through 12 digital input pins, the output pin dropped down to 0V. When I turn the encoder back on it goes back up to about 4V.

I have tried connecting the output pin to ground and obviously the voltage goes to 0, but as soon as I remove the connection to ground the voltage springs back up to around 4V. It appears as though somehow the voltage being fed to the digital input pins (in the form of a ~5V digital input signal) is preventing the digital output pin from going to ground. I have no idea why this is the case, I have searched all over and could not find any similar complaints. My code is posted below, any help is greatly appreciated!

unsigned long CamAngle = 0;       // Variable to store encoder value
unsigned long PrevCamAngle = 0;   // Variable to store previous encoder value
int i = 0;                        // Cycle index
int BDC[] = {683,2048,3413};      // BDC angle (12-bit encoder value)
int TDC[] = {0,1365,2731};        // TDC angle (12-bit encoder value)

boolean TDCycle = false;          // TDC Cycle
boolean BDCycle = false;          // BDC Cycle
boolean Cycle = true;             // Encoder rollover cycle (replaces TDC cycle 0)

void setup()
{
  pinMode(37, INPUT);           // Encoder bit 0 (PORTC-0)
  pinMode(36, INPUT);           // Encoder bit 1 (PORTC-1)
  pinMode(35, INPUT);           // Encoder bit 2 (PORTC-2)
  pinMode(34, INPUT);           // Encoder bit 3 (PORTC-3)
  pinMode(22, INPUT);           // Encoder bit 4 (PORTA-0)
  pinMode(23, INPUT);           // Encoder bit 5 (PORTA-1)
  pinMode(24, INPUT);           // Encoder bit 6 (PORTA-2)
  pinMode(25, INPUT);           // Encoder bit 7 (PORTA-3)
  pinMode(26, INPUT);           // Encoder bit 8 (PORTA-4)
  pinMode(27, INPUT);           // Encoder bit 9 (PORTA-5)
  pinMode(28, INPUT);           // Encoder bit 10 (PORTA-6)
  pinMode(29, INPUT);           // Encoder bit 11 (PORTA-7)

  pinMode(30, OUTPUT);          // Set PORTC pin 8 to output (stop pin float)
  pinMode(31, OUTPUT);          // Set PORTC pin 7 to output (stop pin float)
  pinMode(32, OUTPUT);          // Set PORTC pin 6 to output (stop pin float)
  pinMode(33, OUTPUT);          // Set PORTC pin 5 to output (stop pin float)

  digitalWrite(30, LOW);        // Set PORTC pin 8 low (stop pin float)
  digitalWrite(31, LOW);        // Set PORTC pin 7 low (stop pin float)
  digitalWrite(32, LOW);        // Set PORTC pin 6 low (stop pin float)
  digitalWrite(33, LOW);        // Set PORTC pin 5 low (stop pin float)

  pinMode(53, OUTPUT);          // Set pin 53 (PORTB-0) as digital output
  digitalWrite(53, LOW);        // Set pin 53 (PORTB-0) LOW

}

void loop()
{

  // Cam Angle Update
  PrevCamAngle = CamAngle;      // Set variable to previous encoder value
  CamAngle = (PINA << 4) + PINC;    // Read encoder, set variable to value

  if (TDCycle == true && CamAngle >= TDC[i])  // Wait for encoder to reach angle if cycle active
  {
    PORTB = 0;                                  // Set digital pin 53 LOW
    TDCycle = false;
    BDCycle = true;
  }

  if (BDCycle == true && CamAngle >= BDC[i])  // Wait for encoder to reach angle if cycle active
  {
    PORTB = 1;                                  // Set digital pin 53 HIGH
    TDCycle = false;
    BDCycle = true;
    i++;
    if (i > 2)                                  // Reset every 3 cycles (3 cycles per revolution)
    {
      i = 0;
      BDCycle = false;
      Cycle = true;
    }
  }

  if (Cycle == true && CamAngle < (PrevCamAngle + 1))  // Wait for encoder to cycle back to 0
  {
    PORTB = 0;                                  // Set digital pin 53 LOW
    BDCycle = true;
    Cycle = false;
  }      

}

As you can see I am utilizing direct port manipulation, however I have the same issues when I use the Arduino library commands as well. I'm fairly certain this is some sort of hardware issue, however I could be wrong.

  • 4
    Could you post a picture of the wiring? – Gerben Dec 2 '14 at 19:16
  • Have you linked the ground of the encoder to the arduino's ground? – meiamsome Dec 2 '14 at 20:43
  • Yes, the encoder ground is linked to the Arduino's ground. I will try to get a schematic of the wiring up shortly. – Jason Abbas Dec 2 '14 at 21:04
  • What is the output connected to? Also is there any resistor between the pin and the connected device? – Sourcery Dec 5 '14 at 13:24
  • 1
    Sounds like a pull-up / pull-down resistor problem. You're leaving the pin floating instead of giving it the physical ability to go to 0V. – Chris K Jan 2 '15 at 8:08
2

I think you have two issues here.

First:

Much to my surprise, when I unplug the Arduino, the digital output pin is still reading 4V.

With a powered device connected to the input pins, the overvoltage protection diodes power your 5V line with what is called "parasitic power". Those diodes are supposed to clamp an input pin to not exceed 5V, but if the power is off, they actually supply 5V (assuming at least some of the pins are high), hence powering up the processor. It is not designed to do this, and you should not power off the processor in this way.


Second:

My problem is that when the digital output pin is told to go low, it only goes down to about 4V.

I tried out your code, but without the encoder to hand, I just comment out the three "if" tests:

//  if (TDCycle == true && CamAngle >= TDC[i])  
...
//  if (BDCycle == true && CamAngle >= BDC[i])  
...
//  if (Cycle == true && CamAngle < (PrevCamAngle + 1))  

A multimeter on pin 53 reads 0.98V, however this is because the pin is being turned on and off quickly. I can't work out for sure whether some or all of these conditions would be satisfied in sequence (they don't seem directly related). One thing you could do, since you seem to want pin 53 either on or off is use "else", eg.

if (TDCycle == true && CamAngle >= TDC[i])  
{
...
} else if (BDCycle == true && CamAngle >= BDC[i]) 
{
...
}
else if (Cycle == true && CamAngle < (PrevCamAngle + 1))  
{
...
}

Now you won't have multiple attempts to turn the pin on and off through one turn through the loop.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.