plcLib (Arduino): Counting and Counters

Version 0.8 of the software introduces counters, which can activate an output once a predetermined number of events have occurred. A counter 'object' may be configured to count up, down, or a combination of both.

Each counter has four inputs, and four outputs, shown at the left and right of above diagram, respectively. In practice, only a subset of these may be required, depending on the type of counter required.

Up Counter

At its simplest, an up counter counts pulses received on its countUp input, activating the 'finished' or upperQ output when the required number of input pulses have been detected. To illustrate the process, the following example creates an up counter which counts from 0 to 10, driven by switch presses applied to input X0.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

   Up Counter - Counts 10 pulses on Input 0 with switch debounce

   Connections:
   Count input - switch connected to input X0 (Arduino pin A0)
   Clear input - switch connected to input X1 (Arduino pin A1)
   Preset input - switch connected to input X2 (Arduino pin A2)
   Lower Q output - LED connected to output Y0 (Arduino pin 3)
   Upper Q output - LED connected to output Y1 (Arduino pin 5)

   Software and Documentation:
   http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(10);           // Final count = 10, starting at zero
unsigned long TIMER0 = 0;  // Define variable used to hold timer 0 elapsed time

void setup() {
  setupPLC();              // Setup inputs and outputs
}

void loop() {
  in(X0);                  // Read Input 0
  timerOn(TIMER0, 10);     // 10 ms switch debounce delay
  ctr.countUp();           // Count up
  
  in(X1);                  // Read input X1
  ctr.clear();             // Clear counter (counter at lower limit)
  
  in(X2);                  // Read input X2
  ctr.preset();            // Preset counter (counter at upper limit)

  ctr.lowerQ();            // Display Count Down output on Y0
  out(Y0);
  
  ctr.upperQ();            // Display Count Up output on Y1
  out(Y1);
}
Source location: File > Examples > plcLib > Counters > CountUp

Examining the above listing, the first step is to use the Counter command to create a counter object ctr, at the same time setting the final value to 10, which is equivalent to the presetValue property of the counter. The counter defaults to being an up counter, so the internal count value is initially zero, causing the lowerQ output to be activated. Pulses applied to the X0 input are linked to the countUp input, causing the internal count value to be incremented by each 0 to 1 transition. After 10 pulses, the count becomes equal to the upper limit or preset value, causing the upperQ output to be enabled.

A commonly encountered problem with counter circuits is switch bounce, where the switch contacts 'bounce' several times (over a period of a few milliseconds) before settling. This in turn may cause a single switch press to update the counter several times in rapid succession. To avoid this effect, notice that a 10 millisecond on-delay timer has been linked in series with the X0 switch connected to the countUp input.

It may also be necessary to manually force the counter to go back to the start, which is achieved in the above example by connecting switch input X1 to the clear input of the counter. The preset input (connected to switch input X2) performs a similar function, but this time setting the internal count to the final or preset value. Hence pressing the switches connected to inputs X1 or X2 will cause the lowerQ or upperQ outputs to be immediately activated, respectively.

Down Counter

The creation of a down counter is quite similar, as shown in the following listing.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

   Down Counter - Counts 5 pulses on Input 0 with switch debounce

   Connections:
   Count input - switch connected to input X0 (Arduino pin A0)
   Clear input - switch connected to input X1 (Arduino pin A1)
   Preset input - switch connected to input X2 (Arduino pin A2)
   Lower Q output - LED connected to output Y0 (Arduino pin 3)
   Upper Q output - LED connected to output Y1 (Arduino pin 5)

   Software and Documentation:
   http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(5, 1);         // Counts down, starting at 5
unsigned long TIMER0 = 0;  // Define variable used to hold timer 0 elapsed time

void setup() {
  setupPLC();              // Setup inputs and outputs
}

void loop() {
  in(X0);                  // Read Input 0
  timerOn(TIMER0, 10);     // 10 ms switch debounce delay
  ctr.countDown();         // Count down
  
  in(X1);                  // Read input X1
  ctr.clear();             // Clear counter (counter at lower limit)
  
  in(X2);                  // Read input X2
  ctr.preset();            // Preset counter (counter at upper limit)

  ctr.lowerQ();            // Display Count Down output on Y0
  out(Y0);
  
  ctr.upperQ();            // Display Count Up output on Y1
  out(Y1);
}
Source location: File > Examples > plcLib > Counters > CountDown

The first difference is in the creation of the Counter object ctr, using the Counter ctr(5, 1); command. As well setting the preset value to 5, the optional second parameter has a value of 1, causing the initial count value to be set equal to the upper limit, which is suitable for a down counter. (Omitting the second parameter, or setting it to zero inialises the count to zero). Input X0 is then connected to the countDown input, while output Y0 is driven by lowerQ. Hence Y0 will go high after 5 pulses have been received on input X0.

Up/Down Counter

It is straightforward to combine these two approaches in order to create a device capable of counting up or down, as shown in the example below.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

   Up-down Counter - Counts up or down in the range 0-10

   Connections:
   Count up input - switch connected to input X0 (Arduino pin A0)
   Count down input - switch connected to input X1 (Arduino pin A1)
   Clear input - switch connected to input X2 (Arduino pin A2)
   Preset input - switch connected to input X3 (Arduino pin A3)
   Lower Q output - LED connected to output Y0 (Arduino pin 3)
   Upper Q output - LED connected to output Y1 (Arduino pin 5)

   Software and Documentation:
   http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(10);           // Counts up or down in range 0-10, starting at zero
unsigned long TIMER0 = 0;  // Define variable used to hold timer 0 elapsed time
unsigned long TIMER1 = 0;  // Define variable used to hold timer 1 elapsed time

void setup() {
  setupPLC();              // Setup inputs and outputs
}

void loop() {
  in(X0);                  // Read Input 0
  timerOn(TIMER0, 10);     // 10 ms switch debounce delay
  ctr.countUp();           // Count up

  in(X1);                  // Read Input 1
  timerOn(TIMER1, 10);     // 10 ms switch debounce delay
  ctr.countDown();         // Count down

  in(X2);                  // Read input X1
  ctr.clear();             // Clear counter (counter at lower limit)
  
  in(X3);                  // Read input X2
  ctr.preset();            // Preset counter (counter at upper limit)

  ctr.lowerQ();            // Display Count Down output on Y0
  out(Y0);
  
  ctr.upperQ();            // Display Count Up output on Y1
  out(Y1);
}
Source location: File > Examples > plcLib > Counters> CountUpDown

The above counter has separate count-up and count-down inputs linked to input switches X0 and X1 respectively, and each counter input has its own debounced switch input.

Debugging Counter-based Applications

The output of a counter is activated once the defined number of pulses have been detected, but the internal count value is not normally visible to the user. In effect, the counter is either 'finished' or 'not finished'. It may sometimes be useful to view the internal count for debugging purposes, as shown in the following example.

#include <plcLib.h>

/* Programmable Logic Controller Library for the Arduino and Compatibles

   Up-down Counter - Counts up or down in the range 0-10
   (Sends current count to serial monitor)

   Connections:
   Count up input - switch connected to input X0 (Arduino pin A0)
   Count down input - switch connected to input X1 (Arduino pin A1)
   Clear input - switch connected to input X2 (Arduino pin A2)
   Preset input - switch connected to input X3 (Arduino pin A3)
   Lower Q output - LED connected to output Y0 (Arduino pin 3)
   Upper Q output - LED connected to output Y1 (Arduino pin 5)

   Software and Documentation:
   http://www.electronics-micros.com/software-hardware/plclib-arduino/

*/

Counter ctr(10);           // Counts up or down in range 0-10, starting at zero
unsigned long TIMER0 = 0;  // Define variable used to hold timer 0 elapsed time
unsigned long TIMER1 = 0;  // Define variable used to hold timer 1 elapsed time

void setup() {
  setupPLC();              // Setup inputs and outputs
  Serial.begin(9600);      // Open serial connection over USB
}

void loop() {
  in(X0);                  // Read Input 0
  timerOn(TIMER0, 10);     // 10 ms switch debounce delay
  ctr.countUp();           // Count up

  in(X1);                  // Read Input 1
  timerOn(TIMER1, 10);     // 10 ms switch debounce delay
  ctr.countDown();         // Count down

  in(X2);                  // Read input X1
  ctr.clear();             // Clear counter (counter at lower limit)
  
  in(X3);                  // Read input X2
  ctr.preset();            // Preset counter (counter at upper limit)

  ctr.lowerQ();            // Display Count Down output on Y0
  out(Y0);
  
  ctr.upperQ();            // Display Count Up output on Y1
  out(Y1);

  Serial.println(ctr.count());  // Send count to serial port
  delay(100);
}
Source location: File > Examples > plcLib > Counters > CountUpDownDebug

To debug the application, simply open the Serial Monitor while the sketch is running. This will repeatedly display the internal count value, with the repetition interval controlled by the delay command towards the end of the listing. (However, don't forget to remove the debugging code, once your application is working as intended.)

Related Topics

top