EtherTen with DMD - Internet Text Display

The Dot Matrix Display (DMD) is a 32x16 array of high-brightness LEDs for visually striking effects. [Product Page]
Snip
Posts: 2
Joined: Wed May 23, 2012 2:22 am

EtherTen with DMD - Internet Text Display

Post by Snip » Wed May 23, 2012 2:40 am

Hi Guys, first time posting in here...

Ok, I am trying to put together a project that will read some text from a website and display it on the DMD.

I am using the project I found here: http://bildr.org/2011/06/arduino-ethernet-client/
and I have mixed the code with the example DMD demo to get the following:

Code: Select all

//ARDUINO 1.0+ ONLY
//ARDUINO 1.0+ ONLY
#include <Ethernet.h>
#include <SPI.h>        //SPI.h must be included as DMD is written by SPI (the IDE complains otherwise)
#include <DMD.h>        //
#include <TimerOne.h>   //
#include "SystemFont5x7.h"
#include "Arial_black_16.h"

//CONFIGURE
byte server[] = { 174,123,231,247 }; //ip Address of the server you will connect to

//Fire up the DMD library as dmd
#define DISPLAYS_ACROSS 1
#define DISPLAYS_DOWN 1
DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);

void ScanDMD()
{ 
  dmd.scanDisplayBySPI();
}

//The location to go to on the server
//make sure to keep HTTP/1.0 at the end, this is telling it what type of file it is
String location = "/~bildr/examples/ethernet/ HTTP/1.0";

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

EthernetClient client;

char inString[32]; // string for incoming serial data
int stringPos = 0; // string index counter
boolean startRead = false; // is reading?

void setup(void){
  Ethernet.begin(mac);
  Serial.begin(9600);
  //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
   Timer1.initialize( 5000 );           //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
   Timer1.attachInterrupt( ScanDMD );   //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()

   //clear/init the DMD pixels held in RAM
   dmd.clearScreen( true );   //true is normal (all pixels off), false is negative (all pixels on)
}

void loop(){
  String pageValue = connectAndRead(); //connect to the server and read the output

  Serial.println(pageValue); //print out the findings.

  delay(1000); //wait 1 sec before connecting again

  byte b;
   
   // 10 x 14 font clock, including demo of OR and NOR modes for pixels so that the flashing colon can be overlayed
   dmd.clearScreen( true );
   dmd.selectFont(Arial_Black_16);
   
   delay( 1000 );

   dmd.drawMarquee("VARIABLE HERE",18,(32*DISPLAYS_ACROSS)-1,0);
   long start=millis();
   long timer=start;
   boolean ret=false;
   while(!ret){
     if ((timer+50) < millis()) {
       ret=dmd.stepMarquee(-1,0);
       timer=millis();
     }
  }   
}

String connectAndRead(){
  //connect to the server

  Serial.println("connecting...");

  //port 80 is typical of a www page
  if (client.connect(server, 80)) {
    Serial.println("connected");
    client.print("GET ");
    client.println(location);
    client.println();

    //Connected - Read the page
    return readPage(); //go and read the output

  }else{
    return "connection failed";
  }

}

String readPage(){
  //read the page, and capture & return everything between '<' and '>'

  stringPos = 0;
  memset( &inString, 0, 32 ); //clear inString memory

  while(true){

    if (client.available()) {
      char c = client.read();

      if (c == '<' ) { //'<' is our begining character
        startRead = true; //Ready to start reading the part 
      }else if(startRead){

        if(c != '>'){ //'>' is our ending character
          inString[stringPos] = c;
          stringPos ++;
        }else{
          //got what we need here! We can disconnect now
          startRead = false;
          client.stop();
          client.flush();
          Serial.println("disconnecting.");
          return inString;

        }

      }
    }

  }

}
The problem I have is that I can not get the text received from the site, $pageValue, to be displayed using the "dmd.drawMarquee("VARIABLE HERE",19,(32*DISPLAYS_ACROSS)-1,0);".

How can I get the variable text to be displayed on the screen?

Any help would be much appreciated.

Alex

User avatar
Simon
Posts: 25
Joined: Wed May 02, 2012 2:40 am

Re: EtherTen with DMD - Internet Text Display

Post by Simon » Wed May 23, 2012 4:21 am

The DMD library doesn't support passing in a String object for the marquee text, so you have to convert it to a character array first:

Code: Select all

    char marqueeString[18];
    pageValue.getBytes(marqueeString, 18);
    dmd.drawMarquee(marqueeString,18,(32*DISPLAYS_ACROSS)-1,0);
I'm assuming the data you're reading is at most 18 bytes long, since that's what you're asking the DMD to display. Adjust as necessary ;)

baldgeek
Posts: 9
Joined: Tue Apr 03, 2012 7:29 pm

Re: EtherTen with DMD - Internet Text Display

Post by baldgeek » Fri May 25, 2012 4:09 am

Wow. Talk about amazing timing......

I have been struggling to get pretty much this very thing going for a while... never would have guessed what the problem was.

I just cant see how to do the conversion you mention in my code.....

Code: Select all

#include <SPI.h>        
#include <DMD.h>        
#include <TimerOne.h>   
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>         
#include "SystemFont5x7.h"
#include "Arial_black_16.h"

//Fire up the DMD library as dmd
#define DISPLAYS_ACROSS 4
#define DISPLAYS_DOWN 1
DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);
// Enter a MAC address and IP address for your controller below.
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 77);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

/*--------------------------------------------------------------------------------------
  Interrupt handler for Timer1 (TimerOne) driven DMD refresh scanning, this gets
  called at the period set in Timer1.initialize();
--------------------------------------------------------------------------------------*/
void ScanDMD()
{ 
  dmd.scanDisplayBySPI();
}

/*--------------------------------------------------------------------------------------
  setup
  Called by the Arduino architecture before the main loop begins
--------------------------------------------------------------------------------------*/
void setup()
{

   //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
   Timer1.initialize( 5000 );           //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
   Timer1.attachInterrupt( ScanDMD );   //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()

   //clear/init the DMD pixels held in RAM
   dmd.clearScreen( true );   //true is normal (all pixels off), false is negative (all pixels on)
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);
  Serial.begin(9600);
}

void loop(void)
{
    // if there is data, read the packet.
    int packetSize = Udp.parsePacket();
      if(packetSize) //Get the size for the dmd
      {
    // read the packet into packetBufffer and spit out so we can sanity check.
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

      }
     dmd.drawMarquee(packetBuffer,packetSize,(32*DISPLAYS_ACROSS)-1,0);   
   long start=millis();
   long timer=start;
   boolean ret=false;
   while(!ret){
     if ((timer+2) < millis()) {
       ret=dmd.stepMarquee(-1,0);
       timer=millis();
     }
   }
  delay(200);   
}
I can see where it needs to happen, but the 'getbytes' command you mention... I cant get it working in the section it should. (Note, I have taken out all my attempts at getting it working here for clarity).

Thanks for your input.
(Oh, and if you have any thoughts on how to do this any differently/more cleanly/just better, please let me know).

Cheers,

Ben.

User avatar
Simon
Posts: 25
Joined: Wed May 02, 2012 2:40 am

Re: EtherTen with DMD - Internet Text Display

Post by Simon » Fri May 25, 2012 9:17 am

Baldgeek,

Your packetBuffer is already a char array, so you don't need (can't) call getBytes on it. You only need to do that if your buffer is a String object.

I can't immediately see why your code won't work, but I haven't run it up. A couple of suggestions though:

* If your packetSize is zero for some reason, you'll still try to write packetBuffer to the DMD. I'd put the drawMarquee() call and the scroll loop inside your if (packetSize) statement.

* I'd consider changing though is your delay between calling dmd.stepMarquee - 2ms is not very long per pixel; I've used 20 or 30ms with good effect.

Have you isolated / tested the DMD from the Ethernet code? That is, rather than read your packetBuffer from the network fill it with some static string and make sure the DMD works first? I have to assume your Serial.println() is outputting the string received properly..?

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: EtherTen with DMD - Internet Text Display

Post by Aussie_Wombat » Fri May 25, 2012 11:07 am

@ Snip
Simons code:
Simon wrote:The DMD library doesn't support passing in a String object for the marquee text, so you have to convert it to a character array first:

Code: Select all

    char marqueeString[18];
    pageValue.getBytes(marqueeString, 18);
    dmd.drawMarquee(marqueeString,18,(32*DISPLAYS_ACROSS)-1,0);
I'm assuming the data you're reading is at most 18 bytes long, since that's what you're asking the DMD to display. Adjust as necessary ;)
I changed the "getBytes" to "toCharArray" and a few other minor code changes for further expansion.

Code: Select all

    char marqueeString[256];
    int myTextLength = pageValue.length();
    pageValue.toCharArray(marqueeString, myTextLength+1);
    dmd.drawMarquee(marqueeString,myTextLength,(32*DISPLAYS_ACROSS)-1,0);
I also changed the code

Code: Select all

char inString[255]; // string for incoming serial data
and

Code: Select all

  memset( &inString, 0, 255 ); //clear inString memory
The DMD then displayed the text "connection failed".

I added the code

Code: Select all

  Serial.println(Ethernet.localIP()); //print out the findings.
just after the Ethernet.begin(mac); line

The serial output returned 0.0.0.0

I set the ip maually for my network..
byte ip[] = {10,1,1,11};
and changed the Ethernet.begin() line to

Code: Select all

    Ethernet.begin(mac , ip );
  delay(3000); 
the delay was for the wiznet chip to initialise..

The serial then returned 10.1.1.11 and my etherten connected to the php page and read in the random 6 digits and displayed them on the DMD, followed by a comma. The only problem was that on the next loop of the code, it returned 0.0.0.0 again.

I changed the server ip to my home account and the location to a folder and html page.

Code: Select all

String location = "/XXuserXX/test/test.html HTTP/1.0";
I enclosed some text (about 45 characters) in the "<" and ">" characters, saved it to the test.html page and reset the etherten.. It connected and displayed the text on the DMD, but again only once.

I moved the Ethernet.begin(mac,ip); code to the void loop(); so that it ran every loop, and the etherten connected and read the page multiple times. BUT then all of a sudden, the serial returned the ip as 0.0.0.0 and it failed again.. If I reset the etherten , sometimes it works, and sometimes it doesn't... If I remove the usb(power) then start it again, it reads from 1 to 10 loops, then again loses the ip...

@ baldgeek haven't had a chance to look at your UDP code...

Hope this helps

Dennis

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: EtherTen with DMD - Internet Text Display

Post by Aussie_Wombat » Fri May 25, 2012 1:52 pm

@ Baldgeek

I changed your code...

Firstly you had to select the font..

dmd.selectFont(Arial_Black_16);

and then I put the UDP fetch code into a routine..

I changed the ip for my network....and the max UDP buffer to 256

again I found that the etherten would lose the ip number after sending data over the SPI bus. I assume that the ethernet chip is being corrupted by the spi data sent by the drawMarquee routine...

If I leave the code running with NO UDP input then the IP stays as set, but the moment I send some UDP data, and it is displayed on the DMD then the ip is lost....
I tried to turn off pin D10 while the DMD drawMarquee code was running and then turn it on again for the UDP/ethernet functions but it does not output to the DMD...

the code is as follows....for one DMD panel (Only have One)

Code: Select all



#include <SPI.h>        
#include <DMD.h>        
#include <TimerOne.h>   
#include <SPI.h>         
#include <Ethernet.h>
#include <EthernetUdp.h>         
#include "SystemFont5x7.h"
#include "Arial_black_16.h"

//Fire up the DMD library as dmd
#define DISPLAYS_ACROSS 1
#define DISPLAYS_DOWN 1
DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10, 1, 1, 11);

unsigned int localPort = 8888;      // local port to listen on
#define UDP_TX_PACKET_MAX_SIZE 256
// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void ScanDMD()
{ 
  dmd.scanDisplayBySPI();
}
String oldText;

void setup() {
     //initialize TimerOne's interrupt/CPU usage used to scan and refresh the display
   Timer1.initialize( 5000 );           //period in microseconds to call ScanDMD. Anything longer than 5000 (5ms) and you can see flicker.
   Timer1.attachInterrupt( ScanDMD );   //attach the Timer1 interrupt to ScanDMD which goes to dmd.scanDisplayBySPI()

   //clear/init the DMD pixels held in RAM
   dmd.clearScreen( true );   //true is normal (all pixels off), false is negative (all pixels on)

  // start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  delay(3000);
  Udp.begin(localPort);

  Serial.begin(9600);

}

void loop() {
        Serial.println(Ethernet.localIP()); //print out the findings.

  
  String displaytext = getUdpCharacters();
        Serial.println("returned data"); //print out the findings.
//        if (displaytext == ""){ displaytext = oldText;}
        Serial.println(displaytext); //print out the findings.
    dmd.selectFont(Arial_Black_16);
digitalWrite(10,HIGH); 
    char marqueeString[256];
    int myTextLength = displaytext.length();
    displaytext.toCharArray(marqueeString, myTextLength+1);
    
    dmd.drawMarquee(marqueeString,myTextLength,(32*DISPLAYS_ACROSS)-1,0);
    long start=millis();
   long timer=start;
   boolean ret=false;
   while(!ret){
     if ((timer+30) < millis()) {
       ret=dmd.stepMarquee(-1,0);
       timer=millis();
     }
   }
 //  oldText = displaytext;
 digitalWrite(10,LOW);
  delay(2000);
  
}

String getUdpCharacters() {
  // if there's data available, read a packet
  int packetSize = Udp.parsePacket();
  if(packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
  String Mytext = String(packetBuffer);
  Mytext = Mytext.substring(0,packetSize);
  return Mytext;
}

Cheers Dennis

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: EtherTen with DMD - Internet Text Display

Post by Aussie_Wombat » Sat May 26, 2012 9:15 am

Hi

Seems the problem with my ip was power related..

I was running the etherten from usb power only. It was obviously enough for just one DMD panel, but with the Ethernet connection, it was not getting enough..

My BAD...

Plugged in a power pack and voila , the ip is not being reset...to 0.0.0.0

now works consistently on both webclient and UDP

Cheers Dennis

User avatar
Simon
Posts: 25
Joined: Wed May 02, 2012 2:40 am

Re: EtherTen with DMD - Internet Text Display

Post by Simon » Sun May 27, 2012 5:20 am

*smacks head*

Yes, I have the same problem! :roll: I have two DMDs which work fine when powered only via the USB, but as soon as I try and bring up the ethernet the whole thing goes south. Obviously the Wiznet chip and DMDs draw too much power for the little 500mA USB supply to manage.

Aussie_Wombat
Posts: 51
Joined: Tue May 22, 2012 12:52 pm
Location: Adelaide, South Australia

Re: EtherTen with DMD - Internet Text Display

Post by Aussie_Wombat » Sun May 27, 2012 7:16 am

Smacks head twice

I just bought another 2 DMD's and connected them up to the powerpack, and they displayed, but lost the ip again when I sent the UDP string...

Then (bangs head multiple times) I inadvertently connected the 3 DMD's to a 12v 5A psu, and fritzed two of them... Now only one works, and luckily the etherten works ok....

Damn, Damn, Damn.
I wonder why the middle one still works....?

Cheers Dennis

baldgeek
Posts: 9
Joined: Tue Apr 03, 2012 7:29 pm

Re: EtherTen with DMD - Internet Text Display

Post by baldgeek » Mon May 28, 2012 10:33 pm

@ Aussie_Wombat

Dennis and Simon, thanks so very much for your assistance, we got it all up and running!!!!!

Now that we have it up and running, I have it connected to my home automation system.
Now I can scroll air temperature and any device data that is in the system.
Soon we will have Tweets showing up and user entered messaged from a yet-to-built web page.
This photo from my mobile phone shows the temperature of my allsky video camera scrolling past.... Just one of about 5 data points I set up in about 30 seconds this morning.

Image

Its funny now, but the last problem I have is that the web cam I have looking at the sign (so people can see their messages as they enter them live via the webpage) is over whelmed by the brightness of the sign!! (Nice problem to have?)

So to conclude.... If you are simply looking for a UDP to dmd interface, the code above works out of the box! What goes in, comes out. Simple!

Dennis, you beat me to the solution with your IP address resetting. Soon as I read it, I knew what the problem was because some one else mentioned much the same issue here on the dmd forums (I had read every single post trying to get my code working).
Im using an old Dell computer power supply as my 5v source. Alls I had to do was short out the grey and green wires and away it went. No load resister needed for my supply. Lucky I guess.

This was my first every Arduino project. Clearly I bit way more off than I could chew, thanks to Freetronics for all their help in making this site (and the dmd!).

Cheers,

Ben.

Post Reply

Who is online

Users browsing this forum: No registered users and 6 guests