From a85131ee17e3c016e05dd96ab06d873e0db95493 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Fri, 30 Oct 2020 13:00:02 +0000 Subject: [PATCH 1/8] experimental --- CommandStation-EX.ino | 7 + DCCEXParser.cpp | 5 + EthernetInterface.cpp | 333 ++++++++++++------------------------------ EthernetInterface.h | 67 +++------ StringFormatter.cpp | 1 + StringFormatter.h | 2 + defines.h | 7 +- 7 files changed, 133 insertions(+), 289 deletions(-) diff --git a/CommandStation-EX.ino b/CommandStation-EX.ino index 9749fea..8b75fc4 100644 --- a/CommandStation-EX.ino +++ b/CommandStation-EX.ino @@ -38,6 +38,10 @@ void setup() WifiInterface::setup(WIFI_SERIAL_LINK_SPEED, F(WIFI_SSID), F(WIFI_PASSWORD), F(WIFI_HOSTNAME), IP_PORT); #endif // WIFI_ON +#if ETHERNET_ON + EthernetInterface::setup(); +#endif // ETHERNET_ON + // Responsibility 3: Start the DCC engine. // Note: this provides DCC with two motor drivers, main and prog, which handle the motor shield(s) // Standard supported devices have pre-configured macros but custome hardware installations require @@ -67,6 +71,9 @@ void loop() #if WIFI_ON WifiInterface::loop(); #endif +#if ETHERNET_ON + EthernetInterface::loop(); +#endif LCDDisplay::loop(); // ignored if LCD not in use diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 64e1213..ec6f049 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -48,6 +48,7 @@ const int HASH_KEYWORD_SLOW = -17209; const int HASH_KEYWORD_PROGBOOST = -6353; const int HASH_KEYWORD_EEPROM = -7168; const int HASH_KEYWORD_LIMIT = 27413; +const int HASH_KEYWORD_ETHERNET = -30767; int DCCEXParser::stashP[MAX_PARAMS]; bool DCCEXParser::stashBusy; @@ -609,6 +610,10 @@ bool DCCEXParser::parseD(Print *stream, int params, int p[]) Diag::WIFI = onOff; return true; + case HASH_KEYWORD_ETHERNET: // + Diag::ETHERNET = onOff; + return true; + case HASH_KEYWORD_WIT: // Diag::WITHROTTLE = onOff; return true; diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp index 3498871..e7d1678 100644 --- a/EthernetInterface.cpp +++ b/EthernetInterface.cpp @@ -16,121 +16,94 @@ * You should have received a copy of the GNU General Public License * along with CommandStation. If not, see . * - * Ethernet Interface added by Gregor Baues */ #include "EthernetInterface.h" #include "DIAG.h" -#include "StringFormatter.h" +#include "CommandDistributor.h" -//#include -#include -#include - - -// Support Functions +EthernetInterface * EthernetInterface::singleton=NULL; /** - * @brief Aquire IP Address from DHCP; if that fails try a statically configured address + * @brief Setup Ethernet Connection + * + */ +void EthernetInterface::setup() +{ + singleton=new EthernetInterface(); + if (!singleton->connected) singleton=NULL; +}; + + +/** + * @brief Aquire IP Address from DHCP and start server * * @return true * @return false */ -bool EthernetInterface::setupConnection() +EthernetInterface::EthernetInterface() { - - singleton=this; + byte mac[]=MAC_ADDRESS; - DIAG(F("\nInitialize Ethernet with DHCP:")); - server = EthernetServer(LISTEN_PORT); // Ethernet Server listening on default port LISTEN_PORT - ip = IPAddress(IP_ADDRESS); // init with fixed IP address needed to get to the server - connected = false; // Connection status - streamer= new MemStream(buffer, MAX_ETH_BUFFER, MAX_ETH_BUFFER, true); // streamer who writes the results to the buffer - - if (Ethernet.begin(EthernetInterface::mac) == 0) + DIAG(F("\n+++++ Ethernet Setup ")); + + if (Ethernet.begin(mac) == 0) { - DIAG(F("\nFailed to configure Ethernet using DHCP ... Trying with fixed IP")); - Ethernet.begin(EthernetInterface::mac, EthernetInterface::ip); // default ip address - - if (Ethernet.hardwareStatus() == EthernetNoHardware) - { - DIAG(F("\nEthernet shield was not found. Sorry, can't run without hardware. :(")); - return false; - }; - if (Ethernet.linkStatus() == LinkOFF) - { - DIAG(F("\nEthernet cable is not connected.")); - return false; - } - } - - ip = Ethernet.localIP(); // reassign the obtained ip address - - DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]); - DIAG(F("\nListening on port: [%d]"), port); - dnsip = Ethernet.dnsServerIP(); - DIAG(F("\nDNS server IP address: [%d.%d.%d.%d] "), ip[0], ip[1], ip[2], ip[3]); - return true; -} - -/** - * @brief Handles command requests recieved via UDP. UDP is a connection less, unreliable protocol as it doesn't maintain state but fast. - * - */ - void EthernetInterface::udpHandler() { - singleton->udpHandler2(); - } - void EthernetInterface::udpHandler2() -{ - - int packetSize = Udp.parsePacket(); - if (packetSize) - { - DIAG(F("\nReceived packet of size:[%d]\n"), packetSize); - IPAddress remote = Udp.remoteIP(); - DIAG(F("From: [%d.%d.%d.%d:"), remote[0], remote[1], remote[2], remote[3]); - char portBuffer[6]; - DIAG(F("%s]\n"), utoa(Udp.remotePort(), portBuffer, 10)); // DIAG has issues with unsigend int's so go through utoa - - // read the packet into packetBufffer - Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); - - DIAG(F("Command: [%s]\n"), packetBuffer); - - streamer->flush(); - - Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); - - ethParser.parse(streamer, (byte *)packetBuffer, true); // set to true so it is sync cf. WifiInterface - - if (streamer->available() == 0) - { - DIAG(F("\nNo response\n")); - } - else - { - // send the reply - DIAG(F("Response: %s\n"), (char *)buffer); - Udp.write((char *)buffer); - Udp.endPacket(); - } - - memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); // reset PacktBuffer + DIAG(F("FAILED ")); + if (Ethernet.hardwareStatus() == EthernetNoHardware) DIAG(F("shield not found")); + else if (Ethernet.linkStatus() == LinkOFF) DIAG(F("cable not connected")); + DIAG(F(" ++++++\n")); + connected=false; return; } + + connected=true; + + IPAddress ip = Ethernet.localIP(); // reassign the obtained ip address + + server = new EthernetServer(LISTEN_PORT); // Ethernet Server listening on default port LISTEN_PORT + server->begin(); + + LCD(4,F("IP: %d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]); + LCD(5,F("Port:%d"), LISTEN_PORT); + + outboundRing=new RingStream(OUTBOUND_RING_SIZE); } /** - * @brief Handles command requests recieved via TCP. Supports up to the max# of simultaneous requests which is 8. The connection gets closed as soon as we finished processing + * @brief Main loop for the EthernetInterface * */ - void EthernetInterface::tcpHandler() +void EthernetInterface::loop() { - singleton->tcpHandler2(); + if (!singleton) return; + + switch (Ethernet.maintain()) + { + case 1: + //renewed fail + DIAG(F("\nEthernet Error: renewed fail\n")); + singleton=NULL; + return; + + case 3: + //rebind fail + DIAG(F("Ethernet Error: rebind fail\n")); + singleton=NULL; + return; + + default: + //nothing happened + break; + } + + singleton->loop2(); + } - void EthernetInterface::tcpHandler2() + + void EthernetInterface::loop2() { // get client from the server - EthernetClient client = getServer().accept(); + EthernetClient client = server->accept(); // check for new client if (client) @@ -148,157 +121,41 @@ bool EthernetInterface::setupConnection() } // check for incoming data from all possible clients - for (byte i = 0; i < MAX_SOCK_NUM; i++) + for (byte socket = 0; socket < MAX_SOCK_NUM; socket++) { - if (clients[i] && clients[i].available() > 0) - { + if (clients[socket]) { + + // stop any clients which disconnect + if (!clients[socket].connected()) + { + if (Diag::ETHERNET) DIAG(F("\nEthernet: disconnect %d \n"), socket); + clients[socket].stop(); + clients[socket]=NULL;//???? + } + int available=clients[socket].available(); + if (available > 0) { + if (Diag::ETHERNET) DIAG(F("\nEthernet: available socket=%d,avail=%d,count="), socket, available); // read bytes from a client - int count = clients[i].read(buffer, MAX_ETH_BUFFER); + int count = clients[socket].read(buffer, MAX_ETH_BUFFER); buffer[count] = '\0'; // terminate the string properly - DIAG(F("\nReceived packet of size:[%d]\n"), count); - DIAG(F("From Client #: [%d]\n"), i); - DIAG(F("Command: [%s]\n"), buffer); - - // as we use buffer for recv and send we have to reset the write position - streamer->setBufferContentPosition(0, 0); - - ethParser.parse(streamer, buffer, true); // set to true to that the execution in DCC is sync - - if (streamer->available() == 0) - { - DIAG(F("No response\n")); - } - else - { - buffer[streamer->available()] = '\0'; // mark end of buffer, so it can be used as a string later - DIAG(F("Response: %s\n"), (char *)buffer); - if (clients[i].connected()) - { - clients[i].write(buffer, streamer->available()); - } - } - } - // stop any clients which disconnect - for (byte i = 0; i < MAX_SOCK_NUM; i++) - { - if (clients[i] && !clients[i].connected()) - { - DIAG(F("Disconnect client #%d \n"), i); - clients[i].stop(); - } + if (Diag::ETHERNET) DIAG(F("%d:%e\n"), socket,buffer); + // execute with data going directly back + outboundRing->mark(socket); + CommandDistributor::parse(socket,buffer,outboundRing); + outboundRing->commit(); + return; // limit the amount of processing that takes place within 1 loop() cycle. + } } } -} -// Class Functions -/** - * @brief Setup Ethernet Connection - * - * @param pt Protocol used - * @param localPort Port number for the connection - */ -void EthernetInterface::setup(protocolType pt, uint16_t localPort) -{ - DIAG(F("\n++++++ Ethernet Setup In Progress ++++++++\n")); - port = localPort; - if (setupConnection()) - { - DIAG(F("\nProtocol: [%s]\n"), pt ? "UDP" : "TCP"); - switch (pt) - { - case UDP: - { - if (Udp.begin(localPort)) - { - connected = true; - protocolHandler = udpHandler; - } - else - { - DIAG(F("\nUDP client failed to start")); - connected = false; - } - break; - }; - case TCP: - { - Ethernet.begin(mac, ip); - EthernetServer server(localPort); - setServer(server); - server.begin(); - connected = true; - protocolHandler = tcpHandler; - break; - }; - default: - { - DIAG(F("Unkown Ethernet protocol; Setup failed")); - connected = false; - return; - } - } + // handle at most 1 outbound transmission + int socketOut=outboundRing->read(); + if (socketOut>=0) { + int count=outboundRing->count(); + if (Diag::ETHERNET) DIAG(F("Ethernet reply socket=%d, count=:%d\n"), socketOut,count); + for(;count>0;count--) clients[socketOut].write(outboundRing->read()); + clients[socketOut].flush(); //maybe + } + } - else - { - connected = false; - }; - DIAG(F("\n++++++ Ethernet Setup %S ++++++++\n"), connected ? F("OK") : F("FAILED")); -}; - -/** - * @brief Setup Ethernet on default port and user choosen protocol - * - * @param pt Protocol UDP or TCP - */ -void EthernetInterface::setup(protocolType pt) -{ - setup(pt, LISTEN_PORT); -}; - -/** - * @brief Ethernet setup with defaults TCP / Listen Port - * - */ -void EthernetInterface::setup() -{ - setup(TCP, LISTEN_PORT); -} - -/** - * @brief Main loop for the EthernetInterface - * - */ -void EthernetInterface::loop() -{ - switch (Ethernet.maintain()) - { - case 1: - //renewed fail - DIAG(F("\nError: renewed fail")); - break; - - case 2: - //renewed success - DIAG(F("\nRenewed success: ")); - ip = Ethernet.localIP(); // reassign the obtained ip address - DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"),ip[0], ip[1], ip[2], ip[3]); - break; - - case 3: - //rebind fail - DIAG(F("Error: rebind fail")); - break; - - case 4: - //rebind success - DIAG(F("Rebind success")); - ip = Ethernet.localIP(); // reassign the obtained ip address - DIAG(F("\nLocal IP address: [%d.%d.%d.%d]"), ip[0], ip[1], ip[2], ip[3]); - break; - - default: - //nothing happened - break; - } - protocolHandler(); -} + diff --git a/EthernetInterface.h b/EthernetInterface.h index b702f04..6350289 100644 --- a/EthernetInterface.h +++ b/EthernetInterface.h @@ -28,6 +28,7 @@ #include #include #include +#include "RingStream.h" /* some generated mac addresses as EthernetShields don't have one by default in HW. * Sometimes they come on a sticker on the EthernetShield then use this address otherwise @@ -46,62 +47,28 @@ * */ #define MAC_ADDRESS { 0x52, 0xB8, 0x8A, 0x8E, 0xCE, 0x21 } // MAC address of your networking card found on the sticker on your card or take one from above -#define IP_ADDRESS 10, 0, 0, 101 // Just in case we don't get an adress from DHCP try a static one; make sure // this one is not used elsewhere and corresponds to your network layout -#define LISTEN_PORT 3366 // default listen port for the server -#define MAX_ETH_BUFFER 250 - -typedef void (*HTTP_CALLBACK)(Print * stream, byte * cmd); - -enum protocolType { - TCP, - UDP -}; - -typedef void (*protocolCallback)(); +#define LISTEN_PORT 2560 // default listen port for the server +#define MAX_ETH_BUFFER 512 +#define OUTBOUND_RING_SIZE 2048 class EthernetInterface { -private: - EthernetServer server; - public: - DCCEXParser ethParser; - bool connected; - byte mac[6]; - IPAddress ip; - uint16_t port; - IPAddress dnsip; - - void setup(protocolType pt, uint16_t lp); // specific port nummber - void setup(protocolType pt); // uses default port number - void setup(); // all defaults (protocol/port) - - protocolCallback protocolHandler; - - void loop(); - - private: - static EthernetInterface * singleton; - char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; // buffer to hold incoming UDP packet, - uint8_t buffer[MAX_ETH_BUFFER]; // buffer provided to the streamer to be filled with the reply (used by TCP also for the recv) - MemStream * streamer; // streamer who writes the results to the buffer - EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield - - bool setupConnection(); - static void udpHandler(); - static void tcpHandler(); - void udpHandler2(); - void tcpHandler2(); - EthernetUDP Udp; - - EthernetServer getServer() { - return server; - }; - void setServer(EthernetServer s) { - server = s; - }; + static void setup(); + static void loop(); + + private: + static EthernetInterface * singleton; + bool connected; + EthernetInterface(); + void loop2(); + EthernetServer * server; + EthernetClient clients[MAX_SOCK_NUM]; // accept up to MAX_SOCK_NUM client connections at the same time; This depends on the chipset used on the Shield + uint8_t buffer[MAX_ETH_BUFFER+1]; // buffer used by TCP for the recv + RingStream * outboundRing; + }; #endif diff --git a/StringFormatter.cpp b/StringFormatter.cpp index 2ecefec..a8ab5cf 100644 --- a/StringFormatter.cpp +++ b/StringFormatter.cpp @@ -37,6 +37,7 @@ bool Diag::ACK=false; bool Diag::CMD=false; bool Diag::WIFI=false; bool Diag::WITHROTTLE=false; +bool Diag::ETHERNET=false; void StringFormatter::diag( const __FlashStringHelper* input...) { diff --git a/StringFormatter.h b/StringFormatter.h index 5cbccf1..5be513f 100644 --- a/StringFormatter.h +++ b/StringFormatter.h @@ -34,6 +34,8 @@ class Diag { static bool CMD; static bool WIFI; static bool WITHROTTLE; + static bool ETHERNET; + }; class StringFormatter diff --git a/defines.h b/defines.h index 4a511c4..6db42e1 100644 --- a/defines.h +++ b/defines.h @@ -27,9 +27,14 @@ #define WIFI_ON true #else #define WIFI_ON false - #endif +#if ENABLE_ETHERNET && (defined(ARDUINO_AVR_MEGA) || defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_SAMD_ZERO)) +#define ETHERNET_ON true +#else +#define ETHERNET_ON false +#endif + //////////////////////////////////////////////////////////////////////////////// // // This defines the speed at which the Arduino will communicate with the ESP8266 module. From 7a5b84ef18b90bcafdc117472418651ad80e26e8 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 31 Oct 2020 11:26:23 +0100 Subject: [PATCH 2/8] handle motorboards with invereted brake pin (like pololu) --- MotorDriver.cpp | 25 +++++++++++++++++++++---- MotorDriver.h | 5 +++-- MotorDrivers.h | 10 +++++++--- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 5420488..c80048e 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -34,7 +34,7 @@ #define ReadPin digitalRead2 #endif -MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, byte brake_pin, +MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, float sense_factor, unsigned int trip_milliamps, byte fault_pin) { powerPin=power_pin; signalPin=signal_pin; @@ -46,7 +46,8 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, byte tripMilliamps=trip_milliamps; rawCurrentTripValue=(int)(trip_milliamps / sense_factor); pinMode(powerPin, OUTPUT); - pinMode(brakePin, OUTPUT); + pinMode(brakePin < 0 ? -brakePin : brakePin, OUTPUT); + setBrake(false); pinMode(signalPin, OUTPUT); if (signalPin2 != UNUSED_PIN) pinMode(signalPin2, OUTPUT); pinMode(currentPin, INPUT); @@ -56,8 +57,24 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, byte void MotorDriver::setPower(bool on) { WritePin(powerPin, on ? HIGH : LOW); } -void MotorDriver::setBrake( bool on) { - WritePin(brakePin, on ? HIGH : LOW); + +// setBrake applies brake if on == true. So to get +// voltage from the motor bride one needs to do a +// setBrake(false). +// If the brakePin is negative that means the sense +// of the brake pin on the motor bridge is inverted +// (HIGH == release brake) and setBrake does +// compensate for that. +// +void MotorDriver::setBrake(bool on) { + bool state = on; + byte pin = brakePin; + if (brakePin < 0) { + pin=-pin; + state=!state; + } + WritePin(pin, state ? HIGH : LOW); + //DIAG(F("BrakePin: %d is %d\n"), pin, ReadPin(pin)); } void MotorDriver::setSignal( bool high) { diff --git a/MotorDriver.h b/MotorDriver.h index cbc09cc..2655605 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -22,7 +22,7 @@ class MotorDriver { public: - MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, byte brake_pin, byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin); + MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin); virtual void setPower( bool on); virtual void setSignal( bool high); virtual void setBrake( bool on); @@ -34,7 +34,8 @@ class MotorDriver { } private: - byte powerPin, signalPin, signalPin2, brakePin,currentPin,faultPin; + byte powerPin, signalPin, signalPin2, currentPin, faultPin; + int8_t brakePin; float senseFactor; unsigned int tripMilliamps; int rawCurrentTripValue; diff --git a/MotorDrivers.h b/MotorDrivers.h index 3695e0a..809d69b 100644 --- a/MotorDrivers.h +++ b/MotorDrivers.h @@ -15,8 +15,12 @@ const byte UNUSED_PIN = 255; -// MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, byte brake_pin, byte current_pin, +// MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, // float senseFactor, unsigned int tripMilliamps, byte faultPin); +// +// If the brakePin is negative that means the sense +// of the brake pin on the motor bridge is inverted +// (HIGH == release brake) // Arduino standard Motor Shield #define STANDARD_MOTOR_SHIELD F("STANDARD_MOTOR_SHIELD"), \ @@ -25,8 +29,8 @@ const byte UNUSED_PIN = 255; // Pololu Motor Shield #define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \ - new MotorDriver(4, 7, UNUSED_PIN, 9, A0, 18, 3000, 12), \ - new MotorDriver(2, 8, UNUSED_PIN, 10, A1, 18, 3000, UNUSED_PIN) + new MotorDriver(4, 7, UNUSED_PIN, -9, A0, 18, 3000, 12), \ + new MotorDriver(2, 8, UNUSED_PIN, -10, A1, 18, 3000, UNUSED_PIN) // Firebox Mk1 #define FIREBOX_MK1 F("FIREBOX_MK1"), \ From 5ad396fbf4f764cb7eeabfb1186cfbba632176fc Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 31 Oct 2020 11:27:29 +0100 Subject: [PATCH 3/8] fix indent --- MotorDriver.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index c80048e..65619ff 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -36,15 +36,15 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, float sense_factor, unsigned int trip_milliamps, byte fault_pin) { - powerPin=power_pin; - signalPin=signal_pin; - signalPin2=signal_pin2; - brakePin=brake_pin; - currentPin=current_pin; - senseFactor=sense_factor; - faultPin=fault_pin; - tripMilliamps=trip_milliamps; - rawCurrentTripValue=(int)(trip_milliamps / sense_factor); + powerPin=power_pin; + signalPin=signal_pin; + signalPin2=signal_pin2; + brakePin=brake_pin; + currentPin=current_pin; + senseFactor=sense_factor; + faultPin=fault_pin; + tripMilliamps=trip_milliamps; + rawCurrentTripValue=(int)(trip_milliamps / sense_factor); pinMode(powerPin, OUTPUT); pinMode(brakePin < 0 ? -brakePin : brakePin, OUTPUT); setBrake(false); From 6f68adbfe99e7573343abf02ea8bae158d7d4846 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 31 Oct 2020 11:29:34 +0100 Subject: [PATCH 4/8] comment negative/inverted pin --- MotorDriver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MotorDriver.h b/MotorDriver.h index 2655605..abfb395 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -35,7 +35,7 @@ class MotorDriver { private: byte powerPin, signalPin, signalPin2, currentPin, faultPin; - int8_t brakePin; + int8_t brakePin; // negative means pin is inverted float senseFactor; unsigned int tripMilliamps; int rawCurrentTripValue; From 34f3abedaf5e9c25325c3d5f22043d74d9dd6d0c Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sat, 31 Oct 2020 22:45:06 +0100 Subject: [PATCH 5/8] different approach to Polplu board and UNUSED_PIN=127 --- MotorDriver.h | 6 ++++-- MotorDrivers.h | 20 ++++++++++++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/MotorDriver.h b/MotorDriver.h index abfb395..3f67080 100644 --- a/MotorDriver.h +++ b/MotorDriver.h @@ -20,6 +20,10 @@ #define MotorDriver_h // Virtualised Motor shield 1-track hardware Interface +#ifndef UNUSED_PIN // sync define with the one in MotorDrivers.h +#define UNUSED_PIN 127 // inside int8_t +#endif + class MotorDriver { public: MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin); @@ -39,7 +43,5 @@ class MotorDriver { float senseFactor; unsigned int tripMilliamps; int rawCurrentTripValue; - const byte UNUSED_PIN = 255; - }; #endif diff --git a/MotorDrivers.h b/MotorDrivers.h index 809d69b..ef1e2cf 100644 --- a/MotorDrivers.h +++ b/MotorDrivers.h @@ -13,7 +13,9 @@ // similar to those defined here, WITHOUT editing this file. You can put your // custom defines in config.h. -const byte UNUSED_PIN = 255; +#ifndef UNUSED_PIN // sync define with the one in MotorDriver.h +#define UNUSED_PIN 127 // inside int8_t +#endif // MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8_t brake_pin, byte current_pin, // float senseFactor, unsigned int tripMilliamps, byte faultPin); @@ -28,9 +30,19 @@ const byte UNUSED_PIN = 255; new MotorDriver(11, 13, UNUSED_PIN, UNUSED_PIN, A1, 2.99, 2000, UNUSED_PIN) // Pololu Motor Shield -#define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \ - new MotorDriver(4, 7, UNUSED_PIN, -9, A0, 18, 3000, 12), \ - new MotorDriver(2, 8, UNUSED_PIN, -10, A1, 18, 3000, UNUSED_PIN) +#define POLOLU_MOTOR_SHIELD F("POLOLU_MOTOR_SHIELD"), \ + new MotorDriver( 9, 7, UNUSED_PIN, -4, A0, 18, 3000, 12), \ + new MotorDriver(10, 8, UNUSED_PIN, UNUSED_PIN, A1, 18, 3000, UNUSED_PIN) +// +// Actually, on the Pololu MC33926 shield the enable lines are tied together on pin 4 and the +// pins 9 and 10 work as "inverted brake" but as we turn on and off the tracks individually +// via the power pins we above use 9 and 10 as power pins and 4 as "inverted brake" which in this +// version of the code always will be high. That means this config is not usable for generating +// a railcom cuotout in the future. For that one must wire the second ^D2 to pin 2 and define +// the motor driver like this: +// new MotorDriver(4, 7, UNUSED_PIN, -9, A0, 18, 3000, 12) +// new MotorDriver(2, 8, UNUSED_PIN, -10, A1, 18, 3000, UNUSED_PIN) +// See Pololu dial_mc33926_shield_schematic.pdf and truth table on page 17 of the MC33926 data sheet. // Firebox Mk1 #define FIREBOX_MK1 F("FIREBOX_MK1"), \ From d248cccf81d5a7a624a867dcc7bc8f4141933ec4 Mon Sep 17 00:00:00 2001 From: Harald Barth Date: Sun, 1 Nov 2020 10:16:29 +0100 Subject: [PATCH 6/8] special treatment for Pololu board --- MotorDriver.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/MotorDriver.cpp b/MotorDriver.cpp index 65619ff..ae832e9 100644 --- a/MotorDriver.cpp +++ b/MotorDriver.cpp @@ -55,6 +55,12 @@ MotorDriver::MotorDriver(byte power_pin, byte signal_pin, byte signal_pin2, int8 } void MotorDriver::setPower(bool on) { + if (brakePin == -4 && on) { + // toggle brake before turning power on - resets overcurrent error + // on the Pololu board if brake is wired to ^D2. + setBrake(true); + setBrake(false); + } WritePin(powerPin, on ? HIGH : LOW); } From eeac7893a6589fb64b5ab1b38654d04c8d82e118 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Thu, 5 Nov 2020 10:53:55 +0000 Subject: [PATCH 7/8] Compiler warning --- WifiInboundHandler.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WifiInboundHandler.h b/WifiInboundHandler.h index 1979565..c2c8865 100644 --- a/WifiInboundHandler.h +++ b/WifiInboundHandler.h @@ -36,8 +36,7 @@ class WifiInboundHandler { IPD_IGNORE_DATA, // got +IPD,c,ll,: ignoring the data that won't fit inblound Ring GOT_CLIENT_ID, // clientid prefix to CONNECTED / CLOSED - GOT_CLIENT_ID2, // clientid prefix to CONNECTED / CLOSED - GOT_CLIENT_ID3 // clientid prefix to CONNECTED / CLOSED + GOT_CLIENT_ID2 // clientid prefix to CONNECTED / CLOSED }; From 6dd4ab0004aafaf1aaf7f7370d02f3749d2fcaca Mon Sep 17 00:00:00 2001 From: Asbelos Date: Thu, 5 Nov 2020 10:54:16 +0000 Subject: [PATCH 8/8] Working Ethernet!! --- EthernetInterface.cpp | 44 +++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/EthernetInterface.cpp b/EthernetInterface.cpp index e7d1678..6251bac 100644 --- a/EthernetInterface.cpp +++ b/EthernetInterface.cpp @@ -45,15 +45,21 @@ EthernetInterface::EthernetInterface() byte mac[]=MAC_ADDRESS; DIAG(F("\n+++++ Ethernet Setup ")); + connected=false; if (Ethernet.begin(mac) == 0) { - DIAG(F("FAILED ")); - if (Ethernet.hardwareStatus() == EthernetNoHardware) DIAG(F("shield not found")); - else if (Ethernet.linkStatus() == LinkOFF) DIAG(F("cable not connected")); - DIAG(F(" ++++++\n")); - connected=false; + DIAG(F("begin FAILED\n")); return; + } + DIAG(F("begin OK.")); + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + DIAG(F("shield not found\n")); + return; + } + if (Ethernet.linkStatus() == LinkOFF) { + DIAG(F("cable not connected\n")); + return; } connected=true; @@ -108,16 +114,20 @@ void EthernetInterface::loop() // check for new client if (client) { - for (byte i = 0; i < MAX_SOCK_NUM; i++) + if (Diag::ETHERNET) DIAG(F("\nEthernet: New client ")); + byte socket; + for (socket = 0; socket < MAX_SOCK_NUM; socket++) { - if (!clients[i]) + if (!clients[socket]) { // On accept() the EthernetServer doesn't track the client anymore // so we store it in our client array - clients[i] = client; + if (Diag::ETHERNET) DIAG(F("%d\n"),socket); + clients[socket] = client; break; } } + if (socket==MAX_SOCK_NUM) DIAG(F("new Ethernet OVERFLOW\n")); } // check for incoming data from all possible clients @@ -125,13 +135,6 @@ void EthernetInterface::loop() { if (clients[socket]) { - // stop any clients which disconnect - if (!clients[socket].connected()) - { - if (Diag::ETHERNET) DIAG(F("\nEthernet: disconnect %d \n"), socket); - clients[socket].stop(); - clients[socket]=NULL;//???? - } int available=clients[socket].available(); if (available > 0) { if (Diag::ETHERNET) DIAG(F("\nEthernet: available socket=%d,avail=%d,count="), socket, available); @@ -148,6 +151,14 @@ void EthernetInterface::loop() } } + // stop any clients which disconnect + for (int socket = 0; socketread(); if (socketOut>=0) { @@ -158,4 +169,5 @@ void EthernetInterface::loop() } } - + +