Arduino Voltmeter

This example demonstrates the capability of µPanel of implementing dynamic panels, which can even completely change at run-time. The presented code implements a multi-channel voltmeter, capable of monitoring up to 4 analog inputs of an Arduino Uno board, at an overall rate of 20 Hz. The user, pressing specific buttons, can add or remove channels on the panels. The application will start presenting an application splash screen. 


  • Arduino UNO Board
  • ESP-01 WiFi module (with µPanel Firmware)
  • ESP-01 Breadboard adapter
  • Breadboard wires (4 lines, Male-Female)



µPanel definition 

The application splash screen is defined as follow:

D!288;{^*30%80,100!288,144{ht2,000,1*14T:&#956Panel;}/3{*5T:Mobile Interactive;_T:Universal Panel;}_{*7T:Voltmeter Example;_*6T#3AA:For Arduino UNO;}}/20*15B0:START;

The application working panel is defined as follow:

Panel Header: D!288;{^%100,20!144|%33B1%80:Add;|%33B2%80:Remove;|%33B3%80:Exit;}
Channel Macro: K1:/{p8*15%87!266_T:AN?= ;M??fb:0.00;T: V;_A??%100fn-d#2881:0:0:1023:!0F0;}$
Channel Macro Usage for first channel: J1(0)

Application splash screen
Initial Working Panel
Runtime screenshot with 2 enabled channels

Arduino Code

String Msg;
char ChNumbers = 1;            // Number of enabled channels
char ChScanning = 0;           // Channel to scan

int ChValues[4] = {0,0,0,0};   // Array of channel values
long LastMeasTime = 0;         // Time of last measurement

void setup() {

  Serial.begin(57600);         // Initialise serial
  delay(3000);                 // Let's the module start
  SendSplashScreen();          // Send Application Splash Screen

void SendSplashScreen()        // Send the splash screen cointaining the Start button
   Serial.print("\n$P:D!288;{^*30%80,100!288,144{ht2,000,1*14T:&#956Panel;}/3{*5T:Mobile Interactive;_T:Universal Panel;}");
   Serial.println("_{*7T:Voltmeter Example;_*6T#3AA:For Arduino UNO;}}/20*15B0:START;");  

void SendPanel(char NumberOfChannels)
   char x; 
   // Send the definition of the Panel header and define the macro to display channels
   Serial.print("K1:/{p8*15%87!266_T:AN?= ;M??fb:0.00;T: V;_A??%100fn-d#2881:0:0:1023:!0F0;}$");
   for(x=0; x<NumberOfChannels; x++)    // Recall the channel Macro to display enabled channel sub-panel
     Serial.print("J1(");               // Macro call keyword
     Serial.print(x,DEC);               // Pass to the macro the number of channel
     Serial.print(")");                 // Terminate the Macro call
   Serial.println("");                  // Terminate the panel definition
   for(x=0; x<NumberOfChannels; x++) DisplayChannel(x);  // Update the channels' value

void DisplayChannel(char c)    // Update the channel value
    Serial.print("#A"); Serial.print(c,DEC); Serial.print(":");  // Update the analog bar value
    Serial.println(ChValues[c]);                                 // with the acquired value (LSB)
    float v = ((float) ChValues[c]) / 1024.0 * 5.0;              // Transfor the LSB into voltage
    Serial.print("#M"); Serial.print(c,DEC);                     // Update the channel value message
    Serial.println(v);                                           // with the acquired value (V)

void loop() {
  int c;
  while ((c = > '\n') Msg += (char) c;  // Read incoming chars, if any, until new line
  if (c == '\n')                                       // is message complete?
    if (Msg.substring(0,4).equals("#B3P")) SendSplashScreen();    // has Exit key been pressed? Splash screen!
    if (Msg.substring(0,4).equals("#B0P")) SendPanel(ChNumbers);  // has Start key been pressed? Display Panel
    if (Msg.substring(0,4).equals("#B1P"))     // has the channel ADD button been pressed?
        ChNumbers++;                           // Increase the number of channels
        if (ChNumbers > 4) ChNumbers = 4;      // up to 4
        SendPanel(ChNumbers);                  // Send the new panel
    if (Msg.substring(0,4).equals("#B2P"))     // has the channel DELETE button been pressed?
        ChNumbers--;                           // Decrease the number of channels
        if (ChNumbers < 1) ChNumbers = 1;      // down to 1
        SendPanel(ChNumbers);                  // Send the new panel
    Msg = "";
  if (millis() - LastMeasTime > 100)                      // is time for a new measurement? 
    if (ChScanning >= ChNumbers) ChScanning = 0;         // if all channels already scanned, restart from 0
    ChValues[ChScanning] = analogRead(A0+ChScanning);    // Read analog value of selected channel
    DisplayChannel(ChScanning++);                        // Update panel and move to the next channel
    LastMeasTime = millis();                             // save the time of this measurement