// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses></https:>.
#define MAX_XPOS 64000 // Start of pickup
#define MIN_XPOS 15000 // End of pickup
#define ARLEN 32 //Length of ADC read buffer from potentiometer
#define ANALOGPIN A4
#define FLAGPIN A5
#define ENABLE 8
#define X_STEP 2
#define X_DIR 5
#define STEP 3
#define DIRECT 6
#define READLOOP 5
#define STEPLOOP 800
boolean toggle0 = 0;
boolean toggle1 = 0;
boolean toggle2 = 0;
boolean step1 = 0;
volatile int steps = 0;
volatile int turns = 0;
volatile boolean turnflag = 0;
bool flagVal = false;
bool xstepFlagHigh=false;
bool xstepFlagLow=true;
unsigned long xPos;
unsigned long timeA;
unsigned long timeMicros;
int xIncrement = 1;
int aRead;
int readbuffer[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned int buffi = 0;
boolean readflag = 0;
void setup(){
//setup will initialize serial, timers, and run a "homing" protocol
Serial.begin(115200);
Serial.write("begin");
//set pins as outputs
pinMode(ENABLE, OUTPUT);
pinMode(DIRECT, OUTPUT);
pinMode(STEP, OUTPUT);
pinMode(X_STEP,OUTPUT);
pinMode(X_DIR,OUTPUT);
pinMode(ANALOGPIN, INPUT);
pinMode(FLAGPIN, INPUT);
digitalWrite(ENABLE,LOW);
digitalWrite(DIRECT,LOW);
digitalWrite(X_DIR, HIGH);
long initSteps = 100000;
//move_forward to get out of any flags
for(int i = 0; i<3200; i++)
{
digitalWrite(X_STEP, HIGH);
delayMicroseconds(350);
digitalWrite(X_STEP,LOW);
delayMicroseconds(350);
}
//change direction and back into the flag
digitalWrite(X_DIR,LOW);
delay(500);
while(flagVal == false && initSteps>0)
{
flagVal = digitalRead(FLAGPIN);
digitalWrite(X_STEP, HIGH);
delayMicroseconds(350);
digitalWrite(X_STEP,LOW);
delayMicroseconds(350);
initSteps--;
}
xPos=0;
digitalWrite(X_DIR,HIGH);
//Move to start of pickup (MIN_XPOS)
for(int i = 0; i<MIN_XPOS; i++)
{
digitalWrite(X_STEP, HIGH);
delayMicroseconds(350);
digitalWrite(X_STEP,LOW);
delayMicroseconds(350);
xPos+=xIncrement;
}
digitalWrite(X_DIR,LOW);
cli();//stop interrupts
//Configure timer
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 24;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11) | (0 << CS10);
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
}//end setup
ISR(TIMER1_COMPA_vect)
//Timer ISR --> try to keep this uncomplicated
{
if (toggle1 && step1){
digitalWrite(3,HIGH);
toggle1 = 0;
}
else{
digitalWrite(3,LOW);
toggle1 = 1;
steps++;
}
if(steps>=3200)
{
if(step1)
{
turns++;
steps = 0;
turnflag = true;
}
}
}
//averages the array of past ADC values to length n
int average (int *readbuffer, unsigned int n)
{
int cumul = 0;
for(int i = 0; i<n; i++)
{
cumul += readbuffer[i];
}
return (int)(cumul/n);
}
void loop(){
timeA = millis();
timeMicros = micros();
int avg = average(readbuffer, 32);
flagVal = digitalRead(FLAGPIN);
//deadzone between 950 and 1024 = "off".
//This means the spindle won't wind.
if(avg>=950)
{
step1=false;
}
else
{
step1 = true;
}
//Verify that it's the right time to step, verify no limit is flagged,
//and then take a step in the right direction
if(timeMicros%STEPLOOP <= STEPLOOP/2 && xstepFlagHigh == true)
{
flagVal=digitalRead(FLAGPIN);
if(flagVal==1 || xPos <= MIN_XPOS)
{
digitalWrite(X_DIR,HIGH);
xIncrement = 1;
}
else if(xPos >= MAX_XPOS)
{
digitalWrite(X_DIR,LOW);
xIncrement = -1;
}
digitalWrite(X_STEP,HIGH);
xPos+= xIncrement;
xstepFlagHigh = false;
xstepFlagLow = true;
}
//Toggle line low if scheduled
if(timeMicros%STEPLOOP > STEPLOOP/2 && xstepFlagLow == true)
{
digitalWrite(X_STEP,LOW);
xstepFlagLow = false;
xstepFlagHigh = true;
}
//Adjust speed of motor by tweaking timer interrupt
//Take a new ADC reading and stuff into bufer
if(timeA%READLOOP==0 && readflag)
{
cli();
OCR1A = (int)(avg/4+36);
aRead = analogRead(ANALOGPIN);
readbuffer[buffi]=aRead;
buffi = (buffi+1)%ARLEN;
sei();
readflag = false;
}
//debounces read schedule
if(timeA%READLOOP>=READLOOP/2)
{
readflag = true;
}
//if a turn has completed, shoot out the total number of turns completed
if(turnflag)
{
turnflag = false;
Serial.print(turns);
Serial.print(" ");
Serial.print(flagVal);
Serial.print("\n");
}
}
Comments
Please log in or sign up to comment.