Narrow Casting public display's with master-slave over Ethernet

About: I'm going to make a Narrow casting Solution that shows a digital clock and a scrolling message on LCD-screens.

Why: I the firm I work, we need digital clocks and messages shown in different places. (could be useful in schools too)

Before: I already have made something similar with a PC running a custom program in adobe air. The screens are connected the computer with a vga splitter and a vga over Cat 5. This works, but the vga-splitter and vga-to-cat5 are expensive.

How: Now this is the interesting part XD

What we need is at least 1 arduino being the master and 1 or more being the slaves.

Master Arduino:

  • webserver where you can submit your text.
  • sendprotocol for sending your message to the slave arduino's

Slave Arduino's:

  • show time (hh:mm:ss)
  • show scrolling message

needed hardware:
master: arduino, Ethernet Shield, realtime clock
slave(s): arduino, Ethernet Shield, realtime clock, output display (I would use MicroVGA to show on 19" LCD screen)

(a cry) for help: Are there people out there willing to help making this project?

Now the first thing to do, is making an arduino sending an message to other arduino's which will than show that message.

Thinking of http://arduino.cc/en/Tutorial/UDPSendReceiveString

The next thing will be making a webinterface where you can submit your message and have it saved. (maybe on SD)

We also need multiple messages and time based messages

You state that you need an Arduino for master,

Why not using a standard Apache server as master, gives you more things like access control, automated texts (fetched with PHP from whereever) etc

The client can be a modified version of the standard webclient - http://arduino.cc/en/Tutorial/WebClient - combined with a Serial LCD like below

(code compiles but not tested)

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

// NETWORK VARS
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0x00};  // must be different for each sketch
byte ip[] = { 192,168,1,177 };
byte server[] = { 173,194,33,104 }; // your webserver here
Client client(server, 80);

// TIMING VARS
unsigned long lastTime = 0;
unsigned long timeOut = 10000L; 

//
void setup() 
{
  Ethernet.begin(mac, ip);
  Serial.begin(19200);
  delay(1000);
  Serial.println("NarrowCast 0.1 ...");
}

//
void loop()
{
  if (millis() - lastTime > timeOut ) 
  {
    lastTime = millis();
    refresh();
  }
}


void refresh()
{
  if (client.connect()) 
  {
    client.println("GET /messageOfTheDay.txt HTTP/1.0");
    client.println();
  }

  delay(1000); // 

  while (client.available()) 
  {
    char c = client.read();
    Serial.print(c);
  }

  if (!client.connected()) 
  {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }
}

I would think that the Master Arduino would need to run as a server, accepting two kinds of requests. One is a request to serve up the page that allows defining the message. It needs to handle the Submit action on that page. This request would come from a browser on a PC.

The other is a request for the message to display. These requests would come from the Arduinos (running client software) that are actually supposed to display the message. The request could contain a time that the last new message was returned. If the current message is still the same, just return a code to indicate that the client should continue showing the old message. Otherwise return a different code and the message. The client would then record when the message was received.

@robtillaart

Why not using a standard Apache server as master

I know this a good solution too, but I want to make a solution that doesn't need a computer, so totally stand alone.
But we could make the master arduino with webserver and txt files written to SD

@PaulS
In our other solution (using adobe air) We have been thinking about the difference between: requesting and sending. Now in our opinion it would be beter to use the broadcast method, thus sending, which means the slave has to listen for broadcasts.

clicking the submit button would therefore broadcast the message and save it to EEPROM (or SD)

@robtillaart and @PaulS Now that I think of it. Making a webserver where you can submit text, that is written in a .txt file written on SD, isn't that hard to make (I think). The same webserver could feed the txt to slaves requesting. All very good, but what if you have multiple messages in multiple groups, like this:

GROUP 1 : slave-ip1 : slave-ip2 : slave-ip3 : slave-ip4 : slave-ip5
GROUP 2 : slave-ip1 : slave-ip4
GROUP 3 : slave-ip4 : slave-ip5

message 1 : text : Good morning : group 1 : mo tu we th fr : 8h30 till 9h30
message 2 : signal : group 2 : mo tu we th fr : 07h00
message 2 : signal : group 2 : mo tu we th fr : 09h00
message 3 : signal : group 2 : mo tu we th fr : 09h15
message 4 : signal : group 2 : mo tu we th fr : 12h00
message 5 : signal : group 2 : mo tu we th fr : 12h30
message 6 : signal : group 2 : mo tu we th : 16h00
message 7 : signal : group 2 : fr : 15h15
message 8 : text : Nice evening : group 1 : mo tu we th : 15h15 till 16h00
message 9 : text : Nice weekend : group 1 : fr : 15h15 till 16h00
message 10 : text : Don't forget your papers : group 3 : th : 7h00 till 15h30
message 11 : text : Don't forget drivers licence : fr : group 1 : 7h00 till 19h00

conclusion: sticking to broadcast (for now)

I know this a good solution too, but I want to make a solution that doesn't need a computer

How will you define the message(s) to be shown.

Now in our opinion it would be beter to use the broadcast method, thus sending, which means the slave has to listen for broadcasts.

Why do you think this is better?

All very good, but what if you have multiple messages in multiple groups, like this:

This is why I don't think that broadcasting is a good idea. As I client, I'm only interest in what I am supposed to do. I don't want to have to listen to every message, and determine if it was meant for me. The server should only tell me what I need to do.

Some thoughts,

use fixed iP addresses, following structure

groups.TXT := { IP, groupnr }*

  • 2 bytes IP address - last 2 bytes sufficient?
  • byte groupnr

groupnr.TXT := { byte days, start, end, message, action } * // message or action is blank not both

  • byte days; 1-7
  • 2 bytes indicate timestart (= 2 second precision) - one byte => 10 minute precision e.g 173 == 17:30
  • 2 bytes indicate timeend
  • byte[16][2] message = string
  • byte action = up to 255 actions can be defined.

quotes.txt

  • file with quotes

setup()
{
Server has a RTC for timekeeping.
When the server starts the groups.txt file is read into memory: byte groups[50][3]; array is as big as # groups. 50 groups is assumption
A listening server is started.
}

loop()
{
When a request comes in the IP address is converted to groupnr,
the appropiate file is opened, and scanned through sequentially to find a 'matching record'
if no matching record can be found a random quote is fetched from the quotes.txt
the message is send back to the requestor . { time, string } // time is included to "sync slaves"
}

if memory permits one can store the records from groupnr.txt in memory too. (MEGA?)

2 cents,
Rob

@robtillaart and @PaulS thanks for your input so far. I really was convinced that "listening" would be better than "asking", but you both made me reconsider.

Now for the Slave Arduino's: They really have to be as simple as possible. Setting them up once (IP, Mask, SERVERIP, but more than that).

I would use the Master Arduino's webinterface to setup: slave unit's (name, ip) and slave groups (name). This way you can put Slaves into different groups without having to change anything on the Slave. (Imaging your slave hanging 5m above the ground together with an 23" inch LCD screen)

@PaulS

How will you define the message(s) to be shown.

this should be Slave dependent end thus a part of the Slave's configuration. (the output client could be a simple 16x2 LCD, LED, VGA, maybe twitter)

@robtillaart indeed there would be a difference in message and action (this could sound a buzzer, telling people it's lunch time)

From now on:

  • I will use MASTER as referring to the Arduino that has the webinterface, group setup and the message "database" and sending messages { byte days, start, end, message, action }
  • I will use SLAVE as referring to the Arduinos that receive messages and do something with it. (display time, txt, sound a buzzer, ...)
  • I will no longer use the word "broadcast", but "sending" and "receiving".

I would use the Master Arduino's webinterface to setup: slave unit's (name, ip)

The web page that the Arduino serves up will have a submit button. Any form fields on the page, along with their contents, will be part of the request sent back to the server for processing. This is useful for defining the message that a slave will be sent, and any time data, etc.

But it is useless for configuring the slaves. The slaves have to pull data from the server. To do that, they need to have an IP address already. Presumably, though, you will have the slave Arduino in hand to load the sketch on it, before sticking up out of reach.

@PaulS

But it is useless for configuring the slaves. The slaves have to pull data from the server. To do that, they need to have an IP address already. Presumably, though, you will have the slave Arduino in hand to load the sketch on it, before sticking up out of reach.

you are right about that and it is what I meant:

  • one time configuration for the slaves (ip, mask, serverip) when you are building them.
  • but the master will decide what slave is in which group, and thus receiving what message.

(maybe I didn't wrote this in a correct way, And now that I see, I didn't)

I would use the Master Arduino's webinterface to setup: slave unit's (name, ip) and slave groups (name)

I meant: One would put the Slave IP in a list through the masters webinterface, so that the master knows what slave exist. (real IP setup is on the slave itself)

Now for the Slave Arduino's: They really have to be as simple as possible.

When a slave asks for new information both the server and the slave are relative simple. See my slave code posted earlier, that is about as simple as it can get (if HTTP based).

How many lines has the 23" LCD screen? VGA shield - http://www.arduino.cc/playground/Main/MicroVGA - ????

Problem with the server is that you need to listen for slaves (99% time) and to updates. The Arduino can only listen to one port simultaneously afaik. That's why I proposed a "real" webserver in the first place.

An alternative is to have 2 Arduino's work together as server, one for the updates, one for the slaves....

One would put the Slave IP in a list through the masters webinterface, so that the master knows what slave exist.

And, presumably, what group it belongs to.

The slave (client, really) then would send its IP to the server, so the server can decide what group it is in, and, therefore, what to send back to it.

@PaulS

And, presumably, what group it belongs to.

this is true and correct :wink:

@robtillaart

How many lines has the 23" LCD screen? VGA shield - http://www.arduino.cc/playground/Main/MicroVGA - ????

This is not a problem, I already have 23" monitors running in low res (800x600)

@PaulS and @robtillaart

Problem with the server is that you need to listen for slaves (99% time) and to updates. The Arduino can only listen to one port simultaneously afaik.

This is why I initially would have turned things around: Master sends when certain time has been reached and Slave listens the whole time. This way the SLAVE has to listen 99% (and display 1%) and the master stays free for updates.

@robtillaart

When a slave asks for new information both the server and the slave are relative simple. See my slave code posted earlier, that is about as simple as it can get (if HTTP based).

Maybe your idea can be used for listening and receiving too. Instead the Slave waits on a question from the master like this:

MASTER: "IP-1, are you listing"
SLAVE-1: "yes, what do you have for me"
MASTER: "TXT, Hello world"
SLAVE-1: "thanks, I'll be displaying that"

MASTER: "IP-2, are you listing"
SLAVE-2: "yes, what do you have for me"
MASTER: "SIGNAL, 1"
SLAVE-2: "thanks, I'll put pin 1 high" (this should be configured into the client, could be anything)

some thoughts

I'll stick to the master sends principle (see above):

SLAVE you shall listen to your MASTER and not ask questions :smiley:

I'll also have been thinking about the scheduling of jobs. Two options:

  • Master does the scheduling and sends the messages to the according slaves when a certain day,time,hour has been reached. Lots of sending. (not good if one should use SMS/GPRS for sending to slave), but you only need 1 RTC
  • Slave does the scheduling and thus the master only sends the messages to the according slaves when someone submits the form on the master's webpage. less sending (only when the form changes). This way you'll send a message to a "billboard" once an leave it like that.

I think the latter is better (slaves are more independent, but the message will contain more data)

so from now on I will use the word "MESSAGE" for the data being send by the master to the slave containing:
{startbit, if it is TXT or SIGNAL, days it should run like mo-tu-we-th-fr-sa-su, start hour, stop hour, the text or pin to toggle, endbit}

so {1,1,1101100,0700,1600,This is the text the display should scroll,0}
reads like {startbit, job is text, mo tu - th fr - -, start at 07h00, stop at 16h00, "This is the text the display should scroll", endbit}

and {1,2,0010011,1601,-,5,0}
reads like {startbit, job is signal, - - we - - sa su, run at 16h01, - , toggle pin 5, endbit} (stop time is not needed, just schedule one)

maybe it's better not to use startbit and endbit.

oh and I bought some Arduino Ethernet w/o PoE module in the arduino store (still need RTC modules and microvga)

As the commands ar not so large one could send the schedule for a slave only once per day. When GPRS is involved consider a local (copy of the ) master.

An advantage of server push is that you can "post" near real time (emergency) information without the overhead of too frequent polling.

@robtillaart

As the commands ar not so large one could send the schedule for a slave only once per day.

true, but if a schedule is only send when it has been changed, you even have less sending and you still have near real time (emergency) information. of course when you are going to use your master to send a message in case of an event (pin 1 gets high), you'll need a different kind of master. But still with the current concept,one could use several masters: one for scheduled events and one (or more) for sensor events. For now I will stick to a Scheduled Master.

an example I could think of:

If a doorbell is pressed, the displays show the text: "someone is waiting at the counter"
or if an emergency button is pressed: sound the alarm en show the text: "evacuate immediately"

This is how the web interface could look on the Master aruino:

Now First thing I'll do is buidling the dummy website, but I'll need help on the part where I need to get to posted data when someone hits Submit.

When you hit submit you'll get something like this in the addressbar:

JB=1&on=1&JT=1&MO=1&TU=1&WE=1&SH=07&SM=25&EH=23&EM=15&PN=1&TX=Hello+World

and it means: JoB1 - active - Job Type = txt - DOTW: Mo th we - start hour 07h15 - end hour 23h25 - Text: "Hello World"