-
-
Save technobly/8313449 to your computer and use it in GitHub Desktop.
//----------------------------------------------- | |
// SPARK CORE CUSTOM PWM FREQUENCY EXAMPLE | |
//=============================================== | |
// Define your own frequency below! | |
// PWM Glitch issue fixed, only sets up PWM once, | |
// ... thereafter sets duty cycle. | |
// This allows true 0 - 100% PWM. | |
// Copy this into a new application at: | |
// https://www.spark.io/build and go nuts! | |
//----------------------------------------------- | |
// Technobly / BDub - Jan 8th, 2014 | |
//=============================================== | |
#define PWM_FREQ 1000 // in Hertz (SET YOUR FREQUENCY) | |
#define ANALOG_PIN A2 // potentiometer connected to analog pin A2 | |
uint16_t TIM_ARR = (uint16_t)(24000000 / PWM_FREQ) - 1; // Don't change! Calc's period. | |
int val = 0; // variable to store the read ADC value | |
void setup() { | |
pinMode(A0, OUTPUT); // sets the pin as output | |
pinMode(A1, OUTPUT); // sets the pin as output | |
pinMode(A4, OUTPUT); // sets the pin as output | |
pinMode(A5, OUTPUT); // sets the pin as output | |
pinMode(A6, OUTPUT); // sets the pin as output | |
pinMode(A7, OUTPUT); // sets the pin as output | |
pinMode(D0, OUTPUT); // sets the pin as output | |
pinMode(D1, OUTPUT); // sets the pin as output | |
} | |
void loop() { | |
// analogRead values go from 0 to 4095, analogWrite values from 0 to 255 | |
// read the input pin (0-4095) and scale it to 0-255 by dividing by 16. | |
val = analogRead(ANALOG_PIN) / 16; | |
// Write newly scaled value to A0, A1, A4, A5, A6, A7, D0 and D1. | |
analogWrite2(A0, val); | |
analogWrite2(A1, val); | |
analogWrite2(A4, val); | |
analogWrite2(A5, val); | |
analogWrite2(A6, val); | |
analogWrite2(A7, val); | |
analogWrite2(D0, val); | |
analogWrite2(D1, val); | |
delay(10); // wait 10 milliseconds | |
} | |
// User defined analogWrite() to gain control of PWM initialization | |
void analogWrite2(uint16_t pin, uint8_t value) { | |
TIM_OCInitTypeDef TIM_OCInitStructure; | |
if (pin >= TOTAL_PINS || PIN_MAP[pin].timer_peripheral == NULL) { | |
return; | |
} | |
// SPI safety check | |
if (SPI.isEnabled() == true && (pin == SCK || pin == MOSI || pin == MISO)) { | |
return; | |
} | |
// I2C safety check | |
if (Wire.isEnabled() == true && (pin == SCL || pin == SDA)) { | |
return; | |
} | |
// Serial1 safety check | |
if (Serial1.isEnabled() == true && (pin == RX || pin == TX)) { | |
return; | |
} | |
if (PIN_MAP[pin].pin_mode != OUTPUT && PIN_MAP[pin].pin_mode != AF_OUTPUT_PUSHPULL) { | |
return; | |
} | |
// Don't re-init PWM and cause a glitch if already setup, just update duty cycle and return. | |
if (PIN_MAP[pin].pin_mode == AF_OUTPUT_PUSHPULL) { | |
TIM_OCInitStructure.TIM_Pulse = (uint16_t)(value * (TIM_ARR + 1) / 255); | |
if (PIN_MAP[pin].timer_ch == TIM_Channel_1) { | |
PIN_MAP[pin].timer_peripheral-> CCR1 = TIM_OCInitStructure.TIM_Pulse; | |
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_2) { | |
PIN_MAP[pin].timer_peripheral-> CCR2 = TIM_OCInitStructure.TIM_Pulse; | |
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_3) { | |
PIN_MAP[pin].timer_peripheral-> CCR3 = TIM_OCInitStructure.TIM_Pulse; | |
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_4) { | |
PIN_MAP[pin].timer_peripheral-> CCR4 = TIM_OCInitStructure.TIM_Pulse; | |
} | |
return; | |
} | |
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; | |
//PWM Frequency : PWM_FREQ (Hz) | |
uint16_t TIM_Prescaler = (uint16_t)(SystemCoreClock / 24000000) - 1; //TIM Counter clock = 24MHz | |
// TIM Channel Duty Cycle(%) = (TIM_CCR / TIM_ARR + 1) * 100 | |
uint16_t TIM_CCR = (uint16_t)(value * (TIM_ARR + 1) / 255); | |
// AFIO clock enable | |
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); | |
pinMode(pin, AF_OUTPUT_PUSHPULL); | |
// TIM clock enable | |
if (PIN_MAP[pin].timer_peripheral == TIM2) | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); | |
else if (PIN_MAP[pin].timer_peripheral == TIM3) | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); | |
else if (PIN_MAP[pin].timer_peripheral == TIM4) | |
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); | |
// Time base configuration | |
TIM_TimeBaseStructure.TIM_Period = TIM_ARR; | |
TIM_TimeBaseStructure.TIM_Prescaler = TIM_Prescaler; | |
TIM_TimeBaseStructure.TIM_ClockDivision = 0; | |
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; | |
TIM_TimeBaseInit(PIN_MAP[pin].timer_peripheral, & TIM_TimeBaseStructure); | |
// PWM1 Mode configuration | |
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; | |
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; | |
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; | |
TIM_OCInitStructure.TIM_Pulse = TIM_CCR; | |
if (PIN_MAP[pin].timer_ch == TIM_Channel_1) { | |
// PWM1 Mode configuration: Channel1 | |
TIM_OC1Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure); | |
TIM_OC1PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable); | |
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_2) { | |
// PWM1 Mode configuration: Channel2 | |
TIM_OC2Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure); | |
TIM_OC2PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable); | |
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_3) { | |
// PWM1 Mode configuration: Channel3 | |
TIM_OC3Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure); | |
TIM_OC3PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable); | |
} else if (PIN_MAP[pin].timer_ch == TIM_Channel_4) { | |
// PWM1 Mode configuration: Channel4 | |
TIM_OC4Init(PIN_MAP[pin].timer_peripheral, & TIM_OCInitStructure); | |
TIM_OC4PreloadConfig(PIN_MAP[pin].timer_peripheral, TIM_OCPreload_Enable); | |
} | |
TIM_ARRPreloadConfig(PIN_MAP[pin].timer_peripheral, ENABLE); | |
// TIM enable counter | |
TIM_Cmd(PIN_MAP[pin].timer_peripheral, ENABLE); | |
} |
Is it possible to change the PWM resolution to 10 bits by changing
uint16_t TIM_CCR = (uint16_t)(value * (TIM_ARR + 1) / 255);
to
uint16_t TIM_CCR = (uint16_t)(value * (TIM_ARR + 1) / 1023);
It seems like it would be that easy but when I try it, LED fading, it appears to rollover at 256
Nevermind I figured out how to get a higher resolution than 8 bit. See my fork for the code.
https://gist.github.com/Sperryfreak01/a4282fce7c64f44036ae
I tried compiling the above code in https://build.particle.io/build
I got these errors:
- "PIN_MAP" was not declared in this scope
Solution: I added the below line
STM32_Pin_Info* PIN_MAP = HAL_Pin_Map(); // Pointer required for highest access speed - "RCC_APB2PeriphClockCmd" was not declared in this scope
I am unable to find which files needs to be included to remove this error
Could anyone of you help me for this?
I have a particle photon, but can't manage to make this code works. Here are the errors :
I'm a newbie with this board, and not much experimented with this kind of feature.
Maybe some const are no more available?
servo-frequency-2.cpp: In function 'void loop()':
servo-frequency-2.cpp:37:37: error: expected ';' before ')' token
pinMode(D1, OUTPUT); // sets the pin as output
^
servo-frequency-2.cpp: In function 'void analogWrite2(uint16_t, uint16_t)':
servo-frequency-2.cpp:96:26: error: 'RCC_APB2Periph_AFIO' was not declared in this scope
uint16_t TIM_Prescaler = (uint16_t)(SystemCoreClock / 24000000) - 1; //TIM Counter clock = 24MHz
^
make[1]: *** [../build/target/user/platform-6servo-frequency-2.o] Error 1
make: *** [user] Error 2
Thanks a lot, copy/paste -> works!