Introduction: Another Arduino Counter

About: Just passing through and staying at all the best places in life

Adaptive reporting parts batch counter

A counter that can adapt to the machine it is fitted to and report data back to other locations e.g. supervisor desk


Here is counter I built as a working prototype for a company I once worked for. This was the second version.

For the first one I used buttons taken from the front of an older “AT” computer case along with LED’s from the same case.

These shields generally have 3 spare DIO’s and 5 spare AIO’s but check your shield as they are not all the same and some have more spares If they are serial based/ i2c etc.

This one has plated through holes on the upper and lower edges that I wired to a distribution block. Soldered mine but recommend using angled pin headers.

Included the text from part of my written company presentation to give you more ideas.

Step 1: Benefits of This Type of Counter.

Capable of sending count data back DIRECTLY to other locations such as supervisor desk for more accurate and reliable part counts with correct configuration.

Can send that count data via multiple methods :- Wireless (multiple frequency options), Ethernet, Serial, GSM or even Local data logging such as SD cards.

Can be mounted in less prone positions than many mechanical counters or even incorporated into many existing electrical panels.

Long term cost savings. As the counter will be mounted “away from the action” its life will be many magnitudes greater than the present mechanical counters. Only the sensors are likely to need replacement but even those will be on a much reduced cycle compared to the present system.

Exceptionally flexible can be programmed to include additional functions on the same board such as machine temperature’s, automated call lights, limited operator monitoring.

Wide +5v to +20 maximum supply voltage. This lends itself to easy integration into many of the existing machines and can also operate via cheap wall adaptors if a reasonable supply is not available.

Cheaper than mechanical counters. Current prototype came in around $30 inclusive of taxes and shipping. The same units can also be obtained or built even cheaper using other options / sources of the same device.

Ability to use “off the shelf components” at very very low cost from suppliers worldwide

Logs and time stamps on logged data will show where and when counters were reset or tampered with. If operators are aware of this they may be less prone to "fudge" numbers which will result in better / more accurate counts.

Should also be possible to add feature to include bar / material type selection resulting in better stock levels of specific parts.

Can be set for either operator (unsecure) or maintenance (secure) increment change for machines that cut multiple parts at once.

Sensor input ( currently shield for demonstration) but easily modified for multiple sources from inductive , capacitive, IR, micro switch, etc. etc.

This program currently set for bar shears with variable increment size ( can accommodate any increment from 1 to 32,767 see above ).

Ability to track total machine cuts / strokes for maintenance & service functions and blade life etc.

Known limitations:-

Upper count limit 32,767 due to 8 bit arithmetic (could use FLOAT to expand counter).

Stuck sensor may continue count but time stamps will show where this happened and this would occur on other electronic counters too.

Can be susceptible to high electrical noise. Must be in screened / metal case in most applications.

Requires power supply.

Step 2: Interfacing

Have had it hooked up to an industrial proxy sensor but that requires its own power supply and can be wired as you would wire a higher voltage / current load.

The output on most industrial sensors is often NOT just a simple on/off pulse but a VOLTAGE pulse so measure yours and add suitable droppers / protection to prevent damage BEFORE you connect it to the Arduino. There are also two, three and four wire variations. I used a four wire and it was harder to interface than a 3 wire which just needed a 500K resistor in the signal line @ 9 volt input to operate the counter.

You should have a decent multimeter if you are going down this route !

If in doubt you can stick to switches or simpler short range PIR / ultrasonic sensors.

For the demo I used it on a local computer and used two programs to set up a quick demonstration. I used “Gobetweeno” and “CoolTerm”

http://mikmo.dk/gobetwino.html

http://freeware.the-meiers.org

These allowed me to capture the data live from the counter and did not require any changes to the program as I already had serial debugging enabled and rather than use the IDE serial screen I just picked the data up from Coolterm.

When it comes to using either of the two programs then rather than go into all the nuances here there is ample documentation on the web sites for those two programs please refer to those. As I said I am quite new to Arduino and I had to use them a bit to get myself going.

The code is heavily documented and a few parts are remarked out as it was either deemed not needed or I did not have the skills to finish it.

If you can make it better feel free
and let me have a copy so that I can improve my skills.

Would love to be able to store and retrieve a few variables in case of a power outage and think I was on the correct path but not clever enough to actually finish it.

Although if you use the “Reporting” side of things it should be easy enough to get the numbers needed back from the reporting computer.

Step 3: Costs and Parts Options

Costings :- updated 12.07.14 **

My first unit was built using an “official “ Arduino, but EBay is your friend and I now have two copies that work just fine. I did run into some issues using a Leonardo due to the way it handles serial communication. This meant I sometimes lost display (blank) at boot up until something changed in the count and then the display would return to normal. So I would avoid those models for the counter.

It is possible as I have done it, to build the same as the one I show for under $6.00

Included the costings as they show how easy it is to build the same counter with options to suit hardware you may already have available. You will have to adapt the code slightly to adjust to differing hardware but it should not be too difficult.

Barest unit including display consisting of 1x Pro Mini atmega328 5V 16M $3.00

** $2.26

Blue IIC I2C TWI 1602 16x2 Serial LCD Module Display $5.00

** $1.99

7 SEGMENT 4 DIGIT DISPLAY (i2C) ** $7.30

(BARE) ** $1.86

TOTAL $8.00

TOTAL 2 ** $4.25

Same as sample unit Arduino Leonardo (updated to UNO) $7.70

** $3.20

Display shield with buttons $6.70

** $1.99

TOTAL $14. TOTAL 2 ** $5.19

Options :-

Power supplies USB derived suit bare unit (cable) $2.00

12V to 5V 3A 15W Car Power DC-DC Power Converters $3.00

Wall outlet to 5V 1A $4.87

Ethernet options with POE (bare board) $

Without POE (bare board) $3.43

** $3.38

With POE (shield) $17.50

Without POE (shield) $8.30

** $5.93

Wireless options NRF24L01+ 2.4GHz Antenna Wireless Transceiver $1.10

** $0.99

433 MHz Transmitter + Receiver Module $1.20

** $1.19

315 MHz Transmitter + Receiver Module $1.30

** $1.28

Bluetooth shield complete $12.00

** $9.89

SIM900 Quad band Wireless GSM/GPRS Shield $32.00

** $21.50

Serial options MAX3232 RS232 to TTL Serial Port Converter Module DB9 Connector $1.70

** $1.65

SD card option SD Slot Socket Reader for Arduino ARM MCU Read and Write $1.00

** $0.82

Data Logger Module Logging Shield Data Recorder Shield for

Arduino UNO SD Card 2 including RTC $6.00

** $5.93

RTC suit bare unit upward $1.00

** $1.45

Many other options are available “off the shelf” to suit other needs. Above is a basic selection only.

Step 4: Code

[code]

/*******************************************************

R.S.P. Humpleby 2014

Project - Adaptive counter can be tailored to any current machine.

Benefits :-

Capable of sending count data back to other locations for more accurate and reliable part counts.

Capable of shutting down machine at end of run for change over

Can tell operator when end of part run is done saving costs in "over run"

Can be mounted in less prone positions than current mechanical counters.

Long term cost savings.

More reliable.

Exceptionally flexible can be programmed to include additional functions on the same board such as machine tempratures, automated call lights, ethernet, data logging, etc.

Wide +5v to +20 maximum supply voltage.

Cheaper than mechanical counters.

Logs and time stamps will show where counters were reset or tampered with.

If operators are aware of this they may be less prone to "fudge" numbers which will result in better / more accurate counts.

Should also be possible to add feature to include bar / material type selection resulting in better stock levels of specific parts.

Can be set for either operator (unsecure)or maintenance (secure) increment change.

Sensor input currently shield for demonstration, but easily modified for multiple sources from inductive , capacitive, IR, microswitch, etc. etc.

This program currently set for bar shears with variable increment size ( can accomodate any increment from 1 to 32,767 see above ).

***********************************************************

known limitations:-

Upper count limit 32,767 due to 8 bit arithmatic (could use FLOAT to expand counter).

Stuck sensor may continue count but time stamps will show where this happened and this would occur on other electronic counters.

Suceptible to high electrical noise. Must be in screened / metal case in most applications.

Requires power supply within 10 foot of MCU.

EEPROM write limit 100,000 !!! at which point unit needs program to 4 new EEPROM locations (512 available)

TO DO *****************************************************

Add EEPROM RECOVER for count in the event of power failure

set up bundle size menu

set up increment menu

***********************************************************

Revision

1.4 using string array.

Auto set increment to single for machines other than shear (defined by sting order).

Add EEPROM WRITE as per George suggestion

Add EEPROM CLEAR for legitimate reset (probably two points)

1.3 added Andrew suggestion of bundle countdown.

Added routine for pin high at bundle end. operator signal.

Added machine list (array) for future use.

1.2 included down count.

Added count increment and upper lower limits.

Improved serial output.

1.1 basic counter up function and reset only.

********************************************************/

#include // Display library

LiquidCrystal lcd(8, 13, 9, 4, 5, 6, 7); // select the pins used on the LCD panel

#include // EEPROM Functions

int bundle = 1000; // bundle size

int nm = 2; // selection of machine 0 = large shear, 1 = small shear etc etc

int lcd_key = 0; // set key initial value

int adc_key_in = 0; // set analog pin for key read

int count = 0; // count from zero

int inc = 50; // set counter increment ********** temp set to 50 for demo only **********

int deb = 300; // 1st debounce / false trigger factor (0.3 seconds)

int del2 = 100; // 2nd debounce / false trigger factor (0.1 seconds)

int led2 = 11; // use 11 as signal indicator for bundle end

int addr = 0; // set up for EEPROM write

int va5 = 1234; // set as an odd count for read back from EEPROM and transfer to bundle not currently used

int bd0 = ((EEPROM.read(0)*4)); // Read bundle value from EEPROM not currently used

int nm0 = ((EEPROM.read(1)*4)); // Read nm value from EEPROM not currently used

int ct0 = ((EEPROM.read(2)*4)); // Read count value from EEPROM not currently used

int in0 = ((EEPROM.read(3)*4)); // Read inc value from EEPROM not currently used

#define btnRIGHT 0 // used to decrement (inc) count steps

#define btnUP 1 // inrement count by ( inc )

#define btnDOWN 2 // decrement count by ( inc )

#define btnLEFT 3 // used to increment (inc) count steps

#define btnSELECT 4 // used to reset counter to zero

#define btnNONE 5 // used for error purposes only

#define endloop 6 // jump to end of bundle routine

#define restart // not yet initiated

// MACHINE LIST (see "nm" variable) You can change these to suit your own needs but I put the machines doing multiple cuts at the front of the list so one cut could be 6 bars which is the basis for the increment count.

char* Str1[ ] = { "LARGE 45 SHEAR ", "SMALL 45 SHEAR ", "STRAIGHT SHEAR ", "PLATE PRESS ", "ROLL FORM ", "SWAGER ", "THREADER ONE ", "THREADER TWO ",

"I/D MACHINE ", "PEELER ", "AUTO PIN ONE ", "AUTO PIN TWO ", "MANUAL PIN ONE ", "MANUAL PIN TWO ", "HEADER ", "WELDER ONE ", "WELDER TWO ", "WELDER THREE " } ;

int read_LCD_buttons() // read the buttons

{

restart;

adc_key_in = analogRead(0); // read the value from the shield

// my buttons when read are centered at these valies: 0, 144, 329, 504, 741

// add approx 50 to those values and check to see if we are close

if (nm >=3) inc = 1; // if machine not shear then increment = 1

if (bundle <=0) return endloop;

if (adc_key_in > 1000) return btnNONE; // generally no switch triggered

// BAR INC

if (adc_key_in < 50 && inc <= 10) inc = inc + 1 ; // increase bar count step size provided no more than 10

EEPROM.write(3, inc); // Store INC in EEPROM @@@@@@@@@@@@@@@@@@@@@@@@

if (adc_key_in < 50) return btnRIGHT;

// COUNTER INC

delay(del2);

if (bundle <=0) return endloop;

if (adc_key_in < 250) count = count + inc ; // increment counter by "inc"

EEPROM.write(2, count); // Store count in EEPROM @@@@@@@@@@@@@@@@@@@@@@@@

if (adc_key_in < 250) bundle = bundle - inc ; // decrease bundle size

if (adc_key_in < 250) return btnUP;

delay(del2);

//COUNTER DEC

if (bundle <=0) return endloop;

if (adc_key_in < 450) count = count -inc ; // decrement counter by "inc"

EEPROM.write(2, count); // Store count in EEPROM @@@@@@@@@@@@@@@@@@@@@@@@

if (adc_key_in < 450) bundle = bundle + inc ; // increase bundle size

EEPROM.write(0, bundle); // Store bundle in EEPROM @@@@@@@@@@@@@@@@@@@@@@@@

if (adc_key_in < 450) return btnDOWN;

// BAR DEC

delay(del2);

if (bundle <=0) return endloop;

if (adc_key_in < 650 && inc >=1) inc = inc - 1 ; // decrement bar count step size

EEPROM.write(3, inc); // Store INC in EEPROM @@@@@@@@@@@@@@@@@@@@@@@@

if (adc_key_in < 650) return btnLEFT;

// ENDLOOP JUMP

delay(del2);

if (bundle <=0) return endloop;

//RESET

delay(del2);

if (adc_key_in < 850) count = 0; // reset counter

if (adc_key_in < 850) bundle = 1000; // reset bundle

for (int i = 0; i < 3; i++) // clear first 5 bytes of EEPROM

EEPROM.write(i, 0); // clear first 5 bytes of EEPROM

if (adc_key_in < 850) return btnSELECT;

return btnNONE; // in case of error

}

void setup() // INITALISE

{

Serial.begin (9600); // Set up serial and remote count using "cool term"

while (!Serial) {

; // wait for serial port to connect. Needed for Leonardo only

}

lcd.begin(16, 2); // set up the LCD's number of columns and rows:

lcd.setCursor(0, 0); // line 1

lcd.print("JENMAR INC c2014"); // splash screen

lcd.setCursor(0, 1); // line 2

lcd.print("ADAPTIVE COUNTER"); // splash screen

delay (5000); // pause 10 seconds

lcd.clear(); // clear screen

lcd.setCursor(0, 0); // line 2

lcd.print(Str1[nm]); // STD MACHINE LOGO

pinMode(led2, OUTPUT); // define signal on

}

void loop() // MAIN LOOP

{

lcd.setCursor(0,1); // move to the begining of the second line

lcd_key = read_LCD_buttons(); // read the buttons

switch (lcd_key) // depending on which button was pushed, we perform an action

{

case btnRIGHT:

{

if (inc >=10) inc = 10; // ensure upper limit

Serial.println(Str1[nm]);

Serial.print (" increment = ");

Serial.println(inc);

delay (deb); // debounce and increment counter step + 1

break;

}

case btnLEFT:

{

if (inc <=0) inc = 1; // ensure lower limit

Serial.println(Str1[nm]);

Serial.print(" Decrement = ");

Serial.println(inc);

delay (deb); //debounce decrement counter step - 1

break;

}

case btnUP:

{

lcd.print(count); // display counter plus count

lcd.print(" BNDL>"); // Bundle text

lcd.print(bundle); // bundle count

lcd.print(" "); // trailing spaces

Serial.println(Str1[nm]);

Serial.print (" UP count ");

Serial.println(count);

delay (deb); // debounce

break;

}

case btnDOWN:

{

lcd.print(count); // display counter minus count

lcd.print(" BNDL>"); // Bundle text

lcd.print(bundle); // bundle count

lcd.print(" "); // trailing spaces

Serial.println(Str1[nm]);

Serial.print (" DOWN count ");

Serial.println(count);

delay (deb); // debounce

break;

}

case btnSELECT:

{

lcd.print(count); // display counter back to zero

lcd.print(" BNDL>"); // Bundle text

lcd.print(bundle); // bundle count

lcd.print(" "); // trailing spaces

Serial.print ("***** ");

Serial.print (Str1[nm]);

Serial.print (" COUNTER RESET ***** = ");

Serial.println(count);

for (int i = 0; i < 4; i++) // clear first 5 bytes of EEPROM

EEPROM.write(i, 0); // clear first 5 bytes of EEPROM

delay (deb); // debounce

break;

}

case endloop:

{

digitalWrite(led2, HIGH); // turn the bundle end signal on

lcd.clear(); // clear screen

lcd.setCursor(0, 0); // line 1

lcd.print("> BUNDLE END <"); // splash screen

lcd.setCursor(0, 1); // line 2

lcd.print("* CHANGE OVER *"); // splash screen

delay (20000); // pause 20 seconds

digitalWrite(led2, LOW); // turn the bundle end signal off

bundle = 1000; // reset bundle

count = 0; // reset counter

for (int i = 0; i < 4; i++) // clear first 5 bytes of EEPROM

EEPROM.write(i, 0); // clear first 5 bytes of EEPROM

lcd.clear(); // clear screen

lcd.setCursor(0, 0); // line 1

lcd.print(Str1[nm]); // STD LOGO

lcd.setCursor(0,1); // line 2

break;

}

case btnNONE:

{ //lcd.print("NONE "); treat as a regular key press

delay (deb); // debounce

break;

}

// case epWRITE:

// {

// Write copies of critical variables to EEPROM

// int va0 = bundle / 4; // prep variables for eeprom

// int va1 = nm / 4; // prep variables for eeprom

// int va2 = count / 4; // prep variables for eeprom

// int va3 = inc / 4; // prep variables for eeprom

// EEPROM.write(0, va0); // write to eeprom

// EEPROM.write(1, va1); // write to eeprom

// EEPROM.write(2, va2); // write to eeprom

// EEPROM.write(3, va3); // write to eeprom

// }

// case EPclear:

// {

// Legitimate reset ****** moved to legit reset section ********

// EEPROM clear routine

// for (int i = 0; i < 4; i++) // clear first 5 bytes of EEPROM

// EEPROM.write(i, 0); // clear first 5 bytes of EEPROM

// break;

// }

// case EPread:

// {

// Read and update variables from EEPROM if they exist and are different from either 0 or initial value

// va0 = (EEPROM.read(0)*4); // Read bundle value from EEPROM

// int bundle = va0 * 4; // Set variables using eeprom

// va1 = (EEPROM.read(1)*4); // Read count value from EEPROM

// int count = va1 * 4; // Set variables using eeprom

// va2 = (EEPROM.read(2)*4); // Read machine name value from EEPROM

// int nm = va2 * 4; // Set variables using eeprom

// va3 = (EEPROM.read(3)*4); // Read increment value from EEPROM

// int inc = va4 * 4; // Set variables using eeprom

// break;

// }

}

}

// EOF

[/code]

Step 5: Poor Video of Version One!

Was designed for one type of machine but potential was seen for manual counting problems and mechanical counter issues on most of the machines in the plant so it was changed up quickly to suit others.

Counter version one

Feel free to use it as you wish but remember where you found it.