Documentation **[[documentation|Home]]**
====== Smart counter for ALTIVAR 11 ======
===== Parts used before implement Smart Counter =====
* ALTIVAR 11 ( ATV11HU41M2E )
* Unstabilized 24V Power Supplie
* 24V signal impuls odometer
===== Smart Counter Function =====
* Count signals from 24V signal impuls odometer (down or up to final preset number)
* Preset count number
* Large display number
* Input Keyboard
* Control Logical Inputs on ALTIVAR 11 (speed, ramp) with Optisolated line
* Control Fault line with Optoisolated line
===== Assembling elements =====
==== Plastic case ====
We will need one plastic case with follow dimension :axbxc\\
It is good decision to use one electrical junction box.
=== Picture ===
{{:smart_counter_altivar11:counter_014.jpg?300|}}
==== Optocouppler ====
We will need 5x Optocuppler for 4x digital outout (L1, L2, L3, L4) and one for optical rotation detection digital input.\\
Depend of function Optocuppler must have right orientation (input parts have LED in circuite).\\
=== Schematic and modification ===
{{:smart_counter_altivar11:oc-module-sch-mod_v100.png?300|}}
=== Picture ===
{{:smart_counter_altivar11:counter_016.jpg?300|}}
==== LCD display & Keyboard====
One 20x4 (2004) character LED display will be used to show information, and 5x tactile switchs (2 gray Up/Down, 1 black 1x/10x/100x, 1 red Stop and 1 green Start). \\
To connect all together it will be use [[lcd_kyb|LCD & Keyboard Adapter Board]] which use 7 digital I/O line for communication with LCD Display and 1 analogue line for connection with 5 keys.
=== Picture ===
{{:smart_counter_altivar11:counter_015.jpg?300|}}
==== I/O screw terminals ====
=== Picture ===
===== Altivar 11 configuration =====
==== Speed and ramp ====
**LSP** (low speed) - from 0 to HSP (default 0Hz) \\
**HSP** (high speed) - from LSP to 200Hz (default 50/60Hz) \\
\\
When 3C is set **LSP** is final working speed predefined via configuration or set via resistor on analog input. \\
\\
Ramp and Ramp2 is predefined in seconds which will take from begining speed till final speed. \\
Image of logical sinalisation: \\
{{:smart_counter_altivar11:altivar_11_speed_control.png?300|}}
==== Input setup ====
**L1** Stop \\
**L2** Run/Forward \\
**L3** Speed2 \\
**L4** Second Ramp \\
==== Part of configuration setup ====
tCC -> ACt -> 3C \\
rrS -> n0 \\
PS2 -> LIA -> LI3 \\
PS2 -> LIb -> n0 \\
PS2 -> SP2 -> 25 \\
rP2 -> LI -> LI4 \\
===== Final product =====
==== Key functionality ====
=== Set counter Part ===
* **Up** (gray) - counter plus x
* **Down** (gray) - counter minus x
* **Multiplay** (black) - set x (1,10,100)
* **Stop** (red) - reset counter to 0
* **Start** (green) - start working part
=== Working Part ===
* **Stop** (red) - stop working part
* **Up** (gray) - start speed 2 set
* **Down** (gray) - stop speed 2 set
Any key press for final screen.\\
==== Hardware ====
=== Picture ===
{{:smart_counter_altivar11:counter_002.jpg?300|}}\\
{{:smart_counter_altivar11:counter_001.jpg?300|}}\\
==== Software ====
/*
Author: Dubravko Penezic
Version: 1.0, 2012
This code is for controling Altivar 11 unit, and counting rotation.
Source code is provided as is, without any warranty.
Distributetd under CC BY v 3.0
http://pcb.daince.net/doku.php?id=arduino_code
*/
/*
include class for formating numbers to string
*/
#include
//initialize class
DpFormatNumber fN;
//7 chars for transforming number to string
char cs[7];
/*
include class for LCD display settings
*/
#include
// LCD digital I/O pins
int BeLi_LCD_pin = 9;
int RS_LCD_pin = 7;
int En_LCD_pin = 8;
int D4_LCD_pin = 13;
int D5_LCD_pin = 12;
int D6_LCD_pin = 11;
int D7_LCD_pin = 10;
// initialize class with interface pins information
LiquidCrystal lcd(RS_LCD_pin, En_LCD_pin, D4_LCD_pin, D5_LCD_pin, D6_LCD_pin, D7_LCD_pin);
/*
include class for showing large 4 row numbers
*/
#include
// initialize class with pointer to LCD class
DpLCDBigNumber4L lcdn(&lcd);
/*
keyboard settings
*/
//Analogue value for key
int adc_key_val[6] ={30, 170, 390, 570, 790, 1024 };
//Key function
int key_fun[6] = {3, //Count up
2, //Count down
4, //10x, reset
0, //Start
1 //Stop
};
//Number of keys
int NUM_KEYS = 6;
//Analog pin
int aKeyPin = 7;
//last key value
int key = 5;
/*
digital output settings
*/
// {pin,LOW|HIGH}
int Lx[4][2] = {
{6,LOW}, // L1 - Stop
{5,LOW}, // L2 - Forward
{3,LOW}, // L3 - Speed 2
{4,LOW} // L4 - Ramp2
};
/*
digital input settings
*/
//Digital pin
int od = 2;
/*
configuration variable for program execution
*/
//pre set counter
long counter = 0;
//counted ticks
long actCounter = 0;
//counting ticks or not
int start_count = 0;
// time in miliseconds waiting for another digit when setting counter
int sCd = 100;
// time in seconds before actualy start motor
int pSt = 15;
//ramp delay time
int Ramp1DT = 3000;
int Ramp2DT = 5000;
//Counter diff mark to stop
long stopDiff = 10;
//Counter diff mark to stop speed 2
long stopSP2Diff = 50;
// work type - 0 setting counter
// 1 counting and controling electro motore
int work_type = 0;
// setup
void setup(void) {
//set output digital pins to OUTPUT state
for (int i = 0; i < 4; i++) {
pinMode(Lx[i][0], OUTPUT);
}
//set all digital input pins to LOW
allLxLow();
//set interupt procdure countRotation to interupt 0 and using RISING parameter
attachInterrupt(0, countRotation, RISING);
// start serial port
Serial.begin(9600);
Serial.println("CounterAltivar11 v 1.0");
Serial.println("Author: Dubravko Penezic, 2013");
Serial.println("CC BY v 3.0");
//set becklite on LCD on
pinMode(BeLi_LCD_pin, OUTPUT);
digitalWrite(BeLi_LCD_pin, HIGH);
//set LCD parameters
lcd.begin(40, 2);
lcd.noCursor();
lcd.clear();
//set big number graphems
lcdn.setGC();
//show welcome message
showStartMessage();
}
//main loop
void loop(void) {
// set counter
if(work_type == 0) setCounter();
// counting
if(work_type == 1) doJob();
}
// interrupt handling
void countRotation() {
if(start_count == 1) actCounter++;
}
/*
setting counter procedures
*/
void setCounter() {
int cv = 1;
showCounter(counter);
while(work_type == 0) {
key = readKeyPad();
if(key == key_fun[0]) counter=counter+cv;
if(key == key_fun[1]) counter=counter-cv;
if(key == key_fun[4]) counter=0;
if(key == key_fun[2] && cv == 1) cv=10;
else if (key == key_fun[2] && cv == 10) cv=100;
else if (key == key_fun[2] && cv == 100) cv = 1;
if(key == key_fun[3]) work_type = 1;
if(key != 5) {
showCounter(counter);
}
delay(sCd);
}
}
/*
couting rotattion and manage motor action
*/
void doJob(){
int finStat = 0;
actCounter = 0;
waitToStart();
if(work_type == 0) finStat = 1;
else {
lcd.clear();
showCounter(counter-actCounter);
start_count=1;
LxStart();
}
while(work_type == 1){
showCounter(counter-actCounter);
key = readKeyPad();
if(key == key_fun[4]){
LxStop();
finStat = 2;
work_type = 0;
}
if(key == key_fun[0])
LxStartSP2();
if(key == key_fun[1])
LxStopSP2();
if((counter-actCounter)= 0) {
fN.UnsInt2ForStr(i,4,true,cs);
lcdn.printStrNo(cs,8);
key = readKeyPad();
if(key == key_fun[4]) work_type = 0;
delay(1000);
i--;
}
}
//job finishing sequence
void waitOnEnd(int finStat, long actCounter) {
String pSt;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Current job done");
lcd.setCursor(20, 0);
lcd.print("Job status:");
lcd.setCursor(32, 0);
if(finStat == 0) lcd.print(" OK ");
else if (finStat == 1) lcd.print("USER brk");
else if (finStat == 2) lcd.print("WORK brk");
pressAnyKey();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Counter set :");
fN.SigLon2ForStr(counter,6,true,cs);
lcd.setCursor(15, 0);
lcd.print(cs);
lcd.setCursor(0, 1);
lcd.print("Counter mess:");
fN.SigLon2ForStr(actCounter,6,true,cs);
lcd.setCursor(15, 1);
lcd.print(cs);
lcd.setCursor(20, 1);
lcd.print("Counter diff:");
fN.SigLon2ForStr(counter-actCounter,6,true,cs);
lcd.setCursor(35, 1);
lcd.print(cs);
pressAnyKey();
}
/*
presentation procedure
*/
void showCounter(long counter_tmp) {
if(counter_tmp<0) fN.SigLon2ForStr(counter_tmp,7,true,cs);
else fN.SigLon2ForStr(counter_tmp,6,true,cs);
lcdn.printStrNo(cs,0);
}
void showStartMessage(){
lcd.setCursor(0, 0);
lcd.print("Altivar Counter v1.0");
lcd.setCursor(0, 1);
lcd.print(" 2013 ");
lcd.setCursor(20, 0);
lcd.print("Author:");
lcd.setCursor(20, 1);
lcd.print("Dubravko Penezic");
delay(5000);
lcd.clear();
}
/*
working with keys
*/
//read key
int readKeyPad() {
int adc_key_in;
int key_begin;
int key_end;
adc_key_in = analogRead(aKeyPin); // read the value from the sensor
key_begin = get_key(adc_key_in); // convert into key press
delay(50); // wait for debounce time
adc_key_in = analogRead(aKeyPin); // read the value from the sensor
key_end = get_key(adc_key_in); // convert into key press
if(key_begin != key_end) return 5; // some error, nothing is press
else return key_begin;
}
// Convert ADC value to key number
int get_key(unsigned int input) {
int k;
for (k = 0; k < NUM_KEYS; k++) {
if (input < adc_key_val[k]) {
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}
//waiting for key to be press
void pressAnyKey() {
delay(5000);
key = readKeyPad();
while(key == 5){
key = readKeyPad();
delay(sCd);
}
}
\\
/*
Author: Dubravko Penezic
Version: 1.0, 2012
This code is for controling Altivar 11 unit, and counting rotation.
Source code is provided as is, without any warranty.
Distributetd under CC BY v 3.0
http://pcb.daince.net/doku.php?id=arduino_code
*/
/*
include class for formating numbers to string
*/
#include
//initialize class
DpFormatNumber fN;
//7 chars for transforming number to string
char cs[7];
/*
include class for LCD display settings
*/
#include
// LCD digital I/O pins
int BeLi_LCD_pin = 9;
int RS_LCD_pin = 7;
int En_LCD_pin = 8;
int D4_LCD_pin = 13;
int D5_LCD_pin = 12;
int D6_LCD_pin = 11;
int D7_LCD_pin = 10;
// initialize class with interface pins information
LiquidCrystal lcd(RS_LCD_pin, En_LCD_pin, D4_LCD_pin, D5_LCD_pin, D6_LCD_pin, D7_LCD_pin);
/*
include class for showing large 4 row numbers
*/
#include
// initialize class with pointer to LCD class
DpLCDBigNumber4L lcdn(&lcd);
/*
keyboard settings
*/
//Analogue value for key
int adc_key_val[6] ={30, 170, 390, 570, 790, 1024 };
//Key function
int key_fun[6] = {3, //Count up
2, //Count down
4, //10x, reset
0, //Start
1 //Stop
};
//Number of keys
int NUM_KEYS = 6;
//Analog pin
int aKeyPin = 7;
//last key value
int key = 5;
/*
digital output settings
*/
// {pin,LOW|HIGH}
int Lx[4][2] = {
{6,LOW}, // L1 - Forvard
{5,LOW}, // L2 - Revers
{3,LOW}, // L3 - Speed 2
{4,LOW} // L4 - Revers
};
/*
digital input settings
*/
//Digital pin
int od = 2;
/*
configuration variable for program execution
*/
//pre set counter
long counter = 0;
//counted ticks
long actCounter = 0;
//counting ticks or not
int start_count = 0;
// time in miliseconds waiting for another digit when setting counter
int sCd = 50;
// time in seconds before actualy start motor
int pSt = 2;
//ramp delay time
int Ramp1DT = 3000;
int Ramp2DT = 5000;
//Counter diff mark to stop
long stopDiff = 2;
//Counter diff mark to stop speed 2
long stopSP2Diff = 10;
// work type - 0 setting counter
// 1 counting and controling electro motore
int work_type = 0;
int reverse=1;
// setup
void setup(void) {
//set output digital pins to OUTPUT state
for (int i = 0; i < 4; i++) {
pinMode(Lx[i][0], OUTPUT);
}
//set all digital input pins to LOW
allLxLow();
//set interupt procdure countRotation to interupt 0 and using RISING parameter
attachInterrupt(0, countRotation, RISING);
// start serial port
Serial.begin(9600);
Serial.println("CounterAltivar11 v 1.0");
Serial.println("Author: Dubravko Penezic, 2013");
Serial.println("CC BY v 3.0");
//set becklite on LCD on
pinMode(BeLi_LCD_pin, OUTPUT);
digitalWrite(BeLi_LCD_pin, HIGH);
//set LCD parameters
lcd.begin(40, 2);
lcd.noCursor();
lcd.clear();
//set big number graphems
lcdn.setGC();
//show welcome message
showStartMessage();
}
//main loop
void loop(void) {
// set counter
if(work_type == 0) setCounter();
// counting
if(work_type == 1) doJob();
}
// interrupt handling
void countRotation() {
if(start_count == 1) actCounter++;
}
/*
setting counter procedures
*/
void setCounter() {
int cv = 1;
showCounter(counter);
while(work_type == 0) {
key = readKeyPad();
if(key == key_fun[0]) counter=counter+cv;
if(key == key_fun[1]) counter=counter-cv;
if(key == key_fun[4]) {
delay(3000);
key = readKeyPad();
if(key == key_fun[4])
counter=0;
}
if(key == key_fun[2] && cv == 1) cv=10;
else if (key == key_fun[2] && cv == 10) cv=100;
else if (key == key_fun[2] && cv == 100) cv = 1;
if(key == key_fun[3]) work_type = 1;
if(key != 5) {
showCounter(counter);
}
delay(sCd);
}
}
/*
couting rotattion and manage motor action
*/
void doJob(){
int finStat = 0;
actCounter = 0;
waitToStart();
if(counter<0)
reverse = -1;
else
reverse = 1;
if(work_type == 0) finStat = 1;
else {
lcd.clear();
showCounter(counter-actCounter);
start_count=1;
LxStart();
}
while(work_type == 1){
// showCounter(counter-actCounter);
showCounter(actCounter);
key = readKeyPad();
if(key == key_fun[2]) {
LxStop();
reverse = reverse * -1;
delay(1000);
LxStart();
}
if(key == key_fun[4]){
LxStop();
finStat = 2;
work_type = 0;
}
if(key == key_fun[0])
LxStartSP2();
if(key == key_fun[1])
LxStopSP2();
if(((counter*reverse)-actCounter)= 0) {
fN.UnsInt2ForStr(i,4,true,cs);
lcdn.printStrNo(cs,8);
key = readKeyPad();
if(key == key_fun[4]) work_type = 0;
delay(1000);
i--;
}
}
//job finishing sequence
void waitOnEnd(int finStat, long actCounter) {
lcd.clear();
showCounter(actCounter);
delay(2000);
key=5;
pressAnyKey();
}
//job finishing sequence
void waitOnEnd1(int finStat, long actCounter) {
String pSt;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Current job done");
lcd.setCursor(20, 0);
lcd.print("Job status:");
lcd.setCursor(32, 0);
if(finStat == 0) lcd.print(" OK ");
else if (finStat == 1) lcd.print("USER brk");
else if (finStat == 2) lcd.print("WORK brk");
pressAnyKey();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Counter set :");
fN.SigLon2ForStr(counter,6,true,cs);
lcd.setCursor(15, 0);
lcd.print(cs);
lcd.setCursor(0, 1);
lcd.print("Counter mess:");
fN.SigLon2ForStr(actCounter,6,true,cs);
lcd.setCursor(15, 1);
lcd.print(cs);
lcd.setCursor(20, 1);
lcd.print("Counter diff:");
fN.SigLon2ForStr(counter-actCounter,6,true,cs);
lcd.setCursor(35, 1);
lcd.print(cs);
pressAnyKey();
}
/*
presentation procedure
*/
void showCounter(long counter_tmp) {
if(counter_tmp<0) fN.SigLon2ForStr(counter_tmp,7,true,cs);
else fN.SigLon2ForStr(counter_tmp,6,true,cs);
lcdn.printStrNo(cs,0);
}
void showStartMessage(){
lcd.setCursor(0, 0);
lcd.print("Altivar Counter v1.0");
lcd.setCursor(0, 1);
lcd.print(" 2013 ");
lcd.setCursor(20, 0);
lcd.print("Author:");
lcd.setCursor(20, 1);
lcd.print("Dubravko Penezic");
delay(5000);
lcd.clear();
}
/*
working with keys
*/
//read key
int readKeyPad() {
int adc_key_in;
int key_begin;
int key_end;
adc_key_in = analogRead(aKeyPin); // read the value from the sensor
key_begin = get_key(adc_key_in); // convert into key press
delay(50); // wait for debounce time
adc_key_in = analogRead(aKeyPin); // read the value from the sensor
key_end = get_key(adc_key_in); // convert into key press
if(key_begin != key_end) return 5; // some error, nothing is press
else return key_begin;
}
// Convert ADC value to key number
int get_key(unsigned int input) {
int k;
for (k = 0; k < NUM_KEYS; k++) {
if (input < adc_key_val[k]) {
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}
//waiting for key to be press
void pressAnyKey() {
delay(2000);
key = readKeyPad();
while(key == 5){
key = readKeyPad();
delay(sCd);
}
}
//
/*
Author: Dubravko Penezic
Version: 1.0, 2012
This code is for counting rotation.
Source code is provided as is, without any warranty.
Distributetd under CC BY v 3.0
http://pcb.daince.net/doku.php?id=arduino_code
*/
// Format numbers to string
#include
DpFormatNumber fN;
// Display settings
#include
#include
// LCD pins
int BeLi_LCD_pin = 9;
int RS_LCD_pin = 7;
int En_LCD_pin = 8;
int D4_LCD_pin = 13;
int D5_LCD_pin = 12;
int D6_LCD_pin = 11;
int D7_LCD_pin = 10;
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(RS_LCD_pin, En_LCD_pin, D4_LCD_pin, D5_LCD_pin, D6_LCD_pin, D7_LCD_pin);
DpLCDBigNumber4L lcdn(&lcd);
//Switch settings
//Analogue value for key
int adc_key_val[6] ={30, 170, 390, 570, 790, 1024 };
//Key function
int key_fun[6] = {3, //Count up
2, //Count down
4, //10x, reset
0, //Start
1 //Stop
};
//Number of keys
int NUM_KEYS = 6;
//Analog pin
int aKeyPin = 7;
int key = 5;
//Digital input
int od = 2;
// work type - 0 setting counter
// 1 counting and controling electro motore
int work_type = 0;
int start_count = 0;
// counter
volatile long actCounter = 0;
boolean counting = false;
char cs[7];
// time in miliseconds waiting for another digiti when setting counter
int sCd = 100;
int Ramp2DT = 5000;
void setup(void) {
pinMode(BeLi_LCD_pin, OUTPUT);
digitalWrite(BeLi_LCD_pin, HIGH);
attachInterrupt(0, countRotation, RISING);
// start serial port
Serial.begin(9600);
Serial.println("Counter v 2.0");
lcd.begin(40, 2);
lcd.noCursor();
lcd.clear();
showStartMessage();
lcdn.setGC();
}
void loop(void) {
showCounter(actCounter);
key = readKeyPad();
if(key == key_fun[4]){
actCounter = 0;
lcd.clear();
}
}
void countRotation() {
actCounter++;
}
void showCounter(long counter_tmp) {
if(counter_tmp<0) fN.SigLon2ForStr(counter_tmp,7,true,cs);
else fN.SigLon2ForStr(counter_tmp,6,true,cs);
lcdn.printStrNo(cs,0);
}
void showStartMessage(){
lcd.setCursor(0, 0);
lcd.print("Counter v1.0");
lcd.setCursor(0, 1);
lcd.print(" 2013 ");
lcd.setCursor(20, 0);
lcd.print("Author:");
lcd.setCursor(20, 1);
lcd.print("Dubravko Penezic");
delay(5000);
lcd.clear();
}
int readKeyPad() {
int adc_key_in;
int key_begin;
int key_end;
adc_key_in = analogRead(aKeyPin); // read the value from the sensor
key_begin = get_key(adc_key_in); // convert into key press
delay(50); // wait for debounce time
adc_key_in = analogRead(aKeyPin); // read the value from the sensor
key_end = get_key(adc_key_in); // convert into key press
if(key_begin != key_end) return 5; // some error, nothing is press
else return key_begin;
}
// Convert ADC value to key number
int get_key(unsigned int input) {
int k;
for (k = 0; k < NUM_KEYS; k++) {
if (input < adc_key_val[k]) {
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}
==== Development cost ====
Parts and accessories cca 65 US$\\
Working time 8-10 hours cca 80 US$\\
===== Parts Documentation =====
* ALTIVAR 11 ( ATV11HU41M2E )
* {{:smart_counter_altivar11:45a11.pdf| Documentation 1}}
* {{:smart_counter_altivar11:telemecanique_variable_speed_drives_altivar_11_-_02.04.pdf| Documentation 2}}
* [[ebay_module_basic_duino|Basic Duino]]
* [[lcd_kyb|LCD & Keyboard Board]]
* [[oc_module|Optocoupler Modular Board]]