#define spr 96 // steps per rev (motor) /* Set axis characteristics above * Pins: * 2 - encoder A * 3 - encoder B * 11 - direction * 12 - step */ #include // initialize the library with the numbers of the interface pins LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int fs = 96; // 96 steps/rev int set = 0; int act = 0; unsigned int ipos = 0; // = 2*act used in rpm mode/ISR int dif = 0; int irpm = 0; // rpm index int rpm = 0; // rpm int sink = 1; // setting increment (mode 0) byte but = 5; byte pbut = 0; // previous button press byte mode = 0; // mode 0 = 10deg, 1 = 1 deg. 2 = 0.1 deg, 3 = rpm byte pmode = 0; byte prtd; byte pprtd; byte saved; // define some values used by the panel and buttons int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 // read the buttons int read_LCD_buttons() { adc_key_in = analogRead(0); // read the value from the sensor // my buttons when read are centered at these valies: 0, 144, 329, 504, 741 // we add approx 50 to those values and check to see if we are close if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result // For V1.1 us this threshold if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; // when all others fail, return this... } void lcdprintno(int ino) { if(ino<100) { lcd.print(" "); } if(ino<10) { lcd.print(" "); } lcd.print(ino); } void settmr1(int treset) { // setup timer1 with reset count TCCR1A = 0; // set entire TCCR1A register to 0 TCCR1B = 0; // same for TCCR1B TCNT1 = 0; //initialize counter value to 0 OCR1A = treset; // set compare match register TCCR1B |= (1 << WGM12); // turn on CTC mode // TCCR1B |= (1 << CS11); // Set bits for 8 prescaler, max = 32.768ms TCCR1B |= (1 << CS10); // Set bits for 1024 prescaler, max = 4.194304s TCCR1B |= (1 << CS12); // Set bits for 1024 prescaler, max = 4.194304s TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt } ISR(TIMER1_COMPA_vect) { PORTB = PINB^B00010000; // toggle PORTB,4 (pin12) ipos += 1; } void setup() { cli(); //stop interrupts pinMode(11, OUTPUT); pinMode(12, OUTPUT); digitalWrite(11, LOW); digitalWrite(12, LOW); // Start LCD lcd.begin(16, 2); lcd.clear(); lcd.setCursor(0,0); // line 1, chr 0 lcd.print("Set 0 "); lcd.setCursor(12,0); // line 1, chr 13 lcd.print("D 1"); lcd.setCursor(0,1); // line 2 lcd.print("Pos 0 "); lcd.setCursor(12,1); // line 2. chr 13 lcd.print(" Run"); pinMode(1,INPUT_PULLUP); // encoder switch pinMode(2,INPUT_PULLUP); // A pinMode(3,INPUT_PULLUP); // B delay(1); // let inputs stabilise pprtd = PIND; } void loop() { // read buttons but = read_LCD_buttons(); if((but!=5)&&(pbut==5)) { cli(); //stop interrupts mode = but; switch(mode) { case 0: sink = 1; lcd.setCursor(0,0); // line 1, chr 1 lcd.print("Set "); lcdprintno(set); lcd.setCursor(9,0); // line 1, chr 10 lcd.print(" D 1"); if(pmode==3) { act = ipos>>1; if(act>=fs) { act -= fs; ipos -= 2*fs; } set = act; lcd.setCursor(4,0); // line 1, chr 5 lcdprintno(set); } break; case 1: sink = 12; lcd.setCursor(0,0); // line 1, chr 1 lcd.print("Set "); lcdprintno(set); lcd.setCursor(9,0); // line 1, chr 10 lcd.print(" D 12"); if(pmode==3) { act = ipos>>1; if(act>=fs) { act -= fs; ipos -= 2*fs; } set = act; lcd.setCursor(4,0); // line 1, chr 5 lcdprintno(set); } break; case 2: sink = 48; lcd.setCursor(0,0); // line 1, chr 1 lcd.print("Set "); lcdprintno(set); lcd.setCursor(9,0); // line 1, chr 10 lcd.print(" D 48"); if(pmode==3) { act = ipos>>1; if(act>=fs) { act -= fs; ipos -= 2*fs; } set = act; lcd.setCursor(4,0); // line 1, chr 5 lcdprintno(set); } break; case 3: lcd.setCursor(0,0); lcd.print("RPM 0 "); irpm = 0; rpm = 0; break; case 4: lcd.setCursor(0,0); lcd.print("RESET? "); break; } pmode= mode; } pbut = but; // read encoder saved = PIND; prtd=saved^pprtd; // xor to find changed prtd &= B00001100; // select 2,3 if(prtd != 0) { if(bitRead(prtd,2)&&bitRead(saved,3)) { // A changed and B high if(mode<3) { if(bitRead(saved,2)!=bitRead(saved,3)) { // if different (xor) set += sink; if(set >= fs){ set -= fs; // oveflow so subtract fs } } else { set -= sink; if(set <0) { set += fs; // neg so add full scale } } lcd.setCursor(4,0); // line 1, chr 5 lcdprintno(set); } if(mode==3) { if(bitRead(saved,2)!=bitRead(saved,3)) { // if different (xor) irpm += 1; } else { irpm -= 1; } if(irpm<0) {irpm = 0;} rpm = irpm; if(irpm>9) {rpm = 5*(irpm-8);} lcd.setCursor(4,0); // line 1, chr 5 lcdprintno(rpm); digitalWrite(11, HIGH); // pos direction ipos = 2*act; // set counter if(rpm == 0){ cli(); //stop interrupts } else { // 1rpm = 2*96 ints/min = 60/96 s-1, 64us clk so 1000000*60/64*96*2*rpm clks settmr1(312500/(rpm*64)); // set up timer interrupt sei(); //allow interrupts } } } } pprtd = saved; // update previous port value // action modes if(mode<3) { // drive motor if(set != act) { dif = set-act; if(dif < 0) { dif += fs; // make pos no in pos direction } if(dif <(fs/2)) { digitalWrite(11, HIGH); // pos direction act += 1; if(act >= fs) { act -= fs; // oveflow so subtract fs } } else { digitalWrite(11, LOW); // backwards act -= 1; if(act<0) { act += fs; // neg so add full scale } } lcd.setCursor(4,1); // line 2, chr 5 lcdprintno(act); digitalWrite(12, HIGH); // step pulse delay(1); // 1ms digitalWrite(12, LOW); delay(1); // 1ms } } if(mode==3) { if(rpm>0) { cli(); //stop interrupts act = ipos>>1; if(act>=fs) { act -= fs; ipos -= 2*fs; } sei(); //enable interrupts } lcd.setCursor(4,1); // line 2, chr 5 lcdprintno(act); delay(2); // switch debounce } if(mode==4) { if((saved&B00000010)==0) { set = 0; act = 0; ipos = 0; lcd.setCursor(4,1); // line 2, chr 5 lcdprintno(act); } delay(2); // switch debounce } }