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