Timing control problems

I've got this project, it uses Processing to access the internet, get an XML file from the national weather service to tell me the current weather conditions. Eventually I want the short term forecast highs and low temps up on my wall on seven segment displays....

The problem I'm having is I can't figure out how to go the the national weather service's site only twice an hour to update (hundreds of thousands of devices are checking this site and if you overuse it they block your IP)

Tried an if statement with the min() function. min() and sec().

Checked my c++ book, not much help.

Anyways, here's the code. For anybody interested I highly recommend looking into XML because it is extremely easy to write and read data over networks with this stuff. I got this up in an hour just by checking Processing's material on the matter.

Here's my Processing code for a one time check, the URL location is for the current weather observations for Minneapolis, MN:

import processing.xml.*;

void setup() { // Download current weather conditions for the mpls area

String url = "http://www.weather.gov/data/current_obs/KANE.xml";

XMLElement rss = new XMLElement(this, url);

XMLElement tempy = rss.getChild("temp_f"); print("The temperature is "); print(tempy.getContent()); println(" degrees");

XMLElement cond= rss.getChild("weather"); print("Prevailing Conditions: "); println(cond.getContent());

XMLElement wind= rss.getChild("wind_string"); print("Winds "); println(wind.getContent());

XMLElement chill= rss.getChild("windchill_f"); print("This is Minnesota so of course you need the chill factor: "); println(chill.getContent());

}

any assistance would be much appreciated.

Where is the timing logic in your code? Posting what you have will make it easier to track down any problems in your code.

If your Arduino code doesn't need to do anything else between updates you can do something like this:

void loop(){ getWeather(); updateDisplay(); delay(30000) ; // delay 30 seconds }

If your Arduino code doesn't need to do anything else between updates you can do something like this:

void loop(){ getWeather(); updateDisplay(); delay(30000) ; // delay 30 seconds }

I appreciate this.

It might be the route, but the thing is, the weather is updated once an hour, about fifteen minutes after I believe. I'd kinda like to check it at a set and predictable time after the website update.

Where is the timing logic in your code? Posting what you have will make it easier to track down any problems in your code.

I'm sorry, I wasn't clear...

I wrote, "Here's my Processing code for a one time check" as I'm kinda in the dark about how to go about with the loop and the timing.

I'm thinking a clock ticking at the top with an if statement maybe.

It might be the route, but the thing is, the weather is updated once an hour, about fifteen minutes after I believe. I'd kinda like to check it at a set and predictable time after the website update.

This is probably overkill but I have an application that uses processing to get the current time, converts it to a unix time_t, sends it to the arduino via the serial port to syncronise time. It uses a clock class running on the arduino that triggers callbacks at preset times or periods.

If you are interested I would be happy to share the code. It's a lot of stuff so it may be better just to post the syncronisation fragments that run on both machines.

But it may be easier just having the arduino send a request for the info every 10 or 15 minutes and have processing only respond if the data has been updated.

Ah, that makes sense.

How are you obtaining the weather data itself? Via a serial line, or using a direct network connection?

It might be the route, but the thing is, the weather is updated once an hour, about fifteen minutes after I believe. I'd kinda like to check it at a set and predictable time after the website update.

This is probably overkill but I have an application that uses processing to get the current time, converts it to a unix time_t, sends it to the arduino via the serial port to syncronise time. It uses a clock class running on the arduino that triggers callbacks at preset times or periods.

Kinda overkill, but the code would be nice.

Simond, the code I posted above accesses weather data over http via XML protocol thats located and updated at the url address located after "string url" . Processing's website has info on how to do this in reference>libraries using accessing yahoo's rss XML newsfeeds as examples.

When you're on the internet, any time you see XML or RSS icons you can easily configure your hardware to retrieve that data.

You can also learn how to write data to upload on the internet using a network connection and your hardware.

Meaning you could mount a camera on some servos and stream the video, and control the camera's angle remotely, or something similar.

I just want a weather stations display on my wall with 7 segment LED displays giving me current temp, and three day high and low temperatures.

eventually I might get fancy and have little illuminated led icons with rain clouds, snowflakes, sunshine.

Oy. I should read your code more carefully - I see now what you're doing :)

So the way I see it you have a couple of options (assuming your internet-connected machine is communicating with the arduino via serial).

  1. Manage time on the internet-connected machine. Use something like cron to obtain the weather data, or manage timing within your app. Either way push it to the arduino.
  2. Manage time on the arduino. Make a request from the arduino to the internet-connected machine at the appropriate time to obtain the weather data and return it to the arduino.

In the first case, using cron will probably be simpler - all the Processing app has to do then is obtain the weather data and do what it likes with it. Adjusting the period of data gathering is a simple matter of editing a crontab.

Managing time within the app itself can be done in a couple of ways, too. The first is to check the (system clock) time, and only obtain weather data at the correct times. The second is to count seconds since the last time weather data was obtained.

Managing time on the arduino might be slightly more problematic due to rollover issues (though these are themselves manageable), and probably unnecessarily complicated for this application.

Hope this is enough to get you started, at least.

Here is the processing code to sync time with the arduino

/**
 * SetArduinoClock. 
 * 
 * Clicking the window sends the current time to the arduino
 *    as the string value of the number of secs since jan 1 1970
 * The com portIndex variable must be set to the Arduino port
 *  
 */
 
import processing.serial.*;

Serial myPort;     // Create object from Serial class
public static final short LF = 10;     // ASCII linefeed
public static final short FONT_SIZE = 14;
public static final short portIndex = 1;  // select the com port
color PCClock = color(153, 51, 0);
PFont fontA;  

void setup() {  
  size(200, 200);
  println(Serial.list());
  println(" Connecting to -> " + Serial.list()[portIndex]);
  myPort = new Serial(this,Serial.list()[portIndex], 19200);

  fontA = loadFont("Eureka90.vlw"); 
  textFont(fontA); 
  textSize( FONT_SIZE);
  stroke(255);
  smooth();
  background(0);
  text("Mouse click to set Arduino time", 5,10);
}

void mousePressed() {
    // java time is in ms, we want secs
    Long now = new Long(System.currentTimeMillis()/ 1000);
    Date timeNow = new Date();
    String time = now.toString();
    char header = 0xff;
    myPort.write(header);
    myPort.write(time);   
    text("Synched " + timeNow.toString(), 2, height - 2 );
    println("Synched " + timeNow.toString());
}

void serialEvent(Serial p) {
  String inString = myPort.readStringUntil(LF); 
  if(inString != null && inString.length() >= 13){    
      if(inString.charAt(0) > 240){ //is it a header ?
           int val = 0;
           long time = 0;
           for(int i = 1; i <= 10; i++)        
              time = time * 10 + (inString.charAt(i) - '0');
           UpdateClock(time);
      }            
  }
  else if( inString != null && inString.length() > 0 )     
     println( inString + " length = " + inString.length());  
}


void UpdateClock( long t){
    int sec, min, hr;
    Long time = new Long(t);
    sec = time.intValue() % 60;
    min = (time.intValue() / 60) % 60 ;
    hr =  (time.intValue() % 86400) / 3660;   
    UpdateClock(sec, min, hr );   
}

void UpdateClock( int sec, int min, int hour){        
  fill(80);
  noStroke();
  // Angles for sin() and cos() start at 3 o'clock;
  // subtract HALF_PI to make them start at the top
  ellipse(100, 100, 160, 160);
  float s = map(sec, 0, 60, 0, TWO_PI) - HALF_PI;
  float m = map(min, 0, 60, 0, TWO_PI) - HALF_PI;
  float h = map(hour % 12, 0, 12, 0, TWO_PI) - HALF_PI;
  stroke(255);
  strokeWeight(1);
  line(100, 100, cos(s) * 72 + 100, sin(s) * 72 + 100);
  strokeWeight(2);
  line(100, 100, cos(m) * 60 + 100, sin(m) * 60 + 100);
  strokeWeight(4);
  line(100, 100, cos(h) * 50 + 100, sin(h) * 50 + 100);  
  // now show the seconds on this pc
  s = map(second(), 0, 60, 0, TWO_PI) - HALF_PI;
  strokeWeight(1);
  stroke(PCClock);
  line(100, 100, cos(s) * 72 + 100, sin(s) * 72 + 100);
  
}

void draw() { 
  
}

And this is an arduino sketch that gets the time and updates every 30 seconds, you would modify the delay for however many minutes you want to check back with processing

#include <ctype.h>  // for isdigit
#define TIME_HEADER  255   // Time messgage is this header follewed by the time data
#define TIME_MSG_LEN  11   // time is sent as HEADER followed by unix time_t as ten ascii digits

/*==============================================================================
 * TIME MACROS
 *============================================================================*/
#define SECS_PER_MIN  (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY  (SECS_PER_HOUR * 24L)

#define GetSec(_time_) (_time_ % SECS_PER_MIN)
#define GetMin(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define GetHour(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)

unsigned long time;

void setup(){
   Serial.begin(19200);  
   Serial.println("Waiting sync");
   while( (time = SynchroniseClock()) == 0) // wait here for the time synch message
      delay(100); 
   sendTime(time);// send the time back to processing      
   int sec = GetSec(time);
   // calculate number of seconds to wait for the next half minute 
   int adjust = 30 - (sec % 30);
   delay( adjust * 1000) ;
   time += adjust;
}

unsigned long  SynchroniseClock() {
// return time_t or 0 if not synched   
unsigned long time = 0;  // this is the same as unix time_t

   while(Serial.available() >=  TIME_MSG_LEN )
      if( Serial.read() == TIME_HEADER ) {        
           char chtime[TIME_MSG_LEN]; // array holding the time data from the PC     
           for(int i =0; i < TIME_MSG_LEN -1; i++)
                chtime[i] = Serial.read();
           chtime[TIME_MSG_LEN-1] = 0;  // null terminate the string
           time = StrToTime(chtime);                   
      }  
      return time;
}

unsigned long StrToTime(char* Str){
// utility function to convert time string to time_t 
  unsigned long result = 0;

  for(int i = 0; isdigit(Str[i]); i++)
    result = 10 * result + (Str[i] - '0') ;
  return result;         
}

void sendTime(unsigned long time){
   Serial.print(TIME_HEADER,BYTE);  // send the time back to processing    
   Serial.println(time,DEC);   
}

void loop(){
   sendTime(time);
   delay(30000); // wait 30 seconds   
   time += 30;   
}