This is a very large sketch and I cannot strip it down to the 120000 character limit. The snipit that I posted is sufficient to demonstrate the problem in my version of the IDE. I don't know how to answer your request. The best I can do is to give you up to void (setup) {
Dale Gloer
[code]
// Simple Wifi Throttle
// Version 4.3 Geoff Bunza 2018
// modified heavily by Phil Abernathy
// Feb 6 trying to get wifi ip as an input from the controls when starting up.
// Feb 8 trying to get new address scheme to work...
/* Feb 15- changes from SWIFT#2 for SWIFT#1
- Feb17
- changed all reading of function switches to the function call where it can be changed if needed.
- Added + 10 to setting address: bell & lights off = +/- 1
-
bell off lights on = +/- 10
-
bell on lights off = +/- 100
-
bell & lights ON = +/- 1000
- Feb 19, changed all necessary variables and constants to arrays of integers, use zero as throttle #1, 1 for #2, etc
- (This was necessary because I did not build each of my three SWIFTS using the same pins. I also found that I physically installed some switches
- ...Lights...horn...upside down so I merely swapped the functions)
- Feb 20 made tname into array, so only ThrottleNum needs to be changed
-
deleting extra code that was left while testing...
- Feb 23, added estop and accel/braking to throttles
-
basically, the oh-so-wierdly complicated code in Need for Speed is done to closer simulate notching and braking. When at speed, if switched to NEU, the Speed knob
-
becomes a brake (can only slow down, cannot speed up in NEU). But it will slow down quicker in NEU than in FWD or REV when Speedknob goes to 0.
- March 8, added !quit as loop requirement to allow throttle to gracefully disconnect from server. However, JMRI handles restarting the throttle very well regardless.
- March 9 added roster for choosing loco number.
- March 10, dressing up and changing-
- March 11-13 added code to investigate end of line characters in client messages-JMRI seems to use CR LF CR LF. Cannot get LNWI to communicate.
- March 21-added code to start heartbeat monitor in server (sends "*+"), and added send heartbeat function calls (where the throttle name is sent to server) in all "while"
-
loops.
-
(note to REAL programmers, don't judge...I got my Associates degree in Electronics Technology in 1985 and that was my last formal training, although I did take
-
Cobol 1 & 2 and "370 Assembler" classes)
-
Heartbeat is set in WiThrottle Preferences (defaults to 10 seconds) but once throttle dissappears, with 10 sec heartbeat, it takes about 11 seconds
-
before JMRI estops the loco and about 17 before dropping all communication.
- March 26. Funny, after adding comments and trying to document, I realize how much I don't know but put into code by using Google searches for examples.
-
"indexOf" for example: I kinda' know, but would have tp look it up again.
- March 27 added heartbeat color to print colon in display (next to Speed colon) as heartbeat.
-
added display "-" if heartbeat failed at all, clear it if success. Coded to QUIT after 2 or more fails.
- March 29 revised code in effort to streamline loop to avoid missing functions...
- March 30 -added fastclock code.
- March 30 add initial power on option to display fastclock instead of direction if DIM switch is active at power on.
- March 30/31-added track power on and power off awareness and displayed status if off
- April 1-3 added code to allow fastclock to be used without Internet connection. The board has a timer so I get the fastclock and subtract it from the board time,
-
then use the difference added to the board time to display as fast clock time.
- April 3- added code to allow a momentum factor to be introduced. heavy and HEAVIER are two levels, displayed with h or H, and set/reset: Neutral, Bell off, Dim, full throttle
-
then shorthorn for heavy (or if heavy already to HEAVIER). Horn reduces the momentum from HEAVIER to heavy, or from heavy to no extra momentum.
-
Also revised throttle speed code to be more reactive to higher throttle by looping faster because difference between throttle and speed is used
-
(actually, eighth or quarter of the difference).
- April 5- added code for fourth SWIFT (BlackSWIFT3)
-
changed battery chack to be called each time that the time is displayed (1/second), and added string for < 10 so 10+ doesn't leave remnant displayed when
-
battery falls below 10
- April 13-added code for indicating that the track power is off while selecting/acquiring new loco. Cleaned up screens when estop is active (avoided clock display)
- April 14-revised code to change the 1/4 speed mode on or off. With Neutral, Bell off, Lights on, not Dim and full throttle, ShortHorn turns on, Horn turns off.
- April 14 or so, changed code to allow FastClock display (in lieu of FWD/REV) Neutral, Bell ON, Lights off and full throttle, ShortHorn turns on, Horn turns off.
- April 15-added code to only display the battery voltage message if the throttle has a battery voltage resistor set up. Saved as array, then assigned to disp_battery variable
-
- added code to allow skipping of the IP addresses stored in the sketch and enter new by keeping REV when logging into SSID.
- April 20-adding code to allow new design with notching selector instead of Speed Pot. Not sure how to incorporate yet, so I will try then test.
- April 20-adding code to allow use of additional switch for "Run/Dispatch".
- April 22-added code for plus weight momentum (more than none, leass than heavy).
- April 22-added code to allow the notching throttles to increase or decrease the speed of each notch by up to 8
-
when 0 speed, in Neu, full notching, Bell ON & Dim, then the shorthorn increases (notch 1-1 up by 1, but only to 8) while
-
horn decreases (notch 1-7 down by 1, but only to where notch 1 is 1)
- April 25-changed code to say relknob (for relative position of knob) when using knob settings. Changed from reqspeed for most of
-
the sketch except the need for speed.
- June 4 - Starting to modify the code to eliminate the deprecated "T" commands to the command station and make them "M" commands.
- June 5 - Code working for multi throttle, but has issues with steal, and "Not Set" in WiThrottle Window. Also fails to re-connect to custom
-
input ssid/password/server IP.
- June 7 - Added code when dispatching to set velocity to 0 and release all locos from throttle. Solved "Not Set" messages.
- June 10-11-changing code for entering wifi and ip.
- June 14-16 Changed display of loco to be the name stored in the roster when chosen from the roster, or the address if not. Shortened dislay if battery monitor is active.
- June 14-16 Cleaned up some left-over code and sped up the loop slightly. Fixed timing issue when selecting characters in the SSID. Doubled up the connection attempts
-
for new server IP addresses that might be slow to report connection.
- June 17-got an LNWI for testing-failed immediately because the heartbeat (identified on my phone using Engine Driver) is 90 seconds, and SWIFT has it as 10.
- June 18-found that LNWI does not use the "f" force function value. Also, using the F1 works all the time, however, the horn and shorthorn use F1 and F0, but the
-
bell, lights and dimming don't like that so I added code to differentiate. Also I could not get the old functions to read in, so the bell, horn, lights or
-
dimming would have be opposite until fixed (if they are on when starting the loco). I worked on the code for starting a new loco to use existing state and
-
changng what I need to match how the switches are set when starting.
-
-
I added lots of debug printing to the serial monitor in the Arduino environment.
-
-
I have an awful time connecting to the LNWI, and it seems like every other try, it works. Hmmm, I've heard about that but not what the fix is.
-
I changed the array for sign-in ssid, password and server ip to have the LNWI listed twice. If if fails the first time, it connects the 2nd.
-
I changed the loop code to always read the client output and use it/display it to the debug serial monitor. I shortened the code run
-
during the heartbeat and used the loop client read to confirm heartbeat from the server.
-
- August-added code for starting and shutting down Paragon2 decoders. Two locos (1563 and 1863) have Paragon2 and always come up shutdown when track power is started
-
(or interrupted). Added the F9 on when acquiring, and toggle F9 when dispatching.
- August 18, looking at possible OTA code. Added new one to list, although not physically built
/
/
- Throttle Layout:
-
___________________________
- | TB TA | TB is Bell; TA is lights with UP=On, center off=on but dim
- | |
- | OLED DISPLAY |
- | OLED DISPLAY |
- | OLED DISPLAY |
- | |
- | TDir (PB) SpeedPot | PB is momentary; Horn (DOWN), TC=ShortHorn (UP)
- | |
- |__________________________|
-
*/
// Usage:
// Turning Power On requests a Loco Address change
// 1. display will change -- direction indicates addr up or down
// 2. Setting Direction SW to center/neutral for about 1 second gets out of address set mode
// 3. Setting Lights to DIM before turning on sets the display to FastClock instead of direction
// 4. Setting Bell ON before turning on sets the start mode to "heavy" (momentum, with "h" in speed box)
//
// While running a train:
// Setting Bell off, Lights ON, Direction to NEUTRAL, SpeedPot full ON and ShortHorn makes 1/4 throttle for switching,
// Setting Bell off, Lights ON, Direction to NEUTRAL, SpeedPot full ON and Horn will change from 1/4 to FULL throttle available
// Setting Bell ON, Lights ON, Direction to NEUTRAL, and SpeedPot full ON will toggle the MUTE function (F8) on decoder.
// Setting Bell OFF, Lights to Dim, Direction to Neutral, SpeedPot full on with ShortHorn increases Momentum to h, or to H if h.
// Setting Bell OFF, Lights to Dim, Direction to Neutral, SpeedPot full on with Horn decreases Momentum to normal, or to h if H.
// While DISPATCHED, with Bell & Lights ON, and SpeedPot full ON, REV will turn track Power OFF via JMRI
// While DISPATCHED, with Bell & Lights ON, and SpeedPot full ON, FWD will turn track Power ON via JMRI
// While DISPATCHED, with Bell Off, Lights ON DIM, Direction to REV, and SpeedPot full ON will offer QUIT?,
// - Lights Off "quits" the server and disconnects from JMRI, however turning lights ON stays connected to JMRI server.
//
// When turning on, several options are available. Normally, all functions are OFF and Direction switch in Neutral, Speed pot off (full CCW).
// The sequence of normal startup is that it will use the 1st pre-programmed WiFi and Password to try to connect. A count will progress on the display
// with "Trying wifi..." and "FWD to try next" messages until it either connects to the wifi or the Direction lever is moved to FWD.
// If not connected, when Direction lever is in FWD, "NEU to try" and the next WiFi SSID will be shown. This contiunues for the 4 or 5 pre-programmed
// WiFi SSID and password combos.
// - Once connected, it looks for the JMRI server by trying (one at a time) the 3 pre-programmed IP addresses in the sketch (with the
// message "looking for port".
// - If the IP address is known to not be in the three pre-programmed, immediate REV will skip those three just as if no
// server is found (to allow manual entry). If no server is found, it falls through to manual entry of the IP address with "192.168." as a start, and the remainder
// to be added. The display says "New IP-Bell Sets" and in Neutral, the Speed Knob rotates through the pre-defined (allowable) characters. Using REV
// locks the display, and Horn adds the character to the string. When the IP is built to satisfaction (or a mistake is made like I do some times),
// turning the bell on submits the now complete IP address to the sketch to try to connect to the server. On the display, it shows the actual IP
// that it is trying to connect to. If it does not find a server, it throws up and eventually comes back to manual IP entry.
//
// To manually enter a new SSID/password (such as when visiting a foreign railroad not included in the sketch), before turning ON, turn the Direction lever to
// FWD and hold the ShortHorn ON. It will say "newSSID, Bell set" with "addon: " and a character in the bottom line. With the Direction lever in Neutral,
// the Speed knob rotates through all the pre-programmed (allowable) characters that can be added to the SSID. REV locks the character, and Horn adds
// it to the string being built in the middle line. When the string is built to satisfaction (or a mistakes is made-there is no backspace) turning the
// Bell Switch ON changes to "Pswd,lights set" and the password can be built a character at a time (Neu, spin to the char needed then REV and Horn to
// add the character to the string being built). When the string is built to satisfaction (or a mistakes is made-there is no backspace) turning the
// Light Switch ON submits the SSID and Password to the sketch to try to connect. If it connects, it falls through to NEW IP, otherwise it just counts up
// until REV is triggered to re-enter a new SSID. The manually entered SSID, Password and IP address are stored in the EEPROM for reuse later.
//
// If a manual entry has been made, it can be recalled from EEPROM (and used) upon re-starting by FWD and Horn when turning on. Very handy for visiting and
// the throttle is turned off, or battery dies.
//
// If a manual entry has been made, the SSID and Password can be recalled from EEPROM and only require the IP address by FWD, Full Speed, ShortHorn while turning on.
// Useful for when IP address of server has changed on the server since programming was done (I have no idea why the IP address of the server would change
// from one visit to the next, but it has...).
//
// At startup (power on of throttle), if DIM Switch is ON, the Fast Clock (as sent by the server, using computer time if not othwerwise set) is displayed instead
// of direction.
//
// At startup (power on of throttle), if Bell is ON, the throttle is started in heavy mode (with momentum programmed in)
//
// When MUTE wait screen is active, Direction Lever FWD displays Fast Clock time
//
// When Dispatched, DIM and ShortHorn will display the Fast Clock time.
//
///////////////////////////////////////////////////
// WiFi Server Definitions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
const int tpPort = 12090;
char ssidchar [20] = "anything" ;
int ssidstrlen ;
char pwordchar [20] = "something" ;
int pwordstrlen ;
int mystringlen ;
int prom_address_start ;
// 2 dim array[rows][elements] each line is one wifi ssid (and password), and three IP addresses to be checked for the server at that ssid
String serverstrs [5][5] = {{"JMRI\0", "\0", "192.168.254.15\0" , "192.168.254.2\0" , "192.168.254.3\0"},
{"jmri\0", "\0", "192.168.0.100\0" , "192.168.0.101\0" , "192.168.0.101\0" },
{"Dtx1-LnServer_0007-7\0", "digitrax1234\0", "192.168.7.1\0" , "192.168.8.1\0" , "192.168.9.1\0"},
{"Dtx1-LnServer_0007-7\0", "digitrax1234\0", "192.168.7.1\0" , "192.168.8.1\0" , "192.168.9.1\0"},
// {"Dtx5-GSMRRHO _0946-7\0", "digitrax1234\0", "192.168.7.1\0" , "192.168.8.1\0" , "192.168.9.1\0"},
// {"Dtx5-GSMRRHO _07CE-7\0", "\0", "192.168.7.1\0" , "192.168.8.1\0" , "192.168.9.1\0" },
{"PhilSue2500-RAV\0", "roger2008\0", "10.10.10.102\0" , "10.21.18.16\0" , "192.168.0.12\0" } };
// {"RAV-FileHub-162E\0", "11111111\0", "10.10.10.222\0" , "10.21.18.16\0" , "192.168.0.12\0" } };
// {"PhilSue\0", "roger2008\0", "192.168.1.128\0" , "192.168.1.132\0" , "192.168.1.100\0" } };
// {"JMRI\0", "\0", "192.168.254.15\0" , "192.168.254.3\0" , "192.168.254.2\0" }
int ipaddressstrlen ;
char ipaddresschar [ 17 ] ;
String LocalIPAddress ;
bool dispbattery = false ;
// Roster can be saved up to 30 locos in this configuration. Each Roster entry is sent as Loco name(String), Loco number(Integer), and Short or Long address (String)
// and is stored in three arrays.
String Lname[ 50 ] = { "BNSF 1000", "SF 8517"};
int Lnumber[ 50 ] = { 1000, 8517 } ;
String Llongshort[ 50 ] = { "L","L" } ;
String LnumberStr ;
String Lnametemp ;
String LocoDispName ;
bool Steal_Required = false ;
bool StealLoco = false ;
String rosterString ;
int heartbeat_timeout ;
bool timeset = false ;
String LtimeHourstr ;
long Ltime ;
long LtimeHour ;
int FastDiffHour ;
String LtimeMinutestr ;
int LtimeMinute ;
int LtimeSecond ;
int oldLtimeSecond ;
String LtimeSecondstr ;
int FastDiffMinute ;
int FastDiffSecond ;
bool FastLocalTimeSet = false;
bool showtime = false ;
char timeStringBuff [50]; // 50 chars should be enough
int tm_hour = 8 ;
int tm_min = 55 ;
int tempLMinute ;
bool DiffSet = false ;
String addressfromclient ;
int lenofaddress ;
String ClientString ;
String oldClientString ;
int ClientStringDelay = 50 ;
String OrigRosterString ;
String rosterEntriesStr ;
String VersionNumberStr ;
bool setfromroster = false ;
int rosterEntries= 0 ;
int rosterNumber ;
String rosterEntry ;
int rosterEntryLen ;
int rosterEntryStart ;
String rosterField ;
int rosterFieldLen ;
int rosterFieldStart ;
String rosterEntryStarter = "[" ;
String rosterEntryEnder = "]" ;
String rosterFieldStarter = "{" ;
String EndLine = "NL"; // carriage return is \r, while newline is \n.
//
long fastclock = 1553763535L ; // fastclock from Digitrax is number of seconds since 1/1/1970
String fastclockstr ;
#define minsperhour = 60 ; //
#define hoursperday = 24 ; //
String Ltimestr ;
char* localtm ;
long elapsedseconds ;
long elapsedminutes ;
long elapsedhours ;
int fasthour ; // hour to display
String fasthourstr ;
int fastminute ; // minute to display
String fastminutestr ;
int fastsecond ;
String fastsecondstr ;
bool Fclockget = false ;
int DispFastSecond ;
String DispFastSecondstr ;
int DispFastMinute ;
String DispFastMinutestr ;
int DispFastHour ;
String DispFastHourstr ;
bool useheartbeat = false ; // June 17-added to eliminate heartbeat for testing with LNWI
bool heartbeatconfirmed = false ;
int heartbeatfailcount = 0 ;
long HBmillis = 0 ;
long HBcheckmillis = 0 ;
bool HBtimingstarted = false ;
bool commfail = false ;
String heartbeatcolor ="white" ;
/*
- As of August 7, all information needed for each throttle that might be different is listed in this section.
- As of Feb 23, 2019
- throttles built for Phil and Ron (paid and more); Requested by (and paid) Jerry K
- Requested by Tom P (paid), David C, and Ken says no more than TWO (but low priority) for the Depot
*/
//
//
//_______________________________________________________________________________________________________________________________________________
//// ********************************************************************************************************************************************|
//// -Throttle num: Phil=0, WhiteRed=1, DavidC-BlackBlueSwift=2, Jerry-BlackBlackSwift3=3, BlackRedSWIFT=4, Notched=5 |
//// TomSlideWhite=6 RonSlideBlack = 7 ANewOne=8 |
//// ------- |
//// --- |
int ThrottleNum = 2 ; // arrays used a zero based numbering so Swift #1 is 0 |
//// -`-- |
//// ------- |
//// Throttle: 0 is Phil, 1 is JimWsWhiteRed, 2 is David's, 3 is Jerry's, 4 is BlackW/RedKnob, 5 is Notched, |
//// 6 is TomsWhiteSlide, 7 is RonsBlackSlide, 8 is a New One |
//// *******************************************************************************************************************************************|
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
String tname[ ] = { "SWIFT#0", "JimSWIFTRed#1", "DavidSWIFTBlue2", "JerrysBlackSwift3", "SWIFTRed4", "Notched5", "TomSlide6", "RonSlide7", "NewOneOTA" } ; // zero based numbering
bool flipScreenVertically[ ] = { true, true, false, true, true, false, false, false, false } ;
bool UsingNotches [ ] = {false, false, false, false, false, true, false, false, false } ; // only #5 uses notches...
int NumberOfThrottlesBuilt = 9 ;
//
//
// Switch assignment table: Ordered list of function pins
int TDirFwdLow [ ] = { 25, 32, 32, 32, 13, 25, 4, 4, 4 } ; // Forward on direction switch
int TDirRevLow [ ] = { 32, 25, 25, 25, 12, 32, 5, 5, 5 } ; // Reverse on direction switch
int PB [ ] = { 26, 27, 26, 26, 33, 27, 26, 27, 27 } ; // PB: - Horn, was a pushbutton-changed to momentary spdt switch
int TA [ ] = { 4, 5, 5, 2, 5, 5, 2, 2, 2 } ; // TA: - Lights switch
int TB [ ] = { 2, 4, 4, 4, 4, 4, 32, 32, 32 } ; // TB: - Bell
int TC [ ] = { 5, 2, 2, 5, 2, 2, 0, 0, 0 } ; // TC: - Dim
int SH [ ] = { 27, 26, 27, 27, 25, 26, 25, 26, 26 } ; // SH: - ShortHorn
int TD [ ] = { 12, 12, 12, 12, 14, 12, 12, 12, 12 } ; // TD: not used SPDT toggle active HIGH
int TE [ ] = { 13, 13, 13, 13, 15, 14, 14, 14, 14 } ; // TE: not used SPDT toggle active HIGH
int TF [ ] = { 14, 14, 14, 14, 16, 15, 15, 15, 15 } ; // TF: not used SPDT toggle active HIGH
int TG [ ] = { 15, 15, 15, 15, 18, 16, 16, 16, 16 } ; // TG: not used SPDT toggle active HIGH
int ADC_Ch [ ] = { 39, 39, 39, 39, 39, 39, 36, 36, 36 } ; // Center Wiper of 10K Speed Potentiometer Ends=GND & +3.3V
int ADC_Ch2 [ ] = { 36, 36, 36, 36, 36, 36, 39, 39, 39 } ; // Battery monitor through resistor divider 1/4 Ends=ground & center tap not used on SWIFT#1
int OLED_SDA [ ] = { 23, 21, 23, 22, 23, 22, 22, 22, 22 } ; // Data line for I2C OLED Display SDA: SWIFT#1 is 23, RonsSWIFT#2 is 21
int OLED_SCLK [ ] = { 22, 22, 21, 21, 22, 21, 21, 23, 23 } ; // Clock line for I2C OLED Display SCK for both #1 and #2
bool batterymonitor [ ] = {false, true, false, false, false, true, false, false, false } ;
//
/
- End of throttle uniqure information.
- August 7, 2019
-
*/
// adding definition for pins used in notching throttle
int notchpin [ ] = { 13, 14, 15, 16, 17, 18, 19, 3, 1 } ; // notch refers to speed setting on rotary switch (which one is grounded)
int oldnotch ;
int notchsetting = 0 ;
bool NotchedThrottle = false ;
int initialnotchspeed[ ] = { 0, 1, 5, 11, 19, 30, 50, 111, 115 } ;
int notchspeed[ ] = { 0, 1, 5, 11, 19, 30, 50, 111, 115 } ;
//
#define strobes 1
#define LED_BIRED 16
#define LED_BIGRN 17
#define LED_BIBLU 18
#define LED_BIBLU2 19
#define lshift 2
//Function Assignments
#define F0_pin TA[ThrottleNum] // Function 0 pin assignment = lights
#define F1_pin TB[ThrottleNum] // Function 1 pin assignment = bell
#define F2_pin PB[ThrottleNum] // Function 2 pin assignment = horn
#define F3_pin SH[ThrottleNum] // Function 3 pin assignment = short horn
#define F4_pin TD[ThrottleNum] // Function 4 pin assignment - not used
#define F5_pin TE[ThrottleNum] // Function 5 pin assignment - not used
#define F6_pin TF[ThrottleNum] // Function 6 pin assignment - not used
#define F7_pin TC[ThrottleNum] // Function 7 pin assignment - not used
#define bounce_del 20
String lspeedstr ;
int num_functions = 8; // Number of functions supported by this throttle. Changed TO 8 (MAX) to include dimming (7) when reading new loco
int function_pin [ ] ={ F0_pin,F1_pin,F2_pin,F3_pin,F4_pin,F5_pin,F6_pin,F7_pin }; // Ordered list of function pins
int function_map [ ] ={ 0, 1, 2, 3, 4, 5 , 6, 7}; // this will map the pin list to actual functions
byte function_value [ ]={LOW, LOW, HIGH, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW };
// retained value of each function, more than used by SWIFT but 28 are sent from server
byte setF = 1;
byte setR = 1;
String lastDirection = "N" ; // Feb 2 added to allow neutral and back if in same direction
byte alternate = 0;
byte throttlealternate = 0;
byte LightLoopCount = 0 ;
byte BellLoopCount = 0 ;
byte DimLoopCount = 0 ;
int rawbattery = 0 ;
int relativebattery = 0 ;
String relativebatterystr ;
String batterystr = "..........,,,,,,,,,,,,,,,," ;
int oldrelativebattery = -1 ;
int F8 = 0;
int dispcount = 0; // counting while PB in and loco dispatched...
int wifiTries = 0;
int ipTries = 0 ;
String GetWiFiFrom = "table" ; // table, mem or entry
String GetIPFrom = "table" ; // table, mem or entry
int charposition = 1;
int arrayposition = 0;
int dispHeartbeat_x = 50 ;
int dispHeartbeat_y = 22 ;
int dispLoco_x = 0 ; // x coordinate for Loco to be displayed.
int dispLoco_y = 45 ;
int dispDCC_x = 42 ; // x coordinate for Loco Number to be displayed.
int dispDCC_y = 45 ;
int dispBell_x = 0 ; // x coordinate for Bell On to be displayed.
int dispBell_y = 0 ;
int dispLights_x = 106 ; // x coordinate for Lights On to be displayed.
int dispLights_y = 0 ;
int dispPower_x = 88 ; // x coordinate for Track Power status to be displayed.
int dispPower_y = 45 ;
int dispDim_x = 70 ; // x coordinate for Dim to be displayed.
int dispDim_y = 0 ;
int dispFull_x = 38 ; // x coordinate for throttle limit (1/4) to be displayed.
int dispFull_y = 0 ;
int dispBatt_x = 86 ; // x coordinate for Battery status to be displayed.
int dispBatt_y = 29 ;
int dispPlusMinus_x = 60 ;
int dispPlusMinus_y = 22 ;
String newcharacter;
String oldcharacter;
String wifimsg ;
char newssid[20] ;
String newssidstr ;
String ssidcharacters = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789-. -";
char newpassword[20] ;
String newpasswordstr ;
String passwordcharacters = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789-!@#$%^&*()+..";
String newipaddress = "192.168.1.100";
char ipaddress[16];
String newPort = "12090" ;
String ipaddresscharacters = "1234567890...";
bool LocoAssigned = false ;
bool newssidset ;
bool newpasswordset;
bool ipset ;
bool dispatched = true ;
bool runtrains = false ;
bool TurnFunctionOn= false ;
int function_number ;
String function_number_str ;
bool LightSwitchOn = false ;
bool oldLightSwitchOn = false ;
bool dim = false ;
bool olddim = false ;
bool BellSwitchOn = false ;
bool oldBellSwitchOn = false ;
bool hornon = false ;
bool HornDisp = true ;
bool oldhornon = false ;
bool shorthornon = false ;
bool oldshorthornon = false ;
bool mute = false ;
bool mute_displayed = false ;
bool newipset = false ;
bool mutewait = true ;
bool wificonnected = false ;
bool poweron = true ;
String poweronStatus[3] = {"Off","On","Unk"};
bool poweronsent = false ;
bool poweroffdisplayed = false ;
bool estop = false ;
String DirLever = "NEU" ;
bool inNeutral = true ;
bool goingforward = false ;
bool locostopped = true ;
bool goingbackward = false ;
int accellbump = 0 ;
int base_speed_repeat_bump = 6 ;
int base_speed_repeat_coast = 150 ;
int base_speed_repeat_brake = 2 ;
int speed_repeat_bump = base_speed_repeat_bump ;
int speed_repeat_coast = base_speed_repeat_coast ;
int speed_repeat_brake = base_speed_repeat_brake ;
int plusspeed_repeat_bump = 18 ;
int plusspeed_repeat_coast = 180 ;
int plusspeed_repeat_brake = 6 ;
int hspeed_repeat_bump = 50 ;
int hspeed_repeat_coast = 240 ;
int hspeed_repeat_brake = 12 ;
int Hspeed_repeat_bump = 180 ;
int Hspeed_repeat_coast = 360 ;
int Hspeed_repeat_brake = 18 ;
int speed_repeat_ctr = speed_repeat_bump;
bool plusweight = false ;
bool heavy = false ;
bool heavier = false ;
int heavywait = 0;
String heavystr ;
bool quit = false ;
String throttle = "Full" ;
// ******** REMOVE THE "//" IN THE FOLLOWING LINE TO SEND DEBUGGING -- -- -- I did remove that.
// ******** INFO TO THE SERIAL MONITOR
#define DEBUG
// For a connection via I2C using Wire include
#include "SSD1306Wire.h"
#include <WiFi.h>
#include <EEPROM.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
#include <time.h>
#include <sys/time.h>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Initialize the OLED display using Wire library
SSD1306Wire display(0x3c, OLED_SDA[ThrottleNum], OLED_SCLK[ThrottleNum]); // I2C addr, SDA, SCK for SWIFT#1
boolean testv = false;
int DCC_address;
String LocoString ;
int temp_address;
byte foffset[ ] = {0, 17, 34, 51, 68, 85, 102, 119}; // not used but kept as reference to where digits can be printed.
String fcs[ ] = {"0","1","2","3","4","5","6","7"};
boolean fvalue [ ] = {false, false, false, false, false, false, false, false, false };
int lspeed = 0;
int ltemp = 0;
int rawpot = 0;
int oldrawpot = 0 ;
int throttlediff = 0;
int throttlediff_sixteenth = 0 ;
int throttlediff_eighth = 0 ;
int speedchange = 0;
int reqspeed = 0 ;
int relknob = 0 ;
int oldrelknob1 = 0 ;
int oldrelknob2 = 0 ;
int testrelknob = 0 ;
byte ftn_temp = 0;
int i,j,k,l = 0 ;
String xmits ; // to avoid string space overlap
// String newline = "\n" ;
String newline = "" ; // 7-6-2019 try to eliminate bad message from server due to null line
#define fdelay 1
#define ldelay 250
String jmri_res; //buffer to hold incoming response
int lastread = 0;
long delta = 290;
WiFiClient client;
boolean setaddr;
#define EEPROM_SIZE 64
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Setup starts, Setup starts, Setup starts, Setup starts, Setup starts, Setup starts, Setup starts, Setup starts,
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {