Pages: [1]   Go Down
Author Topic: Client, Server and UDP on one Arduino  (Read 2372 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, i've read a few threads with no real suggestion how fix my current problem:

According to the datasheet of the Wiznet Ethernet Shield (http://arduino.cc/en/Main/ArduinoEthernetShield) it supports up to four simultanios connections.

So my idea was to build the following:

Web-Server (controling arduino - running in void loop())
Pachube Client (receives Data through XBEE)
UDP Client (NTP Sync every 12 Hours)

I was able to get the web-server running.

I've also found some pachube-clients - one works well.

To get NTP i've also figured out a few - and got it running.

Combinend to on 18k program it doesn't even get through setup()....

Code:
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>
#include <TextFinder.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <NewSoftSerial.h>

// Network
byte mac[] = {0xDE,0xAD, 0xBE,0xEF,0xFE,0xED};
byte ip[] = { 192,168,0,177 };
byte subnet[] = {255,255,255,0};
byte gateway[] = {192,168,0,1};
byte pachube[] = {173,203,98,29};
Server server(80);
//Client client(pachube, 80);

// NTP Time stuff
unsigned int localPort = 8888;
byte timeServer[] = { 192,53,103,108 };
const int NTP_PACKET_SIZE= 48;
byte packetBuffer[ NTP_PACKET_SIZE];

// NewSoftSerial
uint8_t pin_in = 2, pin_out = 3;
NewSoftSerial mySerial(pin_in, pin_out);

// XBee
const byte startbyte = 0x7E;
const byte RemoteAT = 0x17;
const byte ApplyChanges = 0x02;

// Runtime-Variables
boolean delayrun = false;

// Pachube-Stuff
float xbee_temp_01 = 0;
float xbee_light_01 = 0;

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  //Serial.println("Serial Ports");
  Ethernet.begin(mac, ip, gateway, subnet);
 
  server.begin();
  Udp.begin(localPort);
 
  // Initial Tasks
  Alarm.timerOnce(15, getNTP);
 
  // Daily Tasks
  Alarm.alarmRepeat(18,10,0, getNTP);
  Alarm.alarmRepeat(5,10,0, getNTP);
  Alarm.alarmRepeat(23,59,40, endofday);
 
  // Repeating Tasks
  Alarm.timerRepeat(60, RepeatTask);
 
  // Timers for prog
  Alarm.alarmRepeat(20,0,0, prog1_an_timerless);
  Alarm.alarmRepeat(20,10,0, prog_aus);
  Alarm.alarmRepeat(20,10,2, prog2_an_timerless);
  Alarm.alarmRepeat(20,20,2, prog_aus);

  Serial.println("Setup done");
}

I've also raised the number of available Timers in TimeAlarms.h to #define dtNBR_ALARMS 20 so that i can have plenty alarms.

Anybody have an idea, how to fix this??
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


How much RAM are you using?
UNO has only 2K ... and seeing the list of includes that could be a point of attention ...


As the NTP server is needed only once per 12 hours, I would not start listening in setup() but make a function that is called once every 12 hours that creates the NTP client fetch a time and removes the client again. To fetch the time through NTP normally uses less than a second. Think you should consider to shutdown the webserver for that second so it will free sockets...
   
If you add Serial.print statements between the lines of setup() how far does setup() go before it freezes?
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I'm using an arduino uno - Binary sketch size: 15470 bytes (of a 32256 byte maximum)

It freezes completely (no message from setup()) if add the following to void loop()
if (year() == 1970){
    Serial.println("Datum falsch!");
    getNTP();
}

In the getNTP() i'll added the Udp.begin(localPort); and removed it from the setup()

my loop() looks like this now:
Code:
void loop()
{
  Serial.println("Loop startet");
  delay(1000);
  Alarm.delay(0);
  if (year() == 1970){
    Serial.println("Datum falsch!");
    getNTP();
  }
  Client client = server.available();
  if (client) {
    Serial.println("Webserver Start");
    TextFinder  finder(client ); 
    while (client.connected()) {     
      if (client.available()) {
        boolean dodelay = false;
        boolean dostop = false;
        boolean dogo = false;       
        if( finder.find("GET /") ) {             
          while(finder.findUntil("command", "\n\r")){ 
            char type = client.read();
            int syntax_1 = finder.getValue();
            switch (type);

And ends with: client.stop();

Should i store this in an extra procedure ?

Could it also be, that i've added to much Timers?

The client.stop command stops the server also, right?

If I understand your suggestion right the "program" should run like this:

Webserver, NTP, Pachube
Ethernet Init -> UDP init -> NTP get -> UDP stop -> Webserver start -> look for webserver data -> Webserver stop -> Pachube Client start-> Pachube update -> Pachub Client Stop -> End
Own function:
NTP - including UDP init, NTP get, UDP stop
Webserver - including Webserver start, look for webserver data, Webserver stop
Pachube - including Pachube client init, Pachube update, Pachube Client stop


Webserver, Pachube
Ethernet Init -> Webserver start -> look for webserver data -> Webserver stop -> Pachube Client start-> Pachube update -> Pachube Client Stop -> End
Webserver - including Webserver start, look for webserver data, Webserver stop
Pachube - including Pachube client start, Pachube update, Pachube Client stop

Are the following commands for the above the right choice?
Ethernet init: Ethernet.begin(mac, ip, gateway, subnet);
UDP init: Udp.begin(localPort);
UDP stop: No idea
Webserver start: server.begin(); (Is the port 80 needed??) - Client client = server.available();
Webserver stop: client.stop();
Pachube client start: Client client(pachube, 80);
Pachube client stop: client.stop();

Thx for your help.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I'm using an arduino uno - Binary sketch size: 15470 bytes (of a 32256 byte maximum)

That is the amount of FLASH (also known as program memory) THe Arduino has separated program and data memory.



Quote
If I understand your suggestion right the "program" should run like this:

Webserver, NTP, Pachube
Ethernet Init -> UDP init -> NTP get -> UDP stop -> Webserver start -> look for webserver data -> Webserver stop -> Pachube Client start-> Pachube update -> Pachub Client Stop -> End
Own function:
NTP - including UDP init, NTP get, UDP stop
Webserver - including Webserver start, look for webserver data, Webserver stop
Pachube - including Pachube client init, Pachube update, Pachube Client stop
Yes you got the idea

in pseudocode
loop()
{
  HowLongCanTheWebRun = max (24 hours, howLongUNtil NTP, howLongUNtilPachube);

  runTheWeb for HowLongCanTheWebRun;

  if (time to runNTP) doNTP();
 
  if (time to Pachube) doPachube()
}

Do you have a link to the Alarm library used?


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks,

How can i determine, how much programm and data memory I've used?

the link to the time-library: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1263305457

so i will try to build the code with a few if's and let the timer-thing rest for a while...

How to stop the udp client? Does it "unload" automaticly, when the runtime of the function ends or do i need to put a command at the end of the function?
Quote
Ethernet init: Ethernet.begin(mac, ip, gateway, subnet);
UDP init: Udp.begin(localPort);
UDP stop: No idea
Webserver start: server.begin(); (Is the port 80 needed??) - Client client = server.available();
Webserver stop: client.stop();
Pachube client start: Client client(pachube, 80);
Pachube client stop: client.stop();

Are the other commands right?

Thanks for the pseudo-code - it helps me to better understand the flow.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46026
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How to stop the udp client?
The UDP class derives from Stream. It has a stop() method.

Code:
/* Release any resources being used by this UDP instance */
void UDP::stop()
{
  if (_sock == MAX_SOCK_NUM)
    return;

  close(_sock);

  EthernetClass::_server_port[_sock] = 0;
  _sock = MAX_SOCK_NUM;
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I can't find this in my udp.h or udp.cpp

Where did you get the your udp library?

my new experiment also don't work...

Code:
#include <SPI.h>
#include <Ethernet.h>
#include <Udp.h>
#include <TextFinder.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <NewSoftSerial.h>

// Network
byte mac[] = {0xDE,0xAD, 0xBE,0xEF,0xFE,0xED};
byte ip[] = {192,168,0,177};
byte subnet[] = {255,255,255,0};
byte gateway[] = {192,168,0,1};
byte pachube[] = {173,203,98,29};

// NTP Time stuff
unsigned int localPort = 8888;
byte timeServer[] = { 192,53,103,108 };
const int NTP_PACKET_SIZE= 48;
byte packetBuffer[ NTP_PACKET_SIZE];

// NewSoftSerial
uint8_t pin_in = 2, pin_out = 3;
NewSoftSerial mySerial(pin_in, pin_out);

// XBee
const byte startbyte = 0x7E;
const byte RemoteAT = 0x17;
const byte ApplyChanges = 0x02;

// Runtime-Variables
boolean delayrun = false;

// Pachube-Stuff
float xbee_temp_01 = 0;
float xbee_light_01 = 0;

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  Serial.println("Serial Ports");
  Ethernet.begin(mac, ip, gateway, subnet);
  Serial.println("Ethernet done");
}

void loop()
{
  Serial.println("Loop start");
  delay(1000);
  Alarm.delay(0);
  if (year() == 1970){
    Serial.println("Date not set!");
    getNTP();
  }
  // Time-dependent Stuff
  switch (hour()){
    case 23:
    switch (minute()){
      case 20:
      //getNTP();
     
      case 54:
      endofday();
    }
    break;
   
    case 20:
    switch (minute()){
      case 1:
      prog_ein(11);
      break;
     
      case 11:
      prog1_aus();
      break;
     
      case 12:
      prog_ein(21);
      break;
     
      case 22:
      prog2_aus();
      break;
    }
  }
  if (second() == 30){
    RepeatTask();
  }
   
  // Webserver
  webserver();
}
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 168
Posts: 12428
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

small remark...

Code:
  if (year() == 1970){
    Serial.println("Date not set!");
    getNTP();
  }

This part should typically be in setup, in fact in setup() you call getNTP() allways!!

furthermore the    delay(1000);  in loop() is not needed . Why wait ...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

sorry for being a "wisenheimer" but if the year changes to 2011 he would'nt do getNTP()

The delay was an relict from some test (where i println'ed that the loop was reached - it messed up the serial monitor)

tried it with getNTP in setup - still does'nt "boot" - no response to serial - even no response to ping... (Host is down)
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

a little success - after removing the udp.h and TimeAlarms.h

Strange thing: The Arduino "reboots" pretty often (Seeing the Serial done and Ethernet done Messages...)

Much more strange thing:
After the success of getting the sketch back to work, i've tried to enable udp.h (without the code for getNTP()) - works fine.

When I add the getNTP code it does'nt "boot"

Code:
// NTP-Stuff
void getNTP()
{
  Serial.println("NTP Begins");
  Udp.begin(localPort);
  delay(10);
  sendNTPpacket(timeServer); // send an NTP packet to a time server
  delay(1000);  
  if ( Udp.available() ) {  
    Udp.readPacket(packetBuffer,NTP_PACKET_SIZE);
    unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
    unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);  
    unsigned long secsSince1900 = highWord << 16 | lowWord;  
    const unsigned long seventyYears = 2208988800UL;    
    unsigned long epoch = secsSince1900 - seventyYears;  
      
    setTime(epoch);
    int dst = hour() + 2;
    setTime(dst,minute(),second(),day(),month(),year());
  }
}

unsigned long sendNTPpacket(byte *address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  packetBuffer[0] = 0b11100011;
  packetBuffer[1] = 0;
  packetBuffer[2] = 6;
  packetBuffer[3] = 0xEC;
  packetBuffer[12]  = 49;
  packetBuffer[13]  = 0x4E;
  packetBuffer[14]  = 49;
  packetBuffer[15]  = 52;  
  Udp.sendPacket( packetBuffer,NTP_PACKET_SIZE,  address, 123);
}

I've got my upd libraries from there: http://code.google.com/p/arduino/source/browse/?r=1094#svn%2Ftrunk%2Flibraries%2FEthernet%253Fstate%253Dclosed

I don't get the clue...
« Last Edit: July 19, 2011, 03:02:58 pm by bjoernhoefer » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 548
Posts: 46026
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
When I add the getNTP code it does'nt "boot"
This is almost certainly a sign that you have run out of memory.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 42
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

hmmm... sounds not too good....

is there any possibility to "save" some of this - or should I get a Arduino Mega, do I have other options?

Sorry for asking stupid questions...
Logged

Pages: [1]   Go Up
Jump to: