summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--linz/glasslathe/platformio.ini1
-rw-r--r--linz/glasslathe/src/main.cpp205
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 @@
12platform = atmelsam 12platform = atmelsam
13framework = arduino 13framework = arduino
14board = mkrzero 14board = mkrzero
15lib_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 @@
1#include <Arduino.h> 1#include <Arduino.h>
2#include <Bounce2.h>
3
4// relais board:
5// A1 = potentiometer
6// SDA = 24V+
7// SCL = direction in
8
9// PIN A1 potentiometer
10// PIN 0
11// PIN 1 relay 1
12// PIN 2 relay 2
13// PIN 3
14// PIN 4 direction in
15// PIN 5 motor frequency out
16// PIN 6 motor direction out
17// PIN 7 CAN interrupt
18
19#define POTI_PIN 1
20#define DIRECTION_PIN 4
21#define MOTOR_FREQUENCY_PIN 5 // hardcoded in SetupTimer()
22#define MOTOR_DIRECTION_PIN 6
23
24#define POT_JITTER_THRESHOLD 20
25
26void SetupTimer();
27void StopTimer();
28void RestartTimer();
29void SetFrequencyOutput(uint16_t frequency);
30void SetMotorOutput(uint16_t rpm);
31float fscale(int inputValue, float originalMin, float originalMax,
32 float newBegin, float newEnd, float curve);
33
34Bounce direction_button;
35const int frequency_max = 6000;
36
37struct {
38 int direction = 0;
39 int frequency = 0;
40 int potValue = 1023;
41} current, target;
42bool timer_enabled = false;
2 43
3#define LED_PIN 4 44void setup()
4#define POT_PIN 2 45{
46 Serial.begin(9600);
47 pinMode(MOTOR_FREQUENCY_PIN, OUTPUT);
48
49 direction_button.attach(DIRECTION_PIN, INPUT_PULLUP);
50 target.direction = current.direction = !direction_button.read();
51 pinMode(MOTOR_DIRECTION_PIN, OUTPUT);
52 digitalWrite(MOTOR_DIRECTION_PIN, target.direction);
5 53
6#define POT_JITTER_THRESHOLD 10 54 SetupTimer();
55}
7 56
8int potValue = 0; 57void loop()
58{
59 direction_button.update();
60 if (direction_button.changed())
61 {
62 target.direction = !direction_button.read();
63 Serial.print("target direction: ");
64 Serial.println(target.direction, DEC);
65 }
66
67 int newPotValue = 1023 - analogRead(POTI_PIN); // inverse input values
68 if (newPotValue < 30)
69 newPotValue = 0;
70 else if (newPotValue > 1000)
71 newPotValue = 1023;
72 if (abs(newPotValue - target.potValue) > POT_JITTER_THRESHOLD)
73 {
74 target.potValue = newPotValue;
75 Serial.print("newPotValue: ");
76 Serial.println(newPotValue, DEC);
77 //target.frequency = (int)fscale(target.potValue / 10, 0, 102, 0, frequency_max, -4);
78 target.frequency = map(target.potValue / 10, 0, 102, 0, frequency_max);
79 Serial.print("target frequency: ");
80 Serial.println(target.frequency, DEC);
81 }
82
83 const int step_delay = 300;
84 if (current.frequency != target.frequency || current.direction != target.direction)
85 {
86 if (!timer_enabled && target.frequency != 0)
87 {
88 RestartTimer();
89 timer_enabled = true;
90 Serial.println("enable motor");
91 delay(step_delay);
92 }
93
94 /*int step = (current.potValue < 20) ? 1
95 : (current.potValue < 100) ? 2
96 : (current.potValue < 300) ? 3
97 : (current.potValue < 400) ? 5
98 : (current.potValue < 500) ? 10
99 : 20;*/
100 int step = (current.frequency > 5000) ? 1
101 : (current.frequency > 4500) ? 2
102 : (current.frequency > 4000) ? 5
103 : (current.frequency > 3000) ? 10
104 : (current.frequency > 1000) ? 25
105 : 50;
106 int frequency = (current.direction == target.direction) ? target.frequency : 0;
107 step = min(abs(frequency - current.frequency), step);
108 if (frequency < current.frequency)
109 step *= -1;
110 current.frequency += step;
111
112 SetFrequencyOutput(current.frequency);
113 //Serial.print("current potValue: ");
114 //Serial.print(current.potValue, DEC);
115 Serial.print("current frequency: ");
116 Serial.println(current.frequency, DEC);
117 delay(step_delay);
118
119 if (current.frequency == 0 && current.direction != target.direction)
120 {
121 StopTimer();
122 timer_enabled = false;
123 Serial.println("disable motor");
124
125 current.direction = target.direction;
126 digitalWrite(MOTOR_DIRECTION_PIN, target.direction);
127 Serial.print("changed direction to: ");
128 Serial.println(current.direction, DEC);
129
130 delay(step_delay);
131 }
132 }
133 else if (timer_enabled && newPotValue == 0)
134 {
135 StopTimer();
136 timer_enabled = false;
137 Serial.println("disable motor");
138 delay(step_delay);
139 }
140}
9 141
10void SetupTimer() 142void SetupTimer()
11{ 143{
@@ -25,16 +157,16 @@ void SetupTimer()
25 // Connect the TCC timers to the port outputs - port pins are paired odd PMUO and even PMUXE 157 // Connect the TCC timers to the port outputs - port pins are paired odd PMUO and even PMUXE
26 // F & E specify the timers: TCC0, TCC1 and TCC2 158 // F & E specify the timers: TCC0, TCC1 and TCC2
27 PORT->Group[g_APinDescription[5].ulPort].PMUX[g_APinDescription[5].ulPin >> 1].reg = PORT_PMUX_PMUXO_F; 159 PORT->Group[g_APinDescription[5].ulPort].PMUX[g_APinDescription[5].ulPin >> 1].reg = PORT_PMUX_PMUXO_F;
28 160
29 // Feed GCLK4 to TCC0 and TCC1 161 // Feed GCLK4 to TCC0 and TCC1
30 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1 162 GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1
31 GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4 163 GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
32 GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1 164 GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
33 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization 165 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
34 166
35 TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Single slope PWM operation 167 TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Single slope PWM operation
36 while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization 168 while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization
37 169
38 TCC0->PER.reg = 4799; // Set the frequency of the PWM on TCC0 to 10kHz 170 TCC0->PER.reg = 4799; // Set the frequency of the PWM on TCC0 to 10kHz
39 while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization 171 while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization
40 172
@@ -42,15 +174,15 @@ void SetupTimer()
42 while (TCC0->SYNCBUSY.bit.CC2); // Wait for synchronization 174 while (TCC0->SYNCBUSY.bit.CC2); // Wait for synchronization
43 TCC0->CC[3].reg = 2399; // TCC0 CC3 - 50% duty-cycle on D12 175 TCC0->CC[3].reg = 2399; // TCC0 CC3 - 50% duty-cycle on D12
44 while (TCC0->SYNCBUSY.bit.CC3); // Wait for synchronization 176 while (TCC0->SYNCBUSY.bit.CC3); // Wait for synchronization
45 177
46 // Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the timer 178 // Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the timer
47 TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1 179 TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1
48 TCC_CTRLA_ENABLE; // Enable the TCC0 output 180 TCC_CTRLA_ENABLE; // Enable the TCC0 output
49 while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization 181 while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization
50 182
51 //Stop TCC0 counter on MCU initialization (stepper initially stopped) 183 //Stop TCC0 counter on MCU initialization (stepper initially stopped)
52 //TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_STOP; // Force the TCC0 timer to STOP 184 TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_STOP; // Force the TCC0 timer to STOP
53 //while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization 185 while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization
54} 186}
55 187
56void StopTimer() 188void StopTimer()
@@ -67,15 +199,13 @@ void RestartTimer()
67 while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization 199 while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization
68} 200}
69 201
70uint32_t stepperFrequencyDivisor = 4799; //Sets the starting frequency equal to 1hz
71
72void SetFrequencyOutput(uint16_t frequency) 202void SetFrequencyOutput(uint16_t frequency)
73{ 203{
74 stepperFrequencyDivisor = round(48000000 / frequency); 204 uint32_t stepperFrequencyDivisor = round(48000000 / frequency);
75 205
76 TCC0->PERB.reg = stepperFrequencyDivisor - 1; // Set the starting frequency of the PWM on TCC0 to 1Hz 206 TCC0->PERB.reg = stepperFrequencyDivisor - 1; // Set the starting frequency of the PWM on TCC0 to 1Hz
77 while (TCC0->SYNCBUSY.bit.PERB); // Wait for synchronization 207 while (TCC0->SYNCBUSY.bit.PERB); // Wait for synchronization
78 208
79 TCC0->CCB[1].reg = (stepperFrequencyDivisor / 2) - 1; // TCC0 CC2 - 50% duty-cycle 209 TCC0->CCB[1].reg = (stepperFrequencyDivisor / 2) - 1; // TCC0 CC2 - 50% duty-cycle
80 while (TCC0->SYNCBUSY.bit.CCB2); // Wait for synchronization 210 while (TCC0->SYNCBUSY.bit.CCB2); // Wait for synchronization
81} 211}
@@ -86,27 +216,36 @@ void SetMotorOutput(uint16_t rpm)
86 SetFrequencyOutput(rpm * stepperHzToRPM); 216 SetFrequencyOutput(rpm * stepperHzToRPM);
87} 217}
88 218
89void setup() 219float fscale(int inputValue, float originalMin, float originalMax,
220 float newBegin, float newEnd, float curve)
90{ 221{
91 SetupTimer(); 222 // condition curve parameter
92} 223 curve = constrain(curve, -10, 10);
224 curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
225 curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function
93 226
94void loop() 227 // Check for out of range inputValues
95{ 228 inputValue = constrain(inputValue, originalMin, originalMax);
96 /*int newPotValue = analogRead(POT_PIN); 229
97 if (abs(newPotValue - potValue) > POT_JITTER_THRESHOLD) 230 // Check for originalMin > originalMax - the math for all other cases i.e. negative numbers seems to work out fine
98 { 231 if (originalMin > originalMax)
99 potValue = newPotValue; 232 return 0;
100 SetFrequencyOutput(map(potValue, 0, 1023, 0, 20000)); 233
101 }*/ 234 // Zero Refference the values
102 for(uint8_t i = 0; i <= 20; i++) 235 float originalRange = originalMax - originalMin;
236 float zeroRefCurVal = inputValue - originalMin;
237 float normalizedCurVal = zeroRefCurVal / originalRange; // normalize to 0 - 1 float
238
239 float rangedValue = 0;
240 if (newEnd > newBegin)
103 { 241 {
104 SetFrequencyOutput(i * 1000); 242 float newRange = newEnd - newBegin;
105 delay(10000); 243 rangedValue = (pow(normalizedCurVal, curve) * newRange) + newBegin;
106 } 244 }
107 for(uint8_t i = 20; i >= 0; i--) 245 else
108 { 246 {
109 SetFrequencyOutput(i * 1000); 247 float newRange = newBegin - newEnd;
110 delay(10000); 248 rangedValue = newBegin - (pow(normalizedCurVal, curve) * newRange);
111 } 249 }
250 return rangedValue;
112} 251}