diff options
| author | manuel <manuel@mausz.at> | 2020-12-26 18:01:43 +0100 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2020-12-26 18:01:43 +0100 |
| commit | 137a96ca3291aaf66678ce05b80de646cc34e540 (patch) | |
| tree | 5f92638a6a0f673444a8fb1cc251be042f546a51 | |
| parent | a517cd8db485faaf0e63122798ddd266371cb36e (diff) | |
| download | arduino-137a96ca3291aaf66678ce05b80de646cc34e540.tar.gz arduino-137a96ca3291aaf66678ce05b80de646cc34e540.tar.bz2 arduino-137a96ca3291aaf66678ce05b80de646cc34e540.zip | |
glasslathe: fix frequency for zero
| -rw-r--r-- | linz/glasslathe/platformio.ini | 7 | ||||
| -rw-r--r-- | 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 @@ | |||
| 8 | ; Please visit documentation for the other options and examples | 8 | ; Please visit documentation for the other options and examples |
| 9 | ; https://docs.platformio.org/page/projectconf.html | 9 | ; https://docs.platformio.org/page/projectconf.html |
| 10 | 10 | ||
| 11 | [env:nanoatmega328new] | 11 | [env:mkrzero] |
| 12 | platform = atmelavr | 12 | platform = atmelsam |
| 13 | board = nanoatmega328new | ||
| 14 | framework = arduino | 13 | framework = arduino |
| 15 | lib_deps = paulstoffregen/TimerOne @ ^1.1 \ No newline at end of file | 14 | 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 @@ | |||
| 1 | #include <Arduino.h> | 1 | #include <Arduino.h> |
| 2 | #include <TimerOne.h> | ||
| 3 | 2 | ||
| 4 | void analogWriteSAH_Init(void) | 3 | #define LED_PIN 4 |
| 4 | #define POT_PIN 2 | ||
| 5 | |||
| 6 | #define POT_JITTER_THRESHOLD 10 | ||
| 7 | |||
| 8 | int potValue = 0; | ||
| 9 | |||
| 10 | void SetupTimer() | ||
| 5 | { | 11 | { |
| 6 | // Stop the timer while we muck with it | 12 | GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz |
| 7 | TCCR1B = (0 << ICNC1) | (0 << ICES1) | (0 << WGM13) | (0 << WGM12) | (0 << CS12) | (0 << CS11) | (0 << CS10); | 13 | GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4 |
| 8 | 14 | while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization | |
| 9 | // Set the timer to mode 14... | 15 | |
| 10 | // | 16 | GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW |
| 11 | // Mode WGM13 WGM12 WGM11 WGM10 Timer/Counter Mode of Operation TOP Update of OCR1x at TOV1 Flag Set on | 17 | GCLK_GENCTRL_GENEN | // Enable GCLK4 |
| 12 | // CTC1 PWM11 PWM10 | 18 | GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source |
| 13 | // ---- ----- ----- ----- ----- ------------------------------- ---- ----------------------- ----------- | 19 | GCLK_GENCTRL_ID(4); // Select GCLK4 |
| 14 | // 14 1 1 1 0 Fast PWM ICR1 BOTTOM TOP | 20 | while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization |
| 15 | 21 | ||
| 16 | // Set output on Channel A to... | 22 | // Enable the port multiplexer for port D5 |
| 17 | // | 23 | PORT->Group[g_APinDescription[5].ulPort].PINCFG[g_APinDescription[5].ulPin].bit.PMUXEN = 1; |
| 18 | // COM1A1 COM1A0 Description | 24 | |
| 19 | // ------ ------ ----------------------------------------------------------- | 25 | // Connect the TCC timers to the port outputs - port pins are paired odd PMUO and even PMUXE |
| 20 | // 1 0 Clear OC1A/OC1B on Compare Match (Set output to low level). | 26 | // F & E specify the timers: TCC0, TCC1 and TCC2 |
| 21 | TCCR1A = | 27 | PORT->Group[g_APinDescription[5].ulPort].PMUX[g_APinDescription[5].ulPin >> 1].reg = PORT_PMUX_PMUXO_F; |
| 22 | (1 << COM1A1) | (0 << COM1A0) | // COM1A1, COM1A0 = 1, 0 | 28 | |
| 23 | (0 << COM1B1) | (0 << COM1B0) | | 29 | // Feed GCLK4 to TCC0 and TCC1 |
| 24 | (1 << WGM11) | (0 << WGM10); // WGM11, WGM10 = 1, 0 | 30 | GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TCC0 and TCC1 |
| 25 | 31 | GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4 | |
| 26 | // Set TOP to... | 32 | GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1 |
| 27 | // | 33 | while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization |
| 28 | // fclk_I/O = 16000000 | 34 | |
| 29 | // N = 1 | 35 | TCC0->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM; // Single slope PWM operation |
| 30 | // TOP = 799 | 36 | while (TCC0->SYNCBUSY.bit.WAVE); // Wait for synchronization |
| 31 | // | 37 | |
| 32 | // fOCnxPWM = fclk_I/O / (N * (1 + TOP)) | 38 | TCC0->PER.reg = 4799; // Set the frequency of the PWM on TCC0 to 10kHz |
| 33 | // fOCnxPWM = 16000000 / (1 * (1 + 799)) | 39 | while (TCC0->SYNCBUSY.bit.PER); // Wait for synchronization |
| 34 | // fOCnxPWM = 16000000 / 800 | 40 | |
| 35 | // fOCnxPWM = 20000 | 41 | TCC0->CC[2].reg = 2399; // TCC0 CC2 - 50% duty-cycle on D10 |
| 36 | ICR1 = 799; | 42 | while (TCC0->SYNCBUSY.bit.CC2); // Wait for synchronization |
| 37 | 43 | TCC0->CC[3].reg = 2399; // TCC0 CC3 - 50% duty-cycle on D12 | |
| 38 | // Ensure the first slope is complete | 44 | while (TCC0->SYNCBUSY.bit.CC3); // Wait for synchronization |
| 39 | TCNT1 = 0; | 45 | |
| 40 | 46 | // Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the timer | |
| 41 | // Ensure Channel B is irrelevant | 47 | TCC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1 |
| 42 | OCR1B = 0; | 48 | TCC_CTRLA_ENABLE; // Enable the TCC0 output |
| 43 | 49 | while (TCC0->SYNCBUSY.bit.ENABLE); // Wait for synchronization | |
| 44 | // Ensure Channel A starts at zero / off | 50 | |
| 45 | OCR1A = 0; | 51 | //Stop TCC0 counter on MCU initialization (stepper initially stopped) |
| 46 | 52 | //TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_STOP; // Force the TCC0 timer to STOP | |
| 47 | // We don't need no stinkin interrupts | 53 | //while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization |
| 48 | TIMSK1 = (0 << ICIE1) | (0 << OCIE1B) | (0 << OCIE1A) | (0 << TOIE1); | ||
| 49 | |||
| 50 | // Ensure the Channel A pin is configured for output | ||
| 51 | DDRB |= (1 << DDB1); | ||
| 52 | |||
| 53 | // Start the timer... | ||
| 54 | // | ||
| 55 | // CS12 CS11 CS10 Description | ||
| 56 | // ---- ---- ---- ------------------------ | ||
| 57 | // 0 0 1 clkI/O/1 (No prescaling) | ||
| 58 | TCCR1B = | ||
| 59 | (0 << ICNC1) | (0 << ICES1) | | ||
| 60 | (1 << WGM13) | (1 << WGM12) | // WGM13, WGM12 = 1, 1 | ||
| 61 | (0 << CS12) | (0 << CS11) | (1 << CS10); | ||
| 62 | } | 54 | } |
| 63 | 55 | ||
| 64 | void analogWriteD9(uint16_t value) | 56 | void StopTimer() |
| 65 | { | 57 | { |
| 66 | if ((value >= 0) && (value < 800)) | 58 | //Stop TCC0 counter on MCU initialization (stepper initially stopped) |
| 67 | { | 59 | TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_STOP; // Force the TCC0 timer to STOP |
| 68 | OCR1A = value; | 60 | while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization |
| 69 | } | 61 | } |
| 62 | |||
| 63 | void RestartTimer() | ||
| 64 | { | ||
| 65 | // put your main code here, to run repeatedly: | ||
| 66 | TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER; // Force the TCC0 timer to START | ||
| 67 | while (TCC0->SYNCBUSY.bit.CTRLB); // Wait for synchronization | ||
| 68 | } | ||
| 69 | |||
| 70 | uint32_t stepperFrequencyDivisor = 4799; //Sets the starting frequency equal to 1hz | ||
| 71 | |||
| 72 | void SetFrequencyOutput(uint16_t frequency) | ||
| 73 | { | ||
| 74 | stepperFrequencyDivisor = round(48000000 / frequency); | ||
| 75 | |||
| 76 | 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 | ||
| 78 | |||
| 79 | TCC0->CCB[1].reg = (stepperFrequencyDivisor / 2) - 1; // TCC0 CC2 - 50% duty-cycle | ||
| 80 | while (TCC0->SYNCBUSY.bit.CCB2); // Wait for synchronization | ||
| 81 | } | ||
| 82 | |||
| 83 | void SetMotorOutput(uint16_t rpm) | ||
| 84 | { | ||
| 85 | const float stepperHzToRPM = 1; //6.67hz runs the stepper at 1 RPM | ||
| 86 | SetFrequencyOutput(rpm * stepperHzToRPM); | ||
| 70 | } | 87 | } |
| 71 | 88 | ||
| 72 | void setup() | 89 | void setup() |
| 73 | { | 90 | { |
| 74 | //analogWriteSAH_Init(); | 91 | SetupTimer(); |
| 75 | Timer1.initialize(50); | ||
| 76 | Timer1.pwm(9, 1024/2); | ||
| 77 | Serial.begin(9600); | ||
| 78 | } | 92 | } |
| 79 | 93 | ||
| 80 | void loop() | 94 | void loop() |
| 81 | { | 95 | { |
| 82 | static int old_poti = 0; | 96 | /*int newPotValue = analogRead(POT_PIN); |
| 83 | int poti = analogRead(A7) / 10; | 97 | if (abs(newPotValue - potValue) > POT_JITTER_THRESHOLD) |
| 84 | if (poti != old_poti) { | 98 | { |
| 85 | // period_us = 1 / khz * 1000 | 99 | potValue = newPotValue; |
| 86 | int period_us = (poti == 0) ? 0 : map(poti, 1, 102, 600, 50); | 100 | SetFrequencyOutput(map(potValue, 0, 1023, 0, 20000)); |
| 87 | Timer1.initialize(period_us); | 101 | }*/ |
| 88 | Timer1.pwm(9, 1024/2); | 102 | for(uint8_t i = 0; i <= 20; i++) |
| 89 | Serial.println(poti); | 103 | { |
| 90 | Serial.println(period_us); | 104 | SetFrequencyOutput(i * 1000); |
| 91 | old_poti = poti; | 105 | delay(10000); |
| 92 | } | 106 | } |
| 93 | //Timer1.setPeriod(); | 107 | for(uint8_t i = 20; i >= 0; i--) |
| 94 | //Timer1.setPeriod(50); | 108 | { |
| 95 | //Timer1.restart(); | 109 | SetFrequencyOutput(i * 1000); |
| 96 | 110 | delay(10000); | |
| 97 | #if 0 | ||
| 98 | for (float frequency = 500; frequency < 3000; frequency = frequency + 1) { | ||
| 99 | float T = 1 / frequency * 1000000; | ||
| 100 | //Timer1.setPeriod(T); | ||
| 101 | delay(5); | ||
| 102 | } | 111 | } |
| 103 | #endif | 112 | } |
| 104 | } \ No newline at end of file | ||
