Yes it works now. Made another implementation of the pulse IRQ and all that. We'll see if I keep this or go back to the older. It is IMPORTANT, REQUIRED to use a 4.9 linux kernel for it to work. There are obviously bugs in the RealTek network drivers R8168/R8169 in 5+ kernels. All this work could have been avoided with a 4.9 kernel.
This commit is contained in:
@@ -8,8 +8,9 @@ class StepGen2
|
|||||||
public:
|
public:
|
||||||
volatile double_t actualPosition;
|
volatile double_t actualPosition;
|
||||||
volatile int32_t nSteps;
|
volatile int32_t nSteps;
|
||||||
volatile uint32_t timerPulseSteps;
|
|
||||||
volatile uint32_t timerFrequency;
|
volatile uint32_t timerFrequency;
|
||||||
|
volatile int32_t timerPosition = 0;
|
||||||
|
volatile int32_t timerEndPosition = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
volatile float Tstartf; // Starting delay in secs
|
volatile float Tstartf; // Starting delay in secs
|
||||||
@@ -21,7 +22,7 @@ public:
|
|||||||
HardwareTimer *startTimer; // Use timers 10,11,13,14
|
HardwareTimer *startTimer; // Use timers 10,11,13,14
|
||||||
uint8_t dirPin;
|
uint8_t dirPin;
|
||||||
PinName stepPin;
|
PinName stepPin;
|
||||||
uint32_t Tjitter = 400; // Longest time from IRQ to handling in handleStepper, unit is microseconds
|
uint32_t Tjitter = 350; // Longest time from IRQ to handling in handleStepper, unit is microseconds
|
||||||
uint64_t dbg;
|
uint64_t dbg;
|
||||||
const uint16_t t2 = 5; // DIR is ahead of PUL with at least 5 usecs
|
const uint16_t t2 = 5; // DIR is ahead of PUL with at least 5 usecs
|
||||||
const uint16_t t3 = 3; // Pulse width at least 2.5 usecs
|
const uint16_t t3 = 3; // Pulse width at least 2.5 usecs
|
||||||
@@ -37,8 +38,8 @@ public:
|
|||||||
volatile uint8_t enabled; // Enabled step generator
|
volatile uint8_t enabled; // Enabled step generator
|
||||||
volatile float frequency;
|
volatile float frequency;
|
||||||
|
|
||||||
static uint32_t sync0CycleTime; // Nominal EtherCAT cycle time nanoseconds
|
static uint32_t sync0CycleTime; // Nominal EtherCAT cycle time nanoseconds
|
||||||
volatile float lcncCycleTime; // Linuxcnc nominal cycle time in sec (1 ms often)
|
volatile float lcncCycleTime; // Linuxcnc nominal cycle time in sec (1 ms often)
|
||||||
|
|
||||||
StepGen2(TIM_TypeDef *Timer, uint32_t _timerChannel, PinName _stepPin, uint8_t _dirPin, void irq(void), TIM_TypeDef *Timer2, void irq2(void));
|
StepGen2(TIM_TypeDef *Timer, uint32_t _timerChannel, PinName _stepPin, uint8_t _dirPin, void irq(void), TIM_TypeDef *Timer2, void irq2(void));
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ class extend32to64
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int64_t previousTimeValue = 0;
|
int64_t previousTimeValue = 0;
|
||||||
const uint64_t ONE_PERIOD = 4294967296; // almost UINT32_MAX;
|
const uint64_t ONE_PERIOD = 4294967296; // almost UINT32_MAX;
|
||||||
const uint64_t HALF_PERIOD = 2147483648; // Half of that
|
const uint64_t HALF_PERIOD = 2147483648; // Half of that
|
||||||
int64_t extendTime(uint32_t in);
|
int64_t extendTime(uint32_t in);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -63,11 +63,14 @@ uint32_t StepGen2::handleStepper(uint64_t irqTime, uint16_t nLoops)
|
|||||||
Tpulses = abs(nSteps) / frequency;
|
Tpulses = abs(nSteps) / frequency;
|
||||||
}
|
}
|
||||||
updatePos(5);
|
updatePos(5);
|
||||||
return 1;
|
|
||||||
uint32_t timeSinceISR = (longTime.extendTime(micros()) - irqTime); // Diff time from ISR (usecs)
|
uint32_t timeSinceISR = (longTime.extendTime(micros()) - irqTime); // Diff time from ISR (usecs)
|
||||||
dbg = timeSinceISR; //
|
dbg = timeSinceISR; //
|
||||||
Tstartu = Tjitter + uint32_t(Tstartf * 1e6) - timeSinceISR; // Have already wasted some time since the irq.
|
Tstartu = Tjitter + uint32_t(Tstartf * 1e6) - timeSinceISR; // Have already wasted some time since the irq.
|
||||||
|
|
||||||
|
if (nSteps == 0) // Can do this much earlier, but want some calculated data for debugging
|
||||||
|
return updatePos(1);
|
||||||
|
|
||||||
timerFrequency = uint32_t(ceil(frequency));
|
timerFrequency = uint32_t(ceil(frequency));
|
||||||
startTimer->setOverflow(Tstartu, MICROSEC_FORMAT); // All handled by irqs
|
startTimer->setOverflow(Tstartu, MICROSEC_FORMAT); // All handled by irqs
|
||||||
startTimer->refresh();
|
startTimer->refresh();
|
||||||
@@ -77,13 +80,13 @@ uint32_t StepGen2::handleStepper(uint64_t irqTime, uint16_t nLoops)
|
|||||||
|
|
||||||
void StepGen2::startTimerCB()
|
void StepGen2::startTimerCB()
|
||||||
{
|
{
|
||||||
startTimer->pause(); // Once is enough.
|
startTimer->pause(); // Once is enough.
|
||||||
digitalWrite(dirPin, nSteps < 0 ? HIGH : LOW);
|
digitalWriteFast(digitalPinToPinName(dirPin), nSteps < 0 ? HIGH : LOW); // nSteps negative => decrease, HIGH
|
||||||
// There will be a short break here for t2 usecs, in the future.
|
// There will be a short break here for t2 usecs, in the future.
|
||||||
timerPulseSteps = abs(nSteps);
|
timerEndPosition += nSteps;
|
||||||
pulseTimer->setMode(pulseTimerChan, TIMER_OUTPUT_COMPARE_PWM2, stepPin);
|
pulseTimer->pause();
|
||||||
|
pulseTimer->setMode(pulseTimerChan, TIMER_OUTPUT_COMPARE_PWM1, stepPin);
|
||||||
pulseTimer->setOverflow(timerFrequency, HERTZ_FORMAT);
|
pulseTimer->setOverflow(timerFrequency, HERTZ_FORMAT);
|
||||||
// pulseTimer->setCaptureCompare(pulseTimerChan, t3, MICROSEC_COMPARE_FORMAT);
|
|
||||||
pulseTimer->setCaptureCompare(pulseTimerChan, 50, PERCENT_COMPARE_FORMAT);
|
pulseTimer->setCaptureCompare(pulseTimerChan, 50, PERCENT_COMPARE_FORMAT);
|
||||||
pulseTimer->refresh();
|
pulseTimer->refresh();
|
||||||
pulseTimer->resume();
|
pulseTimer->resume();
|
||||||
@@ -91,10 +94,21 @@ void StepGen2::startTimerCB()
|
|||||||
|
|
||||||
void StepGen2::pulseTimerCB()
|
void StepGen2::pulseTimerCB()
|
||||||
{
|
{
|
||||||
--timerPulseSteps;
|
int16_t dir = digitalReadFast(digitalPinToPinName(dirPin));
|
||||||
if (timerPulseSteps == 0)
|
if (dir == HIGH)
|
||||||
{
|
timerPosition--;
|
||||||
|
else
|
||||||
|
timerPosition++;
|
||||||
|
int32_t diffPosition = timerEndPosition - timerPosition; // Same "polarity" as nSteps
|
||||||
|
if (diffPosition == 0)
|
||||||
pulseTimer->pause();
|
pulseTimer->pause();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (diffPosition < 0 && dir == LOW) // Change direction. Should not end up here, but alas
|
||||||
|
digitalWriteFast(digitalPinToPinName(dirPin), HIGH); // Normal is to be HIGH when decreasing
|
||||||
|
if (diffPosition > 0 && dir == HIGH) // Change direction. Should not end up here, but alas
|
||||||
|
digitalWriteFast(digitalPinToPinName(dirPin), LOW); // Normal is to be LOW when increasing
|
||||||
|
// Normally nothing is needed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,6 @@ void cb_set_outputs(void) // Master outputs gets here, slave inputs, first opera
|
|||||||
// Step2.reqPos(Obj.CommandedPosition2);
|
// Step2.reqPos(Obj.CommandedPosition2);
|
||||||
// Step2.setScale(Obj.StepsPerMM2);
|
// Step2.setScale(Obj.StepsPerMM2);
|
||||||
// Step2.enable(1);
|
// Step2.enable(1);
|
||||||
Obj.ActualPosition1 = Obj.CommandedPosition1; // Step1.actPos();
|
|
||||||
Obj.ActualPosition2 = Obj.CommandedPosition2; // Step2.actPos();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t nLoops;
|
uint16_t nLoops;
|
||||||
@@ -78,6 +76,9 @@ void cb_get_inputs(void) // Set Master inputs, slave outputs, last operation
|
|||||||
Obj.EncPos = Encoder1.currentPos();
|
Obj.EncPos = Encoder1.currentPos();
|
||||||
Obj.EncFrequency = Encoder1.frequency(ESCvar.Time);
|
Obj.EncFrequency = Encoder1.frequency(ESCvar.Time);
|
||||||
Obj.IndexByte = Encoder1.getIndexState();
|
Obj.IndexByte = Encoder1.getIndexState();
|
||||||
|
float_t ap2 = Obj.ActualPosition2;
|
||||||
|
Obj.ActualPosition1 = Obj.CommandedPosition1; // Step1.actPos();
|
||||||
|
Obj.ActualPosition2 = Obj.CommandedPosition2; // Step2.actPos();
|
||||||
|
|
||||||
uint64_t dTim = nowTime - thenTime; // Debug. Getting jitter over the last 200 milliseconds
|
uint64_t dTim = nowTime - thenTime; // Debug. Getting jitter over the last 200 milliseconds
|
||||||
Tim.push(dTim);
|
Tim.push(dTim);
|
||||||
@@ -93,9 +94,9 @@ void cb_get_inputs(void) // Set Master inputs, slave outputs, last operation
|
|||||||
thenTime = irqTime;
|
thenTime = irqTime;
|
||||||
Obj.DiffT = longTime.extendTime(micros()) - irqTime; // max_Tim - min_Tim; // Debug
|
Obj.DiffT = longTime.extendTime(micros()) - irqTime; // max_Tim - min_Tim; // Debug
|
||||||
Obj.D1 = Step2.frequency;
|
Obj.D1 = Step2.frequency;
|
||||||
Obj.D2 = nLoops;
|
Obj.D2 = Step2.nSteps;
|
||||||
Obj.D3 = max_Tim - min_Tim;
|
Obj.D3 = abs(1000 * (ap2 - Obj.CommandedPosition2)); // Step2.actPos();
|
||||||
Obj.D4 = ALEventIRQ;
|
Obj.D4 = Step2.Tstartu;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESC_interrupt_enable(uint32_t mask);
|
void ESC_interrupt_enable(uint32_t mask);
|
||||||
@@ -139,8 +140,8 @@ void loop(void)
|
|||||||
{
|
{
|
||||||
nowTime = longTime.extendTime(micros());
|
nowTime = longTime.extendTime(micros());
|
||||||
/* Read local time from ESC*/
|
/* Read local time from ESC*/
|
||||||
ESC_read(ESCREG_LOCALTIME, (void *)&ESCvar.Time, sizeof(ESCvar.Time));
|
// ESC_read(ESCREG_LOCALTIME, (void *)&ESCvar.Time, sizeof(ESCvar.Time));
|
||||||
ESCvar.Time = etohl(ESCvar.Time);
|
// ESCvar.Time = etohl(ESCvar.Time);
|
||||||
DIG_process(ALEventIRQ, DIG_PROCESS_WD_FLAG | DIG_PROCESS_OUTPUTS_FLAG |
|
DIG_process(ALEventIRQ, DIG_PROCESS_WD_FLAG | DIG_PROCESS_OUTPUTS_FLAG |
|
||||||
DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
|
DIG_PROCESS_APP_HOOK_FLAG | DIG_PROCESS_INPUTS_FLAG);
|
||||||
serveIRQ = 0;
|
serveIRQ = 0;
|
||||||
@@ -148,14 +149,14 @@ void loop(void)
|
|||||||
ecat_slv_poll();
|
ecat_slv_poll();
|
||||||
}
|
}
|
||||||
dTime = longTime.extendTime(micros()) - irqTime;
|
dTime = longTime.extendTime(micros()) - irqTime;
|
||||||
if ((dTime > 500 && dTime < 800) || dTime > 5000) // Don't run ecat_slv_poll when expecting to serve interrupt
|
if (dTime > 5000) // Don't run ecat_slv_poll when expecting to serve interrupt
|
||||||
ecat_slv_poll();
|
ecat_slv_poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void sync0Handler(void)
|
void sync0Handler(void)
|
||||||
{
|
{
|
||||||
ALEventIRQ = ESC_ALeventread();
|
ALEventIRQ = ESC_ALeventread();
|
||||||
if (ALEventIRQ & ESCREG_ALEVENT_SM2)
|
// if (ALEventIRQ & ESCREG_ALEVENT_SM2)
|
||||||
{
|
{
|
||||||
serveIRQ = 1;
|
serveIRQ = 1;
|
||||||
irqTime = longTime.extendTime(micros());
|
irqTime = longTime.extendTime(micros());
|
||||||
|
|||||||
Reference in New Issue
Block a user