Led Dimming

I am working on a thought to control leds based on weather over the course of 30 minutes. This might have to be refined as it appears that I can only do the one http request as the arduino is busy is that a correct assumption. Second I would like to change the brightness at a slower rate on the led is there a way to increment it slower then by one?

void RemoteDigitalWeatherDim()
{
  int ledPin = atoi(param1); // Param1 should be one digit port
  int dimValue = atoi(param2); // Param2 should be a value 0 to 255
  int dimDelay = 0;
  int dimStart = 60;
  int randNumber = 0;
  int time = 0;
  digitalWrite(ledPin, 1);
  randomSeed(analogRead(0));
  
  randNumber = random(5,10);
  dimDelay = (dimStart / randNumber)/2;
  time = time + dimDelay;
  
  while (time < dimStart)
  {
    for (int i=0; i<dimValue; i++)
    {
      PrintNumber("i", i);
      analogWrite(ledPin, i);
      delay(dimDelay);
    }
    for (int i=dimValue; i >= 0; i--)
    {
      analogWrite(ledPin, i);
      delay(dimDelay);
    }
    PrintNumber("dimDelay", dimDelay);
    PrintNumber("time", time);
    randNumber = random(5,10);
    time = time + dimDelay;
    dimDelay = (dimStart / randNumber)/2;
  }

  //-- Send response back to browser --
  server.print("D");
  server.print(ledPin, DEC);
  server.print(" is dimming ");
  server.print(dimValue, DEC);
  server.print("%");

  //-- Send debug message to serial port --
  Serial.println("RemoteDigitalDim");
  PrintNumber("ledPin", ledPin);
  PrintNumber("dimValue", dimValue);
 
}

it appears that I can only do the one http request as the arduino is busy is that a correct assumption.

Maybe, maybe not. You didn't post all of your code, so it's hard to see where you make the request, and why you can't make more of them.

Second I would like to change the brightness at a slower rate on the led is there a way to increment it slower then by one?

No, but you can make it stay at each level for a longer time.

Here is the whole code. Learning as i go on arduino coding. I understand my second question now after realizing what I was trying to do. So now the question is about being able to handle multiple http requests at the same time. The RemoteDigitalWeatherDim() in my code takes almost 30 minutes to complete as that is the way I have it setup to simulate weather conditions. The issue is I am unable to do or pull anything else during this time. Any suggestions?

/* Arduino Server base by Hari Wiguna, g33k.blogspot.com modified by Brant Nielson*/

#include <SPI.h>
#include <Ethernet.h>
#include <string.h>

byte mac[] = {0x00, 0x1E, 0x2A, 0x77, 0x24, 0x02 }; //Unique mac address within your network.
byte ip[] = {10,172,192,40}; //Unique ip address within your network.

Server server(80); //Set Listening on port 80

//Client Browser Paramater Declaration
char cmd[20];
char param1[20];
char param2[20];

//Port Setup
void SetupPorts()
{
  pinMode(9,OUTPUT); //Led 1 connected on Pin 9 for PWM.
}

void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();

  Serial.begin(115200);
  SetupPorts();
}

#define bufferMax 256
int bufferSize;
char buffer[bufferMax];

void loop()
{
  Client client = server.available();
  if (client)
  {
    WaitForRequest(client);
    ParseReceivedRequest();
    PerformRequestedCommands();
    
    client.stop();
  }
}

//Function to set buffer[] and bufferSize.
void WaitForRequest(Client client)
{
  bufferSize = 0;

  while (client.connected()) {
    if (client.available()) {
      char c = client.read();
      if (c == '\n')
        break;
      else
        if (bufferSize < bufferMax)
          buffer[bufferSize++] = c;
        else
          break;
    }
  }
}

//Function to parse the client request.
void ParseReceivedRequest()
{  
  //Received buffer contains "GET /cmd/param1/param2 HTTP/1.1".  We break this apart.
  char* slash1;
  char* slash2;
  char* slash3;
  char* space2;
  
  slash1 = strstr(buffer, "/") + 1; //Looks for the first slash.
  slash2 = strstr(slash1, "/") + 1; //Looks for the second slash.
  slash3 = strstr(slash2, "/") + 1; //Looks for a third slash.
  space2 = strstr(slash2, " ") + 1; //Looks for space after second slash in case there is no third slash.
  if (slash3 > space2) slash3=slash2;

  PrintString("slash1",slash1);
  PrintString("slash2",slash2);
  PrintString("slash3",slash3);
  PrintString("space2",space2);
  
  //Start with blank string and concatenate.
  cmd[0] = 0;
  param1[0] = 0;
  param2[0] = 0;
  
  strncat(cmd, slash1, slash2-slash1-1);
  strncat(param1, slash2, slash3-slash2-1);
  strncat(param2, slash3, space2-slash3-1);
  
  PrintString("cmd",cmd);
  PrintString("param1",param1);
  PrintString("param2",param2);
}

//Function to get cmd paramater and routes to function to perform the cmd.
void PerformRequestedCommands()
{
  if ( strcmp(cmd,"digitalWrite") == 0 ) RemoteDigitalWrite();
  if ( strcmp(cmd,"digitalDim") == 0 ) RemoteDigitalDim();
  if ( strcmp(cmd,"digitalWeatherDim") == 0 ) RemoteDigitalWeatherDim();
  if ( strcmp(cmd,"digitalRead") == 0 ) RemoteDigitalRead();
  if ( strcmp(cmd,"analogRead") == 0 ) RemoteAnalogRead();
}

//Function to turn led1 on and off.
void RemoteDigitalWrite()
{
  int ledPin = atoi(param1); //Param1 should be one digit port.
  int ledState = atoi(param2); //Param2 should be either 1 or 0.
  digitalWrite(ledPin, ledState);

  //Send response back to browser.
  server.print("D");
  server.print(ledPin, DEC);
  server.print(" is ");
  server.print( (ledState==1) ? "ON" : "off" );

  //Send debug message to serial port.
  Serial.println("RemoteDigitalWrite");
  PrintNumber("ledPin", ledPin);
  PrintNumber("ledState", ledState);
}

//Function to set brightness of led1.
void RemoteDigitalDim()
{
  int ledPin = atoi(param1); //Param1 should be one digit port.
  int dimValue = atoi(param2); //Param2 should be 1 to 255.
  digitalWrite(ledPin, 1);
  analogWrite(ledPin, dimValue);

  //Send response back to browser.
  server.print("D");
  server.print(ledPin, DEC);
  server.print(" is dimming ");
  server.print(dimValue, DEC);
  server.print("%");

  //Send debug message to serial port.
  Serial.println("RemoteDigitalDim");
  PrintNumber("ledPin", ledPin);
  PrintNumber("dimValue", dimValue);
}

//Function to set random brightness of led1 over approximately 30 minutes.
void RemoteDigitalWeatherDim()
{
  int ledPin = atoi(param1); //Param1 should be one digit port.
  int dimValue = atoi(param2); //Param2 should be either 1 or 255.
  digitalWrite(ledPin, 1);
  int var = 0;
  randomSeed(analogRead(0));
  int randDelay = random(400,600);
  while (var < 4)
  {
    int randDelay = random(400,600);
  
    for (int i=0; i<dimValue; i++)
    {
      analogWrite(ledPin, i);
      delay(randDelay);
    }
    int i=0;
    for (int i=0; i<255; i++)
    {
      delay(350);
    }
    for (int i=dimValue; i>0; i--)
    {
      analogWrite(ledPin, i);
      delay(randDelay);
    }
    var++;
  }
  for (int i=0; i<dimValue; i++)
  {
    analogWrite(ledPin, i);
    delay(randDelay);
  }

  //Send response back to browser.
  server.print("D");
  server.print(ledPin, DEC);
  server.print(" is dimming ");
  server.print(dimValue, DEC);
  server.print("%");

  //Send debug message to serial port.
  Serial.println("RemoteDigitalDim");
  PrintNumber("ledPin", ledPin);
  PrintNumber("dimValue", dimValue);
}

//Function to read digital pin state.
void RemoteDigitalRead()
{
  int ledPin = atoi(param1); //Param1 should be one digit digital port.
  int ledValue = digitalRead(ledPin);
  
  //Send response back to browser.
  server.print("D");
  server.print(ledPin, DEC);
  server.print(" is ");
  server.print(ledValue,DEC);
  
  //Send debug message to serial port.
  Serial.println("RemoteDigitalRead");
  PrintNumber("ledPin", ledPin);
  PrintNumber("ledValue", ledValue);
}

//Function to read analog pin state.
void RemoteAnalogRead()
{
  int analogPin = atoi(param1); //Param1 should be one digit analog port.
  int analogValue = analogRead(analogPin);
  
  //Send response back to browser.
  server.print("A");
  server.print(analogPin, DEC);
  server.print(" is ");
  server.print(analogValue,DEC);
  
  //Send debug message to serial port.
  Serial.println("RemoteAnalogRead");
  PrintNumber("analogPin", analogPin);
  PrintNumber("analogValue", analogValue);
}

//Function to serial print strings.
void PrintString(char* label, char* str)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(str);
}

//Function to serial print numbers.
void PrintNumber(char* label, int number)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(number, DEC);
}

You could convert it to using states instead of loops. Or you could add a line to do the http request inside the existing loops.

You will need to explain state or point me in that direction. As far as the request and moving it to the other loops would I just do something like ...

void loop()
{
  Client client = server.available();
  if (client)
  {
    DigitalWrite(client);
    DigitalDim(client);
  }
}
void DigitalWrite()
{
  WaitForRequest(client);
  ParseReceivedRequest();
  PerformRequestedCommands();

  client.stop();
}

That way client.stop resides in my other functions instead of it holding up the loop.

Basically, for converting the loops to a state, you make RemoteDigitalDim() enable a variable. The loop() function then checks this variable for enabled and updates the led according to the time that has lapsed since RemoteDigitalDim() was called.

You may also want to revisit ParseReceivedRequest() and see what happens if the query only has 1 slash.

Parsing appears to be ok. The issue comes down to the tie up of the client connection processing since I am letting it take 30 minutes during that time it holds the connection open not allowing any other connections. The concept is simulate outside lighting 30 min sunrise, sunset, and clouds.

If there is a better way to do this I would sure like to know.

This is untested and I don’t work much with state machines, but it should work. (Insert UpdateDigitalWeatherDim() into your loop() function). It doesn’t do exactly what your method does, but with a little finagling it could.

int ledPin, dimValue;
int dwd_start_time;

void UpdateDigitalWeatherDim()
{
    static int a_value = 0; // current pin value
    static int a_step = 1;  // which way to step the value
    
    //unsigned short dt_ms = millis() - dwd_start_time; <-- OOPS
    unsigned long dt_ms = millis() - dwd_start_time;
    
    // 30 minutes has elapsed (or we are not updating)
    if (dt_ms > 1000 * 1800 || dwd_start_time == 0)
    {
        // Reset everything
        dwd_start_time = 0;
        a_value = 0;
        a_step  = 1;
        return;
    }
    
    // Write the current value
    int randDelay = random(400,600);
    analogWrite(ledPin, a_value);
    delay(randDelay);
    
    a_value += a_step;
    if (a_value == dimValue) a_step = -1;
    if (a_value == 0       ) a_step =  1;
}

//Function to set random brightness of led1 over approximately 30 minutes.
void RemoteDigitalWeatherDim()
{
    ledPin = atoi(param1); //Param1 should be one digit port.
    dimValue = atoi(param2); //Param2 should be either 1 or 255.
    digitalWrite(ledPin, 1);
    int var = 0;
    randomSeed(analogRead(0));

    // Initialize our update routine
    dwd_start_time = millis();
    
    //Send response back to browser.
    server.print("D");
    server.print(ledPin, DEC);
    server.print(" is dimming ");
    server.print(dimValue, DEC);
    server.print("%");

    //Send debug message to serial port.
    Serial.println("RemoteDigitalDim");
    PrintNumber("ledPin", ledPin);
    PrintNumber("dimValue", dimValue);
}
dt_ms > 1000 * 1800

Need to be careful with those constants.

AWOL: dt_ms > 1000 * 1800

Need to be careful with those constants.

why?

Because in some places 1000 * 1800 == 30 528

unsigned short dt_ms = millis() - dwd_start_time;
    
    // 30 minutes has elapsed (or we are not updating)

Always a good idea to ensure your data type is capable of representing the range of values you need,

AWOL: Because in some places 1000 * 1800 == 30 528

unsigned short dt_ms = millis() - dwd_start_time;
    
    // 30 minutes has elapsed (or we are not updating)

Always a good idea to ensure your data type is capable of representing the range of values you need,

I considered that, but didn't actually do the math. nice catch

Thanks a ton for the help it appears that this will work once I get the placement correct. If I refresh the page multiple times it lights the led. If I move the Update function to the loop inside the client check it just sits and waits if I move it outside the I get a crazy loop of checking and resetting.

So what is the proper placement.

void loop()
{
  Client client = server.available();
  if (client)
  {
    WaitForRequest(client);
    ParseReceivedRequest();
    PerformRequestedCommands();
    client.stop();
  }  
  RemoteDigitalWeatherDim;
}
//Function to get cmd paramater and routes to function to perform the cmd.
void PerformRequestedCommands()
{
  if ( strcmp(cmd,"digitalWrite") == 0 ) RemoteDigitalWrite();
  if ( strcmp(cmd,"digitalDim") == 0 ) RemoteDigitalDim();
  if ( strcmp(cmd,"digitalWeatherDim") == 0 ) RemoteDigitalWeatherDim();
  if ( strcmp(cmd,"digitalRead") == 0 ) RemoteDigitalRead();
  if ( strcmp(cmd,"analogRead") == 0 ) RemoteAnalogRead();
}
void UpdateDigitalWeatherDim()
{
    Serial.println("Updating Weather");
   
    int ledPin = atoi(param1);
    int dimValue = atoi(param2);
    
    static int a_value = 0; // current pin value
    static int a_step = 0;  // which way to step the value
    
    unsigned long dt_ms = millis() - dwd_start_time;
    
    // 30 minutes has elapsed (or we are not updating)
    if (dt_ms > 1000 * 1800 || dwd_start_time == 0)
    {
      Serial.println("Resetting Weather Loop");
      // Reset everything
      dwd_start_time = 0;
      a_value = 0;
      a_step  = 1;
      
      return;
    }
    
    // Write the current value
    analogWrite(ledPin, a_value);
    delay(10);
    
    a_value += a_step;
    
    if (a_value == dimValue) 
    {
      Serial.println("Subtracting 1");
      a_step = -1;
    }
    if (a_value == 0)
    {
      Serial.println("Adding 1");
      a_step =  1;
    }
}
//Function to set random brightness of led1 over approximately 30 minutes.
void RemoteDigitalWeatherDim()
{
    Serial.println("Running Weather Sim");
    
    int ledPin = atoi(param1); //Param1 should be one digit port.
    int dimValue = atoi(param2);  //Param2 should be either 1 or 255.
    
    //digitalWrite(ledPin, 1);
    randomSeed(analogRead(0));

    // Initialize our update routine
    dwd_start_time = millis();
    
    //Send response back to browser.
    server.print("D");
    server.print(ledPin, DEC);
    server.print(" is dimming ");
    server.print(dimValue, DEC);
    server.print("%");

    //Send debug message to serial port.
    Serial.println("RemoteWeatherDigitalDim");
    PrintNumber("ledPin", ledPin);
    PrintNumber("dimValue", dimValue);
}
if (dt_ms > 1000 * 1800

Does this work?

If (dt_ms > 1000 * 1800) // || dwd_start_time == 0 does appear to make it better to a point however once I get to a a_value=30 then it becomes true and resets the values and it goes crazy.

Try:if (dt_ms > 1000UL * 1800UL

Thanks a ton for the help guys on this. This did solve the issue what does the ul signal for a noob like me. This does fix the issue of being able to send multiple requests as well. Now just to figure out why there is an issue with the led kicking on. A digitalRead caused it to come on now it is fading in and out correctly but didn't come on at the beginning.

Ah unsigned long the power of search.

  RemoteDigitalWeatherDim;

This does not do what you think it does.

Yeah it was a typo.