Generic Panel for Process Control

Blockzitat
I have written two programs, one for Arduino and one for processing. Both programms work together to build a generic control panel for process (control of automation, for example control any type of actuator, relay, lamps, cameras, alarms, motor, servos, light signals, railway trakc, model railway, etc.

The idea is to submit both programms to put in category tutorials for new people, therefore I am submiting them for improvements , comments in general, etc.
Follows the Arduino programm

[code]
// Control Panel Ard_to_pross    25 06-23

/* If the programm receives a number "1" (room1) switch ON Led 1 and return to process the character "B",  
 *  receives "2" (room 2) switch ON Led 2 On and return to process the character "C"
 *  receives "3" (room 3) switch ON Led 3 On and return to process the character "D"
 *  receives "4" (room 4) switch ON Led 4 On and return to process the character "E"
 *  receives "5" (room 5) switch ON Led 5 On and return to process the character "F"
 *  receives "6" (room 6) switch ON Led 6 On and return to process the character "G"
 * To establish the handshake with the PC an "A" will be sent until contact is established.
*/


int val;                // Data received from serial port
char controlNunber;
int led1State = HIGH;         // current State of LED 1 at start
int led2State = HIGH;         // current State of LED 2 at start
int led3State = HIGH;         // current State of LED 3 at start
int led4State = HIGH;         // current State of LED 4 at start
int led5State = HIGH;         // current State of LED 5 at start
int led6State = HIGH;         // current State of LED 6 at start

int ledPin1 = 12;         // Set the pin to digital I/O 12
int ledPin2 = 11;         // Set the pin to digital I/O 11
int ledPin3 = 10;         // Set the pin to digital I/O 10 
int ledPin4 = 9;          // Set the pin to digital I/O  9 
int ledPin5 = 8;          // Set the pin to digital I/O  8 
int ledPin6 = 7;          // Set the pin to digital I/O  7 

void setup()
{
  pinMode(ledPin1, OUTPUT);             // Declare pin 12 as an output
  pinMode(ledPin2, OUTPUT);             // Declare pin 11 as an output 
  pinMode(ledPin3, OUTPUT);             // Declare pin 10 as an output 
  pinMode(ledPin4, OUTPUT);             // Declare pin  9 as an output
  pinMode(ledPin5, OUTPUT);             // Declare pin  8 as an output
  pinMode(ledPin6, OUTPUT);             // Declare pin  7 as an output
       
  Serial.begin(9600);                  // Serial Port speed
  establishContact();                  // send a character "A" to establish contact until receiver responds

}

void loop()
{
  if (Serial.available() > 0) // if serial available functions returns 1
    // it means that some data has been received in the
    // serial buffer of Arduino
    val = Serial.read();

 //--------------------------------------------------------------------------------
 {
   // val = Serial.read();
  // To check the value of variavle val uses either the ASCII code for the character or alternative 
  //the character between "" example write '1' or number 49 ASCII code for 1.
   
    if (val == 49)           // Check if an '1' has been received   49 is ASCI code for "1"
      {
      digitalWrite (ledPin1, led1State);   // Turn ON Led Room 1
      Serial.println("B");           //  Return B, Led switched on
      led1State =! led1State;
      delay (50);
     } 


    if (val == 50)                  //Check if an '2' has been received   50 is ASCI code for "2"
    {
      digitalWrite (ledPin2, led2State);    // Turn OFF Led Room 2
      Serial.println("C");           //  Return C,Led switched on
      led2State =! led2State;
      delay(50);
    }
   
     if (val == '3')                 //Check if an '3' has been received.   
    {
      digitalWrite (ledPin3, led3State);    // Turn On Led Room 3
      Serial.println("D");           //  Return C,Led switched on
      led3State =! led3State;
      delay(50); 
    }
  
    if (val == '4')                  //Check if an '4' has been received
    {
      digitalWrite (ledPin4, led4State);    // Turn On Led Room 4
      Serial.println("E");           //  Return E,Led switched on
      led4State =! led4State;
      delay(50);
    }
  
   if (val == '5')                   //Check if an '5' has been received
    {
      digitalWrite (ledPin5, led5State);   // Turn On Led Room 5
      Serial.println("F");          //  Return F,Led switched on
      led5State =! led5State;
      delay(50);
    }
 
   if (val == '6')                   //Check if an '6' has been received
    {
      digitalWrite (ledPin6, led6State);   // Turn On Led Room 6
      Serial.println("G");          //  Return G,Led switched on
      led6State =! led6State;
      delay(50);
    }
  }
  
  //-------------------------------------------------------------------------------- 
 
}

 // Routine to send a character "A" to establish contact until receiver responds

void establishContact()
{
  while (Serial.available() <= 0)
  {
    Serial.println("A");          // send a capital A to process
    delay(300);
  }
}

void ready ()
{
 Serial.println("R");          // send a capital R to process
    delay(300);
}
[/code]

Here follows the Processing programm

// Control Panel pross to Ard 25 06 23

// Generic Control Panel  

// Works with programm: Control Panel Ard_to_pross    25 06-23

/* Example for Control Switching of LED   (LED-Control)
LEDs can be change for any type of actuator, relay, lamps, cameras, alarms, motor, servos, light signals, etc.

This programm can be changed to display for example a process, a railway track, etc, and linked with Arduino
can control physical elements.

The programm contains the communication overhead for serial communication with processing programms

Programm draw six buttons
Click on one button will send to arduino a number 1, 2, 3, 4, 5 or 6 according to the room number

Arduino will switch the corresponding Led and answer with the character "B" (room1),  "C" (room 2), "D" (room 3),
"D" (room4),  "E" (room 5), "F" (room6) and processing will change the color of the button and write "On".

A new click on a button will change again the status of the button(change colour and write Off)
Arduino will change the status of the Led (Toggle)
*/

import processing.serial.*;     //import the Serial library
Serial myPort;                //the Serial port object
 
int portIndex = 0; // set this to the port connected to Arduino
int val; // Data received from the serial port

int tog1 = 0; // Toggle switch for On/Off room1
int tog2 = 0; // Toggle switch for On/Off room2
int tog3 = 0; // Toggle switch for On/Off room3
int tog4 = 0; // Toggle switch for On/Off room4
int tog5 = 0; // Toggle switch for On/Off room5
int tog6 = 0; // Toggle switch for On/Off room6


char controlNunber;

Boolean firstContact = false;  // Since we are doing serial handshaking
                               // we need to check if we have heard from the microcontroller

void setup() {
  size(300, 300);  //make our canvas 200 x 200 pixels big
                   //  initialize the serial port and set the baud rate to 9600
                  
         

 myPort = new Serial(this, Serial.list() [0], 9600);
 myPort.bufferUntil ('\n');
 
 
    background(200);    //set it here so no fuzzy text on screen
    
 //Initial text on canvas mask, all buttons yellow with Off written on them.
 // Drawing of buttons
 //Initial text on canvas mask, all lights OFF  start

 fill(255,252,214); // Room 1
 rect(50, 30, 50,50);              // (Origin (x,y) width, height
  fill(15,13,13); 
  text("Room 1", 55,25);
   text("Off", 66,60);

 fill(255,252,214);  // Room 2
 rect(200, 30, 50, 50);
  fill(15,13,13); 
  text("Room 2", 205,25);
   text("Off", 213,60);
  
  fill(255,252,214);  // Room 3
 rect(50, 120, 50,50);
  fill(15,13,13); 
  text("Room 3 ", 55,115);
    text("Off", 68,150);

 fill(255,252,214);  // Room 4
 rect(200, 120, 50, 50);
  fill(15,13,13); 
  text("Room 4", 205,115);
   text("Off", 213,150);
   
  fill(255,252,214);  // Room 5
 rect(50, 210, 50,50);
  fill(15,13,13); 
  text("Room 5  ", 55,205);
    text("Off", 68,240);

 fill(255,252,214);  // Room 6
 rect(200, 210, 50, 50);
  fill(15,13,13); 
  text("Room 6", 205,205);
    text("Off", 216,240);

//Initial text on canvas mask, all lights OFF  End
    
    
    // Control Panel Ready Light  Start
    // Arduino has all Leds Off.  Start, ready button is red until ready to operate when it change to green. 
    
    fill(250,46,28); 
    circle(150, 150, 20);
    fill(15,13,13); 
   text("Ready", 135,135); 
   
  // Control Panel Ready Light  End 
    
 }
 

void draw()
{
  
 if (mousePressed == true)    // Check where is the mouse set start
{
if(mouseX >= 50 && mouseX < 100 && mouseY >= 50 && mouseY < 100)
 { 
     //println("                                           Mouse pressed on Button room 1");
       myPort.write('1');        //send a 1
       myPort.write ('0'); 
       delay   (150);
 }
 if(mouseX >= 200 && mouseX < 250 && mouseY >= 50 && mouseY < 100)
 { 
     //println("                                           Mouse pressed on Button room 2");
     myPort.write('2');        //send a 2
     myPort.write ('0');
     delay   (150);
   }
 

if(mouseX >= 50&& mouseX < 100&& mouseY >= 120 && mouseY < 170)
 { 
    //println("                                           Mouse pressed on Button room 3");
     myPort.write('3');        //send a 3
     myPort.write ('0');
     delay   (150);
 }

if(mouseX >= 200 && mouseX < 250 && mouseY >= 120 && mouseY < 170)
 { 
     //println("                                           Mouse pressed on Button room 4");
     myPort.write('4');        //send a 4
     myPort.write ('0');
     delay   (150);
 }


if(mouseX >= 50&& mouseX < 100&& mouseY >= 210 && mouseY < 260)
 { 
     //println("                                           Mouse pressed on Button room 5");
     myPort.write('5');        //send a 5
     myPort.write ('0');
     delay   (150);
 }


if(mouseX >= 200 && mouseX < 250 && mouseY >= 210 && mouseY < 260)
 { 
     // println("                                           Mouse pressed on Button room 6");
     myPort.write('6');        //send a 6
     myPort.write ('0');
     delay   (150);
 }
// Check where is the mouse set end
}


//-------------------------------------- 

// Check If data is available,
    if ( myPort.available() > 0) 
     {
       val = myPort.read(); // read it and store it in val
       //  print(val);     //for debbuging 
           fill(28,250,92);   // If data is in buffer, chage Ready Button to green. Operation can start
    circle(150, 150, 20);
     }
     
 //--------------------------------------
 

if ((val) == 66)     // "B" received, Led switched on   
     {
       controlNunber = 66;     // ASCII code for "B", Alternative instead of ASCII code it can be used: "B"
       cleanPanel(controlNunber);
       imprimir(controlNunber);  
         }
     
 if ((val) == 67)     // "C" received, Led switched Off
     { 
       controlNunber = 67;        // ASCII code for "C"
       cleanPanel(controlNunber);
       imprimir(controlNunber);  
     }
     
      if ((val) == 68)     // "C" received, Led switched Off
     { 
       controlNunber = 68;        // ASCII code for "D"
       cleanPanel(controlNunber);
       imprimir(controlNunber);  
     }
     
     if ((val) == 69)     // "E" received, Led switched Off
     { 
       controlNunber = 69;        // ASCII code for "E"
       cleanPanel(controlNunber); 
       imprimir(controlNunber);  
     }
    
     if ((val) == 70)     // "F" received, Led switched Off
      { 
       controlNunber = 70;        // ASCII code for "F"
       cleanPanel(controlNunber);
       imprimir(controlNunber);  
      }
     
      if ((val) == 71)     // "F" received, Led switched Off
      { 
       controlNunber = 71;        // ASCII code for "G"
       cleanPanel(controlNunber);
       imprimir(controlNunber);  
      }    
 }

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

void cleanPanel(char x)   //To clear text redraw the button and write it again  start
{ 
  //println("x", x);   for debbuging  
switch(controlNunber) 
  {
   case 'B':                        // Room 1
     if ((val == 66)  && (tog1 == 1))
     {
      fill(255,252,214);
      rect(50, 30, 50,50);
     } 
   
     else
     {
      fill(106,242,10);  
      rect(50, 30, 50,50);
     }  
     break;    

   case 'C':                        // Room 2
     if ((val == 67)  && (tog2 == 1))
     {
      fill(255,252,214);
      rect(200, 30, 50,50);
      } 
   
     else
     {
      fill(106,242,10);  
      rect(200, 30, 50,50);
     }  
     break;


 case 'D':                        // Room 3
     if ((val == 68)  && (tog3 == 1))
     {
      fill(255,252,214);
      rect(50, 120, 50,50);
      } 
   
     else
     {
      fill(106,242,10);  
      rect(50, 120, 50,50);
     }  
     break;    

 case 'E':                        // Room 4
     if ((val == 69)  && (tog4 == 1))
     {
      fill(255,252,214);
      rect(200, 120, 50,50);
     } 
   
     else
     {
      fill(106,242,10);  
      rect(200, 120, 50,50);
     }  
     break;


 case 'F':                        // Room 5
     if ((val == 70)  && (tog5 == 1))
     {
      fill(255,252,214);
      rect(50, 210, 50,50);
     } 
   
     else
     {
      fill(106,242,10);  
      rect(50, 210, 50,50);
     }  
     break;  

 case 'G':                        // Room 6
     if ((val == 71)  && (tog6 == 1))
     {
      fill(255,252,214);
      rect(200, 210, 50,50);
     } 
   
     else
     {
      fill(106,242,10);  
      rect(200, 210, 50,50);
     //  println(" clear ON", tog6,val);   for debbuging
     }  
     break;

   default:
     {
       //println("Zulu");   // Does not execute
      }
     break;
  }
} 
//To clear text redraw the button and write it again  end
//###################


void imprimir(char y)        // Imprimir legende on Button (On or Off) Start
 {
     // println("x", y);  for debbuging
  
  switch(controlNunber) 
  {
   case 'B':                        // Room 1
     fill(15,13,13); 
      if (tog1 == 0)
     {
        tog1= 1;
       text("On", 66,60);
     }
     else
     {
          tog1= 0;
           text("Off", 66,60);
     }
      break;
    
  case 'C': 
        fill(15,13,13);               // Room 2
       if (tog2 == 0)
         {
          tog2= 1;
          text("On", 213,60);
          }
       
       else
         {
         tog2= 0;
         text("Off", 213,60);
         }
     break;
  
 case 'D':             // Room 3

     fill(15,13,13); 
        if (tog3 == 0)
     {
        tog3= 1;
       text("On", 66,150);
      }
     else
         {
           tog3= 0;
           text("Off", 66,150);
            }
      break;
    
       case 'E':             // Room 4
     fill(15,13,13); 
        if (tog4 == 0)
     {
        tog4= 1;
      text("On", 213,150);
     }
     else
     {
           tog4= 0;
          text("Off", 213,150);
          }
      break;

   
      case 'F':             // Room 5
     fill(15,13,13); 
        if (tog5 == 0)
     {
        tog5= 1;
      text("On", 66,240);
      }
   
       else
          {
           tog5= 0;
          text("Off", 66,240);
           }
      break ; 

     case 'G':             // Room 6
     fill(15,13,13); 
        if (tog6 == 0)
     {
        tog6= 1;
      text("On", 213,240);
     }
     
        else
         {
           tog6= 0;
          text("Off", 213,240);
          }
      break;
 // Imprimir legende on Button (On or Off) end
    
  default:
   { //println("Zulu");   // Does not execute
   }
   break;
 }  
}  

This is screaming "arrays" at me.

That screams "mid-1970s"

The compiler knows what the value of '1' is; the comment is unnecessary.

2 Likes

I have add that both codes wrote most by "copy-paste" method and hardly can be an example of good style for users of the forum...

2 Likes

Seems to me you are just sending an indexed character, why not something like

    if (val >= '1' and val <= '6')
      {
      int index = val - '1';
      digitalWrite (ledPins[index], ledStates[index]);   // Turn ON Led x Room x
      Serial.println('A' + index);           //  Return B, Led switched on
      ledStates[index] =!ledStates[index];
      delay (50);
      }

or something similar, and be 1/6 the code. There are several other places where arrays can achieve almost 6x code size reduction.

1 Like

As long as people keep on using numbers for characters, I do appreciate it; I don't know the ASCII table by heart.

It would not be necessary if the character was used

if (val == '1')

In other places it's done as it (in my opinion) should. @condorp, be consistent

Unless there is Bluetooth involved :wink:

1 Like

Your program is a good example of a "state machine" so perhaps it would be better to use a switch-case structure?

Yes, it is a state machine, but as I wrote it for people with very little knowlege I tried to keep it as simple as possible without worrying to "set the record " straight. Hope that does not offend you.

May I remind you that SAP is based on software of 60/70 (mainframes) and it is today a multimillon dolar business.
With respect to the '1', of course the compiler knows it, but the people with little knowledge may not. A comment may be unnecessary for someone but rather have too many than too little. It does not harm.
With respect to different ways to do it, it is done on purpose to show the differents possibilities (dont forget the programm is intended for people with low knowledge, or just starting with programming). In the literature you find both ways.

Because beeing intended for people just starting to write programms, I do not burden them with elegant statements, that may be a better style, but I sacrifice it for the sake of simplicity.
Hope it doesn't hurt your feeling of aesthetics

My point was that if you'd used the literal '1', it would have been obvious to all, and the comment would be unnecessary.

Imagine how big it would be if it were popular and suitable for embedded systems.

Comment 1
You are aware the Processing has methods to handle mouse and keyboard events? If your use e.g. the mouseClicked() event handler, all your mouse related code can go in there cleaning up the draw() method. Any reason you don't use that?

Processing also has a serialEvent() though I've burned my fingers a few times with it (but that is more than likely my mistake). Alternatively write a method (call it e.g. serialHandler()) and place all your receive functionality in there and call it from draw().

That would make your processing code basically look like

void setup()
{
  ...
  ...
}

void draw()
{
  serialHandler();
  ...
  ...
}

void mouseClicked()
{
  ...
  ...
}

void serialHandler()
{
  ...
  ...
}

void cleanPanel(char x)
{
  ...
  ...
}

void imprimir(char y)
{
  ...
  ...
}

Comment 2
Why do you pass parameters to cleanPanel() and imprimer() and not use them?

Comment 3

You have prepared to use a portIndex but when you open the port you use a hardcoded index.
Further, wouldn't it be much nicer to use the name? E.g.

String portName = "COM3";
...
...
 myPort = new Serial(this, portName, 9600)

I live mostly in a Windows world and I know that it works; I do not know if this works in Linux or Apple.

The only use of an index would, in my opinion, be if the user could actually select something from a dropdown list or so.

Comment 4

You're working with text; so the only possibility is characters ('1', 'A' etc); if the char variable would represent a number, you use 49 and so on. You will not teach beginners much by confusing them or teaching them the wrong way. I know that both are used but every time I see 49 instead of '1', I want to cry. And as pointed out by @anon56112670, it's a lot easier to understand. As I said, be consistent.

1 Like

Writing the bad code intentially as way of learning is definitely is not a good idea. No, to be honest I think you wrote it as best as you can. It would be better learn programming first before starting to teach others.

1 Like

Thank you for you detailled information. I do not know about the mouseClicked() event handler. I am rather new to both environments, Arduino and processin.

I will certainly use your suggestions in the future. I must confess, I am a bit reluctant to change SW that is aready working and fulfilling its functions. But as you said, there is always room for improvements and leaning.

Best regards

-----Original-Nachricht-----

I appreciate your comments, just as I said I want to show to new people the possibilities around. The first time I saw them I was a bit intrigue with them.

Well SAP is for Bussiness applications, much loved an hated by the people...

-----Original-Nachricht-----

Your sad opinion. If you now so much do something usefull and wrote a tutorial

-----Original-Nachricht-----

I have about 6 weeks experience in Processing :wink:

Search Reference / Processing.org for Mouse and for Keyboard; both will come in handy.

I respect your opinion It is the right way to do it, if you have the time. Believe me, I have been teaching at an university for 20 years and the method works specially for people that Need a quick fix ”now” and do not have the time to start learning but need to understand it very fast. It is just to give them a starting base. Would they have time, they do not need a tutorial or guide to learn. Anybody is intelligent enough to do it.

What is a bad code?, is it a code that do not work, or fulfil the purpose and that is hardly the case here. If you do not believe it just rigg the circuit and try it. Style? Beauty is in the eyes of the beholder. Have you ever used assembler?

You see, you give a starting point to the students and them give them the task to perfect it. It work as a dream and present them with a challenge that they take kindly.

That it does not conform to the conventional teaching tradition, I agree. But if anybody will adhere to traditional methods, mankind would not have had genius like Mozart; Beethoven, Einstein etc (Not that I am a genius or near it) It’s is just a case of thinking outside the box and being practical. History is full of examples of quick fixes (specially during wars), elegant? No they are not but work (sometimes anyway).

Does it help you this code in any way?

Learn bad habits, fast?
That's a Good Thing?

I have some very bad dreams.

1 Like

I'm not sure if I understand. If you're asking if your code will help me, the answer is "no"; I think that I'm too experienced. But I like looking at other people's code to see how they solve problems and learn from that.