Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

SOLVED - loading application shuts down wixel - lights out


#1

when I load the following application (initially used io_repeater app as a model) all the lights go off it is no longer recognized by the config utility and I have to short 3V3 and P2_2 to start the bootloader mode. Once I do that it is programmable and is recognized by the config utility - But if I reload the program it does it again.

/** 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:
https://www.pololu.com/docs/0J46
*/

/** 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 <uart1.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

void configureCom();

#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};

// 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 3.3V signal causes transistor to switch
								//			which activates 6A relay that controls 12V to electromagnet)
int32 CODE param_P0_1_link = 0; // left turn motion Hall Sensor switch 1 (GND if on and +5V if off)
int32 CODE param_P0_2_link = 0; // left turn motion Hall Sensor switch 2 (GND if on and +5V if off)
int32 CODE param_P0_3_link = 0; // right turn motion Hall Sensor switch 1 (GND if on and +5V if off)
int32 CODE param_P0_4_link = 0; // right turn motion Hall Sensor switch 2 (GND if on and +5V if off)
int32 CODE param_P0_5_link = 0;
int32 CODE param_P1_0_link = -4; // flasher button
int32 CODE param_P1_1_link = 0;
int32 CODE param_P1_2_link = -2; // left turn signal on - output
int32 CODE param_P1_3_link = -1; // right turn signal on - output
int32 CODE param_P1_4_link = 0; // signal lever in place for right turn (GND if on and +5V if off - uses Hall Sensor)
int32 CODE param_P1_5_link = 0; // signal lever in place for left turn  (GND if on and +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 button pushed - output goes to dash wixel to
int32 CODE param_P2_1_link = 0; // red LED

#define TRUE 1
#define FALSE 0

int32 nTurnOffDelayMs = 20;
int32 nMagnetPassedDelayMs = 0;


// 4 Hall Sensor switches are placed in 2 pairs around steering column in clockwise order
// with zero degrees being vertical - one pair at -30 degrees and one pair at +30 degrees

// paired below neutral location of magnet on steering shaft (inside steering column)
// thus, from heutral position, turning wheel to left encounters hall sensor 1 first
#define TURNING_LEFT_SENSOR_1_PIN 1 // P0_1 // indicates movement of steering wheel
#define TURNING_LEFT_SENSOR_2_PIN 2 // P0_2 // indicates movement of steering wheel
// paired above neutral location of magnet on steering shaft (inside steering column)
// thus, from neutral position, turning wheel to right encounters hall sensor 1 first
#define TURNING_RT_SENSOR_1_PIN 3 // P0_3 // indicates movement of steering wheel
#define TURNING_RT_SENSOR_2_PIN 4 // P0_4 // indicates movement of steering wheel
#define FLASHER_BUTTON_PUSHED_PIN 10 // P1_0 // grounded when flasher button pressed
#define LEFT_TURN_SIGNAL_PIN 12 // P1_2 // turns on/off Left turn relay by transfering its value to dash wixel
#define RIGHT_TURN_SIGNAL_PIN 13 // P1_3 // turns on/off Right turn relay by transferring its value to dash wixel
#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 HORN_PRESSED_PIN 16 // P1_6 //grounded when horn button pressed
#define HORN_SOUNDING_PIN 17 // P1_7 // turns on/off horn relay by transferring its value to dash wixel

#define ELECTROMAGNET_PIN 0 // P0_0

static uint8 nLeftMotionSwitch1Passed = 0;
static uint8 nLeftMotionSwitch2Passed = 0;
static uint8 nRightMotionSwitch1Passed = FALSE;
static uint8 nRightMotionSwitch2Passed = FALSE;

void checkPinState();
void energizeElectroMagnet(uint8 bEnergize);
void initSignalVars();

/** Functions *****************************************************************/
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;
}

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);
       //     if (tmp == FLASHER_BUTTON_PUSHED_PIN || tmp == HORN_PRESSED_PIN)
        //    {
            	// when horn or flasher button has been pressed or
            	// turned ON horn or flasher pin is grounded or LOW  - so initialize to HIGH
          //      setDigitalOutput(tmp, HIGH);
          //  }
            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
    P0INP |= 0b00011110;
}

// 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();
	initSignalVars();

	configureCom();

    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();
    }
}

void checkPinState()
{
	// 1. check if signal is on
	//		if not on return
	// 2. if signal is on
	//		a. get state of hall switches
		// 		i. if a hall switch is low then it has been switched and thus is grounded and
		//			is currently being passed by magnet
		// 			indicating that wheel of car is being turned
		// 		ii. check if any hall switches have been passed by a magnet
		//			if none passed then set this hall switch var and return.
		// 		iii. if other hall switch has been passed then
		//			depending on current hall switch being passed
		// 			and what had passed before we know which way wheel is being turned
		//				- if signal is on set turn direction var
		//		iv. if signal is on and direction of wheel has not changed then return
		//		v. if signal is on and direction of wheel has changed then set pin to release
		//			electromagnet holding signal arm and return it to neutral position

	//////////////////////////////////////////////////////////////////////
	// Handle horn
	//////////////////////////////////////////////////////////////////////

	if (!isPinHigh(HORN_PRESSED_PIN) && !isPinHigh(HORN_SOUNDING_PIN)) // horn button pushed
																		// but horn not turned on
	{
		// sound horn
		setDigitalOutput(HORN_SOUNDING_PIN, HIGH);
	}
	else if (isPinHigh(HORN_SOUNDING_PIN) && isPinHigh(HORN_PRESSED_PIN)) // horn button not pushed
																			// but horn is on, so turn off horn
	{
		// turn off horn
		setDigitalOutput(HORN_SOUNDING_PIN, LOW);
	}

	//////////////////////////////////////////////////////////////////////
	// Handle emergency flasher
	//////////////////////////////////////////////////////////////////////

	if (!isPinHigh(FLASHER_BUTTON_PUSHED_PIN)) // flasher button has been pushed
	{
		setDigitalOutput(RIGHT_TURN_SIGNAL_PIN, HIGH);
		setDigitalOutput(LEFT_TURN_SIGNAL_PIN, HIGH);
	}
	else if (isPinHigh(FLASHER_BUTTON_PUSHED_PIN) // flasher button not pushed
			&& isPinHigh(SIGNAL_ARM_AT_RIGHT_TURN_POS) // signal arm not in rt turn pos
			&& isPinHigh(SIGNAL_ARM_AT_LEFT_TURN_POS) // signal arm not in lft turn pos
			&& isPinHigh(RIGHT_TURN_SIGNAL_PIN) // rt turn signal is on
			&& isPinHigh(LEFT_TURN_SIGNAL_PIN)) // lft turn signal is on
	{
		// turn off flashers
		setDigitalOutput(RIGHT_TURN_SIGNAL_PIN, LOW);
		setDigitalOutput(LEFT_TURN_SIGNAL_PIN, LOW);
	}

	//////////////////////////////////////////////////////////////////////
	// Handle right turn signal
	//////////////////////////////////////////////////////////////////////

	else if (isPinHigh(FLASHER_BUTTON_PUSHED_PIN) // flasher not on
			&& !isPinHigh(SIGNAL_ARM_AT_RIGHT_TURN_POS) // signal arm in rt turn pos
			&& !isPinHigh(RIGHT_TURN_SIGNAL_PIN)) // rt turn signal not on
	{
		// so turn on right signal
		setDigitalOutput(RIGHT_TURN_SIGNAL_PIN, HIGH);
	}

	//////////////////////////////////////////////////////////////////////
	// Handle left turn signal
	//////////////////////////////////////////////////////////////////////

	else if (isPinHigh(FLASHER_BUTTON_PUSHED_PIN) // flasher not on
			&& !isPinHigh(SIGNAL_ARM_AT_LEFT_TURN_POS) // signal arm in lft turn pos
			&& !isPinHigh(LEFT_TURN_SIGNAL_PIN)) // lft turn signal not on
	{
		// so turn on left signal
		setDigitalOutput(LEFT_TURN_SIGNAL_PIN, HIGH);
	}

	//////////////////////////////////////////////////////////////////////
	// keep track of when wheel is turned back the other way after a turn
	//////////////////////////////////////////////////////////////////////

	if (isPinHigh(LEFT_TURN_SIGNAL_PIN) // left turn signal is turned on
			&& isPinHigh(FLASHER_BUTTON_PUSHED_PIN)) // and flasher is off
	{
		if (!isPinHigh(TURNING_LEFT_SENSOR_1_PIN))
		{
	//		nComPrintCount = 0;
			// left turn switch 1 is low so magnet is passing switch now (hall output = 0V)
			// - just started turning wheel for left turn
			//			or finishing slight left turn and wheel is returning to right
			nLeftMotionSwitch1Passed++;
			delayMs(250);
			if (nLeftMotionSwitch2Passed == 0 && nLeftMotionSwitch1Passed > 1)
			{
				// have passed switch 1 are returning wheel to right after slight turn
				// return lever to neutral position
				energizeElectroMagnet(FALSE);
			}
			else
			{
				delayMs(nMagnetPassedDelayMs);
			}
		}
		else if (!isPinHigh(TURNING_LEFT_SENSOR_2_PIN))
		{
			// left turn switch 2 is low so magnet is passing switch now (hall output = 0V)
			// - determine if continuing to turn wheel to left
			//		or are starting to move wheel to right finishing turn
			nLeftMotionSwitch2Passed++;
			delayMs(250);
			if ((nLeftMotionSwitch1Passed > 0
					&& (nLeftMotionSwitch1Passed < nLeftMotionSwitch2Passed))
					|| nLeftMotionSwitch2Passed >= 3)
			{
				// have passed switches 1 and 2 and are returning wheel to right after turn
				// return lever to neutral position
				energizeElectroMagnet(FALSE);
			}
			else
			{
				// are continuing to turn wheel to left for left turn
				delayMs(nMagnetPassedDelayMs);
			}
		}
		else
		{
	//		nComPrintCount = 0;
		}
	}
	else if (isPinHigh(RIGHT_TURN_SIGNAL_PIN) // right turn signal is on
			&& isPinHigh(FLASHER_BUTTON_PUSHED_PIN)) // and flasher is off
	{
		if (!isPinHigh(TURNING_RT_SENSOR_1_PIN))
		{
			// right turn switch 1 is low so magnet is passing switch now (hall output = 0V)
			// - just started turning wheel for right turn
			//			or finishing slight right turn and wheel is returning to right
			{
				nRightMotionSwitch1Passed++;
				if (nRightMotionSwitch1Passed > 1)
				{
					// have passed switches 1 and 2 and are returning wheel to left after turn
					// return lever to neutral position
					energizeElectroMagnet(FALSE);
				}
				else
				{
					delayMs(nMagnetPassedDelayMs);
				}
			}
		}
		else if (!isPinHigh(TURNING_RT_SENSOR_2_PIN))
		{
			// right turn switch 2 is low so magnet is passing switch now (hall output = 0V)
			// - determine if continuing to turn wheel to right
			//		or are starting to move wheel to left finishing turn
			nRightMotionSwitch2Passed++;
			if ((nRightMotionSwitch1Passed > 0
					&& (nRightMotionSwitch1Passed < nRightMotionSwitch2Passed))
					|| nRightMotionSwitch2Passed >= 3)
			{
				// have passed switches 1 and 2 and are returning wheel to left after turn
				// return lever to neutral position
				energizeElectroMagnet(FALSE);
			}
			else
			{
				// are continuing to turn wheel to right for right turn
				delayMs(nMagnetPassedDelayMs);
			}
		}
	}
	else
	{
		// neither signal is on so just re-init all vars
		initSignalVars();
	//	nComPrintCount = 0;
	}
}

void energizeElectroMagnet(uint8 bEnergize)
{
	// energize electromagnet to hold signal lever in left or right turn position
	if (bEnergize)
	{
		setDigitalInput(ELECTROMAGNET_PIN, HIGH);
	}
	else
	{
		// turn off electromagnet to release signal lever to neutral position
		setDigitalInput(ELECTROMAGNET_PIN, LOW);
		// resets all vars to false
		initSignalVars();
	}
}

//  resets all vars to false
//	and return signal arm to neutral position
void initSignalVars()
{
	nLeftMotionSwitch1Passed = 0;
	nLeftMotionSwitch2Passed = 0;
	nRightMotionSwitch1Passed = 0;
	nRightMotionSwitch2Passed = 0;
	// de-energize electromagnet to return signal arm to neutral position
	energizeElectroMagnet(FALSE);
	// make sure flasher pin is HIGH (it is P1_0 and will float if not set high)
	setDigitalInput(FLASHER_BUTTON_PUSHED_PIN, HIGH);
}

void configureCom()
{
	uart1Init();
	uart1SetBaudRate(2400);
	uart1SetParity(PARITY_NONE);
	uart1SetStopBits(STOP_BITS_1);
}

/* int sendCom(char * inString, uint8 sendCrLf)
{
	uint8 nLen = strlen(inString);
	uint8 i = 0;
	while (uart1TxAvailable() && i < nLen)
	{
		uart1TxSendByte(inString[i]);
		i++;
	}
	if (sendCrLf == TRUE)
	{
		if (uart1TxAvailable())
		{
			uart1TxSendByte(13);
		}
		if (uart1TxAvailable())
		{
			uart1TxSendByte(10);
		}
	}
	return i;
}*/

#2

It no longer freezes the Wixel when I load the program after I comment out the line:

setDigitalInput(ELECTROMAGNET_PIN, LOW);

in function energizeElectroMagnet()

where: #define ELECTROMAGNET_PIN 0 // P0_0

Why is that?


#3

Well I figured it out. I added a Boolean variable that kept track of whether electromagnet was energized or not and checked it before energizing or de-energizing the electromagnet. I guess it was spending all its time de-energizing the electromagnet.

Sorry to take up time and space on this. :unamused:


#4

Hello, Burke.

I am glad you figured out what the issue was; thanks for letting us know!

-Jon