This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello!
I'm quite new to this. I am in need of some guidance, just so you can put me in the right direction because I am clueless at the moment. I am getting CAN messages with some values which will correspond to pulses for a stepper motor. For example, if byte 1 contains 5, I will need to generate 5 pulses to the stepper motor with a 50k HZ PWM and when next message arrives which contains 6 in byte 1, I will need to generate 6 pulses and so forth (the pulses can vary). So I need something that counts rising edges that reaches the desired pulse value and then interrupts (disable the PWM? or put the duty cycle on 0?) until the next CAN message arrives and do the same thing. Is CCP timer enough here? Any tip would be greatly appreciated!
(I am able to send and receive CAN messages)
The FreeRTOS is for using threads. Currently I have the CAN receive in one thread and the motor control in another one. If I manage with the task above I will increase with 3 more threads for 3 more motors (IF it is possible). Sorry if I'm unclear.
Using the EK-TM4C123GXL board.
Thanks for your time,
Giancarlo
Giancarlo Kuosmanen said:I'm quite new to this. I am in need of some guidance,
OK, given your subject line this sounds like you've set yourself a challenge
Giancarlo Kuosmanen said:. I am getting CAN messages with some values which will correspond to pulses for a stepper motor.
Uh-oh.
Giancarlo Kuosmanen said:For example, if byte 1 contains 5, I will need to generate 5 pulses to the stepper motor with a 50k HZ PWM and when next message arrives which contains 6 in byte 1, I will need to generate 6 pulses and so forth (the pulses can vary).
OK, what do you do if the message is repeated or lost (both of which are natural occurrences in the CAN protocol)?
Giancarlo Kuosmanen said:So I need something that counts rising edges that reaches the desired pulse value and then interrupts (disable the PWM? or put the duty cycle on 0?) until the next CAN message arrives and do the same thing. Is CCP timer enough here?
You're generating the pulses why are you counting them externally?
Robert
Your "Tag" notes, "Do not depend on perfection."
Yet your response - and its summarizing "tag" - (both) very well meet that "dependency!" Crack staff (2 this holiday) & myself - all applaud...
Robert Adsett said:You're generating the pulses why are you counting them externally?
Robert
The problem of sending amount of pulses defined in a CAN message was solved using a timer and ccp split to count rising edges on the pwm signal and disabling the timer using TimerDisable.
The first message works perfectly, however disabling and enabling the timer does not work every time.
Here is the code:
void rising_interrupt(void) { TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT); pulse_control[1].tick++; if(pulse_control[1].tick > (pulse_control[1].num_pulses)*32-1) { TimerDisable(TIMER0_BASE, TIMER_B); } UARTprintf("tick interrupt1: %u\t\n",pulse_control[1].tick); } void initMotors(void) { uint32_t Period = SysCtlClockGet()/25000; // 50kHZ pwm //uint32_t dutyCycle = Period / 2; // 50% duty cycle /*This part Enables the Timer CCP <Capture/Compare/PWM> MOTOR1 */ SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); //Enable the F port // Enable and configure Timer0 peripheral. GPIOPinConfigure(GPIO_PF1_T0CCP1); //Enable the PF1 pin for TimerB | Timer0 PWM0 //GPIOPinConfigure(GPIO_PF0_T0CCP0); //Enable the PF0 pin for TimerA | Timer0 GPIOPinTypeTimer(GPIO_PORTF_BASE,GPIO_PIN_1); //GPIOPinTypeTimer(GPIO_PORTF_BASE,GPIO_PIN_0); SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0); //Even:T0CCP0 Pins:PF0 or PB6 || Odd:T0CCP1 Pins: PB7 or PF1 /* Using timer0 for PWM and rising edge count */ TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM|TIMER_CFG_B_CAP_COUNT_UP); TimerLoadSet(TIMER0_BASE, TIMER_B, Period -1); //Period - 1 because 0 counts. //TimerMatchSet(TIMER0_BASE, TIMER_B, dutyCycle); /* Rising edges */ TimerControlEvent(TIMER0_BASE, TIMER_B, TIMER_EVENT_POS_EDGE); //Measures Rising Edges //TimerLoadSet(TIMER0_BASE,TIMER_A,Period - 1); TimerEnable(TIMER0_BASE,TIMER_B); //TimerEnable(TIMER0_BASE,TIMER_A); //interrupt // Registers a interrupt function to be called when timer b hits a pos edge event IntRegister(INT_TIMER0B, rising_interrupt); // Makes sure the interrupt is cleared TimerIntClear(TIMER0_BASE, TIMER_CAPB_EVENT); // Enable the indicated timer interrupt source. TimerIntEnable(TIMER0_BASE, TIMER_CAPB_EVENT); // The specified interrupt is enabled in the interrupt controller. IntEnable(INT_TIMER0B); } void MotorControl_one(void * pvParameters) { struct canMsgs canREC; uint32_t Period = SysCtlClockGet()/25000; // 25kHZ pwm uint32_t dutyCycle = (Period / 2); // 50% duty cycle initMotors(); xQueueReceive(QueH,&canREC,0); while(1) { if(canREC.CANmsgRX.ui32MsgID == 1) { TimerEnable(TIMER0_BASE, TIMER_B); TimerMatchSet(TIMER0_BASE, TIMER_B, dutyCycle); //PWM pulse_control[1].tick=0; pulse_control[1].num_pulses = canREC.CANmsgRX.pui8MsgData[1]; } vTaskSuspend(MotorOne); } }
Now my question is if there are alternative ways of enabling and disabling the pwm signal?
Giancarlo Kuosmanen said:The problem of sending amount of pulses defined in a CAN message
It doesn't address the issue of the fragility of the CAN message itself though.
Giancarlo Kuosmanen said:Now my question is if there are alternative ways of enabling and disabling the pwm signal?
Why use a PWM?
Robert
Giancarlo Kuosmanen said:You can ignore CAN overall.
Nope, sorry I cannot. A delta based protocol is asking for problems.
Giancarlo Kuosmanen said:We send PWM to a microstep driver for a stepper motor
I know what you are doing with it. I'm asking why it must be PWM rather than some other form of pulse generator.
Giancarlo Kuosmanen said:We know that the driver needs 3200 pulses/rev so a tip on how to count pulses/rising edges would be greatly appreciated.
I don't see why you need to count pulses. Just generate the correct number of pulses. Adding the counting step is only making your task harder.
Robert
Robert Adsett said:I know what you are doing with it. I'm asking why it must be PWM rather than some other form of pulse generator.
What do you mean with any other form of pulse generator, like externally?
Robert Adsett said:I don't see why you need to count pulses. Just generate the correct number of pulses. Adding the counting step is only making your task harder.
Are you suggesting ouputting high and low signals using a delay? Or what other kind of method?
Giancarlo
Giancarlo Kuosmanen said:Robert AdsettI know what you are doing with it. I'm asking why it must be PWM rather than some other form of pulse generator.What do you mean with any other form of pulse generator, like externally?
No, you've got a highly sophisticated microcontroller with a handful of timers, there are several ways to generate pulses. A PWM is suitable for providing a rough D/A or for driving power devices but using it to asynchronously generate a specific number of pulses is to pick one of the hardest methods to use.
Giancarlo Kuosmanen said:Robert AdsettI don't see why you need to count pulses. Just generate the correct number of pulses. Adding the counting step is only making your task harder.Are you suggesting ouputting high and low signals using a delay? Or what other kind of method?
Let's try the simplest pseudo-code
void GeneratePulses(unsigned int n) { while(n>0) { GeneratePulse(); n--; } }
It really can be that straightforward. Once you have it working, then you can optimize.
Robert
Robert Adsett said:Let's try the simplest pseudo-code
void GeneratePulses(unsigned int n) { while(n>0) { GeneratePulse(); n--; } }It really can be that straightforward. Once you have it working, then you can optimize.
Possible for you to mention a functionality that could be of use from the cortex? OPM(One pulse mode)?
Giancarlo Kuosmanen said:Possible for you to mention a functionality that could be of use from the cortex? OPM(One pulse mode)?
GPIO
Timers
There's two. The speed of the pulse chain you can output may be restricted by your receiving devices capability more than the micro's capability to generate. Once you have it working and it proves necessary you can move to incorporating interrupts.
Robert
Robert Adsett said:GPIO
Timers
We're using timers and GPIO and manage to control the angles of the motor. But thanks anyways, sorry if the explanations weren't that great and some misunderstanding occured.