From 137a96ca3291aaf66678ce05b80de646cc34e540 Mon Sep 17 00:00:00 2001 From: manuel Date: Sat, 26 Dec 2020 18:01:43 +0100 Subject: glasslathe: fix frequency for zero --- linz/glasslathe/platformio.ini | 7 +- linz/glasslathe/src/main.cpp | 184 +++++++++++++++++++++-------------------- 2 files changed, 99 insertions(+), 92 deletions(-) diff --git a/linz/glasslathe/platformio.ini b/linz/glasslathe/platformio.ini index f2cb76e..ed9ba0a 100644 --- a/linz/glasslathe/platformio.ini +++ b/linz/glasslathe/platformio.ini @@ -8,8 +8,7 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:nanoatmega328new] -platform = atmelavr -board = nanoatmega328new +[env:mkrzero] +platform = atmelsam framework = arduino -lib_deps = paulstoffregen/TimerOne @ ^1.1 \ No newline at end of file +board = mkrzero diff --git a/linz/glasslathe/src/main.cpp b/linz/glasslathe/src/main.cpp index 85b49dd..cd39208 100644 --- a/linz/glasslathe/src/main.cpp +++ b/linz/glasslathe/src/main.cpp @@ -1,104 +1,112 @@ #include -#include -void analogWriteSAH_Init(void) +#define LED_PIN 4 +#define POT_PIN 2 + +#define POT_JITTER_THRESHOLD 10 + +int potValue = 0; + +void SetupTimer() { - // Stop the timer while we muck with it - TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10); - - // Set the timer to mode 14... - // - // Mode WGM13 WGM12 WGM11 WGM10 Timer/Counter Mode of Operation TOP Update of OCR1x at TOV1 Flag Set on - // CTC1 PWM11 PWM10 - // ---- ----- ----- ----- ----- ------------------------------- ---- ----------------------- ----------- - // 14 1 1 1 0 Fast PWM ICR1 BOTTOM TOP - - // Set output on Channel A to... - // - // COM1A1 COM1A0 Description - // ------ ------ ----------------------------------------------------------- - // 1 0 Clear OC1A/OC1B on Compare Match (Set output to low level). - TCCR1A = - (1 << COM1A1) | (0 << COM1A0) | // COM1A1, COM1A0 = 1, 0 - (0 << COM1B1) | (0 << COM1B0) | - (1 << WGM11) | (0 << WGM10); // WGM11, WGM10 = 1, 0 - - // Set TOP to... - // - // fclk_I/O = 16000000 - // N = 1 - // TOP = 799 - // - // fOCnxPWM = fclk_I/O / (N * (1 + TOP)) - // fOCnxPWM = 16000000 / (1 * (1 + 799)) - // fOCnxPWM = 16000000 / 800 - // fOCnxPWM = 20000 - ICR1 = 799; - - // Ensure the first slope is complete - TCNT1 = 0; - - // Ensure Channel B is irrelevant - OCR1B = 0; - - // Ensure Channel A starts at zero / off - OCR1A = 0; - - // We don't need no stinkin interrupts - TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (0 << TOIE1); - - // Ensure the Channel A pin is configured for output - DDRB |= (1 << DDB1); - - // Start the timer... - // - // CS12 CS11 CS10 Description - // ---- ---- ---- ------------------------ - // 0 0 1 clkI/O/1 (No prescaling) - TCCR1B = - (0 << ICNC1) | (0 << ICES1) | - (1 << WGM13) | (1 << WGM12) | // WGM13, WGM12 = 1, 1 - (0 << CS12) | (0 << CS11) | (1 << CS10); + GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz + GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW + GCLK_GENCTRL_GENEN | // Enable GCLK4 + GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source + GCLK_GENCTRL_ID(4); // Select GCLK4 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + // Enable the port multiplexer for port D5 + PORT->Group[g_APinDescription[5].ulPort].PINCFG[g_APinDescription[5].ulPin].bit.PMUXEN = 1; + + // 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 + + 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 + + TCC0->CC[2].reg = 2399; // TCC0 CC2 - 50% duty-cycle on D10 + 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 } -void analogWriteD9(uint16_t value) +void StopTimer() { - if ((value >= 0) && (value < 800)) - { - OCR1A = value; - } + //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 +} + +void RestartTimer() +{ + // put your main code here, to run repeatedly: + TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER; // Force the TCC0 timer to START + 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); + + 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 +} + +void SetMotorOutput(uint16_t rpm) +{ + const float stepperHzToRPM = 1; //6.67hz runs the stepper at 1 RPM + SetFrequencyOutput(rpm * stepperHzToRPM); } void setup() { - //analogWriteSAH_Init(); - Timer1.initialize(50); - Timer1.pwm(9, 1024/2); - Serial.begin(9600); + SetupTimer(); } void loop() { - static int old_poti = 0; - int poti = analogRead(A7) / 10; - if (poti != old_poti) { - // period_us = 1 / khz * 1000 - int period_us = (poti == 0) ? 0 : map(poti, 1, 102, 600, 50); - Timer1.initialize(period_us); - Timer1.pwm(9, 1024/2); - Serial.println(poti); - Serial.println(period_us); - old_poti = poti; + /*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++) + { + SetFrequencyOutput(i * 1000); + delay(10000); } - //Timer1.setPeriod(); - //Timer1.setPeriod(50); - //Timer1.restart(); - -#if 0 - for (float frequency = 500; frequency < 3000; frequency = frequency + 1) { - float T = 1 / frequency * 1000000; - //Timer1.setPeriod(T); - delay(5); + for(uint8_t i = 20; i >= 0; i--) + { + SetFrequencyOutput(i * 1000); + delay(10000); } -#endif -} \ No newline at end of file +} -- cgit v1.2.3