The following is the current code (Still in prototyping, not complete yet).
The line where it hangs is "LocoNet.reportSensor( address, value == sensorOccupied );"
Any help is of course appreciated.
I'm hoping there is just something simple that I've overlooked.
Note that we've also tried several of the sample programs that are included with the LocoNet library and all of those hit the same problem such that as soon as any function that does a transmit is called then it hangs.
#include <LocoNet.h>
#include <EEPROM.h>
// Pins: Communication
// TX: library defaults to 6 and we can change it
// RX: Library forces it to be 8
#define pinTX 7
// Pins: Device setup and control
#define pinLED 13
#define pinButton 12
// Pins: Sensor reading
// SR pin 1 -> load -> D2
// SR pin 15 -> clockEnable -> D3
// SR pin 7 -> dataIn -> D4
// SR pin 2 -> clockIn -> D5
#define pinLoad 2
#define pinClockEnable 3
#define pinDataIn 4
#define pinClockIn 5
// Control sampling collection from sensors
#define sensorOccupied 1
#define sensorNotOccupied 0
#define sampleMax 50
#define sampleThreshold 5
#define sensorInterval 2000
#define sensorCount 8
int sampleCount;
int sensorSample[sensorCount];
int sensorValue[sensorCount];
int sensorPreviousValue[sensorCount];
unsigned long sensorPreviousTime[sensorCount];
// Device addresses and communciation
uint16_t addressDecoder;
static LnBuf LnTxBuffer ;
// Device state and control
#define serialBaud 9600
#define loopDelay 10
#define defaultAddress 1999
#define useDefaultAddress 1
int state;
int firstPass;
void setup() {
// Perform all initiatlization and setup for the device
Serial.begin(serialBaud);
Serial.println("Setup Started");
// Control pins for the device
pinMode(pinLED, OUTPUT);
pinMode(pinButton, INPUT_PULLUP);
// Shift register pins
pinMode(pinLoad, OUTPUT);
pinMode(pinClockEnable, OUTPUT);
pinMode(pinDataIn, INPUT);
pinMode(pinClockIn, OUTPUT);
// First initialize the LocoNet interface, specifying the TX Pin
LocoNet.init(pinTX);
// Initialize a LocoNet packet buffer to buffer bytes from the PC
initLnBuf(&LnTxBuffer) ;
// Initialize sensor values
initSensors();
// Get the current address for the device
readAddress();
// Go into regular operating state
setState(0);
firstPass = 1;
outputLED();
Serial.println("Setup Complete");
}
void loop() {
// Main loop of the device that will be called repeatidly as long as
// the dvice is running.
if (firstPass == 1) {
sendAllsensors();
}
firstPass = 0;
handleButton();
handleMessagesRecieved();
if (state == 0) {
readSensors();
}
outputLED();
delay(loopDelay);
}
void handleButton(){
// Check if the programming button is being pushed and set the
// next state that it should be toggLED to
if(!digitalRead(pinButton))
{
switch (state)
{
case 0:
setState(1);
break;
case 1:
setState(0);
break;
}
}
}
void handleMessagesRecieved(){
// Check for any received LocoNet packets
lnMsg *LnPacket = LocoNet.receive();
if( LnPacket )
{
//printRXpacket(LnPacket);
// Global power on
if ( LnPacket -> data[0] == 0x83 ) {
sendAllsensors();
}
// Programming
if ( LnPacket -> data[0] == 0xB0 )
{
byte address_received = LnPacket -> data[1];
switch (state)
{
case 1:
// We are in programming state for the the decoder address
// Capture the address that has been sent and store it
Serial.println("Action : - Received B0 - Storing address");
addressDecoder = address_received;
writeAddress(0, addressDecoder);
setState(0);
break;
}
}
}
}
void initSensors() {
// Setup the initial values for all sensors.
for (int i = 0; i<sensorCount; i++) {
sensorSample[i] = 0;
sensorValue[i] = sensorNotOccupied;
sensorPreviousValue[i] = sensorNotOccupied;
sensorPreviousTime[i] = 0;
}
sampleCount = 0;
}
void outputLED() {
// Based on the state that the decvice is in control the LED
int lamp;
// Choose the speicfic LED settings for the state that the device is in
switch (state) {
case 0:
lamp = 400;
break;
case 1:
lamp = 400;
break;
}
if (state != 0) {
digitalWrite(pinLED, HIGH);
delay (lamp/2);
digitalWrite(pinLED, LOW);
delay (lamp/2);
} else
{
digitalWrite(pinLED, LOW);
}
}
void printState()
{
switch (state) {
case 0:
Serial.println("State 0 - Normal operation");
break;
case 1:
Serial.println("State 1 - Decoder Address to be acquired");
break;
}
}
void setState( int newState ) {
// Change the device from one state to another
Serial.print("State Change : ");
Serial.print(state);
Serial.print(" -> ");
Serial.println(newState);
state = newState;
printState();
}
void printAddress() {
Serial.print("Address decoder : ");
Serial.println(addressDecoder);
}
void readAddress() {
// Read the device address informaiton from the EPROM
if (useDefaultAddress == 0) {
addressDecoder = EEPROM.read(0);
} else {
addressDecoder = defaultAddress;
}
printAddress();
}
void writeAddress(int slot, uint16_t address) {
// Update the device address in the EPROM.
// Check first if the value actaully needs to be updated so that we can limit
// effect of too many EPROM writes over the lifetime of the device
if ( address != EEPROM.read(slot) ) {
EEPROM.write(slot, address);
}
readAddress();
}
void printRXpacket(lnMsg *LnPacket) {
// Print out a message that has been recieved from the LocoNet
uint8_t Length = getLnMsgSize( LnPacket ) ;
Serial.print("RX: ");
for( uint8_t Index = 0; Index < Length; Index++ )
{
Serial.print(LnPacket->data[ Index ], HEX);
Serial.print(" ");
}
Serial.println();
}
void sendSensorMessage(uint16_t address, int value) {
// Send out an invidiual sensor status to the LocoNet
if ( value == 0 ) {
Serial.println("Sensor: " + (String)address + " : Occupied");
} else {
Serial.println("Sensor: " + (String)address + " : Unoccupied");
}
LocoNet.reportSensor( address, value == sensorOccupied );
}
void sendAllsensors()
{
// Go through all sensors and send their status out to the LocoNet
Serial.println("Send all sensors");
for (int i = 0; i<sensorCount; i++) {
sendSensorMessage((addressDecoder + i), !sensorValue[i]);
}
}
void sendSensor(int sensorNumber) {
// Send an individual sensor status out to the LocoNet.
// It will only send if the previous time it was sent it had a different value.
// It will also only send if a threshold time value for the sending has been reached to avoid
// exsesive sending of messages.
unsigned long currentTime = millis();
if ((sensorValue[sensorNumber] != sensorPreviousValue[sensorNumber]) && (currentTime - sensorPreviousTime[sensorNumber] >= sensorInterval))
{
sensorPreviousValue[sensorNumber] = sensorValue[sensorNumber];
sensorPreviousTime[sensorNumber] = currentTime;
sendSensorMessage((addressDecoder + sensorNumber), !sensorValue[sensorNumber]);
}
}
void readSensors() {
// Read all sensors and send out messages
// Read from shift register for all sensors
// Use sampling to decide when to change the actual sensor value
// Get a sample of the state of all sensors via the shift register
digitalWrite(pinLoad, LOW);
delayMicroseconds(5);
digitalWrite(pinLoad, HIGH);
delayMicroseconds(5);
digitalWrite(pinClockIn, HIGH);
digitalWrite(pinClockEnable, LOW);
byte incoming1 = shiftIn(pinDataIn, pinClockIn, LSBFIRST);
//byte incoming2 = shiftIn(pinDataIn, pinClockIn, LSBFIRST);
//byte incoming3 = shiftIn(pinDataIn, pinClockIn, LSBFIRST);
digitalWrite(pinClockEnable, HIGH);
// Sample counter is increased so that we can tell if we are at a point where we want to
// determine the sensor value
sampleCount = sampleCount + 1;
// Each invidivual sensor is mapped from a specific bit on a specific input byte.
// We invert the sesnor value and add the value such that we count the number of times that the
// sensor sees activity
//sensorSample[0] = sensorSample[0] + !bitRead(incoming1,0);
sensorSample[1] = sensorSample[1] + !bitRead(incoming1,1);
//sensorSample[2] = sensorSample[2] + !bitRead(incoming1,2);
//sensorSample[3] = sensorSample[3] + !bitRead(incoming1,3);
//sensorSample[4] = sensorSample[4] + !bitRead(incoming1,4);
//sensorSample[5] = sensorSample[5] + !bitRead(incoming1,5);
//sensorSample[6] = sensorSample[6] + !bitRead(incoming1,6);
//sensorSample[7] = sensorSample[7] + !bitRead(incoming1,7);
//sensorSample[8] = sensorSample[8] + !bitRead(incoming2,0);
//sensorSample[9] = sensorSample[9] + !bitRead(incoming2,1);
//sensorSample[10] = sensorSample[10] + !bitRead(incoming2,2);
//sensorSample[11] = sensorSample[11] + !bitRead(incoming2,3);
//sensorSample[12] = sensorSample[12] + !bitRead(incoming2,4);
//sensorSample[13] = sensorSample[13] + !bitRead(incoming2,5);
//sensorSample[14] = sensorSample[14] + !bitRead(incoming2,6);
//sensorSample[15] = sensorSample[15] + !bitRead(incoming2,7);
//sensorSample[16] = sensorSample[16] + !bitRead(incoming3,0);
//sensorSample[17] = sensorSample[17] + !bitRead(incoming3,1);
//sensorSample[18] = sensorSample[18] + !bitRead(incoming3,2);
//sensorSample[19] = sensorSample[19] + !bitRead(incoming3,3);
//sensorSample[20] = sensorSample[20] + !bitRead(incoming3,4);
//sensorSample[21] = sensorSample[21] + !bitRead(incoming3,5);
//sensorSample[22] = sensorSample[22] + !bitRead(incoming3,6);
//sensorSample[23] = sensorSample[23] + !bitRead(incoming3,7);
// If we are at a point where we have done enough samples then we make a decision for each
// sensor to set the current value
if ( sampleCount >= sampleMax ) {
// Check each sensor to see if the samples have passed the threhold or not
for (int i=0; i < sensorCount; i++) {
if ( sensorSample[i] >= sampleThreshold ) {
sensorValue[i] = sensorOccupied;
} else {
sensorValue[i] = sensorNotOccupied;
}
sensorSample[i] = 0;
}
sampleCount = 0;
// Send out sensor deltas
for ( int i=0; i < sensorCount; i++) {
sendSensor (i);
}
}
}