Fix for missing pinmode:
/*
cncstepper003c for Due
Step stepper in one direction. Time in microseconds
Detect Z
Count A, B
No delay for serial
Correct bug where CW/CCW is detected.
Put stepper pin on 53, dir on 51
Emit Gray code
*/
const byte NoTools = 8;
const unsigned int PulsesPerRotation=8000; // Encoder pulses, not steps.
const byte GrayCode[NoTools]={7,6,4,5,1,0,2,3}; // Had to invert these because Acorn inputs are active low.
const int PulsesPerTool=PulsesPerRotation/NoTools;
const int GrayTolerance=PulsesPerTool/10; // Tolerance AFTER toolpos is reached. If we're dropping pulses though, there are bigger problems
const byte StepperStepPin = 51;
const byte StepperDirPin = 53;
const byte AcornRotatePin = 11;
const byte Z_Pin = 4;
const byte A_Pin = 2; // Pins 2 and 3 on the Nano are interrupt pins.
const byte B_Pin = 3;
const byte NotAToolPos=255; // We're not near any tool position
const int PrintInterval = 250; // Milliseconds
const unsigned int StepInterval = 350; // Microseconds
int ShadowPulseCount=0; // Copied from PulseCount when we need to use it
byte CurrentTool=0; // Index of current tool runs 0-7. This is C, so tool one is actually index 0
int ToolPositions[NoTools]={0,1000,2000,3000,4000,5000,6000,7000}; // Where is each tool in position. Calibration changes this
volatile int PulseCount;
volatile int CCWPulseCount=0; // Set by the interrupt routines - remove after testing
volatile bool SawA=false;
volatile bool SawB=false;
void setup()
{
Serial.begin(115200);
while (!Serial)
; // Do nothing
Serial.println(__FILE__); // Tell me the name of the file that was compiled to make this - useful version check.
pinMode(Z_Pin,INPUT_PULLUP);
pinMode(A_Pin,INPUT_PULLUP);
pinMode(B_Pin,INPUT_PULLUP);
pinMode(8,OUTPUT); // Gray code low bit
pinMode(9,OUTPUT); // Next Gray code bit
pinMode(10,OUTPUT); // Next Gray code bit
pinMode(StepperStepPin,OUTPUT);
pinMode(StepperDirPin,OUTPUT);
pinMode(AcornRotatePin,INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(A_Pin), EncoderPulseA, CHANGE);
attachInterrupt(digitalPinToInterrupt(B_Pin), EncoderPulseB, CHANGE);
}
void EncoderPulseA() // Interrupt service routine for A pin
{
byte AState=digitalRead(A_Pin);
byte BState=digitalRead(B_Pin);
SawA=true;
if(AState!=BState)
{
PulseCount++; // CW
}
else
{
CCWPulseCount++;
PulseCount--; // CCW
}
}
/*
This is the equivalent code for the B pulse.
*/
void EncoderPulseB() // Interrupt service routine for B pin
{
byte AState=digitalRead(A_Pin);
byte BState=digitalRead(B_Pin);
SawB=true;
if(AState==BState)
{
PulseCount++; // CW
}
else
{
CCWPulseCount++;
PulseCount--; // CCW
}
}
void loop()
{
Step();
HandleZPin();
PrintPulses();
}
void Step()
{
static unsigned long StepperTime=0;
static byte StepperStepPinState=LOW;
if(digitalRead(AcornRotatePin)==LOW)
{
HandleGrayCode();
if(micros()-StepperTime > StepInterval)
{
digitalWrite(StepperStepPin,StepperStepPinState);
if(StepperStepPinState==LOW)
{
StepperStepPinState=HIGH;
}
else
{
StepperStepPinState=LOW;
}
StepperTime=micros();
}
}
}
void HandleZPin()
{
static byte ZStatus=LOW;
byte ZRead=digitalRead(Z_Pin);
if(ZStatus != ZRead)
{
if(ZStatus==LOW && ZRead==HIGH) // Probably need to figure which end of the pulse is an accurate home position
{
// Z Just became HIGH
ZeroPulseCount();
Serial.println("Found home");
}
ZStatus=ZRead;
}
}
void ZeroPulseCount()
{
ShadowPulseCount=GetShadowPulses();
//if(ShadowPulseCount != (PulsesPerRotation-1))
{
Serial.print(F("Zero pulse at pulses: "));
Serial.println(ShadowPulseCount);
}
noInterrupts();
PulseCount=ShadowPulseCount=CCWPulseCount=0;
interrupts();
}
int GetShadowPulses()
{
int Pulses;
noInterrupts();
Pulses=PulseCount;
interrupts();
return Pulses;
}
void PrintPulses()
{
static unsigned int LastPrint=0;
int Pulses;
if(millis()-LastPrint > PrintInterval)
{
noInterrupts();
Pulses=PulseCount;
interrupts();
Serial.print("Saw A: ");
Serial.print(SawA);
Serial.print(" Saw B: ");
Serial.print(SawB);
Serial.print("Pulses: ");
Serial.println(Pulses);
LastPrint=millis();
}
}
bool HandleGrayCode()
{
bool ToolWasChanged=false;
ShadowPulseCount=GetShadowPulses();
byte Graytool = GetGrayToolNumber(); // Which tool pos are we near, if any?
if(Graytool != NotAToolPos) // Are we close enough?
{
if(CurrentTool != Graytool) // If actual differs from what we're reporting via gray code, time for the next Gray code
{
CurrentTool = Graytool;
Serial.print(F("Tool: "));
Serial.print(CurrentTool);
Serial.print(F(" pulses: "));
Serial.println(ShadowPulseCount);
int CCWPulses;
//Testing - remove later
noInterrupts();
CCWPulses=CCWPulseCount;
interrupts();
Serial.print(F("CCWPulses: "));
Serial.println(CCWPulses);
EmitGrayCode(CurrentTool);
ToolWasChanged=true;
}
}
return ToolWasChanged;
}
/*
For Gray code purposes, we want to indicate a new tool when we get to the precise tool position.
However, I've left a little tolerance because that's what the earlier code was doing without explicitly saying so.
In reality, if we miss a pulse, the repeatable accuracy is gone. There should be a check when we zero the count that we
actually got a full rotation of pulses.
This will only switch when we're at or just past the calibrated tool position. Maybe I should error out if it isn't exact
This way the reverse rotation of the Sprag won't trigger a Gray code change.
*/
byte GetGrayToolNumber()
{
byte ToolNumber = NotAToolPos; // Maintain ignorance if we're not at the right encoder pos for a tool or a little beyond
ShadowPulseCount=GetShadowPulses();
for(byte lp=0;lp<NoTools;lp++)
{
int diff = ShadowPulseCount-ToolPositions[lp]; //How far are we from the tool's known stop (default or calibrated)
if(diff >= 0 && diff < GrayTolerance)
{ //Found it
ToolNumber = lp; // Set it
break; // All done
}
}
return ToolNumber;
}
/*
Gray code outputs are pins 8, 9, and 10. Current s/w on Acorn requires a fourth pin, but this is just tied low
To avoid intermediate states on the pins which the Acorn might act on, all three must be set at the same time
That means direct port manipulation, which makes the code harder to read but is necessary here.
*/
void EmitGrayCode(int Tool)
{
//byte port = OUTSET; // Sending low three bits. High two are not accessible. Make sure bits in between are left alone.
//byte setting = port | GrayCode[Tool];
//PORTB = setting; // Ugly, but fast and more importantly, simultaneous
digitalWrite(8,GrayCode[Tool]&1);
digitalWrite(9,GrayCode[Tool]&2);
digitalWrite(10,GrayCode[Tool]&4);
}