Show Posts
Pages: [1]
1  Using Arduino / Networking, Protocols, and Devices / WiShield/tcp questions on: September 07, 2013, 10:31:43 pm
I'm (re)writing a sketch that runs on a Yellowjacket hooked to a LED display. This setup is updated by another computer on the wireless network to display different messages on the LED display. Originally I spent a bunch of time putting a webserver on the Yellowjacket that could be updated with REST commands, but this was at the very threshhold of what the Yellowjacket can handle [with my code, anyways]. I'd like now to try something a little easier, and simply have it update through TCP/IP commands. If you can think of an easier way to do this, please feel free to present new options! smiley

Right now I'm experimenting on the WiShield's SocketApp example, which appears to work fine. However, I'm running into some stumbling blocks getting past the example. The example uses a "handle_connection" function that does the real work, but this is in the socketapp.c file and I need something I can interact with in my main sketch. Is there a better API or a way I can inject code into socketapp.c that will allow me to handle the send and receives in my main sketch? I need the contents of the inputbuffer to be passed to the LED driver code and I'm not coming up with how to get from here to there, so to speak...

>^,,^<
2  Using Arduino / Project Guidance / Re: Yellowjacket + PS2/You LED sign + WiServer = *almost AWESOME* (Out of memory?) on: March 15, 2013, 09:24:29 pm
Here's my final [reasonably] stable code, in case its helpful to anyone else. I optimized it as much as I can, but know there is probably more possible. Let me know if you see anything else to help improve performance or stability! I might put this up as an Instructable later so all feedback is welcome. smiley

Code:
/*
*    REST-driven LED Display board
*    
*    To use, point a browser to your IP address along with the REST commands.
*    Example: http://192.168.1.20/read will display what is currently be displayed on the board.
*    Example 2: http://192.168.1.20/write/1/OneLongTest will write OneLongTest to line 1 of the board.
*/


// for the wifi:
#include <EEPROM.h>
#include <TinyREST.h>
#include <WiServer.h>
// for the display:
#include <string.h>
#include "MatrixDisplay.h"
#include "DisplayToolbox.h"
#include "font.h"


#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,20}; // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"Your_SSID_Here"}; // max 32 bytes

unsigned char security_type = 3; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"Your_password_here"}; // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {};

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------

// Matrix display configuration parameters ----------------------------------------

const int numLines = 5;        // Max number of lines
const int displayTime = 2500;  // Length of time in milliseconds to display each line
const int gapTime = 10;        // Time gap between lines
const int maxLineLength = 30; // Maximum length of a line in characters

char lines[numLines][maxLineLength];
char text[maxLineLength];

int textLength;          // Holds current line length in pixels
int strLength;           // Holds current line length in characters
int currentLine = 0;     // Index of current line

const prog_char defaultText[] PROGMEM = {"I've been reset!"};
const prog_char msgRecvText[] PROGMEM = {"<html><p>Message Recieved By Server</p></html>"};
const prog_char msgRecvStartText[] PROGMEM = {"<html><p>"};
const prog_char msgRecvEndText[] PROGMEM = {"</p></html>"};

// Character lookup string -- used to map the characters from the keyboard onto the font data array
const prog_char charLookup[] PROGMEM = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*(),-.?></\\|[]_=+:'\"{}";

// Macro to make it the initDisplay function a little easier to understand
#define setMaster(dispNum, CSPin) initDisplay(dispNum,CSPin,true)
#define setSlave(dispNum, CSPin) initDisplay(dispNum,CSPin,false)

// Initialize matrix
MatrixDisplay disp(3,16,15, true);
DisplayToolbox toolbox(&disp);

// Prepare boundaries
uint8_t X_MAX = 0;
uint8_t Y_MAX = 0;

// End of matrix display configuration parameters ----------------------------------------

TinyREST rest = TinyREST();
static char cmd_read_string[] = {"read"};
static char cmd_write_string[] = {"write"};

// Define states for FSM
#define INITIALSTATE 0
#define SCROLLWRITINGSTATE 1
#define SCROLLWAITINGSTATE 2
#define FIXEDWAITINGLONGSTATE 3
#define FIXEDWAITINGSHORTSTATE 4


int lineNum;
long previousMillis = 0;
long currentMillis = 0;
int current_state = INITIALSTATE;

int end_pos;
int x_pos;

// This is our page serving function that generates web pages
boolean sendMyPage(char* URL) {
  return rest.handleURL(URL);
}


void setup() {
  // Initialize WiServer and have it use the sendMyPage function to serve pages
  rest.init();
  rest.addCommand(cmd_read_string, 0, testCallback);
  rest.addCommand(cmd_write_string, 2, testCallback);
  WiServer.init(sendMyPage);
  
  // Enable Serial output and ask WiServer to generate log messages (optional)
  Serial.begin(57600);
  
  // Enable matrix display, set default text
  strcpy_P(lines[0], defaultText);
  
  // Fetch display bounds
  X_MAX = disp.getDisplayCount() * (disp.getDisplayWidth()-1)+3;
  Y_MAX = disp.getDisplayHeight()-1;
 
  // Prepare displays
  disp.setMaster(0,4);
  disp.setSlave(1,5);
  disp.setSlave(2,6);
}

void loop(){

  // Run WiServer
  WiServer.server_task();
  rest.loop();
  
  // Update Display
  currentMillis = millis();
  
  //Simple FSM for the display
  switch (current_state)
  {
    case INITIALSTATE:
      // Update Display
      strLength = strlen(lines[currentLine]); // Number of characters in the string
      textLength = (strLength*6); // Width of string in pixels
  
      strcpy(text, lines[currentLine]);
      //Determine text type, either fixed or scrolling
      if (strLength >= 1) {
        if (textLength < (X_MAX + 1)) {
          // Use fixedText()
          fixedText(text);
          current_state = FIXEDWAITINGLONGSTATE;
        } else {
          // Use scrollText()
          current_state = SCROLLWRITINGSTATE;
          end_pos = 0 - textLength;
          x_pos = X_MAX;
        }
        // Update times
        previousMillis = currentMillis;
      } else {
        // No text on this line to print. Procede to next line. Same state.
        nextLine();
      }
      break;
    case SCROLLWRITINGSTATE:
      // Write one scrolling line
      if (x_pos > end_pos) {
        disp.clear();
        drawString(x_pos, 1, text);
        disp.syncDisplays();
        x_pos--;
      } else {
        current_state = SCROLLWAITINGSTATE;
      }
      break;
    case SCROLLWAITINGSTATE:
      // Are we still waiting on the gap delay?
      if (currentMillis - previousMillis > gapTime) {
        // Gap delay complete
        nextLine();
        current_state = INITIALSTATE;
      }
      break;
    case FIXEDWAITINGLONGSTATE:
      // Are we still waiting on the display delay?
      if (currentMillis - previousMillis > displayTime) {
        // Display delay complete
        disp.clear();
        disp.syncDisplays();
        previousMillis = currentMillis;
        current_state = FIXEDWAITINGSHORTSTATE;
      }
      break;
    case FIXEDWAITINGSHORTSTATE:
      // Are we still waiting on the gap delay?
      if (currentMillis - previousMillis > gapTime) {
        // Gap delay complete
        nextLine();
        current_state = INITIALSTATE;
      }
      break;
  }
        
  //get_free_memory();
}

//This is where the lines being displayed on the message board can be updated (or read).
static int testCallback(TinyREST *srv, char *cmd, int len, char **args, void *blind){
  if (strcmp(cmd, cmd_read_string)==0) {
    //read the string
    WiServer.print_P(msgRecvStartText);
    for (int i = 0; i < numLines; i++) {
      if ( strlen(lines[i]) > 1 )
        WiServer.print(i);
        WiServer.print(lines[i]);
        WiServer.print("<br \\>");
      }
    WiServer.print_P(msgRecvEndText);
    return RESPONSE_INLINE_OK;
  } else if (strcmp(cmd, cmd_write_string)==0) {
    //write the string
    if (len == 2)
    {
      lineNum = atoi(args[0]);
      if (lineNum >= 0 && lineNum < maxLineLength)
      {
        if (strlen(args[1]) < maxLineLength)
          strcpy(lines[lineNum], args[1]);
        WiServer.print_P(msgRecvStartText);
        WiServer.print(F("Wrote "));
        WiServer.print(lines[lineNum]);
        WiServer.print(F(" to line "));
        WiServer.print(lineNum);
        WiServer.print_P(msgRecvEndText);
      }
    } else {
      WiServer.print_P(msgRecvText);
    }
    return RESPONSE_INLINE_OK;
  }
  return RESPONSE_OK;
}

void nextLine(){
   if(currentLine < (numLines -1)){
      currentLine++;
   }else{
     currentLine = 0;
   }    
}


// Write a line of static (non-scrolling) text to the display
void fixedText(char* text){
  int y = 1;
  int x = 0;
  disp.clear();
  drawString(x,y,text);
  disp.syncDisplays();
}


// Output a string to the display
void drawString(int x, uint8_t y, char* c){
  for(char i=0; i< strLength; i++){
    drawChar(x, y, c[i]);
    x+=6; // Width of each glyph
  }
}


// Output a single character to the display
void drawChar(int x, int y, char c){
  int dots;
  
  c = getIndex(charLookup, c);
  
  for (char col=0; col< 5; col++) {
    if((x+col+1)>0 && x < X_MAX){ // dont write to the display buffer if the location is out of range
      dots = pgm_read_byte_near(&myfont[c][col]);
      for (char row=0; row < 7; row++) {
        if (dots & (64>>row))       // only 7 rows.
          toolbox.setPixel(x+col, y+row, 1);
        else
          toolbox.setPixel(x+col, y+row, 0);
      }
    }
  }
}

int getIndex(const prog_char* str, char c)
{
  const prog_char* e = strchr_P(str, c);
  if (e) {
    return (int)(e - str);
  }
  else
    return -1;
}

3  Using Arduino / Project Guidance / Re: Yellowjacket + PS2/You LED sign + WiServer = *almost AWESOME* (Out of memory?) on: March 15, 2013, 04:03:52 pm
Okay, getting REALLY close now!!! I refactored the code Pylon pointed out having blocking delays:

Code:
// Update Display
  currentMillis = millis();
 
  //Simple FSM for the display
  switch (current_state)
  {
    case INITIALSTATE:
     
      get_free_memory();
   
      // Update Display
      strLength = strlen(lines[currentLine]); // Number of characters in the string
      textLength = (strLength*6); // Width of string in pixels
 
      strcpy(text, lines[currentLine]);
      //Determine text type, either fixed or scrolling
      if (strLength > 1) {
        if (textLength < (X_MAX + 1)) {
          // Use fixedText()
          fixedText(text);
          current_state = FIXEDWAITINGLONGSTATE;
        } else {
          // Use scrollText()
          scrollText(text);
          current_state = SCROLLWAITINGSTATE;
        }
        // Update times
        previousMillis = currentMillis;
      } else {
        // No text on this line to print. Procede to next line. Same state.
        nextLine();
      }
      break;
    case SCROLLWAITINGSTATE:
      // Are we still waiting on the gap delay?
      if (currentMillis - previousMillis > gapTime) {
        // Gap delay complete
        nextLine();
        current_state = INITIALSTATE;
      }
      break;
    case FIXEDWAITINGLONGSTATE:
      // Are we still waiting on the display delay?
      if (currentMillis - previousMillis > displayTime) {
        // Display delay complete
        disp.clear();
        disp.syncDisplays();
        previousMillis = currentMillis;
        current_state = FIXEDWAITINGSHORTSTATE;
      }
      break;
    case FIXEDWAITINGSHORTSTATE:
      // Are we still waiting on the gap delay?
      if (currentMillis - previousMillis > gapTime) {
        // Gap delay complete
        nextLine();
        current_state = INITIALSTATE;
      }
      break;
  }

So now the webserver will respond, but for some reason if the text is long enough to scroll, then only one of the 3 LED panels actually displays the scrolling text. Static text correctly shows up on all 3 LED panels. Ideas?

[EDIT] - Upon further examination, it appears that everything works correctly as long as the scrollText function isn't used. If the text is long enough to start ScrollText, I lose two of the displays (the leftmost two) and the web server quits responding again. I'm going to start digging into the scrollText code and see if I can figure out what's going on.

[EDIT 2] - Looks like turning the displays shadow buffer to "true" fixed the part where two of the displays quit working. However, the scrolling is still a blocking action and is preventing the web server from responding while active. I need to figure out a way to unblock the scrolling function...
4  Using Arduino / Project Guidance / Re: Yellowjacket + PS2/You LED sign + WiServer = *almost AWESOME* (Out of memory?) on: March 15, 2013, 02:26:08 pm
Thanks Pylon! That makes complete sense. I'll work on refactoring that code right now! I believe that will fix the web server not responding issue.

I'm still worried about the display not fully working though, so I guess that will be next to investigate after this...
5  Using Arduino / Project Guidance / Re: Yellowjacket + PS2/You LED sign + WiServer = *almost AWESOME* (Out of memory!) on: March 15, 2013, 01:51:21 pm
Okay, I've removed all the String instances, and converted as much as I can to PROGMEM as well. After all this optimization, the board is still unable to correctly run both the web server and the display. Using a memory check function I found, I appear to still have anywhere from 200 to 400 bytes free of SRAM, so although I'm near maxed, this should be working.

Strange thing is, if you comment out the "Update Display" part of the loop() function, the web server works. If you keep the code present, then the web server doesn't respond to requests and only one of the three LED panels appears to work. I'm getting closer, but I'm still missing something! Can anyone help??

Code:
/*
*    REST-driven LED Display board
*   
*
*/


// for the wifi:
#include <EEPROM.h>
#include <TinyREST.h>
#include <WiServer.h>
// for the display:
#include <string.h>
#include "MatrixDisplay.h"
#include "DisplayToolbox.h"
#include "font.h"


#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,20}; // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"SSID"}; // max 32 bytes

unsigned char security_type = 3; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"passphrase"}; // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = {};

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------

// Matrix display configuration parameters ----------------------------------------

const int numLines = 1;        // Max number of lines
const int displayTime = 2500;  // Length of time in milliseconds to display each line
const int gapTime = 10;        // Time gap between lines
const int maxLineLength = 50; // Maximum length of a line in characters

char lines[numLines][maxLineLength];
char text[maxLineLength];

int textLength;          // Holds current line length in pixels
int strLength;           // Holds current line length in characters
int currentLine = 0;     // Index of current line

const prog_char defaultText[] PROGMEM = {"Awaiting input..."};
const prog_char msgRecvText[] PROGMEM = {"<html><p>Message Recieved By Server</p></html>"};
const prog_char msgRecvStartText[] PROGMEM = {"<html><p>"};
const prog_char msgRecvEndText[] PROGMEM = {"</p></html>"};

// Character lookup string -- used to map the characters from the keyboard onto the font data array
const prog_char charLookup[] PROGMEM = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*(),-.?></\\|[]_=+:'\"{}";

// Memory test
extern int __bss_end;
extern int *__brkval;


// Macro to make it the initDisplay function a little easier to understand
#define setMaster(dispNum, CSPin) initDisplay(dispNum,CSPin,true)
#define setSlave(dispNum, CSPin) initDisplay(dispNum,CSPin,false)

// Initialize matrix
MatrixDisplay disp(3,16,15, false);
DisplayToolbox toolbox(&disp);

// Prepare boundaries
uint8_t X_MAX = 0;
uint8_t Y_MAX = 0;

// End of matrix display configuration parameters ----------------------------------------

TinyREST rest = TinyREST();
static char cmd_read_string[] = {"string_read"};
static char cmd_write_string[] = {"string_write"};

int lineNum;

// This is our page serving function that generates web pages
boolean sendMyPage(char* URL) {
  return rest.handleURL(URL);
}


void setup() {
  // Initialize WiServer and have it use the sendMyPage function to serve pages
  rest.init();
  rest.addCommand(cmd_read_string, 2, testCallback);
  rest.addCommand(cmd_write_string, 2, testCallback);
  WiServer.init(sendMyPage);
 
  // Enable Serial output and ask WiServer to generate log messages (optional)
  Serial.begin(57600);
  //WiServer.enableVerboseMode(true);
  Serial.println("PROGRAM START");
 
  // Enable matrix display
  for(int i=0; i<numLines; i++){
    strcpy_P(lines[i], defaultText);
  }
 
  // Fetch display bounds
  X_MAX = disp.getDisplayCount() * (disp.getDisplayWidth()-1)+3;
  Y_MAX = disp.getDisplayHeight()-1;
 
  // Prepare displays
  disp.setMaster(0,4);
  disp.setSlave(1,5);
  disp.setSlave(2,6);
}

void loop(){

  // Run WiServer
  WiServer.server_task();
  rest.loop();
 
  // Update Display
  strLength = strlen(lines[currentLine]); // Number of characters in the string
  textLength = (strLength*6); // Width of string in pixels
 
  strcpy(text, lines[currentLine]);
 
  //** Uncommenting this section causes the web server to not respond!
 
//  if(strLength > 1){
//     if(textLength < (X_MAX +1)){
//       fixedText(text);
//       delay(displayTime);
//       disp.clear();
//       disp.syncDisplays();
//       delay(gapTime);
//     }else{
//       scrollText(text);
//       delay(gapTime);
//     }
//   }
//   nextLine();
   
   //get_free_memory();
}

//This is where the lines being displayed on the message board can be updated (or read).
static int testCallback(TinyREST *srv, char *cmd, int len, char **args, void *blind){
  if (strcmp(cmd, cmd_read_string)==0) {
    //read the string
    //To be implemented if there is space.
   WiServer.print_P(msgRecvText);
    return RESPONSE_INLINE_OK;
  } else if (strcmp(cmd, cmd_write_string)==0) {
    //write the string
    if (len == 2)
    {
      lineNum = atoi(args[0]);
      if (lineNum >= 0 && lineNum < maxLineLength)
      {
        strcpy(lines[lineNum], args[1]);
        WiServer.print_P(msgRecvStartText);
        WiServer.print(F("Wrote "));
        WiServer.print(args[1]);
        WiServer.print(F(" to line "));
        WiServer.print(lineNum);
        WiServer.print_P(msgRecvEndText);
      }
    } else {
      WiServer.print_P(msgRecvText);
    }
    return RESPONSE_INLINE_OK;
  }
  return RESPONSE_OK;
}

void nextLine(){
   if(currentLine < (numLines -1)){
      currentLine++;
   }else{
     currentLine = 0;
   }   
}

void scrollText(char* text){
  int y=1;
  int endPos = 0 - textLength;
  int loopCount = 0;
  for(int Xpos = X_MAX; Xpos > endPos; Xpos--){
    loopCount++;
    disp.clear();
    drawString(Xpos,y,text);
    disp.syncDisplays();
  }
}


// Write a line of static (non-scrolling) text to the display
void fixedText(char* text){
  int y = 1;
  int x = 0;
  disp.clear();
  drawString(x,y,text);
  disp.syncDisplays();
}


// Output a string to the display
void drawString(int x, uint8_t y, char* c){
  for(char i=0; i< strLength; i++){
    drawChar(x, y, c[i]);
    x+=6; // Width of each glyph
  }
}


// Output a single character to the display
void drawChar(int x, int y, char c){
  int dots;
 
  c = getIndex(charLookup, c);
 
  for (char col=0; col< 5; col++) {
    if((x+col+1)>0 && x < X_MAX){ // dont write to the display buffer if the location is out of range
      dots = pgm_read_byte_near(&myfont[c][col]);
      for (char row=0; row < 7; row++) {
        if (dots & (64>>row))         // only 7 rows.
          toolbox.setPixel(x+col, y+row, 1);
        else
          toolbox.setPixel(x+col, y+row, 0);
      }
    }
  }
}

int getIndex(const prog_char* str, char c)
{
  const prog_char* e = strchr_P(str, c);
  if (e) {
    return (int)(e - str);
  }
  else
    return -1;
}

// Memory check
int get_free_memory(){
  int free_memory;
  if((int)__brkval == 0)
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
  else
    free_memory = ((int)&free_memory) - ((int)__brkval);
    Serial.println(free_memory);
  return free_memory;
}

6  Using Arduino / Project Guidance / Yellowjacket + PS2/You LED sign + WiServer = *almost AWESOME* (Out of memory?) on: March 10, 2013, 08:39:18 pm
I have a PS2You LED message board that I decided would make a great wall clock/calendar/weather station/etc. and connected it to a Rugged Circuits Yellowjacket. The intent is to update the LED message board over wifi using a simple REST-like interface. After some experimentation, I can get the REST services working over wifi, or I can get the LED message board to update, but I can't seem to do both. This appears to be an issue with the Yellowjacket running out of SRAM while attempting to use both the WiServer library and the DisplayMatrix library at the same time.

I've posted my code below (which could probably be refactored some to decrease the SRAM memory usage) but I suspect that I'm going to need to refactor one or both libraries to get enough free memory to make everything work properly. Can anyone offer any help or suggestions on the best way to approach this? I'm afraid its been a long time since I've had to do any optimization of this type... smiley

Code:
/*
 * A simple sketch that uses WiServer to recieve a web call and update the display
 */
// for the wifi:
#include <EEPROM.h>
#include <TinyREST.h>
#include <WiServer.h>
// for the display:
#include <string.h>
#include "MatrixDisplay.h"
#include "DisplayToolbox.h"
#include "font.h"

#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,20}; // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"TESTSSID"}; // max 32 bytes

unsigned char security_type = 3; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"testpassphrase"}; // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
};

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------

// Matrix display configuration parameters ----------------------------------------

const int numLines = 6;        // Max number of lines
const int displayTime = 2500;  // Length of time in milliseconds to display each line
const int gapTime = 10;        // Time gap between lines
const int maxLineLength = 100; // Maximum length of a line in characters

String textLines[numLines];     // Array of text lines

int textLength;          // Holds current line length in pixels
int strLength;           // Holds current line length in characters
int currentLine = 0;     // Index of current line


char defaultText[numLines][30] = {{"Awaiting input..."}};

// Character lookup string -- used to map the characters from the keyboard onto the font data array
// (This should probably be moved to program memory in some form in the future)
String charLookup  = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*(),-.?></\\|[]_=+:'\"{}";

// Macro to make it the initDisplay function a little easier to understand
#define setMaster(dispNum, CSPin) initDisplay(dispNum,CSPin,true)
#define setSlave(dispNum, CSPin) initDisplay(dispNum,CSPin,false)

// Initialize matrix
//MatrixDisplay disp(3,16,15, true);
//DisplayToolbox toolbox(&disp);

// Prepare boundaries
uint8_t X_MAX = 0;
uint8_t Y_MAX = 0;

#define is_printable(c) (!(c&0x80))  

int line = 0;
const unsigned int MAX_INPUT = 100;

// End of matrix display configuration parameters ----------------------------------------

TinyREST rest = TinyREST();
static char cmd_read_string[] = {"string_read"};
static char cmd_write_string[] = {"string_write"};

// This is our page serving function that generates web pages
boolean sendMyPage(char* URL) {
  
  return rest.handleURL(URL);
  
}


void setup() {
  // Initialize WiServer and have it use the sendMyPage function to serve pages
  rest.init();
  rest.addCommand(cmd_read_string, 2, testCallback);
  rest.addCommand(cmd_write_string, 2, testCallback);
  WiServer.init(sendMyPage);
  
  // Enable Serial output and ask WiServer to generate log messages (optional)
  Serial.begin(57600);
  WiServer.enableVerboseMode(true);
  
  // Enable matrix display
//  for(int i=0; i<numLines; i++){
//    textLines[i] = defaultText[i];
//    Serial.println(defaultText[i]);
//  }  
//
//  // Fetch display bounds
//  X_MAX = disp.getDisplayCount() * (disp.getDisplayWidth()-1)+3;
//  Y_MAX = disp.getDisplayHeight()-1;
//
//  // Prepare displays
//  disp.setMaster(0,4);
//  disp.setSlave(1,5);
//  disp.setSlave(2,6);
}

void loop(){

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

//This is where the lines being displayed on the message board can be updated (or read). To be implemented when memory issues are resolved.
static int testCallback(TinyREST *srv, char *cmd, int len, char **args, void *blind){
  if (strcmp(cmd, cmd_read_string)==0) {
    //read the string
    WiServer.print("<html>");
    WiServer.print("***Pretending to read string!");
    WiServer.print("</html>");
    Serial.println("***Pretending to read string!");
    return RESPONSE_INLINE_OK;
  } else if (strcmp(cmd, cmd_write_string)==0) {
    //write the string
    WiServer.print("<html>");
    WiServer.print("***Pretending to write string!");
    WiServer.print("</html>");
    Serial.println("***Pretending to write string!");
    return RESPONSE_INLINE_OK;
  }
  return RESPONSE_OK;
}
7  Using Arduino / Displays / MatrixDisplay + WiServer = not compatible? on: March 05, 2013, 04:47:04 pm
I have a PC/2/You LED sign that I've wired to a RuggedCircuits Yellowjacket, for the purposes of having a sign that can be updated from any local web browser. The goal is to run a simple webserver on the Yellowjacket that takes REST-like calls to update the LED display. I've been able to successfully run the webserver code, and I've also confirmed that the LED sign works (after moving the two signal pins from 10/11 to 15/16). HOWEVER, as soon as I start to try to use both in the same sketch, the webserver appears to quit working. More specifically, as soon as I add the following line that instantiates the display, the webserver fails to ever connect to my wifi network:
Code:
// Init Matrix
MatrixDisplay disp(3,16,15, false);

I have two thoughts on the culprit: either I'm running out of memory at runtime, or there is something conflicting between the two libraries.

Anyone have any idea what could be causing the conflict? I never receive any errors, but adding this singlar line of code is enough to cause the Yellowjacket to no longer be able to connect to the wifi network nor respond to web requests (obviously).

My test code:
Code:
/*
 * A simple sketch that uses WiServer to serve a web page
 */
// for the wifi:
#include <EEPROM.h>
#include <TinyREST.h>
#include <WiServer.h>
// for the display:
#include <string.h>
#include "MatrixDisplay.h"
#include "DisplayToolbox.h"
#include "font.h"

#define WIRELESS_MODE_INFRA 1
#define WIRELESS_MODE_ADHOC 2

// Wireless configuration parameters ----------------------------------------
unsigned char local_ip[] = {192,168,1,20}; // IP address of WiShield
unsigned char gateway_ip[] = {192,168,1,1}; // router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"Home"}; // max 32 bytes

unsigned char security_type = 3; // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2

// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"password"}; // max 64 characters

// WEP 128-bit keys
// sample HEX keys
prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, // Key 0
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 1
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Key 2
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Key 3
};

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters ----------------------------------------

// Matrix display configuration parameters ----------------------------------------

const int numLines = 6;        // Max number of lines
const int displayTime = 2500;  // Length of time in milliseconds to display each line
const int gapTime = 10;        // Time gap between lines
const int maxLineLength = 100; // Maximum length of a line in characters

String textLines[numLines];     // Array of text lines

int textLength;          // Holds current line length in pixels
int strLength;           // Holds current line length in characters
int currentLine = 0;     // Index of current line


char defaultText[numLines][30] = {{"Awaiting input..."}};

// Character lookup string -- used to map the characters from the keyboard onto the font data array
// (This should probably be moved to program memory in some form in the future)
String charLookup  = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*(),-.?></\\|[]_=+:'\"{}";

// Memory test
extern int __bss_end;
extern int *__brkval;

// Macro to make it the initDisplay function a little easier to understand
#define setMaster(dispNum, CSPin) initDisplay(dispNum,CSPin,true)
#define setSlave(dispNum, CSPin) initDisplay(dispNum,CSPin,false)

// Initialize matrix
//MatrixDisplay disp(3,16,15, true);  // <= Uncommenting this line prevents the Yellowjacket from connecting. :(
//DisplayToolbox toolbox(&disp);

// Prepare boundaries
uint8_t X_MAX = 0;
uint8_t Y_MAX = 0;

#define is_printable(c) (!(c&0x80))   

int line = 0;
const unsigned int MAX_INPUT = 100;

// End of matrix display configuration parameters ----------------------------------------

TinyREST rest = TinyREST();
static char cmd_read_string[] = {"string_read"};
static char cmd_write_string[] = {"string_write"};

// This is our page serving function that generates web pages
boolean sendMyPage(char* URL) {
 
  return rest.handleURL(URL);
 
}


void setup() {
  // Initialize WiServer and have it use the sendMyPage function to serve pages
  rest.init();
  rest.addCommand(cmd_read_string, 2, testCallback);
  rest.addCommand(cmd_write_string, 2, testCallback);
  WiServer.init(sendMyPage);
 
  // Enable Serial output and ask WiServer to generate log messages (optional)
  Serial.begin(57600);
  WiServer.enableVerboseMode(true);
 
  // Enable matrix display
//  for(int i=0; i<numLines; i++){
//    textLines[i] = defaultText[i];
//    Serial.println(defaultText[i]);
//  } 
//
//  // Fetch display bounds
//  X_MAX = disp.getDisplayCount() * (disp.getDisplayWidth()-1)+3;
//  Y_MAX = disp.getDisplayHeight()-1;
//
//  // Prepare displays
//  disp.setMaster(0,4);
//  disp.setSlave(1,5);
//  disp.setSlave(2,6);
}

void loop(){

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

static int testCallback(TinyREST *srv, char *cmd, int len, char **args, void *blind){
  if (strcmp(cmd, cmd_read_string)==0) {
    //read the string
    WiServer.print("<html>");
    WiServer.print("***Pretending to read string!");
    WiServer.print("</html>");
    Serial.println("***Pretending to read string!");
    return RESPONSE_INLINE_OK;
  } else if (strcmp(cmd, cmd_write_string)==0) {
    //write the string
    WiServer.print("<html>");
    WiServer.print("***Pretending to write string!");
    WiServer.print("</html>");
    Serial.println("***Pretending to write string!");
    return RESPONSE_INLINE_OK;
  }
  return RESPONSE_OK;
}
Pages: [1]