20
20
#include < SPI.h>
21
21
#include < Ethernet.h>
22
22
#include < EthernetUdp.h>
23
- #include < CircularBuffer.h>
24
- #include < BitBool.h>
23
+ #include < CircularBuffer.h> // CircularBuffer https://github.com/rlogiacco/CircularBuffer
24
+ #include < BitBool.h> // BitBool https://github.com/Chris--A/BitBool
25
+ #include < TrueRandom.h> // https://github.com/sirleech/TrueRandom
26
+ #include < EEPROM.h>
25
27
26
28
// RS485 settings
27
29
#define BAUD 9600
31
33
#define MAX_RETRY 5 // maximum number of retries for sending Modbus RTU request
32
34
33
35
// TCP and UDP settings
34
- byte mac[] = { 0xDE , 0xAD , 0xBE , 0xEF , 0xFE , 0xED }; // MAC - change to something more random...
36
+
35
37
IPAddress ip (192 , 168 , 1 , 10 );
36
38
IPAddress gateway (192 , 168 , 1 , 1 );
37
39
IPAddress subnet (255 , 255 , 255 , 0 );
@@ -50,7 +52,8 @@ IPAddress subnet(255, 255, 255, 0);
50
52
#define SerialTxControl 6 // Arduino Pin for RS485 Direction control
51
53
#define ethResetPin 7 // OPTIONAL: Ethernet shield reset pin (deals with power on reset issue of the ethernet shield)
52
54
53
-
55
+ // App will generate unique MAC address, bytes 4, 5 and 6 will hold random value
56
+ byte mac[6 ] = { 0x90 , 0xA2 , 0xDA , 0x00 , 0x00 , 0x00 };
54
57
#define UDP_TX_PACKET_MAX_SIZE BUFFER_SIZE
55
58
56
59
typedef struct {
@@ -104,11 +107,10 @@ class MicroTimer {
104
107
};
105
108
106
109
boolean MicroTimer::isOver () {
107
- if (micros () - timestampLastHitMs < sleepTimeMs) {
108
- return false ;
110
+ if (( unsigned long )( micros () - timestampLastHitMs) > sleepTimeMs) {
111
+ return true ;
109
112
}
110
- timestampLastHitMs = micros ();
111
- return true ;
113
+ return false ;
112
114
}
113
115
114
116
void MicroTimer::start (unsigned long sleepTimeMs) {
@@ -126,11 +128,10 @@ class Timer {
126
128
};
127
129
128
130
boolean Timer::isOver () {
129
- if (millis () - timestampLastHitMs < sleepTimeMs) {
130
- return false ;
131
+ if (( unsigned long )( millis () - timestampLastHitMs) > sleepTimeMs) {
132
+ return true ;
131
133
}
132
- timestampLastHitMs = millis ();
133
- return true ;
134
+ return false ;
134
135
}
135
136
136
137
void Timer::start (unsigned long sleepTimeMs) {
@@ -160,8 +161,21 @@ void setup() /****** SETUP: RUNS ONCE ******/
160
161
digitalWrite (ethResetPin, HIGH);
161
162
delay (500 );
162
163
pinMode (ethResetPin, INPUT);
163
- delay (500 );
164
+ delay (1000 );
164
165
#endif
166
+ // MAC stored in EEPROM
167
+ if (EEPROM.read (1 ) == ' #' ) {
168
+ for (int i = 3 ; i < 6 ; i++)
169
+ mac[i] = EEPROM.read (i);
170
+ }
171
+ // MAC not set, generate random value
172
+ else {
173
+ for (int i = 3 ; i < 6 ; i++) {
174
+ mac[i] = TrueRandom.randomByte ();
175
+ EEPROM.write (i, mac[i]);
176
+ }
177
+ EEPROM.write (1 , ' #' );
178
+ }
165
179
166
180
Ethernet.begin (mac, ip);
167
181
Ethernet.setRetransmissionTimeout (20 ); // speed up ethernet
@@ -386,7 +400,7 @@ void processUdpTcp()
386
400
387
401
void sendSerial ()
388
402
{
389
- if (sendingData == true ) {
403
+ if (sendingData == true && txDelay. isOver () && !rxNdx) { // avoid bus collision, only send when we are not receiving data
390
404
if (Serial.availableForWrite () > 0 && txNdx == 0 && digitalRead (SerialTxControl) == RS485Receive) {
391
405
digitalWrite (SerialTxControl, RS485Transmit); // Enable RS485 Transmit
392
406
crc = 0xFFFF ;
0 commit comments