Go Down

Topic: analogWrite() question (Read 948 times) previous topic - next topic

amorri21

Hi all,
I have the below code that is taken and adapted from other members of this forum and the www. Everything works great with it except the analogWrite() function towards the bottom of the file. The way it works is that I hit an IP (ie. http:10.0.0.1/analogWrite/5/200) and it parses it and sets the pwm pin 5 to a setting of 200. I guess the only problem is that the analogWrite doesn't work, the digitalWrite works beautifully though. What actually happens when I visit the analogWrite link mentioned above is that the led, which is in a low pass filter, flashes briefly and doesn't stay on. I know it isn't a filter problem because I wrote a really simple sketch that just sets the analogWrite values outright and it behaves fine. Any ideas? I know its a little messy and the stuff towards the top is just so I can see the pin states while I am working with it. Thanks for any suggestions.

Code: [Select]
//ARDUINO 1.0+ ONLY
//ARDUINO 1.0+ ONLY

#include <Ethernet.h>
#include <SPI.h>
boolean reading = false;

////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
  byte ip[] = { 192, 168, 0, 30 };   //Manual setup only
  byte gateway[] = { 192, 168, 0, 1 }; //Manual setup only
  byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only

  // if need to change the MAC address (Very Rare)
  byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

  EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////
int ledPin = 13;         
#define bufferMax 128
int bufferSize;
char buffer[bufferMax];

char cmd[15];    // Nothing magical about 15, increase these if you need longer commands/parameters
char param1[15];
char param2[15];

void setup(){
  Serial.begin(9600);

  //Pins 10,11,12 & 13 are used by the ethernet shield

  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);

  //Ethernet.begin(mac);
  Ethernet.begin(mac, ip, gateway, subnet); //for manual setup

  server.begin();
  Serial.println(Ethernet.localIP());

}

void loop(){
  // listen for incoming clients, and process qequest.
// checkForClient();

  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
   
    WaitForRequest(client);
    ParseReceivedRequest();
    PerformRequestedCommands();
   
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
       
        if(reading && c == ' ') reading = false;
        if(c == '?') reading = true; //found the ?, begin reading the info

        char d = 'a';
        if(reading){
          Serial.print(c);
          char d = c;
        }
       
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");
                    // add a meta refresh tag, so the browser pulls again every 10 seconds:
          client.println("<meta http-equiv=\"refresh\" content=\"10\">");
          // output the value of each analog input pin
          //client.print("this is a test");
          for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
            int sensorReading = analogRead(analogChannel);
            client.print("analog input ");
            client.print(analogChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");       
          }
          for (int digitalChannel = 0; digitalChannel < 10; digitalChannel++) {
            int sensorReading = digitalRead(digitalChannel);
            client.print("Digital PinMode ");
            client.print(digitalChannel);
            client.print(" is ");
            client.print(sensorReading);
            client.println("<br />");       
          }
          client.println("<br />");       
          client.println("c=");
          client.println(c);
          client.println("<br />");       
          client.println("p1=");
          client.println(param1);
          client.println("<br />");       
          client.println("p2=");
          client.println(param2);
          client.println("</html>");

          break;
        }

      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");

  }

}




void WaitForRequest(EthernetClient client) // Sets buffer[] and bufferSize
{
  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;
    }
  }
 
  PrintNumber("bufferSize", bufferSize);
}


void ParseReceivedRequest()
{
  Serial.println("in ParseReceivedRequest");
  Serial.println(buffer);
 
  //Received buffer contains "GET /cmd/param1/param2 HTTP/1.1".  Break it up.
  char* slash1;
  char* slash2;
  char* slash3;
  char* space2;
 
  slash1 = strstr(buffer, "/") + 1; // Look for first slash
  slash2 = strstr(slash1, "/") + 1; // second slash
  slash3 = strstr(slash2, "/") + 1; // third slash
  space2 = strstr(slash2, " ") + 1; // 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);
 
  // strncpy does not automatically add terminating zero, but strncat does! So 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);
}

void PerformRequestedCommands()
{
  if ( strcmp(cmd,"digitalWrite") == 0 ) RemoteDigitalWrite();
  if ( strcmp(cmd,"analogWrite") == 0 ) RemoteAnalogWrite();
}

void RemoteDigitalWrite()
{
  int ledPin = param1[0] - '0'; // Param1 should be one digit port
  int ledState = param2[0] - '0'; // Param2 should be either 1 or 0
  digitalWrite(ledPin, ledState);
}

void RemoteAnalogWrite()
{
  // If desired, use more server.print() to send http header instead of just sending the analog value.
  int pwmPin = param1[0] - '0'; // Param1 should be one digit analog port
  int pwmState = param2[0] - '0'; // Param2 should be between 0 and 255
  analogWrite(pwmPin, pwmState);         
}

void PrintString(char* label, char* str)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(str);
}
void PrintNumber(char* label, int number)
{
  Serial.print(label);
  Serial.print("=");
  Serial.println(number, DEC);
}

PeterH


I guess the only problem is that the analogWrite doesn't work, the digitalWrite works beautifully though. What actually happens when I visit the analogWrite link mentioned above is that the led, which is in a low pass filter, flashes briefly and doesn't stay on.


Are you certain that you're accessing a pwm-capable pin? Which board are you using, and which pin number?
I only provide help via the forum - please do not contact me for private consultancy.

amorri21

pretty sure... the Uno board, Pin5. Like I said I turned on the led on pin5 with a short little script (below) and it worked just fine.

Code: [Select]
int ledPin = 5;    // LED connected to digital pin 9

void setup()  {
  // nothing happens in setup
}

void loop()  {
    analogWrite(ledPin, 200);                                     
}

Arrch

Code: [Select]

void RemoteAnalogWrite()
{
  // If desired, use more server.print() to send http header instead of just sending the analog value.
  int pwmPin = param1[0] - '0'; // Param1 should be one digit analog port
  int pwmState = param2[0] - '0'; // Param2 should be between 0 and 255
  analogWrite(pwmPin, pwmState);         
}


This looks like an excellent place to put some debug prints to tell you what the values of pwmPin and pwmState.

PaulS

Code: [Select]
  int pwmState = param2[0] - '0'; // Param2 should be between 0 and 255
Clearly, pwmState will be a one digit number. If you have an LED attached to this pin, a value of 9 may not be high enough to make the LED turn on, even dimly.

amorri21

Thank you for that. I have tried changing that value to a 3 digit string and it still doesn't work... fun times...

amorri21

In addition I set the values pwmPin = 5 and pwmState = 200 and the light just flashes once, and due to the "meta refresh" towards the top of the code the light will blink every ten seconds.

MisterResistor

How long is this condition true  ?  "if ( strcmp(cmd,"analogWrite") == 0 ) RemoteAnalogWrite();"

amorri21

Learning,
I am not sure I understand the question - I believe I am just defining my functions in that line.

PeterH


I am not sure I understand the question - I believe I am just defining my functions in that line.


In that case I'm sure you don't understand the question, because that is not defining the 'function', it is performing it.


Thank you for that. I have tried changing that value to a 3 digit string and it still doesn't work... fun times...


Maybe there was a problem with the way you tried changing that value to a 3 digit string. Of course, it's rather hard to see your code from here ...
I only provide help via the forum - please do not contact me for private consultancy.

MisterResistor

#10
Feb 11, 2013, 04:49 am Last Edit: Feb 11, 2013, 04:55 am by Learning Reason: 1
Amorri,  the "if" statement is performing your analog write function ONLY when the compare == (is equal to 0). As soon as the compare is NOT equal to 0 (it's pretty quick), the if statement returns FALSE. Probably why your analogWrite stops.

For the heck of it, change the  ==  to  != (not equal)  and see what happens.

PeterH


Amorri,  the "if" statement is performing your analog write function ONLY when the compare == (is equal to 0). As soon as the compare is NOT equal to 0 (it's pretty quick), the if statement returns FALSE. Probably why your analogWrite stops.


I think you may have misunderstood what analogWrite() does. Once started, the output will continue until it is explicitly stopped by another write operation on that pin.
I only provide help via the forum - please do not contact me for private consultancy.

amorri21

PeterH and Learning,
Thank you for the suggestions. And yes PeterH I am definitely new to this... Below is how I changed it to a three digit value and from reading the serial it looks like its getting the correct variable now (also below). Learning, I also tried to change that if statement to !=0 and that didn't seem to change anything after I flashed the ard.

Change to digit string...
Code: [Select]
{
  // If desired, use more server.print() to send http header instead of just sending the analog value.
  int pwmPin = param1[0] - '0'; // Param1 should be one digit analog port
  int pwmState = param2[000] - '000'; // Param2 should be between 0 and 255
  analogWrite(pwmPin, pwmState);
  Serial.print("test");
  Serial.print(param1);
  Serial.println(param2); 
}


And here is the output of the serial.

192.168.0.30
bufferSize=32
in ParseReceivedRequest
GET /analogWrite/3/255 HTTP/1.1

slash1=analogWrite/3/255 HTTP/1.1

slash2=3/255 HTTP/1.1

slash3=255 HTTP/1.1

space2=HTTP/1.1

cmd=analogWrite
param1=3
param2=255
test3255
new client
Host: 192.168.0.30
client disonnected

PaulS

Code: [Select]
  int pwmState = param2[000] - '000'; // Param2 should be between 0 and 255
What the heck is this supposed to do?  param2 is a NULL terminated array of characters. Subtracting the multibyte character '000' (which is nonsense on the Arduino) from the first element of the array is NOT how to make a number out of the string.

I suspect that you need to make friends with atoi().

Go Up