Hi
I got a sketch to work with my IoTT Loconet shield on a Uno but when I tried to use it on a Mega it did not work. On the Uno the TX pin in the sketch was set to 6. On the Mega I tried to set the TX to 6, 47 and 7 with no luck. I really want to use a Mega so I can get up to 9 turnouts with associated LEDs and pushbuttons. Otherwise I am limited to 2 turnouts on the UNO.
Any suggestions?
Sketch attached. I realize it can be edited down to remove serial print statements and unneeded code.
Thanks in advance`
[code]
/*
Contributed code
version 0 = original code unmodified
version 1 = minor mods to servo timing
version 2 = works on Uno
version 3 = Mega256
*/
#include <LocoNet.h>
#include <BiColorLED.h>
#include <ServoTimer2.h> // library replaces Servo. Servo had conflict with timer1 in LocoNet library
#define LN_TX_PIN 47 // MEGA
// #define LN_TX_PIN 6 // UNO
// #define LN_TX_PIN 7 // LocoShield
// LN_RX_PIN Hardcoded in library for UNO and MEGA. Will not work with Leonardo (yet)
// -----------------------------------------------------------------------------
enum { LedOff = HIGH, LedOn = LOW };
enum { TURNOUT_NORMAL = 1, TURNOUT_DIVERGING = 0 };
// description of a turnout
struct Turnout {
const byte PinBut;
const byte PinServo;
const byte PinLedNor;
const byte PinLedDiv;
const int LnetAdr;
const int ValNormal;
const int ValDiverge;
const char *desc;
// BiColorLED leds;
ServoTimer2 servo;
bool swNormal;
byte butState;
};
// turnout descriptions
Turnout turnouts [] = {
// but servo led1 led2 lnAdr open close
{ 2, 5, 3, 4, 71, 1400, 1115, "t0" },
{ 9, 12, 10, 11, 72, 1425, 1200, "t1" },
};
const int Nturnout = sizeof(turnouts)/sizeof(Turnout);
int loconetDirection;
char s [90];
// -----------------------------------------------------------------------------
// Construct a Loconet packet that requests a turnout to set/change its state
void sendOPC_SW_REQ (int address, byte dir, byte on) {
lnMsg SendPacket ;
int sw2 = 0x00;
if (dir == TURNOUT_NORMAL) {
sw2 |= B00100000;
}
if (on) {
sw2 |= B00010000;
}
sw2 |= (address >> 7) & 0x0F;
SendPacket.data[ 0 ] = OPC_SW_REQ ;
SendPacket.data[ 1 ] = address & 0x7F ;
SendPacket.data[ 2 ] = sw2 ;
LocoNet.send ( &SendPacket );
}
// -----------------------------------------------------------------------------
// Some turnout decoders (DS54?) can use solenoids, this code emulates the digitrax
// throttles in toggling the "power" bit to cause a pulse
void setLNTurnout (int address, byte dir) {
sendOPC_SW_REQ (address - 1, dir, 1);
sendOPC_SW_REQ (address - 1, dir, 0);
}
// -----------------------------------------------------------------------------
void
setTurnout (
Turnout *t,
bool swNormal )
{
sprintf (s, "setTurnout: %s %s", t->desc, swNormal ? "N" : "D");
Serial.println (s);
t->swNormal = swNormal;
if (t->swNormal) {
t->servo.write (t->ValNormal);
digitalWrite (t->PinLedNor, LedOn);
digitalWrite (t->PinLedDiv, LedOff);
setLNTurnout (t->LnetAdr, TURNOUT_NORMAL);
}
else {
t->servo.write (t->ValDiverge);
digitalWrite (t->PinLedNor, LedOff);
digitalWrite (t->PinLedDiv, LedOn);
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (115200);
LocoNet.init (LN_TX_PIN);
Turnout *t = turnouts;
for (int n = 0; n < Nturnout; n++, t++) {
pinMode (t->PinBut, INPUT_PULLUP);
t->butState = digitalRead (t->PinBut);
t->servo.attach (t->PinServo);
pinMode (t->PinLedNor, OUTPUT);
pinMode (t->PinLedDiv, OUTPUT);
setTurnout (t, true); // normal
}
}
// -----------------------------------------------------------------------------
void loop ()
{
Turnout *t = turnouts;
for (int n = 0; n < Nturnout; n++, t++) {
byte but = digitalRead (t->PinBut);
if (t->butState != but) { // state change
t->butState = but;
delay (20); // debounce
if (LOW == but) // pressed
setTurnout (t, ! t->swNormal);
}
}
// check for switch message from Loconet throttle
lnMsg *LnPacket = LocoNet.receive ();
if (LnPacket) {
LocoNet.processSwitchSensorMessage (LnPacket);
// this function will call the specially named functions below...
}
}
// -----------------------------------------------------------------------------
/* void
locoNetMsg (
uint16_t address,
uint8_t output,
uint8_t direction )
{
Turnout *t = turnouts;
for (int n = 0; n < Nturnout; n++, t++) {
if (address == t->LnetAdr)
setTurnout (t, TURNOUT_NORMAL == direction);
}
}
*/
// -----------------------------------------------------------------------------
// Callbacks from LocoNet.processSwitchSensorMessage () ...
// We tie into the ones connected to turnouts so we can capture anything
// that can change (or indicatea change to) a turnout's position.
void notifySensor ( uint16_t Address, uint8_t State )
{ /* ignore, not a turnout related action */
}
// -----------------------------------------------------------------------------
void notifySwitchRequest (
uint16_t address,
uint8_t output,
uint8_t direction )
{
Serial.print ("Switch request");
Serial.print (address);
Serial.print(" ");
Serial.print(output);
Serial.print(" ");
Serial.println(direction);
if(output == 16)
{
// Serial.println ("Output = 16");
//locoNetMsg (address, output, direction);
Turnout *t = turnouts;
// Serial.print ("Number of turnouts =");
// Serial.println (Nturnout);
for (int n = 0; n < Nturnout; n++, t++) {
// Serial.print (" Loconet address = ");
// Serial.print (address);
// Serial.print ("matrix address");
// Serial.println (t->LnetAdr);
if (address == t->LnetAdr) {
// setTurnout (t, direction);
// Serial.print("Called setTurnout");
loconetDirection = direction;
// setTurnout (t, TURNOUT_NORMAL == direction);
setTurnout (t, loconetDirection);
}
}
}
}
// -----------------------------------------------------------------------------
/* void notifySwitchReport (
uint16_t address,
uint8_t output,
uint8_t direction )
{
locoNetMsg (address, output, direction);
}
*/
// -----------------------------------------------------------------------------
/* void notifySwitchState (
uint16_t address,
uint8_t output,
uint8_t direction )
{
// locoNetMsg (address, output, direction);
}
*/
[/code]