Code:
/*****************************************************************************/
/* */
/* CNC Indexer */
/* */
/* Wagner Mello May 2013 */
/* */
/*****************************************************************************/
// v5: May 17 2016 : rewrote Wlcd driver to have a proper print() and minor fixes in the code
// v4: July 29 2013 : Bug backlash solved
// V3: July 13 2013 : Bug newdeg%360 solved
// V2: July 12 2013 : Bug dJog = 0 solved
#include "Arduino.h"
#include
#include
#include
Wlcd lcd = Wlcd(2);
WStepper stp = WStepper();
#define KRT 1
#define KUP 2
#define KDW 3
#define KLF 4
#define KSL 5
#define CW 0
#define CCW 1
/*****************************************************************************/
int Stt;
int Cur;
int Key;
int Div;
long pStp; // Actual position (Steps)
long pDeg; // Actual position (Degrees x 1000)
long cDeg; // Calculated position (Degrees x 1000)
long sRot; // Steps per revolution
long sBkl; // Backlash (Steps)
float sVel; // Velocity (Steps/Second)
float sAcc; // Acceleration (Steps/Second²)
struct Cnf
{
int Mod; // Mode
int Stp; // Full steps per revolution
int Mst; // Microstepping mode
int Red; // Reduction gears
int Mvl; // Maximum velocity (Degrees/Minute)
int Acc; // Acceleration (Degrees/Second²)
int Bkl; // Backlash (Degres x 1000)
int nDiv; // Division mode, number of divisions
long dDeg; // Degree mode, step (Degrees x 1000)
long dJog; // Jog mode step (Degrees x 1000)
}Cnf;
char mIni[8][17] =
{
{" .. "},
{" . . "},
{" . . "},
{" . . "},
{" . . "},
{" . . "},
{" . . "},
{". ."}
};
char mMdd[5][11] =
{
{"Division "},
{"Degree "},
{"Jog "},
{"Continuous"},
{"Config "}
};
char uChr[][8] =
{
{0x04,0x0a,0x04,0x00,0x00,0x00,0x00,0x00}, // 1 Degree
{0x04,0x0e,0x1f,0x15,0x04,0x04,0x04,0x00}, // 2 Up Arrow
{0x04,0x04,0x04,0x15,0x1f,0x0e,0x04,0x00}, // 3 Down Arrow
{0x00,0x06,0x0c,0x1f,0x0c,0x06,0x00,0x00}, // 4 Left Arrow
{0x00,0x0c,0x06,0x1f,0x06,0x0c,0x00,0x00}, // 5 Right Arrow
{0x01,0x01,0x05,0x09,0x1f,0x08,0x04,0x00}, // 6 Return
{0x06,0x09,0x02,0x04,0x0f,0x00,0x00,0x00} // 7 Power 2
};
/*****************************************************************************/
void setup()
{
Stt = 0;
Key = 0;
ReadCnf();
lcd.init();
IniUsrChar();
Cnf.Mod = max(0,min(Cnf.Mod,4));
Cnf.Stp = max(1,min(Cnf.Stp,999));
Cnf.Mst = max(1,min(Cnf.Mst,999));
Cnf.Red = max(1,min(Cnf.Red,999));
Cnf.Mvl = max(1,min(Cnf.Mvl,9999));
Cnf.Acc = max(1,min(Cnf.Acc,999));
Cnf.Bkl = max(0,min(Cnf.Bkl,9999));
Cnf.nDiv = max(1,min(Cnf.nDiv,999));
Cnf.dDeg = max(1,min(Cnf.dDeg,359999));
Cnf.dJog = max(1,min(Cnf.dJog,100000));
sRot = (long)Cnf.Stp*(long)Cnf.Mst*(long)Cnf.Red;
sBkl = (lround)((float)Cnf.Bkl/360000.0*float(sRot));
sVel = (float)Cnf.Mvl/360.0*float(sRot)/60.0;
sAcc = (float)Cnf.Acc/360.0*float(sRot);
stp.Init(sVel,sAcc);
f00();
}
void loop()
{
int k;
if((k = GetKey()) != 0)
{
switch(Stt)
{
case 00:
f00();
break;
case 10:
f10();
break;
case 11:
f11(k);
break;
case 20:
f20();
break;
case 21:
f21(k);
break;
case 22:
f22();
break;
case 23:
f23(k);
break;
case 30:
f30();
break;
case 31:
f31(k);
break;
case 32:
f32();
break;
case 33:
f33(k);
break;
case 40:
f40();
break;
case 41:
f41(k);
break;
case 50:
f50();
break;
case 51:
f51(k);
break;
case 60:
f60();
break;
case 61:
f61(k);
break;
case 62:
f62();
break;
case 63:
f63(k);
break;
case 64:
f64();
break;
case 65:
f65(k);
break;
case 66:
f66();
break;
case 67:
f67(k);
break;
case 68:
f68();
break;
case 69:
f69(k);
break;
case 70:
f70();
break;
case 71:
f71(k);
break;
}
}
}
/*****************************************************************************/
void f00(void) // Start Screen
{
int i,j;
lcd.clear();
lcd.cursor(0);
print(" CNC Indexer");
for(i = 0; i 4)
Cnf.Mod = 0;
lcd.cursorTo(0,5);
print(mMdd[Cnf.Mod]);
break;
case KLF:
f00(); // Start Screen
break;
case KRT:
case KSL:
SaveCnf();
switch(Cnf.Mod)
{
case 0:f20();break;
case 1:f30();break;
case 2:f40();break;
case 3:f50();break;
case 4:f60();break;
}
break;
}
}
void f20(void) // Division Edit Screen
{
char buf[32];
lcd.clear();
sprintf(buf,"nDiv:%.3d ?",Cnf.nDiv);
print(buf);
lcd.cursorTo(1,0);
print("\4Sel\5 \2Edit\3 \6Ac");
lcd.cursorTo(0,7);
lcd.cursor(1);
Stt = 21;
Cur = 0;
}
void f21(int key) // Division Edit Key
{
char buf[16];
switch(key)
{
case KUP:
switch(Cur)
{
case 0:Cnf.nDiv += 1; break;
case 1:Cnf.nDiv += 10; break;
case 2:Cnf.nDiv += 100;break;
}
if(Cnf.nDiv >= 1000)
Cnf.nDiv -= 1000;
Cnf.nDiv = max(1,Cnf.nDiv);
sprintf(buf,"%.3d",Cnf.nDiv);
lcd.cursorTo(0,5);
print(buf);
lcd.cursorTo(0,7-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.nDiv -= 1; break;
case 1:Cnf.nDiv -= 10; break;
case 2:Cnf.nDiv -= 100;break;
}
if(Cnf.nDiv 2)
Cur = 0;
lcd.cursorTo(0,7-Cur);
break;
case KRT:
Cur--;
if(Cur= Cnf.nDiv)
Div = 0;
f = CW;
break;
case KDW:
case KLF:
Div--;
if(Div= 0)
{
lcd.cursorTo(0,4);
print(".......");
lcd.cursorTo(1,8);
print("........");
Index(Cnf.Mod,f,Div,Cnf.nDiv,Cnf.dDeg,Cnf.dJog);
lcd.cursorTo(0,4);
print(" ");
lcd.cursorTo(0,4);
sprintf(buf,"%d/%d",Div,Cnf.nDiv);
print(buf);
lcd.cursorTo(1,8);
PrintDeg();
}
}
void f30(void) // Degree Edit Screen
{
char buf[32];
lcd.clear();
sprintf(buf,"dDeg:%.3ld.%.3ld\1 ?",Cnf.dDeg/1000,Cnf.dDeg%1000);
print(buf);
lcd.cursorTo(1,0);
print("\4Sel\5 \2Edit\3 \6Ac");
lcd.cursorTo(0,7);
lcd.cursor(1);
Stt = 31;
Cur = 4;
}
void f31(int key) // Degree Edit Key
{
char buf[16];
switch(key)
{
case KUP:
switch(Cur)
{
case 0:
Cnf.dDeg += 1;
break;
case 1:
Cnf.dDeg += 10;
break;
case 2:
Cnf.dDeg += 100;
break;
case 4:
Cnf.dDeg += 1000;
break;
case 5:
Cnf.dDeg += 10000;
break;
case 6:
Cnf.dDeg += 100000;
break;
}
if(Cnf.dDeg >= 360000)
Cnf.dDeg -= 360000;
Cnf.dDeg = max(1,Cnf.dDeg);
sprintf(buf,"%.3ld.%.3ld\1",Cnf.dDeg/1000,Cnf.dDeg%1000);
lcd.cursorTo(0,5);
print(buf);
lcd.cursorTo(0,11-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.dDeg -= 1; break;
case 1:Cnf.dDeg -= 10; break;
case 2:Cnf.dDeg -= 100; break;
case 4:Cnf.dDeg -= 1000; break;
case 5:Cnf.dDeg -= 10000; break;
case 6:Cnf.dDeg -= 100000;break;
}
if(Cnf.dDeg 6)
Cur = 0;
lcd.cursorTo(0,11-Cur);
break;
case KRT:
Cur--;
if(Cur == 3)
Cur--;
if(Cur= 0)
{
lcd.cursorTo(0,2);
print("...........");
lcd.cursorTo(1,8);
print("........");
Index(Cnf.Mod,f,Div,Cnf.nDiv,Cnf.dDeg,Cnf.dJog);
lcd.cursorTo(0,2);
print(" ");
lcd.cursorTo(0,2);
sprintf(buf,"%dx%ld.%.3ld\1",Div,Cnf.dDeg/1000,Cnf.dDeg%1000);
print(buf);
lcd.cursorTo(1,8);
PrintDeg();
}
}
void f40(void) // Jog Exec Screen
{
char buf[32];
Div = 0;
pStp = 0;
pDeg = 0;
cDeg = 0;
lcd.clear();
lcd.cursor(0);
sprintf(buf,"J\2\3:%.3ld.%.3ld\1",Cnf.dJog/1000,Cnf.dJog%1000);
print(buf);
lcd.cursorTo(0,13);
print("\6Bk");
lcd.cursorTo(1,0);
print("\4Index\5");
lcd.cursorTo(1,8);
PrintDeg();
Stt = 41;
}
void f41(int key) // Jog Exec Key
{
int f = -1;
char buf[16];
switch(key)
{
case KUP:
Cnf.dJog *= 10;
if(Cnf.dJog>100000)
Cnf.dJog = 1;
sprintf(buf,"%.3ld.%.3ld\1",Cnf.dJog/1000,Cnf.dJog%1000);
lcd.cursorTo(0,4);
print(buf);
break;
case KRT:
Div++;
f = CW;
break;
case KDW:
Cnf.dJog /= 10;
if(Cnf.dJog = 0)
{
lcd.cursorTo(1,8);
print("........");
Index(Cnf.Mod,f,Div,Cnf.nDiv,Cnf.dDeg,Cnf.dJog);
lcd.cursorTo(1,8);
PrintDeg();
}
}
void f50(void) // Continuous Exec Screen
{
Div = 0;
pStp = 0;
pDeg = 0;
cDeg = 0;
lcd.clear();
lcd.cursor(0);
print("Continuous");
lcd.cursorTo(0,13);
print("\6Bk");
lcd.cursorTo(1,0);
print("\4Index\5");
lcd.cursorTo(1,8);
PrintDeg();
Stt = 51;
}
void f51(int key) // Continuous Exec Key
{
int f;
// char buf[16];
f = -1;
switch(key)
{
case KUP:
case KRT:
f = CW;
break;
case KDW:
case KLF:
f = CCW;
break;
case KSL:
f10();
break;
}
if(f >= 0)
{
lcd.cursorTo(1,8);
print("........");
Index(Cnf.Mod,f,Div,Cnf.nDiv,Cnf.dDeg,Cnf.dJog);
lcd.cursorTo(1,8);
PrintDeg();
}
}
void f60(void) // Config Steps/Rev Screen
{
char buf[32];
lcd.clear();
sprintf(buf,"Steps/Rev:%.3d ?", Cnf. Stp);
print(buf);
lcd.cursorTo(1,0);
print("\4Sel\5 \2Edit\3 \6Ac");
lcd.cursorTo(0,12);
lcd.cursor(1);
Stt = 61;
Cur = 0;
}
void f61(int key) // Config Steps/Rev Edit Key
{
char buf[16];
switch(key)
{
case KUP:
switch(Cur)
{
case 0:Cnf.Stp += 1; break;
case 1:Cnf.Stp += 10; break;
case 2:Cnf.Stp += 100;break;
}
if(Cnf.Stp >= 1000)
Cnf.Stp -= 1000;
Cnf.Stp = max(1,Cnf.Stp);
sprintf(buf,"%.3d",Cnf.Stp);
lcd.cursorTo(0,10);
print(buf);
lcd.cursorTo(0,12-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.Stp -= 1; break;
case 1:Cnf.Stp -= 10; break;
case 2:Cnf.Stp -= 100;break;
}
if(Cnf.Stp 2)
Cur = 0;
lcd.cursorTo(0,12-Cur);
break;
case KRT:
Cur--;
if(Cur= 1000)
Cnf.Mst -= 1000;
Cnf.Mst = max(1,Cnf.Mst);
sprintf(buf,"%.3d",Cnf.Mst);
lcd.cursorTo(0,10);
print(buf);
lcd.cursorTo(0,12-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.Mst -= 1; break;
case 1:Cnf.Mst -= 10; break;
case 2:Cnf.Mst -= 100;break;
}
if(Cnf.Mst 2)
Cur = 0;
lcd.cursorTo(0,12-Cur);
break;
case KRT:
Cur--;
if(Cur= 1000)
Cnf.Red -= 1000;
Cnf.Red = max(1,Cnf.Red);
sprintf(buf,"%.3d",Cnf.Red);
lcd.cursorTo(0,10);
print(buf);
lcd.cursorTo(0,12-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.Red -= 1; break;
case 1:Cnf.Red -= 10; break;
case 2:Cnf.Red -= 100;break;
}
if(Cnf.Red 2)
Cur = 0;
lcd.cursorTo(0,12-Cur);
break;
case KRT:
Cur--;
if(Cur= 10000)
Cnf.Mvl -= 10000;
Cnf.Mvl = max(1,Cnf.Mvl);
sprintf(buf,"%.4d",Cnf.Mvl);
lcd.cursorTo(0,10);
print(buf);
lcd.cursorTo(0,13-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.Mvl -= 1; break;
case 1:Cnf.Mvl -= 10; break;
case 2:Cnf.Mvl -= 100; break;
case 3:Cnf.Mvl -= 1000;break;
}
if(Cnf.Mvl 3)
Cur = 0;
lcd.cursorTo(0,13-Cur);
break;
case KRT:
Cur--;
if(Cur= 1000)
Cnf.Acc -= 1000;
Cnf.Acc = max(1,Cnf.Acc);
sprintf(buf,"%.3d",Cnf.Acc);
lcd.cursorTo(0,10);
print(buf);
lcd.cursorTo(0,12-Cur);
break;
case KDW:
switch(Cur)
{
case 0:Cnf.Acc -= 1; break;
case 1:Cnf.Acc -= 10; break;
case 2:Cnf.Acc -= 100; break;
}
if(Cnf.Acc 2)
Cur = 0;
lcd.cursorTo(0,12-Cur);
break;
case KRT:
Cur--;
if(Cur= 10000)
Cnf.Bkl -= 10000;
Cnf.Bkl = max(0,Cnf.Bkl);
sprintf(buf,"%.1d.%.3d?",Cnf.Bkl/1000,Cnf.Bkl%1000);
lcd.cursorTo(0,10);
print(buf);
lcd.cursorTo(0,14-Cur);
break;
case KDW:
switch(Cur)
{
case 0:
Cnf.Bkl -= 1;
break;
case 1:
Cnf.Bkl -= 10;
break;
case 2:
Cnf.Bkl -= 100;
break;
case 4:
Cnf.Bkl -= 1000;
break;
}
if(Cnf.Bkl4)
Cur = 0;
lcd.cursorTo(0,14-Cur);
break;
case KRT:
Cur--;
if(Cur == 3)
Cur--;
if(Cur2)||(newpos != curpos))
{
if(mod= stprot)
stptgo -= stprot;
if(dir)
stptgo += sBkl;
}
else
stptgo = 1E9;
stp.Set(dir,stptgo);
if(mod0)
{
stptgo = min(stpgon,sBkl);
if(stptgo)
{
stp.Set(0,stptgo);
while(stp.Run());
stpgon -= stp.Gone();
}
}
if(dir)
newpos = curpos-stpgon;
else
newpos = curpos+stpgon;
if(newpos= stprot)
newpos -= stprot;
pDeg = lround((float)newpos/(float)stprot*360000.0);
pStp = newpos;
}
cDeg = newdeg;
}
Wlcd.cpp
Code:
/*
EEPROM.h - EEPROM library
Original Copyright (c) 2006 David A. Mellis. All right reserved.
New version by Christopher Andrews 2015.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef EEPROM_H
#define EEPROM_H
#include
#include
#include
/***
EERef class.
This object references an EEPROM cell.
Its purpose is to mimic a typical byte of RAM, however its storage is the EEPROM.
This class has an overhead of two bytes, similar to storing a pointer to an EEPROM cell.
***/
struct EERef{
EERef( const int index )
: index( index ) {}
//Access/read members.
uint8_t operator*() const { return eeprom_read_byte( (uint8_t*) index ); }
operator const uint8_t() const { return **this; }
//Assignment/write members.
EERef &operator=( const EERef &ref ) { return *this = *ref; }
EERef &operator=( uint8_t in ) { return eeprom_write_byte( (uint8_t*) index, in ), *this; }
EERef &operator +=( uint8_t in ) { return *this = **this + in; }
EERef &operator -=( uint8_t in ) { return *this = **this - in; }
EERef &operator *=( uint8_t in ) { return *this = **this * in; }
EERef &operator /=( uint8_t in ) { return *this = **this / in; }
EERef &operator ^=( uint8_t in ) { return *this = **this ^ in; }
EERef &operator %=( uint8_t in ) { return *this = **this % in; }
EERef &operator &=( uint8_t in ) { return *this = **this & in; }
EERef &operator |=( uint8_t in ) { return *this = **this | in; }
EERef &operator >=( uint8_t in ) { return *this = **this >> in; }
EERef &update( uint8_t in ) { return in != *this ? *this = in : *this; }
/** Prefix increment/decrement **/
EERef& operator++() { return *this += 1; }
EERef& operator--() { return *this -= 1; }
/** Postfix increment/decrement **/
uint8_t operator++ (int){
uint8_t ret = **this;
return ++(*this), ret;
}
uint8_t operator-- (int){
uint8_t ret = **this;
return --(*this), ret;
}
int index; //Index of current EEPROM cell.
};
/***
EEPtr class.
This object is a bidirectional pointer to EEPROM cells represented by EERef objects.
Just like a normal pointer type, this can be dereferenced and repositioned using
increment/decrement operators.
***/
struct EEPtr{
EEPtr( const int index )
: index( index ) {}
operator const int() const { return index; }
EEPtr &operator=( int in ) { return index = in, *this; }
//Iterator functionality.
bool operator!=( const EEPtr &ptr ) { return index != ptr.index; }
EERef operator*() { return index; }
/** Prefix & Postfix increment/decrement **/
EEPtr& operator++() { return ++index, *this; }
EEPtr& operator--() { return --index, *this; }
EEPtr operator++ (int) { return index++; }
EEPtr operator-- (int) { return index--; }
int index; //Index of current EEPROM cell.
};
/***
EEPROMClass class.
This object represents the entire EEPROM space.
It wraps the functionality of EEPtr and EERef into a basic interface.
This class is also 100% backwards compatible with earlier Arduino core releases.
***/
typedef union _atad {
uint8_t b[4];
float f;
} t2f;
struct EEPROMClass{
//Basic user access methods.
EERef operator[]( const int idx ) { return idx; }
uint8_t read( int idx ) { return EERef( idx ); }
uint8_t checksum8(void) {
uint8_t csum = 0;
for ( uint16_t index = 0; index > 8) & 0xff);
(EERef( idx+1 )) = ((uint8_t)val & 0xff);
}
void write32( int idx, uint32_t val ) {
(EERef( idx )) = ((uint8_t)(val >> 24) & 0xff);
(EERef( idx+1 )) = ((uint8_t)(val >> 16) & 0xff);
(EERef( idx+2 )) = ((uint8_t)(val >> 8) & 0xff);
(EERef( idx+3 )) = ((uint8_t)val & 0xff);
}
void writeFloat( int idx, float val ) {
t2f r;
r.f = val;
(EERef( idx )) = r.b[0];
(EERef( idx + 1 )) = r.b[1];
(EERef( idx + 2 )) = r.b[2];
(EERef( idx + 3 )) = r.b[3];
}
void update( int idx, uint8_t val ) { EERef( idx ).update( val ); }
static struct EEPROMClass EPC;
uint32_t crc32( void ) {
const unsigned long crc_table[16] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
unsigned long crc = ~0L;
for (uint16_t index = 0; index > 4);
crc = crc_table[(crc ^ (EPC[index] >> 4)) & 0x0f] ^ (crc >> 4);
crc = ~crc;
}
return crc;
}
//STL and C++11 iteration capability.
EEPtr begin() { return 0x00; }
EEPtr end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid.
uint16_t length() { return E2END + 1; }
//Functionality to 'get' and 'put' objects to and from EEPROM.
template T &get( int idx, T &t )
{
EEPtr e = idx;
uint8_t *ptr = (uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) *ptr++ = *e;
return t;
}
template const T &put( int idx, const T &t )
{
EEPtr e = idx;
const uint8_t *ptr = (const uint8_t*) &t;
for( int count = sizeof(T) ; count ; --count, ++e ) (*e).update( *ptr++ );
return t;
}
};
static EEPROMClass EEPROM;
#endif /* EEPROM_H */