Go Down

Topic: CnC Person needs Arduino code Person (Read 4897 times) previous topic - next topic

jumps4

#450
Nov 11, 2019, 05:44 pm Last Edit: Nov 11, 2019, 06:24 pm by jumps4
Good morning WildBill I hope you had a nice Sunday.
I spent a few hours yesterday laying out in my mind a shield for the new Due.
The pin layout was the same as my Uno board so i used it as a reference.
I'll start testing on a breadboard but I want to eventually solder this all down to a board.
Amazon showed up at 9:30 this morning with the new Arduino Due and I'm going to connect it to the breadboard I laid out for the Nano 33 Ble.
Steve






wildbill

cncstepper003 revisited

jumps4

#452
Nov 11, 2019, 07:55 pm Last Edit: Nov 11, 2019, 08:00 pm by jumps4
scope pattern


jumps4

#453
Nov 12, 2019, 04:24 am Last Edit: Nov 12, 2019, 04:27 am by jumps4
I think I fixed the encoder problem
I used 2 sn74hc14n Schmitt triggers 1 to clean 3.3v pulse from encoder the other to convert 3.3v stepper pulse from the Due to 5v pulse and direction to the stepper driver.
 I'm running at 200 microseconds and 8000 pulses every time. I don't need to run the turret this fast ever.

Code: [Select]
/*
 cncstepper003

 Step stepper in one direction. Time in microseconds
 Detect Z
 Count A, B
*/

const byte NoTools=8;
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;  // Not hooked up yet
const int PrintInterval=250; // Milliseconds
const byte GrayCode[NoTools]={7,6,4,5,1,0,2,3};  // Had to invert these because Acorn inputs are active low.

const unsigned int StepInterval=200; // Microseconds

int ShadowPulseCount=0;           // Copied from PulseCount when we need to use it

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
//delay(5000);  // Wait for serial to wake up. Not understood why it's needed

Serial.println(__FILE__);  // Tell me the name of the file that was compiled to make this - useful version check.
pinMode(Z_Pin,INPUT);
pinMode(A_Pin,INPUT);
pinMode(B_Pin,INPUT);
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)
  {
  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();
  }
}


top to bottom
Z from schmitt
A from schmitt
B from schmitt
A from encoder
B from encoder
stepper pulses to driver


wildbill

Very clean. It looks like the Schmitt is inverting A and B, but I don't think it matters.

Serial output looks good, I just need to reverse CW and CCW counts.

wildbill

Here's the fix, with your pin settings and interval spliced in.

Code: [Select]

/*
 cncstepper003 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
*/

const byte NoTools = 8;
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 int PrintInterval = 250; // Milliseconds
const byte GrayCode[NoTools] = {7, 6, 4, 5, 1, 0, 2, 3}; // Had to invert these because Acorn inputs are active low.

const unsigned int StepInterval = 200; // Microseconds

int ShadowPulseCount=0;           // Copied from PulseCount when we need to use it

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);
pinMode(A_Pin,INPUT);
pinMode(B_Pin,INPUT);
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)
  {
  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();
  }
}

wildbill

For next steps, we have choices. I can apply the fixes and pin changes to ufa, or we can continue to gradually add back functionality to what we have working. Either works for me. I think the missing parts are Fram, Gray code and reverse.

jumps4

Good morning WildBill
 I have settled on 350 as the speed 200 was to prove concept and pullup on A,B,Z for extra stability if that will be ok

wildbill

Version with Gray code:
Code: [Select]

/*
 cncstepper003b 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 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 int PrintInterval = 250; // Milliseconds
const int GrayTolerance=PulsesPerTool/10;        // Tolerance AFTER toolpos is reached. If we're dropping pulses though, there are bigger problems
const byte NotAToolPos=255;                      // We're not near any tool position

const unsigned int StepInterval = 200; // 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(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);
}

wildbill

Fix for missing pinmode:
Code: [Select]

/*
 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);
}

wildbill

Full version ufb attached.

jumps4

cal behind zero

wildbill

Here's the latest. Prints less.

wildbill

#463
Nov 12, 2019, 09:53 pm Last Edit: Nov 12, 2019, 09:53 pm by wildbill
We know that the system was better when it was running slower, at least with the original nano. Once the new controller is soldered up, we could verify that this is still true.

If so, it might be worth decelerating as we approach a tool position. I have to stop anyway to wait for the Acorn to indicate whether it wants this tool, so I could make the stop less abrupt.

I think I asked this before (so the answer is probably no): Is there any way for the Acorn to tell me what tool it is looking for?

jumps4

#464
Nov 13, 2019, 03:48 pm Last Edit: Nov 13, 2019, 03:57 pm by jumps4
I'm finding a lot of interference issues being reported about the Due with i2c, Usb, Fram, serial and pwm.
Bleed over and erratic readings.
 Everything was working pretty good and after adding the Fram accuracy is gone.
I'm seeing a lot of different comments on the Fram and due
 I don't think our erratic readings are from the encoder anymore.
In my reading I see default pin settings for Arduino are input high and they can cross signal each other.
https://www.arduino.cc/en/Tutorial/DigitalPins
I'm a bit lost now.
 

Go Up