From beb3de2c0abaa81c47ef571ca9a399a6137c6dea Mon Sep 17 00:00:00 2001 From: manuel Date: Mon, 11 Jan 2021 15:32:58 +0100 Subject: glasslathe: port from glasslathe2 to SAMD21 --- linz/glasslathe/platformio.ini | 1 + linz/glasslathe/src/main.cpp | 205 ++++++++++++++++++++++++++++++++++------- 2 files changed, 173 insertions(+), 33 deletions(-) diff --git a/linz/glasslathe/platformio.ini b/linz/glasslathe/platformio.ini index ed9ba0a..1d524b0 100644 --- a/linz/glasslathe/platformio.ini +++ b/linz/glasslathe/platformio.ini @@ -12,3 +12,4 @@ platform = atmelsam framework = arduino board = mkrzero +lib_deps = Bounce2 diff --git a/linz/glasslathe/src/main.cpp b/linz/glasslathe/src/main.cpp index cd39208..ee1e8d4 100644 --- a/linz/glasslathe/src/main.cpp +++ b/linz/glasslathe/src/main.cpp @@ -1,11 +1,143 @@ #include +#include + +// relais board: +// A1 = potentiometer +// SDA = 24V+ +// SCL = direction in + +// PIN A1 potentiometer +// PIN 0 +// PIN 1 relay 1 +// PIN 2 relay 2 +// PIN 3 +// PIN 4 direction in +// PIN 5 motor frequency out +// PIN 6 motor direction out +// PIN 7 CAN interrupt + +#define POTI_PIN 1 +#define DIRECTION_PIN 4 +#define MOTOR_FREQUENCY_PIN 5 // hardcoded in SetupTimer() +#define MOTOR_DIRECTION_PIN 6 + +#define POT_JITTER_THRESHOLD 20 + +void SetupTimer(); +void StopTimer(); +void RestartTimer(); +void SetFrequencyOutput(uint16_t frequency); +void SetMotorOutput(uint16_t rpm); +float fscale(int inputValue, float originalMin, float originalMax, + float newBegin, float newEnd, float curve); + +Bounce direction_button; +const int frequency_max = 6000; + +struct { + int direction = 0; + int frequency = 0; + int potValue = 1023; +} current, target; +bool timer_enabled = false; -#define LED_PIN 4 -#define POT_PIN 2 +void setup() +{ + Serial.begin(9600); + pinMode(MOTOR_FREQUENCY_PIN, OUTPUT); + + direction_button.attach(DIRECTION_PIN, INPUT_PULLUP); + target.direction = current.direction = !direction_button.read(); + pinMode(MOTOR_DIRECTION_PIN, OUTPUT); + digitalWrite(MOTOR_DIRECTION_PIN, target.direction); -#define POT_JITTER_THRESHOLD 10 + SetupTimer(); +} -int potValue = 0; +void loop() +{ + direction_button.update(); + if (direction_button.changed()) + { + target.direction = !direction_button.read(); + Serial.print("target direction: "); + Serial.println(target.direction, DEC); + } + + int newPotValue = 1023 - analogRead(POTI_PIN); // inverse input values + if (newPotValue < 30) + newPotValue = 0; + else if (newPotValue > 1000) + newPotValue = 1023; + if (abs(newPotValue - target.potValue) > POT_JITTER_THRESHOLD) + { + target.potValue = newPotValue; + Serial.print("newPotValue: "); + Serial.println(newPotValue, DEC); + //target.frequency = (int)fscale(target.potValue / 10, 0, 102, 0, frequency_max, -4); + target.frequency = map(target.potValue / 10, 0, 102, 0, frequency_max); + Serial.print("target frequency: "); + Serial.println(target.frequency, DEC); + } + + const int step_delay = 300; + if (current.frequency != target.frequency || current.direction != target.direction) + { + if (!timer_enabled && target.frequency != 0) + { + RestartTimer(); + timer_enabled = true; + Serial.println("enable motor"); + delay(step_delay); + } + + /*int step = (current.potValue < 20) ? 1 + : (current.potValue < 100) ? 2 + : (current.potValue < 300) ? 3 + : (current.potValue < 400) ? 5 + : (current.potValue < 500) ? 10 + : 20;*/ + int step = (current.frequency > 5000) ? 1 + : (current.frequency > 4500) ? 2 + : (current.frequency > 4000) ? 5 + : (current.frequency > 3000) ? 10 + : (current.frequency > 1000) ? 25 + : 50; + int frequency = (current.direction == target.direction) ? target.frequency : 0; + step = min(abs(frequency - current.frequency), step); + if (frequency < current.frequency) + step *= -1; + current.frequency += step; + + SetFrequencyOutput(current.frequency); + //Serial.print("current potValue: "); + //Serial.print(current.potValue, DEC); + Serial.print("current frequency: "); + Serial.println(current.frequency, DEC); + delay(step_delay); + + if (current.frequency == 0 && current.direction != target.direction) + { + StopTimer(); + timer_enabled = false; + Serial.println("disable motor"); + + current.direction = target.direction; + digitalWrite(MOTOR_DIRECTION_PIN, target.direction); + Serial.print("changed direction to: "); + Serial.println(current.direction, DEC); + + delay(step_delay); + } + } + else if (timer_enabled && newPotValue == 0) + { + StopTimer(); + timer_enabled = false; + Serial.println("disable motor"); + delay(step_delay); + } +} void SetupTimer() { @@ -25,16 +157,16 @@ void SetupTimer() // Connect the TCC timers to the port outputs - port pins are paired odd PMUO and even PMUXE // F & E specify the timers: TCC0, TCC1 and TCC2 PORT->Group[g_APinDescription[5].ulPort].PMUX[g_APinDescription[5].ulPin >> 1].reg = PORT_PMUX_PMUXO_F; - + // Feed GCLK4 to TCC0 and TCC1 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1 GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4 GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1 - while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization - TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Single slope PWM operation + TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Single slope PWM operation while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization - + TCC0->PER.reg = 4799; // Set the frequency of the PWM on TCC0 to 10kHz while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization @@ -42,15 +174,15 @@ void SetupTimer() while (TCC0->SYNCBUSY.bit.CC2); // Wait for synchronization TCC0->CC[3].reg = 2399; // TCC0 CC3 - 50% duty-cycle on D12 while (TCC0->SYNCBUSY.bit.CC3); // Wait for synchronization - + // Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the timer TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1 TCC_CTRLA_ENABLE; // Enable the TCC0 output while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization //Stop TCC0 counter on MCU initialization (stepper initially stopped) - //TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_STOP; // Force the TCC0 timer to STOP - //while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization + TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_STOP; // Force the TCC0 timer to STOP + while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization } void StopTimer() @@ -67,15 +199,13 @@ void RestartTimer() while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization } -uint32_t stepperFrequencyDivisor = 4799; //Sets the starting frequency equal to 1hz - void SetFrequencyOutput(uint16_t frequency) { - stepperFrequencyDivisor = round(48000000 / frequency); - + uint32_t stepperFrequencyDivisor = round(48000000 / frequency); + TCC0->PERB.reg = stepperFrequencyDivisor - 1; // Set the starting frequency of the PWM on TCC0 to 1Hz while (TCC0->SYNCBUSY.bit.PERB); // Wait for synchronization - + TCC0->CCB[1].reg = (stepperFrequencyDivisor / 2) - 1; // TCC0 CC2 - 50% duty-cycle while (TCC0->SYNCBUSY.bit.CCB2); // Wait for synchronization } @@ -86,27 +216,36 @@ void SetMotorOutput(uint16_t rpm) SetFrequencyOutput(rpm * stepperHzToRPM); } -void setup() +float fscale(int inputValue, float originalMin, float originalMax, + float newBegin, float newEnd, float curve) { - SetupTimer(); -} + // condition curve parameter + curve = constrain(curve, -10, 10); + curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output + curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function -void loop() -{ - /*int newPotValue = analogRead(POT_PIN); - if (abs(newPotValue - potValue) > POT_JITTER_THRESHOLD) - { - potValue = newPotValue; - SetFrequencyOutput(map(potValue, 0, 1023, 0, 20000)); - }*/ - for(uint8_t i = 0; i <= 20; i++) + // Check for out of range inputValues + inputValue = constrain(inputValue, originalMin, originalMax); + + // Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine + if (originalMin > originalMax) + return 0; + + // Zero Refference the values + float originalRange = originalMax - originalMin; + float zeroRefCurVal = inputValue - originalMin; + float normalizedCurVal = zeroRefCurVal / originalRange; // normalize to 0 - 1 float + + float rangedValue = 0; + if (newEnd > newBegin) { - SetFrequencyOutput(i * 1000); - delay(10000); + float newRange = newEnd - newBegin; + rangedValue = (pow(normalizedCurVal, curve) * newRange) + newBegin; } - for(uint8_t i = 20; i >= 0; i--) + else { - SetFrequencyOutput(i * 1000); - delay(10000); + float newRange = newBegin - newEnd; + rangedValue = newBegin - (pow(normalizedCurVal, curve) * newRange); } + return rangedValue; } -- cgit v1.2.3