/* * Rotocasting machine * Main program */ #include "U8glib.h" //library for OLED SSD1306 screen. Source : https://github.com/olikraus/u8glib #define encoderPinA 11 //encoder pins #define encoderPinB 12 #define pushPin 13 #define stepPin 6 // A4988 stepper driver pins #define dirPin 5 #define enablePin 7 #define duration 180 // default duration #define ymargin 10 //ymargin between two lines on OLED SSD1306 screen unsigned short encoder = 0b000111; // encoder 6 bits state unsigned short menu = 0; //current command unsigned short in = 0; //inside a command 0 : no, 1: yes unsigned short start = 0; //running 0: no, 1: yes unsigned short rspeed[] = {20,80,150}; //motor speed {min,current,max} unsigned int rtime[] = {1,duration,1200}; //elapsed time {min,current,max} unsigned short rmode = 1; //acceleration mode 0:smooth, 1: medium, 2: sharp unsigned long timer,next; int d; //d : delay before stepper motor next step pulse int r; //r: number of tenth milliseconds before next pulse int i; //i: step number [0..200] on stepper motor int screenWidth; int fontHeight; U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0); //screen object void writeTime() { //write elapsed time on second line screen int l; char stime[11]; short pos = 0; if (rtime[1] >= 600) { //if elapsed time is more than 10 hours stime[pos++] = rtime[1] / 600 + '0'; // add tens digit } if (rtime[1] >= 60) { //if elapsed time is more than 1 hour stime[pos++] = (rtime[1] / 60) % 10 + '0'; // add units digit stime[pos++] =' '; stime[pos++] ='h'; stime[pos++] =' '; } stime[pos++] = (rtime[1] % 60) / 10 + '0'; // add tens digit of minutes stime[pos++] = (rtime[1] % 60) % 10 + '0'; // add units digit of minutes stime[pos++] = ' '; stime[pos++] = 'm'; stime[pos++] = 'n'; stime[pos++] = 0; l = (screenWidth-u8g.getStrWidth(stime))/2; // calculate left margin to center text u8g.drawStr( l, 2*(fontHeight+ymargin), stime); //draw time } void writeMenu() { // write screen depending on menu value char com[16]; int l; switch (menu) { case 0: // start/stop menu if (start) { strcpy(com,"STOP"); } else { strcpy(com,"START"); } l = (screenWidth-u8g.getStrWidth(com))/2; u8g.drawStr( l, fontHeight+ymargin, com); writeTime(); break; case 1: // speed menu strcpy(com,"SPEED"); l = (screenWidth-u8g.getStrWidth(com))/2; if (in) { u8g.drawBox(0, ymargin +2, screenWidth, fontHeight); u8g.setDefaultBackgroundColor(); } u8g.drawStr( l, fontHeight+ymargin, com); u8g.setDefaultForegroundColor(); strcat(itoa(rspeed[1],com,10)," rpm"); d = (screenWidth-u8g.getStrWidth(com))/2; u8g.drawStr( l, 2*(fontHeight+ymargin), com); break; case 2: // duration menu strcpy(com,"DURATION"); l = (screenWidth-u8g.getStrWidth(com))/2; if (in) { u8g.drawBox(0, ymargin +2, screenWidth, fontHeight); u8g.setDefaultBackgroundColor(); } u8g.drawStr( l, fontHeight+ymargin, com); u8g.setDefaultForegroundColor(); writeTime(); break; case 3: // mode menu strcpy(com,"MODE"); d = (screenWidth-u8g.getStrWidth(com))/2; if (in) { u8g.drawBox(0, ymargin +2, screenWidth, fontHeight); u8g.setDefaultBackgroundColor(); } u8g.drawStr( l, fontHeight+ymargin, com); u8g.setDefaultForegroundColor(); switch (rmode) { case 0: strcpy(com,"SMOOTH"); break; case 1: strcpy(com,"MEDIUM"); break; case 2: strcpy(com,"SHARP"); break; } l = (screenWidth-u8g.getStrWidth(com))/2; u8g.drawStr( l, 2*(fontHeight+ymargin), com); break; } } void setup() { //program initialisation pinMode(encoderPinA, INPUT_PULLUP); //encoder pins are in input mode using pull up resistor pinMode(encoderPinB, INPUT_PULLUP); pinMode(pushPin, INPUT_PULLUP); pinMode(stepPin,OUTPUT); pinMode(dirPin,OUTPUT); digitalWrite(dirPin,HIGH); // set dir pin to clockwise rotation pinMode(enablePin,OUTPUT); digitalWrite(enablePin,HIGH); // disable motor u8g.setFont(u8g_font_helvB14); fontHeight = u8g.getFontAscent()-u8g.getFontDescent(); screenWidth = u8g.getWidth(); u8g.firstPage(); //write start menu do { writeMenu(); } while( u8g.nextPage() ); } void loop() { //main loop unsigned short readPin = (unsigned short) digitalRead(encoderPinA); //read encoder pins encoder = (encoder & 0b110111) | (readPin << 3); //write encoderA state in the fourth digit readPin = (unsigned short) digitalRead(encoderPinB); encoder = (encoder & 0b101111) | (readPin << 4); //write encoderB state in the fifth digit readPin = (unsigned short) digitalRead(pushPin); encoder = (encoder & 0b011111) | (readPin << 5); //write push state in the sixth digit if (encoder == 0b110111) { //turn clockwise if (in) { switch (menu) { case 1: // increase speed if (rspeed[1] < rspeed[2]) { rspeed[1] += 10; } break; case 2: // increase time 30mn is time is more than 2 hours, 10mn if more than 10mn and 1mn else if (rtime[1] >= 120) { if (rtime[1] + 30 <= rtime[2]) { rtime[1] += 30 - rtime[1] % 30; } else { rtime[1] = rtime[2]; } } else if (rtime[1] >= 10){ rtime[1] += 10 - rtime[1] % 10; } else { rtime[1] +=1; } break; case 3: // increase mode if (rmode < 2) { rmode++; } break; } } else { menu = (menu + 1) % 4; } u8g.firstPage(); do { writeMenu();; } while( u8g.nextPage() ); } else if (encoder == 0b101111) { //turn counterclockwise if (in) { switch (menu) { case 1: // decrease speed if (rspeed[1] > rspeed[0]) { rspeed[1] -= 10; } break; case 2: //decrease time if (rtime[1] > 120) { if (rtime[1] % 30) { rtime[1] -= rtime[1] % 30; } else { rtime[1] -= 30; } } else if (rtime[1] > 10) { if (rtime[1] % 10) { rtime[1] -= rtime[1] % 10; } else { rtime[1] -= 10 ; } } else if (rtime[1] > rtime[0]) { rtime[1] -= 1 ; } break; case 3: // decrease mode if (rmode > 0) { rmode--; } break; } } else { menu = (menu + 3) % 4; } u8g.firstPage(); do { writeMenu(); } while( u8g.nextPage() ); } else if (encoder == 0b011111) { //push on encoder if (menu == 0) { // push on start/stop start = !start; if (start) { timer = millis(); next = timer; r = 0; i = 0; digitalWrite(enablePin,LOW); // enable motor } else { digitalWrite(enablePin,HIGH); // disable motor } } else { in = !in; } u8g.firstPage(); do { writeMenu(); } while( u8g.nextPage() ); } encoder = encoder >> 3; // write encoder current values to encoder previous values if (start) { if ((millis() -timer) > 60000UL) { // if one more minute is passed, rewrite time rtime[1] = rtime[1] - 1; timer += 60000UL; if (rtime[1] == 0) { //end of time rtime[1] = duration; start = 0; digitalWrite(enablePin,HIGH); // disable motor } u8g.firstPage(); do { writeMenu(); } while( u8g.nextPage() ); } if (millis() > next) { // A4988 control digitalWrite(stepPin,HIGH); // send a pulse to step pin delayMicroseconds(500); digitalWrite(stepPin,LOW); delayMicroseconds(500); d = 3000 / rspeed[1]*(1+sin(0.031416*i)/(2*(3-rmode))); next += d / 10; r += d % 10; if (r >= 5) { r -= 10; next++; } i = (i+1) % 200; } } }