Wednesday, 29 January 2014

mbed controlling a 4D Systems uLCD-43PCT and four LEDS

Hi, I have been playing with the Mbed Microcontroller and the 4D Systems Capacitive 4.3' touchscreen.  In order to familiarise myself with the nuances of the system and because I was asked by a reader of the blog if something was possible....So here we go - this is an example of how to use the 4D systems touch screen to turn four leds on and off.  To keep things simple I am using the four LEDS already present on the Mbed LPC1768 however any LEDS connected to any pins could be used.

So here is the schematic - I'm a great believer in schematics!


I then loaded up 4D Systems graphical development environment - Workshop 4 ready to develop the touchscreen display:


Next to start a completely new project I clicked on the appropriate 'Create a new Project Button'  When presented with the following screen I scrolled down to the appropriate display type - in my case a 4.3 inch capacitive touch screen.  I chose the landscape non reversed orientation because I'm lazy and haven't really decided how I am going to mount the display, all possible permutations of orienting the display are catered for.


Click next when you are ready to continue and the following choose your development environment screen is displayed - Lets choose Visi-Genie because its the most simple and quick to use; I can't stress how good and easy this development environment is!!


The next screen displayed is the workshop for graphical development environment.  On the left side of the screen is what is referred to in the manual as the 'WYSIWYG' of the touch screen.  What you see is what you get - quite literally.  On the right side of the screen are all of the attributes available for the graphical screen objects that you as the designer may place on the WYSIWYG screen:


As I'm doing an example of lighting some external LEDS with some buttons lets add some button objects:

Click on the 'Buttons' tab and then on the fancy buttons icon ( icon with a spanner on an orange background) :-


Next click on the WYSIWYG touch screen to place a 'fancy button' - it will automatically be called winButton0:


On the right side of the screen the 'object inspector' will show all of the pertinent attributes for the winButton0 object.  Lets modify the button so that it is no longer a momentary button and give it a better label than winButton0 and lets also have the display show when the button has been actuated 'On' and 'Off':

Make sure the properties tab is selected

Click on the caption field and change it from winButton0 to something more appropriate - I chose LED 1

Click on the momentary field and change it from 'Yes' to 'No'

Expand the 'StatusWhenOff' field and change the BGcolor to Green and the caption to 'Off' or whatever you like

Expand the 'StatusWhenOn' field and change the BGcolor to Red and the caption to 'On' or whatever you like


You might notice that the WYSIWYG display updates the winButton0 object with your changes...and displays the correct caption and shows the button in 'Off' state.

Next click on the Digits tab and select a userLed object and then click on the WYSIWYG screen:


Update the object attributes for the userLed0 object so that it shines blue on activation - you could choose any colour you liked however the LEDS on the Mbed are blue so I thought it should match!

Once you have done all of that which should only take about five minutes we can then get on with the interactive part of the display control.  What we want to do is have the display send a message to the host microcontroller when the button state changes from 'off' to 'on'.  At the same time we would like to update the userLed0 object on the display from 'off' to 'on' so that the display userLed0 object matches the Mbed LED.  So what we are going to do is use the host microcontroller (Mbed) to poll for an event concerning the winButton objects.  If the winButton Objects report a message then we know that a button has been pressed and it's state will have changed from Off to On.  All we then have to do is get the host micro to send a message to the display telling the virtual LED to change state also and at the same time turn the corresponding actual LED on.

The way this is achieved is to click on the winButton0 object on the WYSIWYG screen and then click on the events tab and then click on the onChanged field.  There should be three options - Report Message, Form0 and userLed0Set - choose ReportMessage and click ok.




As there are four LEDS on the Mbed LPC1768 I repeated this process three more times so that there are four button objects and four virtual LED objects.  All the winButton objects need to be set up to respond on touch to light the corresponding virtual LED and report a message when their state changes.

This is what you should see now if you are ready for compiling and sending to the display:


Now is the time to save your project and ensure all settings are correct.  Save the project as something sensible - I called mine mbedTest but it can be called anything you like.  Click on the comms tab and ensure that your display is connected and the COM port for controlling the display is present. Next click on the project tab - Set the appropriate COM port speed for your project.  In this case speed is not an issue so I chose 9600 baud:


Now its time to upload our touchscreen layout to the display.  Click on the home tab and then click on the 'Build Copy Load' icon.  The design will be compiled and uploaded to the display.  You will be prompted to copy the files to the microSD also.  Once complete remove the microSD card from the reader and put it into the display.  You should be presented with your design on the display and when you touch the buttons they should respond appropriately  - <BIG GRIN>

That should have taken about ten minutes - it probably took longer to read all of this text, it certainly takes me longer to type it!

Now we are on to coding the firmware for Mbed LPC1768 which I am using as the host microcontroller.
Load up and log into the online compiler for the Mbed  in the browser of your choice:

Then start a new program using the blinky LED template, call the program something sensible.


Next import the library files mbed_genie.cpp and mbed_genie.h.  These are the library files which tell the mbed how to control the 4D systems touchscreen display.  Finally paste in the following code:

#include "mbed.h"
#include "mbed_genie.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

bool winButton0Status = false; //holds the "status" of winButton0 object.
bool userLed0Status = false;   //hold the "status" of userLed0 object.

bool winButton1Status = false; //holds the "status" of winButton1 object.
bool userLed1Status = false;   //hold the "status" of userLed1 object.

bool winButton2Status = false; //holds the "status" of winButton2 object.
bool userLed2Status = false;   //hold the "status" of userLed2 object.

bool winButton3Status = false; //holds the "status" of winButton3 object.
bool userLed3Status = false;   //hold the "status" of userLed3 object.


//Event handler for the 4d Systems display
void myGenieEventHandler(void)
{
    genieFrame Event;
    genieDequeueEvent(&Event);

    if(Event.reportObject.cmd == GENIE_REPORT_EVENT) {

        // If the Reported Message was from winbutton0 and userLed0 is off

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
            if ((Event.reportObject.index == 0) && (userLed0Status==false)) {
                printf("LED1 High \r\n");
                wait(0.1);
                winButton0Status=true;
            }
        }

        // If the Reported Message was from winbutton0 and userLed0 is on

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
            if ((Event.reportObject.index == 0) && (userLed0Status == true)) {
                printf("LED1 Low \r\n");
                wait(0.1);
                winButton0Status=false;
            }
        }

        // If the Reported Message was from winbutton1 and userLed1 is off

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
            if ((Event.reportObject.index == 1) && (userLed1Status==false)) {
                printf("LED2 High \r\n");
                wait(0.1);
                winButton1Status=true;
            }
        }

        // If the Reported Message was from winbutton1 and userLed1 is on

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {
            if ((Event.reportObject.index == 1) && (userLed1Status == true)) {
                printf("LED2 Low \r\n");
                wait(0.1);
                winButton1Status=false;
            }
        }

        // If the Reported Message was from winbutton2 and userLed2 is off

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {              
            if ((Event.reportObject.index == 2) && (userLed2Status==false)) {
                printf("LED High \r\n");
                wait(0.1);
                winButton2Status=true;
            }
        }

        // If the Reported Message was from winbutton2 and userLed2 is on

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {              
            if ((Event.reportObject.index == 2) && (userLed2Status == true)) {
                printf("LED Low \r\n");
                wait(0.1);
                winButton2Status=false;
            }
        }
        
        // If the Reported Message was from winbutton3 and userLed3 is off

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {              
            if ((Event.reportObject.index == 3) && (userLed3Status==false)) {
                printf("LED High \r\n");
                wait(0.1);
                winButton3Status=true;
            }
        }

        // If the Reported Message was from winbutton3 and userLed3 is on

        if (Event.reportObject.object == GENIE_OBJ_WINBUTTON) {              
            if ((Event.reportObject.index == 3) && (userLed3Status == true)) {
                printf("LED Low \r\n");
                wait(0.1);
                winButton3Status=false;
            }
        }
    }
}


int main()
{

    SetupGenie();

    genieAttachEventHandler(&myGenieEventHandler);

    printf("Langsters's mbed Visi-Genie LED demo \r\n");

    genieWriteContrast(15); //set screen contrast to full brightness

    while(1) {

        //check if winButton0 is High & set LED0 High 

        if (winButton0Status == true) {
            printf("Button 0 in On State! \r\n");     //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x00, 1); // set virtual LED0 High     
            wait(0.1); // wait 100uS
            led1 = 1; // set actual LED1 High
            userLed0Status = true; // set userLed0Status High

        }

        //check if winButton0 is low & set LED low 

        else if (winButton0Status == false) {
            printf("Button 0 in Off state! \r\n");    //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x00, 0); // set virtual LED0 Low      
            wait(0.1); // wait 100uS
            led1 = 0; // set actual LED1 Low
            userLed0Status = false; //set userLed0Status Low

        }
        
        //check if winButton1 is High & set LED High 
        
        if (winButton1Status == true) {
            printf("Button 1 in On State! \r\n");     //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x01, 1); // set virtual LED0 High     
            wait(0.1); // wait 100uS
            led2 = 1; // set actual LED2 High
            userLed1Status = true; // set userLed1Status High

        }

        //check if winButton1 is low & set LED low 

        else if (winButton1Status == false) {
            printf("Button 1 in Off state! \r\n");    //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x01, 0); // set virtual LED0 Low      
            wait(0.1); // wait 100uS
            led2 = 0; // set actual LED1 Low
            userLed1Status = false; //set userLed1Status Low

        }
        
        //check if winButton2 is High & set LED High 
        
        if (winButton2Status == true) {
            printf("Button 2 in On State! \r\n");     //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x02, 1); // set virtual LED0 High     
            wait(0.1); // wait 100uS
            led3 = 1; // set actual LED2 High
            userLed2Status = true; // set userLed1Status High

        }

        //check if winButton2 is low & set LED low 

        else if (winButton2Status == false) {
            printf("Button 2 in Off state! \r\n");    //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x02, 0); // set virtual LED0 Low      
            wait(0.1); // wait 100uS
            led3 = 0; // set actual LED1 Low
            userLed2Status = false; //set userLed1Status Low

        }
        
        //check if winButton3 is High & set LED High 
        
        if (winButton3Status == true) {
            printf("Button 3 in On State! \r\n");     //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x03, 1); // set virtual LED0 High     
            wait(0.1); // wait 100uS
            led4 = 1; // set actual LED2 High
            userLed3Status = true; // set userLed1Status High

        }

        //check if winButton2 is low & set LED low 

        else if (winButton3Status == false) {
            printf("Button 3 in Off state! \r\n");    //send button status message
            genieWriteObject(GENIE_OBJ_USER_LED, 0x03, 0); // set virtual LED0 Low      
            wait(0.1); // wait 100uS
            led4 = 0; // set actual LED1 Low
            userLed3Status = false; //set userLed1Status Low

        }        
        

    }

}

------------------------------------------------------------------------------------------------------------

You can also import the code as an example from the Mbed cookbook here:

mbed 4D LED Test

The code is fairly simple to understand and is well documented so I'm not going to discuss it more here.

Here is a video showing the screen working - Enjoy.



That's all for now - Langster!