Ethernet functionality works at first...then breaks mid sketch

Hi

In my sketch, the first couple of calls to do Ethernet related things work…but then subsequent ones fail. It’s a bit odd.

Button One pressed.
2012-03-01 09:38:12 Twitter notified.

Button One pressed.
Error : code 403

I find that quite odd.

I get the same result if I take Twitter out of the loop and use a HTTP get request instead. The first one seems to work OK, but then not subsequent ones. Would someone mind taking a look at my code and see if I’ve done something regrettable?

#include <Twitter.h>
#include <Bounce.h>
#include <Wire.h>
#include "RTClib.h"
#include <Servo.h>
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>	

byte mac[] = { 
  0x00, 0x11, 0x22, 0x33, 0xFB, 0x11 
}; 
EthernetClient client;
Twitter twitter("mytwitterhashpass");

unsigned int localPort = 8888;             
byte timeServer[] = {
  193, 79, 237, 14};                        // ntp1.nl.net NTP server  
const int NTP_PACKET_SIZE= 48;             // NTP time stamp is in the first 48 bytes of the message
byte pb[NTP_PACKET_SIZE];                  // buffer to hold incoming and outgoing packets 
#if ARDUINO >= 100
EthernetUDP Udp;
#endif		

Servo servo1;
#define ledPin1 8      		// the number of the LED pin
#define buttonPin 2		// the number of the button pin
const int pinSpeaker = 7;
boolean EthernetRunning = true;
int buttonState = LOW;		// used to set the button state
int LedState1 = LOW;		// used to set the LED state
int LedState2 = LOW;	        // used to set the LED state if LED was already on
long LedOnDuration = 10000;	// time to keep the LED on for (10s)
long FlashRate = 400;		// time to keep the LED on for (0.4s)
long previousMillis1 = 0;	// will store last time LED was updated for press 1
long previousMillis2 = 0;       // will store last time LED was updated for press 2

IPAddress server(207,7,108,103); 

unsigned int RTCUD = 0;
unsigned int INITIALSET = 0;

// Instantiate a Bounce object with a 20 millisecond debounce time
Bounce nursery = Bounce( buttonPin, 500);
int nurseryvalue;

RTC_DS1307 RTC;

enum {
  OFF, ON, FLASH
};

void setup() 
{
  pinMode(buttonPin,INPUT);      
  pinMode(ledPin1,OUTPUT);      
  pinMode(pinSpeaker, OUTPUT);
  digitalWrite(ledPin1, OFF);
  servo1.attach(6);
  LedState1 = OFF;
  LedState2 = OFF;
  Serial.begin(57600);
  Wire.begin();
  RTC.begin();
  Serial.println("Annunciator Panel v0.7");
  Ethernet.begin(mac);	   
  if (Ethernet.begin(mac) == 0) 
  {
    Serial.println("Error: No DHCP!");
    EthernetRunning = false;
  }
  if(EthernetRunning) 
  {
    Udp.begin(localPort);
    Serial.println("DHCP is working so enabling UDP.");
  }
  Serial.println();
  if (! RTC.isrunning()) 
  {
    Serial.println("Error!: The RTC is NOT running/set!");
  }
}

void loop() 
{
  DateTime now = RTC.now();
  nursery.update(); 
  nurseryvalue = nursery.read();
  unsigned long currentMillis = millis();

  char button1msg[162];
  sprintf(button1msg, "Doorbell pressed on %d/%d/%d @ %d:%d", now.day(), now.month(), now.year(), now.hour(), now.minute());
  char button1msg2[162];
  sprintf(button1msg2, "Doorbell pressed again on %d/%d/%d @ %d:%d", now.day(), now.month(), now.year(), now.hour(), now.minute());


  if (currentMillis > 20000 && INITIALSET < 1 && EthernetRunning == true)
  {
    Serial.println("20s have elapsed since power on/reset.");
    Serial.println("A good time to check the clock is running accurately.");
    Serial.println();
    RTCUD = 1;
  }

  if (now.minute() == 58 && now.second() == 50 && EthernetRunning == true)  
  {
    if (RTCUD < 1)  
    {
      Serial.print("Time to set the clock in time for the pips: ");
      Serial.println();
      RTCUD = 1;
    }
  }

  if (RTCUD == 1)
  {
    RTCUD = 0;           // RTC flag - CAN be set again for the morning / evening    
    INITIALSET = 1;      // RTC has been set at least once this instance
    Serial.print("RTC before: ");
    PrintDateTime(RTC.now());
    Serial.println();
    sendNTPpacket(timeServer);
    delay(1000);
    if ( Udp.parsePacket() ) 
    {              
      Udp.read(pb, NTP_PACKET_SIZE);      
      unsigned long t1, t2, t3, t4;
      t1 = t2 = t3 = t4 = 0;
      for (int i=0; i< 4; i++)
      {
        t1 = t1 << 8 | pb[16+i];      
        t2 = t2 << 8 | pb[24+i];      
        t3 = t3 << 8 | pb[32+i];      
        t4 = t4 << 8 | pb[40+i];
      }

      float f1,f2,f3,f4;
      f1 = ((long)pb[20] * 256 + pb[21]) / 65536.0;      
      f2 = ((long)pb[28] * 256 + pb[29]) / 65536.0;      
      f3 = ((long)pb[36] * 256 + pb[37]) / 65536.0;      
      f4 = ((long)pb[44] * 256 + pb[45]) / 65536.0;
      const unsigned long seventyYears = 2208988800UL;
      t1 -= seventyYears;
      t2 -= seventyYears;
      t3 -= seventyYears;
      t4 -= seventyYears;
      t4 += 1;               
      if (f4 > 0.4) t4++;    
      RTC.adjust(DateTime(t4));
      Serial.print("RTC after : ");
      PrintDateTime(RTC.now());
      Serial.println();
      Serial.println("Time update successful");
      RTCUD = 0;      // RTC has been set for the morning / evening    
      INITIALSET = 1;      // RTC has been set for the morning / evening    
    }
    else
    {
      Serial.println("Error: UDP Unavailable");
    }
  }

  if (nurseryvalue == HIGH)
  {
    if (buttonState == OFF)
    {
      // button pressed
      //===============
      buttonState = ON;
      if (LedState1 == OFF)
      {
        // the button's pressed and LED is OFF
        // turn it ON
        //====================================
        digitalWrite(ledPin1, ON);
        LedState1 = ON;
        servo1.write(180);
        previousMillis1 = currentMillis;
        Serial.print("Button One pressed.");
        Serial.println();
        if(EthernetRunning) 
        {
          if (twitter.post(button1msg)) 
          {
            int status = twitter.wait();
            if (status == 200) 
            {
              PrintDateTime(RTC.now());
              Serial.print("Twitter notified.");
              Serial.println();
            } 
            else 
            {
              Serial.print("Error : code ");
              Serial.println(status);
            }
          } 
          else 
          {
            Serial.println("Error: Twitter post failed.");
          }
        }
      }
      else if (LedState1 == ON)
      { 		
        digitalWrite(ledPin1, OFF);
        LedState1 = FLASH;
        servo1.write(180);
        Serial.print("Button One pressed again.");
        Serial.println();
        if(EthernetRunning) 
        {
          if (twitter.post(button1msg2)) 
          {
            int status = twitter.wait();
            if (status == 200) 
            {
              PrintDateTime(RTC.now());
              Serial.print("Twitter notified.");
              Serial.println();
            } 
            else 
            {
              Serial.print("Error : code ");
              Serial.println(status);
            }
          } 
          else 
          {
            Serial.println("Error: Twitter post failed.");
          }
          if (client.connect(server, 80)) 
          {
            //client.println("GET http://www.myserver.org/annunciator/sms.php HTTP/1.0");
            client.println();
            Serial.println("Sending an SMS.");
          }
          else 
          {
            Serial.println("Error: Could not notify myserver.org to send that SMS!");
          }
        }
        previousMillis1 = currentMillis;	
      }
    }
  }
  else
  {
    buttonState = OFF;
    servo1.write(0);
  }

  if (previousMillis1 + LedOnDuration < currentMillis) 
  {		
    digitalWrite(ledPin1, OFF);
    LedState1 = OFF;
  }

  if (LedState1 == FLASH && previousMillis2 + FlashRate < currentMillis) 
  {        	
    digitalWrite(ledPin1, !digitalRead(ledPin1));
    previousMillis2 = currentMillis;
  }
}


void PrintDateTime(DateTime t)
{
  char datestr[24];
  sprintf(datestr, "%04d-%02d-%02d  %02d:%02d:%02d  ", t.year(), t.month(), t.day(), t.hour(), t.minute(), t.second());
  Serial.print(datestr);  
}

unsigned long sendNTPpacket(byte *address)
{
  // set all bytes in the buffer to 0
  memset(pb, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  pb[0] = 0b11100011;   // LI, Version, Mode
  pb[1] = 0;     // Stratum, or type of clock
  pb[2] = 6;     // Polling Interval
  pb[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  pb[12]  = 49; 
  pb[13]  = 0x4E;
  pb[14]  = 49;
  pb[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
#if ARDUINO < 100
  Udp.sendPacket( pb,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
#else
  // IDE 1.0 compatible:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(pb,NTP_PACKET_SIZE);
  Udp.endPacket(); 
#endif	  
}

From the Twitter site on that error code:

403 Forbidden The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits.

https://dev.twitter.com/docs/error-codes-responses

SurferTim: From the Twitter site on that error code:

403 Forbidden The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits.

https://dev.twitter.com/docs/error-codes-responses

Thanks, but nope. Because:

A) I also get this error when I take Twitter out of the loop as I said & B) My messages to Twitter are unique

If you took twitter out of the code, how are you getting that message?

edit: Here is the code that prints the error. How do you print that without posting to twitter?

if (twitter.post(button1msg)) 
          {
            int status = twitter.wait();
            if (status == 200) 
            {
              PrintDateTime(RTC.now());
              Serial.print("Twitter notified.");
              Serial.println();
            } 
            else 
            {
              Serial.print("Error : code ");
              Serial.println(status);
            }
          } 
          else 
          {
            Serial.println("Error: Twitter post failed.");
          }
#include <Bounce.h>
#include <Wire.h>
#include "RTClib.h"
//#include <Servo.h>
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>	

byte mac[] = { 
  0x00, 0x11, 0x22, 0x33, 0xFB, 0x11 
}; 
EthernetClient client;

unsigned int localPort = 8888;             
byte timeServer[] = {
  193, 79, 237, 14};                        // ntp1.nl.net NTP server  
const int NTP_PACKET_SIZE= 48;             // NTP time stamp is in the first 48 bytes of the message
byte pb[NTP_PACKET_SIZE];                  // buffer to hold incoming and outgoing packets 
#if ARDUINO >= 100
EthernetUDP Udp;
#endif		

//Servo servo1;
#define ledPin1 8      		// the number of the LED pin
#define buttonPin 2		// the number of the button pin
const int pinSpeaker = 7;
boolean EthernetRunning = true;
int buttonState = LOW;		// used to set the button state
int LedState1 = LOW;		// used to set the LED state
int LedState2 = LOW;	        // used to set the LED state if LED was already on
long LedOnDuration = 10000;	// time to keep the LED on for (10s)
long FlashRate = 400;		// time to keep the LED on for (0.4s)
long previousMillis1 = 0;	// will store last time LED was updated for press 1
long previousMillis2 = 0;       // will store last time LED was updated for press 2

IPAddress server(207,7,108,203); // Joyent

//The pips
unsigned int pip1 = 0;
unsigned int pip2 = 0;
unsigned int pip3 = 0;
unsigned int pip4 = 0;
unsigned int pip5 = 0;
unsigned int pip6 = 0;
unsigned int RTCUD = 0;
unsigned int INITIALSET = 0;

// Instantiate a Bounce object with a 20 millisecond debounce time
Bounce nursery = Bounce( buttonPin, 500);
int nurseryvalue;

RTC_DS1307 RTC;

enum {
  OFF, ON, FLASH
};

void setup() 
{
  pinMode(buttonPin,INPUT);      
  pinMode(ledPin1,OUTPUT);      
  pinMode(pinSpeaker, OUTPUT);
  digitalWrite(ledPin1, OFF);
  //  servo1.attach(6);
  LedState1 = OFF;
  LedState2 = OFF;
  Serial.begin(57600);
  Wire.begin();
  RTC.begin();
  Serial.println("Annunciator Panel v0.7");
  Ethernet.begin(mac);	   
  if (Ethernet.begin(mac) == 0) 
  {
    Serial.println("Error: No DHCP!");
    EthernetRunning = false;
  }
  if(EthernetRunning) 
  {
    Udp.begin(localPort);
    Serial.println("DHCP is working so enabling UDP.");
  }
  Serial.println();
  if (! RTC.isrunning()) 
  {
    Serial.println("Error!: The RTC is NOT running/set!");
  }
}

void loop() 
{
  DateTime now = RTC.now();
  nursery.update(); 
  nurseryvalue = nursery.read();
  unsigned long currentMillis = millis();

  char button1msg[162];
  sprintf(button1msg, "Doorbell pressed on %d/%d/%d @ %d:%d", now.day(), now.month(), now.year(), now.hour(), now.minute());
  char button1msg2[162];
  sprintf(button1msg2, "Doorbell pressed again on %d/%d/%d @ %d:%d", now.day(), now.month(), now.year(), now.hour(), now.minute());


  if (currentMillis > 20000 && INITIALSET < 1 && EthernetRunning == true)
  {
    Serial.println("20s have elapsed since power on/reset.");
    Serial.println("A good time to check the clock is running accurately.");
    Serial.println();
    RTCUD = 1;
  }

  if (now.minute() == 58 && now.second() == 50 && EthernetRunning == true)  
  {
    if (RTCUD < 1)  
    {
      Serial.print("Time to set the clock in time for the pips: ");
      Serial.println();
      RTCUD = 1;
    }
  }

  if (RTCUD == 1)
  {
    RTCUD = 0;           // RTC flag - CAN be set again for the morning / evening    
    INITIALSET = 1;      // RTC has been set at least once this instance
    Serial.print("RTC before: ");
    PrintDateTime(RTC.now());
    Serial.println();
    sendNTPpacket(timeServer);
    delay(1000);
    if ( Udp.parsePacket() ) 
    {              
      Udp.read(pb, NTP_PACKET_SIZE);      
      unsigned long t1, t2, t3, t4;
      t1 = t2 = t3 = t4 = 0;
      for (int i=0; i< 4; i++)
      {
        t1 = t1 << 8 | pb[16+i];      
        t2 = t2 << 8 | pb[24+i];      
        t3 = t3 << 8 | pb[32+i];      
        t4 = t4 << 8 | pb[40+i];
      }

      float f1,f2,f3,f4;
      f1 = ((long)pb[20] * 256 + pb[21]) / 65536.0;      
      f2 = ((long)pb[28] * 256 + pb[29]) / 65536.0;      
      f3 = ((long)pb[36] * 256 + pb[37]) / 65536.0;      
      f4 = ((long)pb[44] * 256 + pb[45]) / 65536.0;
      const unsigned long seventyYears = 2208988800UL;
      t1 -= seventyYears;
      t2 -= seventyYears;
      t3 -= seventyYears;
      t4 -= seventyYears;
      t4 += 1;               
      if (f4 > 0.4) t4++;    
      RTC.adjust(DateTime(t4));
      Serial.print("RTC after : ");
      PrintDateTime(RTC.now());
      Serial.println();
      Serial.println("Time update successful");
      playTone(50, 3000);
      RTCUD = 0;      // RTC has been set for the morning / evening    
      INITIALSET = 1;      // RTC has been set for the morning / evening    
    }
    else
    {
      Serial.println("Error: UDP Unavailable");
    }
  }

  if (nurseryvalue == HIGH)
  {
    if (buttonState == OFF)
    {
      // button pressed
      //===============
      buttonState = ON;
      if (LedState1 == OFF)
      {
        
        digitalWrite(ledPin1, ON);
        LedState1 = ON;
        //        servo1.write(180);
        previousMillis1 = currentMillis;
        Serial.print("Button One pressed.");
        Serial.println();
        if(EthernetRunning) 
        {
          if (client.connect(server, 80)) 
          {
            //client.println("GET http://www.myserver.org/annunciator/sms.php HTTP/1.0");
            client.println("GET http://www.myserver.org/annunciator/growl.php HTTP/1.0");
            client.println();
            Serial.println("Sending a growl.");
          }
          else 
          {
            Serial.println("Error: Could not send that growl!");
          }
        }
      }
      else if (LedState1 == ON)
      { 		
        
        digitalWrite(ledPin1, OFF);
        LedState1 = FLASH;
        //        servo1.write(180);
        Serial.print("Button One pressed again.");
        Serial.println();
        if(EthernetRunning) 
        {
          if (client.connect(server, 80)) 
          {
            //client.println("GET http://www.myserver.org/annunciator/sms.php HTTP/1.0");
            client.println("GET http://www.myserver.org/annunciator/growl.php HTTP/1.0");
            client.println();
            Serial.println("Sending a growl.");
          }
          else 
          {
            Serial.println("Error: Could not send that growl!");
          }
        }
        previousMillis1 = currentMillis;	
      }
    }
  }
  else
  {
    buttonState = OFF;
    //    servo1.write(0);
  }

  if (previousMillis1 + LedOnDuration < currentMillis) 
  {		
    
    digitalWrite(ledPin1, OFF);
    LedState1 = OFF;
  }

  if (LedState1 == FLASH && previousMillis2 + FlashRate < currentMillis) 
  {        	
    
    digitalWrite(ledPin1, !digitalRead(ledPin1));
    previousMillis2 = currentMillis;
  }


}


void playTone(long duration, int freq) 
{
  duration *= 1000;
  int period = (1.0 / freq) * 1000000;
  long elapsed_time = 0;
  while (elapsed_time < duration) 
  {
    digitalWrite(pinSpeaker,HIGH);
    delayMicroseconds(period / 2);
    digitalWrite(pinSpeaker, LOW);
    delayMicroseconds(period / 2);
    elapsed_time += (period);
  }
}

void PrintDateTime(DateTime t)
{
  char datestr[24];
  sprintf(datestr, "%04d-%02d-%02d  %02d:%02d:%02d  ", t.year(), t.month(), t.day(), t.hour(), t.minute(), t.second());
  Serial.print(datestr);  
}

unsigned long sendNTPpacket(byte *address)
{
  // set all bytes in the buffer to 0
  memset(pb, 0, NTP_PACKET_SIZE); 
  // Initialize values needed to form NTP request
  // (see URL above for details on the packets)
  pb[0] = 0b11100011;   // LI, Version, Mode
  pb[1] = 0;     // Stratum, or type of clock
  pb[2] = 6;     // Polling Interval
  pb[3] = 0xEC;  // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  pb[12]  = 49; 
  pb[13]  = 0x4E;
  pb[14]  = 49;
  pb[15]  = 52;

  // all NTP fields have been given values, now
  // you can send a packet requesting a timestamp: 		   
#if ARDUINO < 100
  Udp.sendPacket( pb,NTP_PACKET_SIZE,  address, 123); //NTP requests are to port 123
#else
  // IDE 1.0 compatible:
  Udp.beginPacket(address, 123); //NTP requests are to port 123
  Udp.write(pb,NTP_PACKET_SIZE);
  Udp.endPacket(); 
#endif	  
}

Sorry - I didn’t include the second code example for brevity. But here it is:
Sending a Growl using a HTTP GET instead. The first growl is received, the second returns “Error: Could not send that growl!”

Maybe if you waited for the server to return the response and closed the connection on the first request, it might work on the second request.

          if (client.connect(server, 80)) 
          {
            //client.println("GET http://www.myserver.org/annunciator/sms.php HTTP/1.0");
            client.println("GET http://www.myserver.org/annunciator/growl.php HTTP/1.0");
            // added host for virtual hosting servers
            client.println("Host: www.myserver.org");
            client.println();
            Serial.println("Sending a growl.");

            // new code
           while(client.connected())
           {
               // wait until server closes the connection
                while(client.available())
                {
                      // the server will not close the connection until this buffer is empty
                      client.read();
                 }
           }

           // close your end after the server closes its end
           client.stop();
          // end of new code
         
          }
          else 
          {
            Serial.println("Error: Could not send that growl!");
          }

SurferTim: Maybe if you waited for the server to return the response and closed the connection on the first request, it might work on the second request.

Fantastic! Thank you!! I thought it would be something like that but didn't know how to implement it.

I took out the bit about the virtual server host as I didn't see why I needed it and it (now) works without it. Is it just for debugging/information?

Glad to hear it is working.

You may not need the "Host: " parameter. I recommend that in case the web server uses virtual hosting. My servers don't, but some web hosting services use that.