Hello,
Ok, so I ran into another issue implementing UDP on the Arduino mega 2560. My program sends periodic messages over UDP to another device (to the PC or another Arduino Mega). The problem appears when initially the Arduino board tries to send messages periodically while nothing is connected to the Ethernet shield RJ connector. As soon as the receiving device is connected, the next time it send a message, it sends all of the previous messages that it tried to send before the receiving device was connected. So for example, it tries to send the string "hi" 3 times while nothing is connected to the RJ connector, the next time it sends the string "hi" when the receiving device is connected it sends "hihihihi" instead. It almost looks like every time it tries to send a packet, it appends it to the previous packet that was not delivered. I figured a way around this by checking Udp.endPacket() to see if it returns 0, then I would do Udp.stop() and then Udp.begin(). This appears to clear the write buffer.
Here are my questions:
Why does Udp behave as I described above?
What is the proper way to correct his behavior? Knowing that I really cannot guarantee that there will always be a device connected the Ethernet Shield to receive UDP packets at power up.
Is my solution to the problem appropriate, that is, is it going to cause some issues down the road since I am calling Udp.begin() in the main loop instead of Setup()?
Here is sample code that causes the problem
#include <SPI.h> // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h> // UDP library from: bjoern@cs.stanford.edu 12/30/2008
byte mac[] = {
0x90, 0xA2, 0xDA, 0x0D, 0x50, 0x57}; //Ethernet shield MAC Address
IPAddress IP(169, 254, 0, 7);
IPAddress IP_Remote(169, 254, 0, 1); // IP address for Remote Arduino
unsigned int localPort = 6101; // local port to listen on
unsigned int Port_Remote = 6180; // Remote Arduino remote port
const int LEDPIN = 2;
volatile byte seconds = 0;
volatile byte count = 0;
// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;
EthernetClient client;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
void setup()
{
pinMode(4,OUTPUT); // for the MEGA 2560 to disable SD
pinMode(LEDPIN, OUTPUT);
// initialize Timer1
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
// set compare match register to desired timer count: (for 1 sec use 15624)
OCR1A = 46874; // set for 3 seconds but this is too long. prefere to use 1 second
// turn on CTC mode:
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler:
TCCR1B |= (1 << CS10);
TCCR1B |= (1 << CS12);
// enable timer compare interrupt:
TIMSK1 |= (1 << OCIE1A);
// enable global interrupts:
sei();
// start the Ethernet and UDP:
Ethernet.begin(mac,IP);
Udp.begin(localPort);
// start the Serial Port:
Serial.begin(9600);
}
void loop()
{
digitalWrite(4,HIGH); // for the MEGA 2560 to disable SD
// if there is nothing connected to the Ehternet shield, then Udp.write() requests get buffered
if ((count >=1 && seconds <=4) || (count >=1 && seconds >=7))
{
Serial.print("Send ping, ");
Udp.beginPacket(IP_Remote, Port_Remote);
Serial.print(" Number of Bytes: ");
Serial.print(Udp.write("ping"));
Serial.print(" ,Send successful? ");
if (!Udp.endPacket())
{
// What are the implications of stopping Udp and then starting it back again in the main loop?
// It appears that stopping Udp and starting it back again clears the write buffer
//Udp.stop(); // stop EthernetUDP
//Udp.begin(localPort); // start EhternetUDP
Serial.println(0);
}
else
{
Serial.println(1);
}
count = 0;
}
int packetSize = Udp.parsePacket();
if(packetSize)
{
Serial.print("Rcvd packet size of: ");
Serial.print(packetSize);
Udp.read(packetBuffer,packetSize);
packetBuffer[packetSize] = '\0';
Serial.print(", Contents:");
Serial.println(packetBuffer);
if (String(packetBuffer) == "s")
{
Serial.print("Send ping, ");
Udp.beginPacket(IP_Remote, Port_Remote);
Serial.print(" Number of Bytes: ");
Serial.print(Udp.write("ping"));
Serial.print(" ,Send successful? ");
Serial.println(Udp.endPacket());
}
}
delay(50);
}
ISR(TIMER1_COMPA_vect)
{
// Toggle Led to see code running
digitalWrite(LEDPIN, !digitalRead(LEDPIN));
seconds++;
count++;
if (seconds > 10)
{
cli(); // disable global interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
sei();
}
}
Thanks