Yun Network Message Board Example with Lessons Learned.

Previously, I did a message board using the Yun console connection and a 2 by 16 parallel interface LCD device and the Yun (Code for 2 by 16 LCD based on the Yun - Arduino Yún - Arduino Forum). In the post, I was asked to try the message board without the console.

I got 4 by 20 LCD device using the two wire (I2C) interface and decide to try it. I was successful with no wires involved and using a browser to enter the message .

Here is the HTML/Javascript that is used by OpenWRT Linux server. The HTML/Javascript code goes into a new directory as index.html under the /mnt/sda1/arduino/www directory like all server HTML code.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title>Ardunio Web Message Board</title>
    <script type="text/javascript">	
	 function toShow()
	  {
	   var xmlhttp = new XMLHttpRequest(); //new request object to xfer data
	   var url = "/data/put/dataKey/";
	   objMessage = document.getElementById("aMessage");  //creates object using DOM
	   var message = objMessage.value;  //no need to trim for white space
	   objMessage.value = ""; //clear old message   
	   //now to form string to transfer data to server as a URL
	   url = url + message;
	   xmlhttp.open("POST", url, true); //false is synchronous mode, asynchronous is preferred
       xmlhttp.setRequestHeader("Content-Type","text/plain;charset=UTF-8");
       xmlhttp.send(null); //no data since URL contains data
	   //window.console.log(message); // console.log is for testing
	   //window.console.log(url);
	  }
	</script>
  </head>
  <body>
    <h1 Align=Center>Arduino Web Server</h1>
    <h2 Align=Center>Message Board for Four Lines by Twenty Characters Display</h2>
    <p Align=Center>This displays using networking to display a 80 character message

    on an Arduino Yun with 4 row by 20 column LCD.  Enter the message

    in the text box beyond and use the submit button to transfer the data.
    
There is no need to enter "carriage returns" and text entry stops at 80 characters.</p><hr>
     <P ALIGN=CENTER>Message: <textarea id="aMessage" cols="19" rows="3" maxlength="80"></textarea></P>
     <p ALIGN=CENTER><input type=button VALUE="Send Message" onclick="toShow()"></p>
  </body>
</html>

Here is the Arduino Yun sketch code:

/*

Legal Boiler Plate
web_LCD_yun started 20 Feb. 2015 by JustGreg under Beerware License
If you use it and see me, then buy me a beer.
This example code is in the public domain without any warranty.

This approach does not use client detection for the display. One
just gets the data and seen any was found.

Finished 21 Feb. It uses 14516 bytes and Global variables are 877 bytes.

*/

// include the library code:
#include <Wire.h> 
/* The Yun uses different pins for the TWI.
   Pin 2 is SDA and not A4 as with Uno
   Pin 3 is SCK and not A5 as with Uno
*/

#include <LiquidCrystal_I2C.h> //version 1.2.1
/* from here: https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
Thank you library developers for this library */

#include <YunServer.h>

/*
Next line is the constructor for LiquidCrystal_I2C library, tells the 
connections used with display module, One needs to check due to manufacturer 
differences
*/
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); 
                   // addr, EN, RW, RS, D4, D5, D6, D7, Backlight, POLARITY
                   
char myData[80]; //buffer for message

/* Listen on default port 5555, the webserver on the Yun
   will forward there all the HTTP requests for us. */
YunServer server;

void setup() 
 {
  // Print a message to the LCD
  lcd.begin(20,4); // initialize the lcd for 20 columns by 4 rows
  lcd.backlight();
  lcd.print("Hello, world!"); //start at column = 0, row =0
  lcd.setCursor(0,1);  //column, row
  lcd.print("Today Arduino rules!");
  lcd.setCursor(0,2);  //column, row
  lcd.print("Some text to display");
  lcd.setCursor(0,3);  //column, row
  lcd.print("More text to display");
  //device and web services setup
  Bridge.begin();
  /* Listen for incoming connection only from localhost
  (no one from the external network could connect) */
  server.listenOnLocalhost();
  server.begin();
 }

void loop() 
 {
  // need to check for new message to display
  int messageSize = Bridge.get("dataKey",myData,80); //return number of char found, 0 to 80
  if (messageSize > 0) //found data
    {
      Bridge.put("dataKey",""); //clear data out to get same data only once
      // got new data!
      lcd.clear(); // cursor at 0 column and 0 row
      int numOfrows = messageSize / 20;
      int remainChars = messageSize % 20;
     for (int i =0; i < messageSize; i++) //i is char # in myData buffer
      {
       int rowNum = i / 20;
       int colNum = i % 20;
       lcd.setCursor(colNum, rowNum);
       lcd.print(myData[i]);
      }
    }
   delay(1000); // Poll every 1 second
  }

This project taught me several lessons. I decide to share them.

The first is if you are unsure or confused about how to do something with an Arduino board, then search the forum. I was able to search the Arduino web site when I had a problem and was able to find the information to fix the problem. Yes, you may have to re-write the search words several times, but, the answer is there.

The second one is two wire interface (I2C) devices are all different. Do not assume they are the same! After trying and failing to get the 20 by 4 display to work using the supplier web page information, which turned out for a older device, I searched the site and found two utilities, I2Cscan (finds the device address) and i2cLCDguesser (determines how the display connects to the I2C module). In finding the i2cLCDguesser, I also found out why the supplier library and several others did not work. The connection information was wrong and hard coded. The referenced library is correct one to use for LCD devices.

The third lesson was in developing the application. I originally want to use the Python "bottle" web server. I did try it with several examples. I found it was like the Ardunio Uno Ethernet server, the HTML code was mixed with the server actions. This makes debugging hard, especially if you are not an expert with HTML. It was far easier to develop the HTML code with a modern browser and associated debug tools. I got the HTML code working after about six hours of effort (see I am not HTML expert :wink: ). The Arduino Yun code took another 8 hours. But, I did know the HTML was correct when developing the Yun code. This is a great help for a non-expert. Please do not take the above as criticism of the Python "bottle" web server. The
Python "bottle" web server is a different approach that probably works great in a different application. I did find it very interesting.

The last lesson was the use of the /data/ page is all on the server side. Initially, I thought I needed to detect the client to get the information. But, after Posting the data, a positive (true) client detection never occurred. It was all on the server and one had to check for the presence of new data.

Yet another good project for the Ultimate Yun Starter Kit for the Internet of things. On to the next project, speaking of the next project, does anyone know of a full keyboard that has the I2C interface. I would like to try to set up a communication system (two Arduino boards with 4 by 20 LCD devices, I2C keyboard, and 2.4 GHz data transceivers). Thank you in advance for any help.

JustGreg:
::::SNIP::::
This project taught me several lessons. I decide to share them.
::::SNIP::::

The last lesson was the use of the /data/ page is all on the server side. Initially, I thought I needed to detect the client to get the information. But, after Posting the data, a positive (true) client detection never occurred. It was all on the server and one had to check for the presence of new data.

::::SNIP::::

@JustGreg,
thanks for posting your code and lessons. I will note this in my documentation.
Could you please extend and clarify this last lesson? It's not clear what you mean when you said,

"a positive (true) client detection never occurred. It was all on the server and one had to check for the presence of new data".

What do you mean when you say "it was all on the server"? and "had to check for (...) new data".

TIA
Jesse

I think he's saying that when you use arduino.local/data/... it's all handled by the Linux side with no interaction from the sketch. It's essentially a remote control version of Bridge.put() and Bridge.get(). The values in the bridge data store just magically changes and it's up to the sketch to poll these values to see if they change. (As a corollary, it also means that two consecutive data puts of the same value won't be seen as a change by the sketch - if you must see every update, use the arduino.local/mailbox or arduino.local/arduino mechanisms.

By "a positive (true) client detection never occurred" it sounds like he was trying to use YunServer.accept() to catch an incoming connection, and return a valid YunClient object. That only happens with an access of the form arduino.local/arduino.

There are several forms of web access that the web server default configuration handles, and they all interact with the sketch in different ways. It's nice to have your choice of methods.

Thank you,ShapeShifter. Your explanation is better than what I would have written. I was trying to use the "YunClient client = server.accept();" to detect the new data. It would never work.

Yes, it appears to me the arduino.local/data/ is on the linux side. The documentation says the data is written to the Linux side memory. The bridge process access the memory locations only when requested by the arduino side code. This may also explain why it takes a bit of time (from other example with measured current value) to get the data. I am no expert in this area. I hope this helps.

@JustGreg,
thanks for your follow up. Your previous comments have additional context.

After reading your response and ShapeShifter's, it appears to me that the entire "Bridge Process", while magical and well done, needs much more documentation. I was up till about 4 this morning looking at various code snippets. As it turns out the source code server for Luci is down. I've posted a message to the mailing list. I'm hopeful about getting more details in the next few days.

Jesse

You are welcome, Jesse. If there is something you or ShapeShifter wish me to try out to help your documentation efforts, then please suggest it. I will give it a try. I can not promise that I will be successful, but, I will give it my best.

I am currently trying to get IDE 1.6.0 working on my Linux system. It works for the Yun, but, I am having problems with Uno USB connections. It is a library dependence issue. For what is proposed for Yun, I will use the version 1.6.0 of the IDE.

I hope this helps.