Bluetooth Display - Part 3

Welcome to the third part of the Bluetooth Display series. Today, in addition to a mandatory additional operator menu item, our display receives a small extension of the hardware! With this new hardware extension, the background brightness of our display can be controlled and configured by software!

For this purpose, we use the port 5 of our Uno's as pulse-width modulation output. This output then controls an IRF520 driver module. This module, which is also used for example for controlling motors, we use to control the ground connection of the built-in leds of the display. (The IRF520 switches to ground)

In this way, you can control the brightness of our display in 255 levels. In addition, it is also convenient from our Bluetooth terminal.

But now to the actual construction and implementation of enlargement. As a first step, we extend our hardware as shown in the following schematic to IRF520 MOS Driver Module.

 

 

Circuit - Bluetooth Display Part 3

In the circuit, the first thing that stands out is that the positive input and output terminals of the IRF520 MOS Driver Modules are not occupied. This is not a circuit error, because these terminals / connections of the module are not necessary for the functioning of our circuit, as we obtain the positive operating voltage for the backlight of the display via the pre-stand directly via the 5 volt rail.

(Even in the module itself, the Terminals Vin and V+ are only bridged and have no active or passive components between the two terminals!)

Therefore, do not be irritated by the switching mode of the module, which differs somewhat from the standard.

Next, for this extension, we upload the following customized code to our Arduino UNO:

 

#include <Spi.H>
#include <Wire.H>
#include <SoftwareSerial.H>
#include <Eeprom.H>
#include <LiquidCrystal.H>
#include <Avr/Sleep.H>

#define MaxInputBufferSize 20 maximum 255 characters to adapt to vlcdr
#define EEpromSize 990

#define rLcdChr 20
#define LcdRows 4
#define interval 1000
#define BackgroundLight 5 Port 5 Backlight LED
#define DelayTOPWROFF 500

EEprom Memory CellAddresses for Configuration
#define EEFadeSeconds  993

#define EEPINA 996
#define EEPINC 997
#define EEPINDD 998


SoftwareSerial mySerial(7, 6); RX, TX
LiquidCrystal Lcd(8, 13, 12, 11, 10, 9);


variables
Byte DisplayBankContent = 0;

Serial Input Handling
Char TBuffer;
Char Cbuffer[MaxInputBufferSize + 1];     USB Code Input Buffer
String Sbuffer = "";                      USB String Input Buffer
Int Value;                                USB Nummeric Input Buffer
Byte Ccount = 0;                          Number received Chars
Byte Inptype = 0;
Boolean StrInput = False;
Boolean NumberInput = False;
Boolean DataInput = False;
Boolean EnterInput = False;
Byte MenueSelection = 0;

Byte SelectedMsg = 0;

Eeprom
Int eeaddress;                 EEPROM Address Pointer
Byte EEPromBanks = 0;          Used for Calculating the EEPROM Banks
SerMnueControl
Byte MnuState = 0;            Maximum menu depth 255 icl Sub
Byte Selectedbank = 0;

Real Time Clock
Long previousMillis = 0;       will store last time was measured
Long previousMillisB = 0;       will store last time was measured

Display Management
Boolean DisplayLock = False;
Boolean Directprint = False;
Boolean EchoMode = True;
Byte DirectprintROW = 0;
Byte DirectprintLine = 0;

Boolean RefreshDisplay = False;
Byte FRMCheck = 0; Used fpr Writing Operations to eeprom so save hosts cycles


PWM Light Control

Byte Currentbrightness = 0;
Byte Targetbrightness = 0;
Byte FadeSeconds = 0; Standard = 3



Void Setup()
{   EEPromBanks = EEpromSize / ((rLcdChr) * LcdRows);   lcd.begin(rLcdChr, LcdRows);   lcd.clear();   lcd.setCursor(0, 0);   lcd.print("    Bluetooth");   lcd.setCursor(0, 1);   lcd.print("     Display");   mySerial.begin(9600);   pinMode(BackgroundLight, OUTPUT); // Displaybeleuchtung / Display AN /AUS   digitalWrite(BackgroundLight, LOW);   // read Config   FadeSeconds = 0;   Currentbrightness = 0;   Targetbrightness = 0;   lcd.setCursor(0, 4);   if (DisplayLock) {     lcd.print("  System gesperrt");   }   // Further Setup Routines / initalizing   lcd.setCursor(0, 0);   Targetbrightness = 255;   mySerial.flush();
}



// ###################################################################################################### //

void loop()

{   SerialcommandProcessor();   runrealTimeClock();   Displayprocessor();   //End Main loop
}

// ###################################################################################################### //


void TextHeader(byte rowm)
{   mySerial.println("Text for Bank " + String( Selectedbank) + " ROW " + String (rowm) + ":");
}

void SerialcommandProcessor()
{   int a;   Inptype = 0;   Inptype = SerInputHandler();   // 0 keine Rückgabe   // 1 Nummer   // 2 String   // 3 Data   if ((Inptype > 0) & (!Directprint))   {     MenueSelection = 0;     if ((MnuState < 2) && (Inptype == 2)) {       Sbuffer.toUpperCase();  // For Easy Entering Commands     }     if ((Sbuffer == "S") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 3;     }     // Erasing ALL EEprom Content     if ((Sbuffer == "E") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 4;     }     if ((Sbuffer == "YES") && (MnuState == 1) && (Inptype == 2))      {       MenueSelection = 5;     }     if ((Sbuffer != "YES") && (MnuState == 1) && (Inptype == 2))     {       MenueSelection = 6;     }     //Edit  Selected Content     if ((Sbuffer == "W") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 7;     }     if ((MnuState == 2) && (value  < EEPromBanks) && (Inptype == 1)) {       MenueSelection = 8;     }     if (MnuState == 3)                                               {       MenueSelection = 9;     }     if (MnuState == 4)                                               {       MenueSelection = 10;     }     //Display  Selected Content     if ((Sbuffer == "P") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 11;     }     if ((MnuState == 5) && (Inptype == 1))                           {       MenueSelection = 12;     }     if ((Sbuffer == "R") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 13;     }     if ((MnuState == 6) && (Inptype == 1))                           {       MenueSelection = 14;     }     if ((Sbuffer == "D") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 15;     }     if ((Sbuffer == "Z") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 16;     }     if ((Sbuffer == "B") && (MnuState == 0) && (Inptype == 2))       {       MenueSelection = 17;     }     if ((MnuState == 7) && (Inptype == 1))                           {       MenueSelection = 18;     }     if ((Sbuffer == "FADE") && (MnuState == 0) && (Inptype == 2))     {       MenueSelection = 19;     }     if (MnuState == 9)                                               {       MenueSelection = 20;     }     if (MnuState == 10)                                              {       MenueSelection = 21;     }     if (MnuState == 12)                                              {       MenueSelection = 25;     }     if (MnuState == 13)                                              {       MenueSelection = 27;     }     if (MnuState == 14)                                              {       MenueSelection = 29;     }     switch (MenueSelection)     {       case 3:         {           mySerial.println("Read EEEPROM Content:" );           mySerial.flush();           for (int a = 0; a < EEPromBanks; a++)           {             mySerial.println("EEPROM Memory Bank: " + String(a) );             mySerial.flush();             for (int b = 1; b <= LcdRows; b++)             {               mySerial.print("Row " + String(b) + ": ");               mySerial.flush();               for (int c = 0; c < rLcdChr; c++)               {                 eeaddress = 0;                 eeaddress = (a * (rLcdChr) * LcdRows) + ((rLcdChr) * b) + c;                 value = EEPROM.read(eeaddress);                 mySerial.print(char(value));                 mySerial.flush();               }               mySerial.println(" ");               mySerial.flush();             }           }           Sbuffer = "";           mySerial.println("No more EEPROM Banks available.");           mySerial.flush();           break;         }       case 4:         {           value = 0;           mySerial.print("Erasing EEPROM ");           mySerial.println("YES/NO:");           mySerial.flush();           MnuState = 1;           Sbuffer = "";           break;         }       case 5:         {           value = 0;           mySerial.print("Erasing EEPROM ");           mySerial.println("Stand by.");           mySerial.flush();           for (int a = 0; a < EEPromBanks; a++)           {             //Memory Bank a             mySerial.println("Clear Bank: " + String(a));             for (int b = 1; b <= LcdRows; b++)             {               for (int c = 0; c < rLcdChr; c++)               {                 eeaddress = 0;                 eeaddress = (a * (rLcdChr) * LcdRows) + ((rLcdChr ) * b) + c;                 FRMCheck = EEPROM.read(eeaddress);                 if (FRMCheck > 0)                 {                   EEPROM.write(eeaddress, 00); // Formatierung                   mySerial.print(".");                   value++;                   delay(30);                   mySerial.flush();                 }               }             }             mySerial.println("");             mySerial.flush();           }           mySerial.println("");           mySerial.println("Finished. " + String(value) + " Bytes cleared");           mySerial.println("");           mySerial.flush();           Sbuffer = "";           MnuState = 0;           break;         }       case 6:         {           value = 0;           Sbuffer = "";           MnuState = 0;           mySerial.println("OP abort.");           mySerial.flush();           break;         }       case 7:         {           mySerial.println("EEPPROM Bank Number (0-" + String(EEPromBanks - 1) + "):");           mySerial.flush();           MnuState = 2;           value = 0;           Sbuffer = "";           break;         }       case 8:         {           Selectedbank = value;           TextHeader(1);           MnuState = 3;           Sbuffer = "";           value = 0;           break;         }       case 9:         {           WriteEEPROM(Selectedbank, 1);           TextHeader(2);           value = 0;           MnuState = 4;           Sbuffer = "";           break;         }       case 10:         {           WriteEEPROM(Selectedbank, 2);           value = 0;           MnuState = 0;           Sbuffer = "";           TextHeader(3);           mySerial.flush();           value = 0;           MnuState = 9;           Sbuffer = "";           break;         }       case 11:         {           value = 0;           mySerial.println("EEPPROM Bank Number (0-" + String(EEPromBanks - 1) + "):");           MnuState = 5;           Sbuffer = "";           mySerial.flush();           break;         }       case 12:         {           SelectedMsg = value;           DisplayBank(value);           break;         }       case 13:         {           value = 0;           mySerial.println("EEPPROM Bank Number (0-" + String(EEPromBanks - 1) + "):");           MnuState = 6;           Sbuffer = "";           mySerial.flush();           break;         }       case 14:         {           a = value;           if ( a < EEPromBanks)           {             mySerial.println("Memory Bank: " + String(a) );             mySerial.flush();             for (int b = 1; b <= LcdRows; b++)             {               mySerial.print("Row " + String(b) + ": ");               mySerial.flush();               for (int c = 0; c < rLcdChr; c++)               {                 eeaddress = 0;                 eeaddress = (a * (rLcdChr) * LcdRows) + ((rLcdChr) * b) + c;                 value = EEPROM.read(eeaddress);                 mySerial.print(char(value));                 mySerial.flush();               }               mySerial.println(" ");               mySerial.flush();             }           } else           {             mySerial.println("Value out of Range.");           }           value = 0;           Sbuffer = "";           MnuState = 0;           break;         }       case 15:         {           // Direct pPrint to Display           Directprint = true;           mySerial.println ("Directprint ON.");           if (Directprint)           {             DirectprintROW = 0;             DirectprintLine = 0;             lcd.clear();             lcd.cursor();             lcd.blink();           }           value = 0;           Sbuffer = "";           MnuState = 0;           break;         }       case 16:         {           value = 0;           Sbuffer = "";           MnuState = 0;           break;         }       case 17:         {           mySerial.println("Display Brightness: (max 255)");           MnuState = 7;           value = 0;           Sbuffer = "";           break;         }       case 18:         {           if ((value < 256))           {             Targetbrightness = value;             mySerial.println("Brightness: " + String (Targetbrightness) + " Set");           } else           {             mySerial.println("Value out of Range.");           }           MnuState = 0;           value = 0;           Sbuffer = "";           break;         }       case 19:         {           mySerial.println("Fade Delay: (max 255 Sec)");           MnuState = 12;           value = 0;           Sbuffer = "";           break;         }       case 20:         {           WriteEEPROM(Selectedbank, 3);           value = 0;           MnuState = 0;           Sbuffer = "";           TextHeader(4);           mySerial.flush();           value = 0;           MnuState = 10;           Sbuffer = "";           break;         }       case 21:         {           WriteEEPROM(Selectedbank, 4);           value = 0;           MnuState = 0;           Sbuffer = "";           break;         }       case 25:         {           if ((value > 0) & (value < 251))           {             FadeSeconds = value;             EEPROM.write(EEFadeSeconds, FadeSeconds);             mySerial.println("Value " + String (value) + " set.");           } else           {             value = 0;             Sbuffer = "";             mySerial.println("Value out of Range.");           }           value = 0;           MnuState = 0;           Sbuffer = "";           break;         }       default:         {           mySerial.println("-------Smart Bluetooth Display 1.1------");           mySerial.println("S - Read ALL EEPROM Banks");           mySerial.println("E - Erase ALL EEPROM Banks");           mySerial.println("W - Write sel. EEPROM Bank");           mySerial.println("R - Read sel. EEPROM Bank");           mySerial.println("P - Print EEPROM Bank on Display");           mySerial.println("----------------------------------------");           mySerial.println("D - Direct Print");           mySerial.println("B - Display Brightness Current Value: " + String (Currentbrightness));           mySerial.println("----------------------------------------");           mySerial.println("Type Cmd and press Enter");           mySerial.flush();           MnuState = 0;           value = 0;           Sbuffer = "";         }     }   } // Eingabe erkannt
}



void WriteEEPROM(byte FBank, byte FRow)
{   byte Writecounter;   Writecounter = 0;   mySerial.print("Saving ");   for (int c = 0; c < rLcdChr; c++)   {     eeaddress = 0;     eeaddress = (FBank * (rLcdChr) * LcdRows) + ((rLcdChr) * FRow) + c;     value = EEPROM.read(eeaddress);     if (Sbuffer[c] != value)     {       EEPROM.write(eeaddress, Sbuffer[c]);       mySerial.print(".");       Writecounter++;     }   }   mySerial.println(" " + String (Writecounter) + " Bytes written.");

}

void ClearCBuffer ()

{   for (byte a = 0; MaxInputBufferSize - 1; a++)     Cbuffer[a] = 0;
}

byte SerInputHandler()
{   byte result = 0;   int c;   int d;   int a;   int b;   result = 0;   if (CheckforserialEvent())   {     if ((NumberInput) and not (DataInput) and not (StrInput))    //Numbers only     {       Sbuffer = "";       value = 0;       StrInput = false;       NumberInput = false;       DataInput = false;       EnterInput = false;       a = 0;       b = 0;       c = 0;       d = 0;       Sbuffer = Cbuffer; // Zahl wird AUCH ! in SBUFFER übernommen, falls benötigt.       if (Ccount == 1) {         value  = Cbuffer[0] - 48 ;       }       if (Ccount == 2) {         a = Cbuffer[0] - 48 ;         a = a * 10;         b = Cbuffer[1] - 48 ;         value = a + b;       }       if (Ccount == 3) {         a = Cbuffer[0] - 48 ;         a = a * 100;         b = Cbuffer[1] - 48 ;         b = b * 10;         c = Cbuffer[2] - 48 ;         value = a + b + c;       }       if (Ccount == 4) {         a = Cbuffer[0] - 48 ;         a = a * 1000;         b = Cbuffer[1] - 48 ;         b = b * 100;         c = Cbuffer[2] - 48 ;         c = c * 10;         d = Cbuffer[3] - 48 ;         value = a + b + c + d;       }       if (Ccount >= 5)       {         Sbuffer = "";         value = 0;         Sbuffer = Cbuffer;         ClearCBuffer;         result = 2;       } else       {         ClearCBuffer;         Ccount = 0;         result = 1;                                                //Number Returncode         NumberInput = false;         StrInput = false;         DataInput = false;         EnterInput = false;         Ccount = 0;         return result;       }     }     if ((StrInput) and not (DataInput))                          //String Input only     {       Sbuffer = "";       Sbuffer = Cbuffer;       value = 0;       StrInput = false;       NumberInput = false;       DataInput = false;       EnterInput = false;       Ccount = 0;       ClearCBuffer;       result = 2;                                                 //Number Returncode     }     if (DataInput) {       Sbuffer = "";       Sbuffer = Cbuffer;       value = 0;       StrInput = false;       NumberInput = false;       DataInput = false;       EnterInput = false;       Ccount = 0;       ClearCBuffer;       result = 3;                                               //Number Returncode     }     if ((EnterInput) and not (StrInput) and not (NumberInput) and not (DataInput))     {       Sbuffer = "";       value = 0;       Ccount = 0;       ClearCBuffer;       result = 4;                                               //Number Returncode     }     NumberInput = false;     StrInput = false;     DataInput = false;     EnterInput = false;     Ccount = 0;     return result;   }   return result;   //End CheckforSerialEvent
}

// Eingabebuffer
boolean CheckforserialEvent()
{   while (mySerial.available()) {     // get the new byte:     TBuffer = mySerial.read();     if (TBuffer > 9 && TBuffer < 14)     {       Cbuffer[Ccount] = 0;       TBuffer = 0;       if (EchoMode)       {         mySerial.print(char(13));         mySerial.flush();       }       if (Directprint)       {         mySerial.println("");         DirectprintLine = 0;         DirectprintROW = DirectprintROW + 1;         if ( DirectprintROW > 3)         {           Directprint = false;           lcd.noCursor();           lcd.noBlink();           Sbuffer = "";           value = 0;         } else         {           lcd.cursor();           lcd.blink();           lcd.setCursor(0, DirectprintROW);         }       }       EnterInput = true;       return true;     } else if (TBuffer > 47 && TBuffer < 58 )     {       if ( Ccount < MaxInputBufferSize)       {         Cbuffer[Ccount] = TBuffer;         Ccount++;         if ((Directprint))         {           lcd.print(char(TBuffer));           DirectprintLine = DirectprintLine + 1;           if ( Ccount > MaxInputBufferSize - 1)           {             lcd.noCursor();             lcd.noBlink();           } else {             lcd.cursor();             lcd.blink();           }         }         if (EchoMode) {           mySerial.print(char(TBuffer));           mySerial.flush();         }       } else {         mySerial.print("#");       }       //Number Input detected       NumberInput = true;     }     else if (TBuffer > 64 && TBuffer < 123 )     {       if ( Ccount < MaxInputBufferSize)       {         Cbuffer[Ccount] = TBuffer;         Ccount++;         if ((Directprint))         {           lcd.print(char(TBuffer));           DirectprintLine = DirectprintLine + 1;           if ( Ccount > MaxInputBufferSize - 1)           {             lcd.noCursor();             lcd.noBlink();           } else {             lcd.cursor();             lcd.blink();           }         }         if (EchoMode) {           mySerial.print(char(TBuffer));           mySerial.flush();         }       } else {         mySerial.print("#");       }       StrInput = true;     }     else if ( (TBuffer == 127 )  |  (TBuffer == 8 ) )     {       if ( DirectprintLine > 0 )       {         DirectprintLine = DirectprintLine - 1;         lcd.setCursor(DirectprintLine, DirectprintROW);         lcd.print(" ");         lcd.setCursor(DirectprintLine, DirectprintROW);       }       if (( DirectprintLine == 0 ) & ( DirectprintROW > 0 ))       {         DirectprintROW = DirectprintROW - 1;         DirectprintLine = rLcdChr - 1;         lcd.setCursor(DirectprintLine, DirectprintROW);       }       if ( Ccount > 0)       {         Ccount--;         Cbuffer[Ccount] = 0;         if ((Directprint))         {           if ( Ccount > MaxInputBufferSize - 1)           {             lcd.noCursor();             lcd.noBlink();           } else {             Lcd.Cursor();             Lcd.Blink();           }         }         If (EchoMode) {           mySerial.Print("-");           mySerial.Flush();         }       }     }     else     {       If ( Ccount < MaxInputBufferSize)       {         Cbuffer[Ccount] = TBuffer;         Ccount++;         If ((Directprint))         {           DirectprintLine = DirectprintLine + 1;           If (TBuffer < 128) {             Lcd.Print(Char(TBuffer));           } else  {             Lcd.Print(String(TBuffer));           }           If ( Ccount > MaxInputBufferSize - 1)           {             Lcd.noCursor();             Lcd.noBlink();           } else {             Lcd.Cursor();             Lcd.Blink();           }         }         If (EchoMode) {           mySerial.Print(Char(TBuffer));           mySerial.Flush();         }       } else {         mySerial.Print("#");       }       Data Input detected       DataInput = True;     }     Return False;   }   Return False;
}

Void Display processor()  With blue display, scroll ingesisising is omitted, as this only "lubricates"
{   If (RefreshDisplay)   {     Lcd.Clear();     RefreshDisplay = False;     for (Int B = 1; B <= LcdRows; B++)     {       Lcd.setCursor(0, B - 1);       for (Int C = 0; C < rLcdChr; C++)       {         eeaddress = 0;         eeaddress = (DisplayBankContent * (rLcdChr) * LcdRows) + ((rLcdChr) * B) + C;         Value = 0;         Value = Eeprom.Read(eeaddress);         If (Value > 31) Don't show special characters         {           mySerial.Print(Char(Value));           Lcd.Print(Char(Value));         } else         {           Lcd.Print(Char(32));         }       }       mySerial.println();     }   }
}

Void runrealTimeClock()    TIMEBASE
{   Real Time Clock & Countdown   long previousMillis = 0;       will store last time was measured   byte SecDivider = 0;   Unsigned Long currentMillis = millis();   Int StepValue = 0;   PWM Display Control   StepValue = 4 * FadeSeconds;   If (currentMillis - previousMillis > StepValue)   {     previousMillis = currentMillis;     If (Currentbrightness < Targetbrightness        )     {       Currentbrightness = Currentbrightness + 1;       analogWrite (BackgroundLight, Currentbrightness);     } else If (Currentbrightness > Targetbrightness)     {       Currentbrightness = Currentbrightness - 1;       analogWrite (BackgroundLight, Currentbrightness);     }   }   If (currentMillis - previousMillisB > 1000)   {     seconds-stroke     previousMillisB = currentMillis;   }
}

Void DisplayBank ( Byte cobank)
{   If (cobank  < EEPromBanks )   {     RefreshDisplay = True;   Initalize Display Output     DisplayBankContent = cobank;     mySerial.println("Bank" + String(cobank) + " is displayed on LCD");     MnuState = 0;     Sbuffer = "";     Value = 0;     mySerial.Flush();   } else   {     mySerial.println("Bank not available.");     Value = 0;     MnuState = 0;     Sbuffer = "";     mySerial.Flush();   }
}

 

Finished! More is no longer necessary.

After this small extension or adjustment of the hardware, the further command "B" for Brightness is now available to us in the Bluetooth menu.

  • B - Display Brightness Current Value: 255

Part 3 - Adjust brightness via the menu

The number given behind it describes the currently set display brightness in a value range from 0 (backlight off) to a maximum of 255 (maximum brightness)

So we always see at a glance what brightness is currently set on our display.

If we now want to change the brightness of the backlight, we select the point "B" (Brightness) and press Enter. We are then asked briefly: Display Brightness: (max 255) and enter our desired value behind it.

Setting the brightness

In this example, we enter 20 as the desired brightness value)

This is acknowledged with the output: Brightness: 20 Set. We now see how the display darkens to the desired value.

For all those interested who want to see the PWM signal that our code generates for controlling brightness, I took screenshots of my oscilloscope once at the value 20 and at the value 200:

Value 20

Value: 20

 

 

Value: 200

Value:200

 

As can be seen, the pulse-pause ratio of the signal differs, while the frequency remains the same. Our eye averages this ratio back to an even brightness.

I wish you a lot of fun rebuilding and, as always, until the next time.

DisplaysFür arduinoProjekte für fortgeschrittene

Leave a comment

All comments are moderated before being published