Pin P0_0 set HIGH only outputs 0.18V

I am using the code (see below) to detect when a magnet passes an OPTEK 0H090U hall sensor, then it sets pin P0_0 to HIGH to cause a TIP120 to switch on a 12V electromagnet. I am using a Pololu #1250 2.5A 12V to 5V step down regulator to supply power to the Wixel through the VIN pin and also to the hall sensors. The 12V source is a wall wart. During testing the USB is also attached but the Wixel and all circuits run off the regulator voltage.

The hall sensor works as expected (with input from regulator of 4.97V, it has 3.79V output with no magnet present and 0.01V when magnet is present). When the magnet is present the code switches P0_0 to HIGH (which is NOT the correct HIGH but is actually 0.18V) and, when the magnet is removed, it correctly switches P0_0 back to 0.0V. There is no fluctuation in the voltage input from the regulator when the hall sensor switches states and P0_0 is set HIGH, thus the Wixel does not “brown out” - no change in LEDs.

Because of the low voltage (0.18V) from pin P0_0, the TIP120 does not switch the 12V to the electromagnet. If I jumper the 3V3 pin directly to the P0_0 pin the TIP120 switches the electromagnet ON as it should.

Is the 3.79V output of the hall sensors going directly to one or the other of pins P1_4 or P1_5 a problem?

Why am I getting such a low voltage from pin P0_0?

[code]
/**

  • SteeringColumnSignal.c
  • code adapted from io_repeater app:

This app allows you to wirelessly extend the reach of your microcontroller’s
I/O lines using two or more Wixels.

For complete documentation and a precompiled version of this app, see the
“I/O Repeater App” section of the Pololu Wixel User’s Guide:


*/

/** Dependencies **************************************************************/
#include <wixel.h>
#include <cc2511_map.h>
#include <board.h>
#include <usb.h>
#include <usb_com.h>
#include <random.h>
#include <time.h>
#include <gpio.h>
#include <radio_queue.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define MAX_TX_INTERVAL 10 // maximum time between transmissions (ms)

#define PIN_COUNT 15
static uint8 CODE pins[PIN_COUNT] = {0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 15, 16, 17, 21};

int8 pinLink(uint8 pin);
// macros to determine whether a pin is an input or output based on its link param
#define IS_INPUT(pin) (pinLink(pin) < 0)
#define IS_OUTPUT(pin) (pinLink(pin) > 0)

// list and count of input pins
static uint8 XDATA inPins[PIN_COUNT];
static uint8 inPinCount = 0;

// list and count of output pins
static uint8 XDATA outPins[PIN_COUNT];
static uint8 outPinCount = 0;

// only tx if we have at least one input; only rx if we have at least one output
static BIT txEnabled = 0;
static BIT rxEnabled = 0;

// In each byte of a buffer:
// bit 7 = pin value
// bits 6:0 = pin link
#define PIN_LINK_OFFSET 0
#define PIN_LINK_MASK 0x7F
#define PIN_VAL_OFFSET 7

/** Parameters ****************************************************************/
int32 CODE param_P0_0_link = 0; // signal lever electromagnet (Wixel’s ~ +2.5V signal causes transistor to switch
// gnd on for electromagnet) - input inits to low
int32 CODE param_P0_1_link = 0; // left turn motion Hall Sensor switch 1 (GND if on and ~ +3.5V if off)
int32 CODE param_P0_2_link = 0; // left turn motion Hall Sensor switch 2 (GND if on and ~ +3.5V if off)
int32 CODE param_P0_3_link = 0; // right turn motion Hall Sensor switch 1 (GND if on and ~ +3.5V if off)
int32 CODE param_P0_4_link = 0; // right turn motion Hall Sensor switch 2 (GND if on and ~ +3.5V if off)
int32 CODE param_P0_5_link = 0; // flasher button ON (grounded) inits to high
int32 CODE param_P1_0_link = -4; // flasher is flashing if HIGH
int32 CODE param_P1_1_link = 0;
int32 CODE param_P1_2_link = -2; // left turn signal on - input inits to low
int32 CODE param_P1_3_link = -1; // right turn signal on - input inits to low
int32 CODE param_P1_4_link = 0; // signal lever in place for right turn (GND if on and ~ +3.5V if off - uses Hall Sensor)
int32 CODE param_P1_5_link = 0; // signal lever in place for left turn (GND if on and ~ +3.5V if off - uses Hall Sensor)
int32 CODE param_P1_6_link = 0; // Horn button pushed (and thus pin is grounded) - input data
int32 CODE param_P1_7_link = -3; // horn ON/OFF - set to high to turn on horn - input inits to low
int32 CODE param_P2_1_link = 0; // red LED

#define TRUE 1
#define FALSE 0

// DO NOT initialize pins that are directly set by an electronic device like a hall sensor. It causes pin to not
// act as expected
#define SIGNAL_ARM_AT_RIGHT_TURN_POS 14 // P1_4 // hall sensor on signal arm board activated by signal arm magnet
#define SIGNAL_ARM_AT_LEFT_TURN_POS 15 // P1_5 // hall sensor on signal arm board activated by signal arm magnet

#define ELECTROMAGNET_PIN 0 // P0_0

void checkPinState();

/** Functions *****************************************************************/

void configurePins(void)
{
uint8 pin, tmp;

// Set all pulled pins to high
// TODO: make this user-configurable
setPort0PullType(HIGH);
setPort1PullType(HIGH);
// Port 2 is pulled low and should remain pulled low; pulling it high would cause problems.

for(pin = 0; pin < PIN_COUNT; pin++)
{
    tmp = pins[pin];

    if (IS_OUTPUT(tmp))
    {
        // This pin is configured as an output, so add it to the list of output pins.
        // The default state of the output pins, as documented in the user's guide, is LOW.
        setDigitalOutput(tmp, LOW);
        outPins[outPinCount++] = tmp;
        rxEnabled = 1;
    }
    else if (IS_INPUT(tmp))
    {
        // This pin is configured as an input, so add it to the list of input pins.
        // The pin is already an input because all pins are inputs by default.
        inPins[inPinCount++] = tmp;
        txEnabled = 1;
    }
}
// Disable pull-ups and pull-downs for pins P0_1, P0_2, P0_3, P0_4.
// so they can be used to read analog voltage
// commented this out because I will need to use these pins for my app

// P0INP |= 0b00011110;
}

void checkPinState()
{
// signal arm may be at either right or left turn hall sensor
// (hall output is at 3.8V when no magnet is present
// - goes to 0.01V when magnet is present
// (VCC to hall sensor is 4.98V supplied by pololu #2850 2.5A, 12V to 5V regulator)
// (same regulator supplies 5V to wixel)
// there are 2 hall sensors and both function as expected - I get the same result at either one
if (!isPinHigh(SIGNAL_ARM_AT_RIGHT_TURN_POS) || !isPinHigh(SIGNAL_ARM_AT_LEFT_TURN_POS))
{
// electromagnet pin sends its output to a TIP120 which is supposed to switch 12V (from wall wart)
// to electromagnet (spec says it draws 0.08A)
// but electromagnet pin only gets to 0.18V and thus does activate TIP120
// - this setup works if I connect 3V3 pin directly to electromagnet pin (0)
setDigitalInput(ELECTROMAGNET_PIN, HIGH);
}
// signal arm magnet is NOT at either right or left turn hall sensor
else if (isPinHigh(SIGNAL_ARM_AT_RIGHT_TURN_POS) && isPinHigh(SIGNAL_ARM_AT_LEFT_TURN_POS))
{
// de-energize electromagnet to release signal arm to neutral position
// here the electromagnet pin goes to 0.0V as expected
setDigitalInput(ELECTROMAGNET_PIN, LOW);
}
}

void updateLeds()
{
usbShowStatusWithGreenLed();

LED_YELLOW(vinPowerPresent());

}

int8 pinLink(uint8 pin)
{
switch(pin)
{
case 0: return param_P0_0_link;
case 1: return param_P0_1_link;
case 2: return param_P0_2_link;
case 3: return param_P0_3_link;
case 4: return param_P0_4_link;
case 5: return param_P0_5_link;
case 10: return param_P1_0_link;
case 11: return param_P1_1_link;
case 12: return param_P1_2_link;
case 13: return param_P1_3_link;
case 14: return param_P1_4_link;
case 15: return param_P1_5_link;
case 16: return param_P1_6_link;
case 17: return param_P1_7_link;
case 21: return param_P2_1_link;
}
return 0;
}

// read the states of input pins on this Wixel into a buffer
void readPins(uint8 XDATA * buf)
{
uint8 pin;

for (pin = 0; pin < inPinCount; pin++)
{
    // put pin link in lower 7 bits, read pin state and put in highest bit
    buf[pin] = (-pinLink(inPins[pin]) << PIN_LINK_OFFSET) | (isPinHigh(inPins[pin]) << PIN_VAL_OFFSET);
}

}

// set the states of output pins on this Wixel based on values from a buffer
void setPins(uint8 XDATA * buf, uint8 byteCount)
{
uint8 byte, pin;

// loop over all bytes in packet
for (byte = 0; byte < byteCount; byte++)
{
    for (pin = 0; pin < outPinCount; pin++)
    {
        // check if this output pin's link matches the link in this packet
        if ((uint8)pinLink(outPins[pin]) == ((buf[byte] >> PIN_LINK_OFFSET) & PIN_LINK_MASK))
        {
            // if so, set the pin state based on the val bit
            setDigitalOutput(outPins[pin], (buf[byte] >> PIN_VAL_OFFSET) & 1);
        }
    }
}

}

void main(void)
{
// pointers to link packets
uint8 XDATA * txBuf;
uint8 XDATA * rxBuf;

uint8 lastTx = 0;

systemInit();
usbInit();

radioQueueInit();

configurePins();

while(1)
{
    boardService();
    updateLeds();
    usbComService();

    // receive pin states from another Wixel and set our output pins
    if (rxEnabled && (rxBuf = radioQueueRxCurrentPacket()))
    {
        setPins(rxBuf + 1, *rxBuf);
        radioQueueRxDoneWithPacket();
    }

    // read our input pins and transmit pin states to other Wixel(s) every MAX_TX_INTERVAL milliseconds
    if (txEnabled && (uint8)(getMs() - lastTx) > MAX_TX_INTERVAL && (txBuf = radioQueueTxCurrentPacket()))
    {
        readPins(txBuf + 1);
        *txBuf = inPinCount; // set packet length byte
        radioQueueTxSendPacket();

        lastTx = getMs();
    }
    checkPinState();
}

}[/code]

Hello.

It appears that these are the lines for controlling P0_0 in the code you posted:

      setDigitalInput(ELECTROMAGNET_PIN, HIGH);
      setDigitalInput(ELECTROMAGNET_PIN, LOW);

Since you are trying to use that pin as an output, you should use setDigitalOutput instead of setDigitalInput. Both functions are documented here:

pololu.github.io/wixel-sdk/gpio_8h.html

–David