Arduino Dashboard

The Arduino Dashboard is inspired by an Andriod App called handbag which provides a set of controls on an Android device talking to the arduino via bluetooth.

As I was working with the arduino, I noticed that the board is connected to the serial port all the time so I decided to use this hard link to provide the arduino with simple controls that are initiated and controlled from inside the arduino sketch. Currently supported controls are

  • title
  • button
  • checkbox
  • combobox
  • slider
  • label
  • chart

For this, I created a Visual Basic based application that has an empty canvas where I have pre-configured controls to provide button, checkboxe, labels, sliders, combobox and a title bar. The controls can be configured and switched on or off at any time in the arduino sketch. There is no limit on the number of controls as they are created dynamically at run time.

As the tool uses the serial port, a communication through bluetooth is available for free. The basic code for the serial communication is based on the concept introduced by Erik Bartmann in his book "Die elektronische Welt mit Arduino entdecken" (O'ReillY)

The Visual Basic project can be downloaded from the download page

To start with, here is a screenshot of the dashboard and the sketch controling it:

The demo arduino sketch:

#include <MsTimer2.h>

int bufferCount;    // Anzahl der eingelesenen Zeichen
char buffer[80];    // Serial Input-Buffer
char temp[80];
char lastpin=2;
int blinkdelay;
boolean dbOpen = false;
boolean readPort = false;
boolean sglPort = false;
int maxSequence = 1;
int sequence = 0;
int c2chrt = 0;

void setup()
{
  Serial.begin(115200);
  for (int i=2;i<14;i++) {
    pinMode(i,OUTPUT);
  }
  MsTimer2::set(150, t2Isr); // 500 ms period
  MsTimer2::start();
}

void loop()
{
  // do nothing for the GUI handling, serial is done through interrupt
}

void serialEvent(){
  char ch = Serial.read();
  buffer[bufferCount] = ch;
  bufferCount++;
  if(ch == 13){
    evalSerialData();
  }
}

void evalSerialData()
{
  int ptr;
  int val;
  strcpy(temp,"");
  if ((buffer[0]=='S')&&(buffer[bufferCount-2]=='E')) {
    strncat(temp, buffer, bufferCount-1);
    if (strcmp(temp,"SQVERSIONE")==0){
      strcpy(temp,"AC 1.0.0");
    }
    if (strcmp(temp,"SINITE")==0){
      // setup the Dashboard
      Serial.println("STTL1Dashboard DemoE");
      Serial.println("SBTN001.0020.0040.0080.0025.Click MeE");
      Serial.println("SCKB001.0105.0040.Led 5E");
      Serial.println("SSLD001.0020.0070.0002.0013.0001.Led SwiperE");
      Serial.println("SSLD011.0020.0150.0000.0250.0025.Led FaderE");
      Serial.println("SCBO001.0020.0240.0080.0025E");
      Serial.println("SCBA001.Port A0E");
      Serial.println("SCBA001.Port A1E");
      Serial.println("SCBA001.Port A2E");
      Serial.println("SCBA001.Port A3E");
      Serial.println("SCBA001.Port A4E");
      Serial.println("SCBA001.Port A5E");
      Serial.println("SCBS001.0002E");
      c2chrt = 2;
      Serial.println("SLBL001.0250.0240.0080.0030.0.00E");
      Serial.println("SCKB011.0335.0040.Chart Timeline DataE");
      Serial.println("SCKB021.0105.0240.Show Port DataE");
      dbOpen = true;
    }
    if (strcmp(temp,"SGoodByeE")==0){
      // stop the Dashboard
      dbOpen = false;
    }
    if ((buffer[1]=='C')&&(buffer[2]=='K')&&(buffer[3]=='B')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
      if (ptr==0) {
        digitalWrite(5,((buffer[6]-48)==1));
      }
      if (ptr==1) {
        readPort = (buffer[6]-48)==1;
      }
      if (ptr==2) {
        sglPort = (buffer[6]-48)==1;
      }
    }
    if ((buffer[1]=='C')&&(buffer[2]=='B')&&(buffer[3]=='O')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
      c2chrt = buffer[12]-48;
      if ((c2chrt<0) || (c2chrt>5)) c2chrt = 0;
    }
    if ((buffer[1]=='B')&&(buffer[2]=='T')&&(buffer[3]=='N')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
      for (int i=2;i<14;i++) {
        digitalWrite(i,!(digitalRead(i)));
      }
    }
    if ((buffer[1]=='S')&&(buffer[2]=='L')&&(buffer[3]=='V')){
      ptr = (buffer[4]-48)*10 + (buffer[5]-48);
      val = (buffer[6]-48)*1000 + (buffer[7]-48)*100 + (buffer[8]-48)*10 + (buffer[9]-48);
      if (ptr==0) {
        digitalWrite(lastpin,LOW);
        lastpin=val;
        digitalWrite(lastpin,HIGH);
      }
      if (ptr==1) {
        analogWrite(10,val);
      }
    }
  }
  else {
    strcpy(temp,"BadCmd: ");
    strncat(temp, buffer, bufferCount);
    Serial.println(temp);
  }
  bufferCount=0;
}

void t2Isr()
{  
  int led_pin = 13;
  int led_pin2 = 12;
  int ar[6];
  int val;
  char dstr[40];

  switch (sequence) {
  case 0:
    for (int i=0; i<6; i++) {
      ar[i] = analogRead(i) + i * 65;
    }
    sprintf(dstr,"STLViii.%4d.%4d.%4d.%4d.%4d.%4dE",ar[0],ar[1],ar[2],ar[3],ar[4],ar[5]);
    if (readPort) {
      if (dbOpen) {
        Serial.println(dstr);
      }
    }
    break;
  case 1:
    if (sglPort) {
      digitalWrite(led_pin, !digitalRead(led_pin));
      if (dbOpen) {
        val = analogRead(c2chrt);
        Serial.print("SLBV001.");
        Serial.print(millis() % 1000);
        Serial.println("E");
        Serial.print("SCHV001.");
        Serial.print(val);
        Serial.println("E");
      }
    }
  }
  sequence++;
  if (sequence>maxSequence) sequence = 0;
}

The demo code sets all pins 2-13 to output. Pressing the button inverst all pin states, The Led Swiper lights the Led matching the slider position, the Led Fader dims the PWM value of pin 10 and the checkbox controls the state of pin 5. It adds at the end a ComboBox with 6 items. With this combobox, the input for the chart underneath is selected and the checkbox decides if data is plotted or not. The Label next to it shows the actual value plotted. The plot data checkbox enables the filling of the timeline chart on the second tab. In the demo, the analog ports are read and sent to the PC with a value shift to show the differnet lines.

The date and time panels allow sending the actual or a user defined time message to be sent to the arduino. A demo sketch for this is under way.

Protocol

The protocol is rather simple: All commands start with an "S" and end with an "E". In  the sketch above, the GUI is set up using the following lines:

Serial.println("STTL1Dashboard DemoE");
Serial.println("SBTN001.0020.0040.0080.0025.Click MeE");
Serial.println("SCKB001.0105.0040.Led 5E");
Serial.println("SSLD001.0020.0070.0002.0013.0001.Led SwiperE");
Serial.println("SSLD011.0020.0150.0000.0250.0025.Led FaderE");
Serial.println("SCBO001.0020.0240.0080.0025E");
Serial.println("SCBA001.item 0E");
Serial.println("SCBA001.item 1E");
Serial.println("SCBA001.item 2E");
Serial.println("SCBA001.item 3E");
Serial.println("SCBS001.0002E");

Control Definition

These are the commands that define controls on the dashboard.

Title

Format: TTLvlabel
TTL - identifier
v - title visible (0=no, 1=yes)
label - free text for the title banner

Button

Format: BTN##v.llll.tttt.wwww.hhhh.label
BTN - identifier
## - number of button
v - button visible (0=no, 1=yes)
llll - position left of border
tttt - position from border top
wwww.hhhh - width and height of button
label - free text for the button
the "." are only for human readability and have no function

Checkbox

Format: CKB##v.llll.tttt.label
CKB - identifier
## - number of checkbox
v - button visible (0=no, 1=yes)
llll - position left of border
tttt - position from border top
label - free text for the button
the "." are only for human readability and have no function

Slider

Format: SLD##v.llll.tttt.mmmm.xxxx.ssss.label
SLD - identifier
## - number of slider
v - 0=no, 1=yes
llll - position left of border
tttt - position from broder top
mmmm - minimum value for slider
xxxx - maximum value for slider
ssss - tick mark step width
label - free text for the title banner

ComboBox

Format: CBO##v.llll.tttt.wwww.hhhh
## - number of combobox
v - combobox visible (0=no, 1=yes)
llll - position left of border
tttt - position from border top
wwww.hhhh - width and height of combobox
the "." are only for human readability and have no function
Format: CBA##i.ItemToAdd
## - number of combobox to add item to
i - ignored
ItemToAdd - free text used as item text
the "." are only for human readability and have no function

Documentation to come: Label-field

Sending Information

The following commands update defined controls

Receiving Information

The following commands are sent to the Arduino fromthe controls:

Button Pressed

Format: BTN##
BTN - identifier
## - number of button pressed

CheckBox State Change

Format: CKB##s
CKB - identifier
## - number of checkbox
s - state of checkbox (1=on, 0=off)

Slider Value Change

Format: SLV##vvvv
SLV - identifier
## number of slider
vvvv - value of slider

ComboBox Selection Change

Format: CBO##ItemLabel
CBO - identifier
## - number of slider
ItemLabel - text of selected item as defined in the control definition

Serial Log

The serial log echos the commands sent to the arduino and aligned the messages received from the arduino