Pages: [1]   Go Down
Author Topic: “WiServer.print” and link “<a href=/ /< a” causing trouble.  (Read 1084 times)
0 Members and 1 Guest are viewing this topic.
Mesa, AZ
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The “WiFiRedback” which uses a Nano Atmega328 acts up when using more than one or two lines of “WiServer.print(”text”)  and/or  a link  “<a href=/  /< a” in a sketch.

The sketch has several “IFs” and when “WiServer.print(“text”) is included within the “IF” the code will operate twice when it should only operate once.  Seems like the return from the “WiServer” code enters at the top of the IF ? Removing most of the “WiServer.print” lines either within or outside of the “Ifs” fixes it.

The sketch is using about 16KB of the available 30KB on the Nano.

Is there a limit how many bytes can be coded using “WiServer.print(“text”)” ?

Is there a limit on how many bytes can be in the URL when using the link function ?
Any amount of bytes beyond 6 seems to cause the same problem as the “WiServer.print” and is not within the “IF” ?
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 617
Posts: 49455
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there a limit how many bytes can be coded using “WiServer.print(“text”)” ?
Yes, and no. There is no limit to the number of characters that can be sent using the print() method. But, there is a limit to how many character strings you can store in SRAM. It appears that you have violated that limit. We'd need to see your code, rather than some vague hand waving, to know for sure.

You can use the F() macro to move the constant strings out for SRAM.
WiServer.print(F("text"));
Logged

Mesa, AZ
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the help. 
Below is the code. It's in bad shape since I'm a beginner at coding.
I grabbed the first example found on the internet that used a "WiShield" to turn LEDs on and off.
Turns out that example was a toggle on and off for LEDs.  So I have attempted to change that to meet my objective.

The objective is to click on Lock to have Pin 4 pulse for 1 Second to Lock and click on Unlock to have Pin 5 pulse for 1 second to unlock.  Along with feedback text messages about being locked or not.
I will control the locks by two methods 1) via Web page, and 2) via URL sent from my automation system.  I have reverse engineerd a Kwikset smart deadbolt and plan to access it's H brigde with the WiFiRedback.

Once I get the output results I'm looking for I will need to learn how to clean the code up.

You can see in the sketch that I have commented out the areas where testing failed using text.  Where web printing usng "WiServer.print ("text")"  caused the outputs to pulse twice instead of once.

I'll take any help I can get.

int redState = 0;
int greenState = 0;

int redPin = 4;
int greenPin = 5;

char garageDoorLock[] = "GDL";  //Remove these Chars when using text
char garageDoorUnlock[] = "GDU";  //Remove these Chars when using text
char eastPatioLock[] = "EPL";  //Remove these Chars when using text
char eastPatioUnlock[] = "EPU";  //Remove these Chars when using text

// Web page serving function
boolean sendMyPage(char* URL) {
 
// East patio door lock 
//if (strcmp(URL, "/eastPatioLock") == 0) {
if (strcmp(URL, "/EPL") == 0){
redState = 1;
     digitalWrite(redPin, redState);
     delay (1000);
     redState = 0;
     digitalWrite(redPin, redState);
    // WiServer.print("Locked <br>");
}

//East patio door unlock
//if (strcmp(URL, "/eastPatioUnlock") == 0) {
if (strcmp(URL, "/EPU") == 0){
     greenState = 1;
     digitalWrite(greenPin, greenState);
     delay (1000);
     greenState = 0;
     digitalWrite(greenPin, greenState);
    // WiServer.print("Unlocked<br>");
 
}

// Garage door lock
if (strcmp(URL, "/GDL") == 0) {
     redState = 1;
     digitalWrite(redPin, redState);
    delay (1000);
     redState = 0;
    digitalWrite(redPin, redState);
       // WiServer.print("Locked <br>");
}
     
// Garage door unlock
if (strcmp(URL, "/GDU") == 0) {
     greenState = 1;
     digitalWrite(greenPin, greenState);
     delay (1000);
     greenState = 0;
  digitalWrite(greenPin, greenState);
     //WiServer.print("Unlocked<br>");
}

// Check if the requested URL matches "/"
// if (strcmp(URL, "/") == 0) {
// Use WiServer’s print and println functions to write out the page content
WiServer.print("<html>");
WiServer.print("Door Deadbolt Control<br><br>");

//WiServer.print("<br>");
printEastDoorStatus(eastPatioLock, redState);
//printEastDoorStatus("eastPatioLock", redState);

printGarageStatus(garageDoorLock, greenState);
//printGarageStatus("garageDoorLock", greenState);

WiServer.print("The page you requested was: ");
WiServer.print(URL);
WiServer.print("</html>");
  // URL was recognized
  return true;
  //}
  // URL not found
return false;
}
void printEastDoorStatus( String doorName, int lightState) {
WiServer.print(doorName);
WiServer.print(" Deadbolt ");
if(lightState ==0) {
  WiServer.print(" <br><b>Click to Lock</b> <a href=/");
  WiServer.print(doorName);
  WiServer.print(">Lock</a><br>");
  //WiServer.print ("<br>");

  WiServer.print(" <b>Click to Unlock</b> <a href=/");
  WiServer.print(eastPatioUnlock);
  //WiServer.print("eastPatioUnlock");
  WiServer.print(">Unlock</a><br>");
  WiServer.print("<br>");
}
}
void printGarageStatus( String doorName, int lightState) {
WiServer.print(doorName);
WiServer.print(" Deadbolt ");
if(lightState ==0) {
  WiServer.print(" <br><b>Click to Lock</b> <a href=/");
  WiServer.print(doorName);
  WiServer.print(">Lock</a><br>");
  //WiServer.print ("<br>");

  WiServer.print(" <b>Click to Unlock</b> <a href=/");
  WiServer.print(garageDoorUnlock);
  WiServer.print(">Unlock</a><br>");
  //WiServer.print("<br>");
}
}
void setup() {
  // Initialize WiServer and have it use the sendMyPage function to serve pages
WiServer.init(sendMyPage);
// Enable Serial output and ask WiServer to generate log messages (optional)
Serial.begin(57600);
WiServer.enableVerboseMode(true);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
}
void loop(){
// Run WiServer
WiServer.server_task();
delay(10);
}
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 617
Posts: 49455
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Calling printGarageStatus() causes the function to convert the char array contents to a String object, pissing away resources that are in short supply. And for what?
Code:
WiServer.print(doorName);
So you can print it to the client. You could just as easily do that with a char pointer, consuming a lot fewer resources.

Deleting code that you no longer need, rather than commenting it out, is a better idea.

printGarageStatus() and printEastPatioStatus() do nearly the same thing. One additional argument would allow you to have one function, rather than two.
Logged

Mesa, AZ
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So the problem is over crowding the resource.  Thats a big thanks.  I was figuring that this code is small and would run even with sloppy coding.

again, thanks
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 617
Posts: 49455
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
So the problem is over crowding the resource.
The problem MAY be one of overusing memory.

Quote
I was figuring that this code is small and would run even with sloppy coding.
It will, IF you are not using more memory than you have.

There is a function you can use to see how much memory you have available: http://arduino.cc/playground/Code/AvailableMemory

Keep in mind that SRAM is used for the heap and the stack, so function calls influence how much memory you are using. Determining, at the end of setup() for instance, that you have enough memory is no guarantee that later, 57 functions deep, you will still have enough memory.

However, the value reported by the function will give you an indication of whether there is a problem, or not. If the function says you have 1800 bytes free, memory is not a problem. If it says you have 200 free, memory could be a problem. If it says you have -14 available, you DO have a problem. Though is will never actually report a negative number.
Logged

Mesa, AZ
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great analysis !
I will check SRAM out.
I knew the Nano had 2KB of SRAM but did not know how it was used until you told me here.
Know I will know if SRAM is in shortage or not.
I tried removing the calls but am still having the problem when I add just a few "WiServer.print"s ?

Again, thanks. 
Logged

Mesa, AZ
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the latest version of the sketch.
I had a heck of a time figuring out how to implement RAM check.
This version seems to check RAM and shows over 600 left.  And I still have the problem of double flashing the Leds.
I was not able to figure out how to call the RAM check.  All of the attempts errored.
Any chance you can make a recommendation of how to do it.
I think all I'm seeing is the RAM value before the sketch runs?
thanks,


int redState = 0;
int greenState = 0;

int redPin = 4;
int greenPin = 5;

unsigned long freeRAM() //RAM checker
       { uint8_t * heapptr, * stackptr;
   stackptr = (uint8_t *)malloc(4); // use stackptr temporarily
   heapptr = stackptr; // save value of heap pointer
   free(stackptr); // free up the memory again (sets stackptr to 0)
   stackptr = (uint8_t *)(SP); // save value of stack pointer
   return ((int) stackptr - (int) heapptr);
   }
char garageDoorLock[] = "gdl";  //Remove these Chars when using text
char garageDoorUnlock[] = "gdu";  //Remove these Chars when using text
char eastPatioLock[] = "epdl";  //Remove these Chars when using text
char eastPatioUnlock[] = "epdu";  //Remove these Chars when using text

// Web page serving function
boolean sendMyPage(char* URL) {
 
WiServer.println(freeRAM(),DEC); //Print freeRAM info

if (strcmp(URL, "/epdl") == 0){
        redState = 1;
     digitalWrite(redPin, redState);
     delay (1000);
     redState = 0;
     digitalWrite(redPin, redState);
      WiServer.print("Locked<br>");
  }

if (strcmp(URL, "/epdu") == 0){
     greenState = 1;
     digitalWrite(greenPin, greenState);
     delay (1000);
     greenState = 0;
     digitalWrite(greenPin, greenState);
    WiServer.print("Unlocked<br>");
  }

// Garage door lock
if (strcmp(URL, "/gdl") == 0) {
     redState = 1;
     digitalWrite(redPin, redState);
    delay (1000);
     redState = 0;
    digitalWrite(redPin, redState);
  }
     
// Garage door unlock
if (strcmp(URL, "/gdu") == 0) {
     greenState = 1;
     digitalWrite(greenPin, greenState);
     delay (1000);
     greenState = 0;
        digitalWrite(greenPin, greenState);
  }

// Check if the requested URL matches "/"
// if (strcmp(URL, "/") == 0)
// Use WiServer’s print and println functions to write out the page content
WiServer.print("<html>");

WiServer.print("The page you requested was: ");
WiServer.print(URL);
WiServer.print("<br><br>");
WiServer.print("</html>");
  WiServer.print("East Patio Door Deadbolt");
  WiServer.print(" <br><b>Click to Lock</b> <a href=/");
  WiServer.print(eastPatioLock);
  WiServer.print(">Lock</a><br>");
   
  WiServer.print(" <b>Click to Unlock</b> <a href=/");
  WiServer.print(eastPatioUnlock);
  WiServer.print(">Unlock</a><br>");

WiServer.print("Garage Door Lock");
 WiServer.print(" <br><b>Click to Lock</b> <a href=/");
  WiServer.print(garageDoorLock);
  WiServer.print(">Lock</a><br>");
 
  WiServer.print(" <b>Click to Unlock</b> <a href=/");
  WiServer.print(garageDoorUnlock);
  WiServer.print(">Unlock</a><br>");

WiServer.print("</html>");


 
void setup(){ 
// Initialize WiServer and have it use the sendMyPage function to serve pages
WiServer.init(sendMyPage);
// Enable Serial output and ask WiServer to generate log messages (optional)
Serial.begin(57600);
WiServer.enableVerboseMode(true);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
}

 
void loop(){
// Run WiServer
WiServer.server_task();
delay(10);
}

Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 617
Posts: 49455
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
WiServer.println(freeRAM(),DEC); //Print freeRAM info
Why not print to the Serial Monitor?
Code:
Serial.print("Free memory: ");
Serial.println(freeRam());

Quote
I think all I'm seeing is the RAM value before the sketch runs?
You are. Using whatever method you use to see the data, copy that code into setup() and loop().

You can use the same technique to see a lot of other stuff. I'd recommend doing to, so you KNOW what the Arduino is seeing/doing.

PS. The code icon, the one with the # on it, is there for a reason. Discover what it does (the Preview button is great) and use it.
Logged

Mesa, AZ
Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks again for all your help.  And with using the Forum too. 
Logged

Pages: [1]   Go Up
Jump to: