How can I do this?
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.
You are going to need to provide more information regarding what device you are targeting, etc.
For the specific device you are targeting, please look at its associated Family User's Guide which supplies information on how to configure the timer modules to generate a PWM. This document is available on the Product Folder on www.ti.com for the specific device.
Also, please note there are code examples for the specific device family that you can reference to quickly configure the device to implement a PWM. These are very simple examples to illustrate this capability.
sry I forgot: MSP430F2274
I am using Timer A, but cannot find, where I can configure the frequency of the pwm signal.
There are many threads in this forum which explain this.
Basically, you set up the CCR0 register of a timer to reset the timer to 0 when it reaches a certain value. So the timer runs form 0 to CCR0 and starts with 0 again.
This gives you the PWM frequency (cycle time).
For the duty cycle of the PWM outputs, you configure CCR1..CCRn (for output 1..n) to set at TAR==0 and reset at TAR==CCRx (reset/set mode), so the ratio of (CCR0+1) and CCRx gives the duty cycle.
There is no explicit 'set frequency' or 'set duty cycle' register, as the same CCR modules can be used for many other things too.
I should add some more information:
-> RTC via SPI on MSP430F2274
-> I read in SLAA120.pdf, that I have to config the DCO (digital controlled oscillator) frequency
in order to change the pwm frequency. Do you have a formula for this?
I'll read 5.2.5 in slau144h.pdf for information about the dco now...
ok, found that code example (msp430x22x4_ta_16.c):
//******************************************************************************
// MSP430F22x4 Demo - Timer_A, PWM TA1-2, Up Mode, DCO SMCLK
//
// Description: This program generates two PWM outputs on P1.2,3 using
// Timer_A configured for up mode. The value in TACCR0, 512-1, defines the PWM
// period and the values in TACCR1 and TACCR2 the PWM duty cycles.
// Using ~1.2MHz SMCLK as TACLK, the timer period is ~425us with
// a 75% duty cycle on P1.2 and 25% on P1.3.
// ACLK = n/a, SMCLK = MCLK = TACLK = default DCO ~1.2MHz
//
// MSP430F22x4
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.2/TA1|--> TACCR1 - 75% PWM
// | P1.3/TA2|--> TACCR2 - 25% PWM
//
// A. Dannenberg
// Texas Instruments Inc.
// April 2006
// Built with CCE Version: 3.2.0 and IAR Embedded Workbench Version: 3.41A
//******************************************************************************
#include "msp430x22x4.h"
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P1DIR |= 0x0C; // P1.2 and P1.3 output
P1SEL |= 0x0C; // P1.2 and P1.3 TA1/2 otions
TACCR0 = 512 - 1; // PWM Period
TACCTL1 = OUTMOD_7; // TACCR1 reset/set
TACCR1 = 384; // TACCR1 PWM duty cycle
TACCTL2 = OUTMOD_7; // TACCR2 reset/set
TACCR2 = 128; // TACCR2 PWM duty cycle
TACTL = TASSEL_2 + MC_1; // SMCLK, up mode
__bis_SR_register(CPUOFF); // Enter LPM0
}
But how can I calculate the "~425us" and "~1.2MHz"?
Is it possible to generate a pwm signal with over 20kHz in order to let the vibrator, that is controlled through the pwm, run smooth?
There is no secret formula. Once you understood how the clock system propagates the signal, it is simple first-grade math.dpolt said:But how can I calculate the "~425us" and "~1.2MHz"?
The clock system provides three clocks: ACLK, SMCLK and MCLK. MCLK is used as the cpu core clock. SMCLK and ACLK are used as clock signal for the different modules.
All three clocks are sourced by an oscillator. This may be the DCo or an external crystal (there are other options as well, btu these are the two main options).
So you can configure the DCo to output a frequency of ~1.25MHz. The DCO output frequencies vary across different devices. Some have a set of measured 'cvalibration values' that program this specific MSP for a DCO of ~1MHz or ~4Mhz or so. However, the default frequency after switching it on is somewhere in the range of 1,1..1,25MHz. See the datasheet for details to guess the range.
This DCO frequency is sourced into SMCLK. Either directly or pre-divided. I think, the default is direct. So SMCLK has ~1.25MHz. With every SMCLK tick, TAR increases by one. (or for every nth, if you use the divider options in TACTL).Once TAR matches TACCR0, it rolls over to 0 (with the next tick). So settign TACCR0 to 512 means that the tiemr rolls over to 0 over 512 SMCLK ticks.
When the timer rolls over to 0, TA.1 and TA.2 are set. When TAR counts to the content of TACCR1 (or TACR2) TA.1 (or TA.2) are reset, based on the OUTMOD setting.
1.2MHz/512 = 426µs.
and 384/512 = 75% duty cycle on TA.1 and 128/512=25% duty cycle on TA.2
ok, thx for your great describtion.
But how do the percentages on TA1 and TA2 influence the frequency?
What do they cause? Are they P1.2 (=TA1) and P1.3 (=TA3) both outputs, that get 75% / 25 % of *???* ?
PS: Sry for these questions, but I´m just beginning to understand this µC-Language ...
Not at all.dpolt said:But how do the percentages on TA1 and TA2 influence the frequency?
The CCR0 setting controls how many tiemr ticks form one PWM cycle. So CCR0 is controlling the PWM frequency for ALL CCR units of this timer. The individual CCRx units and ther programme dvalue define the moment during this timer cycle where the output will be set (or reset, depending on the programmed mode).
So if CCR0 is set to 99 (= 100 ticks since 0 is a tick too), one PWM cycle will take 100 timer ticks. How much this is as a frequency/cycle time depends on the clock signal that clocks the timer. 100 ticks.
The relation of the CCR1 or CCR2 registers to the CR0 calue defines the percentage. If in the above scenario CCR1 is set to 50, you'll get a duty cycle of 50% ((CCR0+1)/CCR1). for 100, you'll get 100% and 1 gives you 1%.
If CCR0 is set to 50, then CCR1=50 will give you 100% and CCR1=25 will give you 50%.
CCR1 outputs on TA.1, CCR2 on TA.2 etc (whatever port pin it might be assigned to, sometiemes, there is more than one option)
So in one sentence: the CCR0 setting controls the PWM cycle time in time rticks, the timer clock source defines the length of a tiemr tick, and the CCRx settings define the duty cycle in relation to the CCR0 setting.
Actually it's not a language, it's just a hardware functionality controlled by register contents. Just like an AND or OR gate, only a 'bit' more complex. And indeed, you could visualize the whole issue as a TTL circuitry (whch it basically is) with the register contents as input signals.dpolt said:I´m just beginning to understand this µC-Language
so in conclusion:
-> with TACCR1 and TACCR2 I can config how much % is "on" in one Period
-> with TACCR0 I can config the Periode = 1 / pwm-frequency
right?
PS: What do the registers on page 279 in the family guide? Sounds similar to the config of TACCR0...
Which ones? I don't have access to my datasheets... And a page number is not a good reference, since it may change from one revision to the next.dpolt said:What do the registers on page 279 in the family guide? Sounds similar to the config of TACCR0...
dpolt said:so in conclusion:
-> with TACCR1 and TACCR2 I can config how much % is "on" in one Period
-> with TACCR0 I can config the Periode = 1 / pwm-frequency
right?
Yes.
dpolt said:
PS: What do the registers on page 279 in the family guide? Sounds similar to the config of TACCR0...
As Jens-Michael Gros has been indicating in his posts, there are a couple of modules within the MSP430F2274 that are important to understand when you want to setup the TimerA to be a PWM. The clock source and the timer itself. It sounds like you know have spent some time looking at the Famiily User's Guide in the TimerA section and with Jens-Michael Gros' additional explanation to understand how it works.
Now you need to spend some time with the clock generation portion. This is the DCO section that you are refereing with page 279. This module will generate the reference clock to the TimerA. Configuring it will be important as well to give the base, reference clock frequency to the TimerA.
I meant slau144h page 279 5.2.5.2
ok I beginning to understand. I´ll try some settings on the oscilloscope in the next days...
THX again.
dpolt said:so in conclusion:
-> with TACCR1 and TACCR2 I can config how much % is "on" in one Period
-> with TACCR0 I can config the Periode = 1 / pwm-frequency
right?
About the %, right. About the frequency, not completely.
The frequency of the pwm so generated is = (TimerA frequency) / (TACCR0+1)
Where (TimerA frequency) = (TimerA clock source TASSEL) / (TimerA clock divider ID)
The SMCLK and ACLK described in the User's Guide as well as an external clock TACLK can all be selected by TASSEL as the TimerA clock source.
dpolt said:PS: What do the registers on page 279 in the family guide? Sounds similar to the config of TACCR0...
It is not clear what register you are asking about.
DCO is an oscillator. You can use it to derive MCLK and/or SMCLK. SMCLK can be used as the TimerA clock source.
ok thx.
so: slau144h page 279 5.2.5.2 is just for external crystals and not for the internal one?
and: special thx for the new formulas and descriptions!
dpolt said:so: slau144h page 279 5.2.5.2 is just for external crystals and not for the internal one?
No, it is for the internal Digital Controlled Oscillator (DCO).
Please take a look at the block diagram of the Basic Clock Module (BCM+) on page 275, Figure 5-1.
of course.
Now I wrote some code:
in main.c:
//PWM-TEST START
init_pwm_motor();
stop_pwm_motor();
test_pwm_motor();
stop_pwm_motor();
//PWM-TEST ENDE
and in pwm.c:
void init_pwm_motor(void){
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P4DIR |= BIT2; // P4.2 output //Daniel
P4SEL |= PWM_MOTOR; // P4.1 - P4.2 TAx options
TACCR0 = 128 - 1; // PWM Period/2
TACCTL2 = OUTMOD_6; // TACCR2 toggle/set
TACCR2 = 64; //Vibr.motor // TACCR2 PWM Duty Cycle -->50% high //Daniel
//TACCR2 = 128; //Coin motor, 0R, no C // TACCR2 PWM Duty Cycle -->100% low //Daniel
TACTL = TASSEL_2 + MC_1 + ID_2; // SMCLK, up mode, Divide=2 //Daniel
}
void run_pwm_motor(void){ // After a given time, the motor can be ajusted from
TACCR2 = 15360; // max power to the lowest running value possible
}
void stop_pwm_motor(void){
TACCTL2 = 0x0000; // Reset Capture/Control Register
TACCR2 = 0; // PWM 100% low
// TACCR0 = 0; // Set PWM period 0
TACTL = MC_0; // Stop Timer_A timer
}
void test_pwm_motor(void){
init_pwm_motor();
TACCR2 = 128; //100% high //Daniel: 100%
wait_ms(3000);
TACCR2 = 64; //50% high //Daniel: 50%
wait_ms(3000);
TACCR2 = 0; //100% low //Daniel: 0%
wait_ms(3000);
TACCR2 = 64; //50% high //Daniel: 50%
wait_ms(3000);
TACCR2 = 128; //100% high //Daniel: 100%
wait_ms(3000);
}
run_pwm_motor is an existing function. I have to find out, what it does...
Is the rest correct? (code = description)
Best regards
Daniel
I wouldn't put this into a module init function. It's easy to forget later that this function messes with a completely unrelated hardware like the WDT.dpolt said:WDTCTL = WDTPW + WDTHOLD; // Stop WDT
Thsi doen' tmake sense if your CCR0 value is 127 and therefore TAR can never get past 127. However, it doesn't harm anyone, you'll get 100% duty cycle.dpolt said:TACCR2 = 15360; // max power to the lowest running value possible
Where did you get it from? Mybe it was written for a different PWM frequency or Timer clock. Perhaps it was for a timer cycle of 65536 ticks and ~24% is the minimum DC the motor requires to run at all. Having a higher timer count per PWM period increases resolution.dpolt said:run_pwm_motor is an existing function. I have to find out, what it does...
stopping the timer is of a good way to freeze the current output state. And clearing TACCTL2 set the OUT bit to 0 and OUTMDOE to OUT bit. Which indeed gives 0% duty cycle. However, after clearing TACCTL2 there is no need to stop the timer (as it affects possible other uses of the timer and other PWM channels). And clearing TACCTL2 for getting a 0% DC requires reprogramming TACCTL2 when you want to set a higher DC later. So use with care. I'd prefer a function "set_PWM_DC" that takes the requested DC as parameter and sets TACCTL2 and TACCR2 accordingly. And "stop_pwm_motor()" would simply be a macro that expands to "set_PWM_DC(0)".dpolt said:void stop_pwm_motor(void){
It looks like, except the port pin stuff, as you didn't include the definitions, so I cannot check whether you're setting the correct bits. And what was the MSP you use? The port pins depend on this info too.dpolt said:Is the rest correct? (code = description)
Ok, let's see:
WDT: What is the difference if I put it in the pwm.h or in the main.c?
TACCR2 = 15360: So I'll have to find out min. TACCR2 the motor starts? (new motor is used!)
stop_pwm_motor: This method would "only" reduce code volume. So it would reduce current consumption?
Ports / Pins: Yes, ports / pins should be correct. I checked it.
PS: Our Debug-Interface is sometimes not working correctly anymore (MSP-FET430UIF). Is there a trick to repair the Debug-Interface? (not so important, but would save time for reconnecting a lot...)
Functionally none. But since WDT is a don't care for PWM, nobody (including yourself after soem time) would expect it there. And later, there might be an UART.c that collides with this WDT setting and you will spend days to figure out what happens, just because you forgot that PWM.c will mess with the WDT.dpolt said:WDT: What is the difference if I put it in the pwm.h or in the main.c?
It's like ordering your emploer to directly re-route some of your salary to pay your rent. Sooner or later you'll forget about it and when you move, your new landlord will complain about not getting money and the old one will be happy for the additional income. (only that in this case, you'll instantly remember what's going on, but for WDT issues, you might not)
The WDT is a global thing, so it should be handled on a global, project specific location and not in a project independend module.
Of course there may be exceptions.
Every motor has a minimum PWM value bbelow it will just stand still. This is because of static friction, parasitic capacitances, rotor core magnetic losses, induction vs. PWM frequency (short pulses just don't scale linerar) etc.dpolt said:TACCR2 = 15360: So I'll have to find out min. TACCR2 the motor starts? (new motor is used!)
Maybe by a few µA if at all.dpolt said:stop_pwm_motor: This method would "only" reduce code volume. So it would reduce current consumption?
I have similar problems sometimes. I guess it is due to electric potential problems. Usually, after disconnecting the FET form the target and reconnecting it, it works again.dpolt said:Our Debug-Interface is sometimes not working correctly anymore (MSP-FET430UIF). Is there a trick to repair the Debug-Interface? (not so important, but would save time for reconnecting a lot...)
WDT: To be honest, I'm not really familiar with the WDT. It is another Timer, right? But what for do I need it? And how exactly should I put it into main.c? 1:1 just copy past before the init_motor() ?
TACCR2 = 15360: Thx for that much information. The vibrator (correct??) is supplied by 5V, runs very smooth and starts very well.
stop_pwm_motor: Ok, thx for the µA-information. Then I'll change my code and save the µAmperes.
-> like this?
void ctl_pwm_motor(a){
TACCR2 = a; // PWM 100% low
}
Debug-Interface: I'm afraid, reconnecting mostly doesn't help. We have another one here, but if two persons need it often... Then I'll have to live with it...
Saving energy is one of my highest priorities.
You don't. You configure the PWM cycle length, which is 1/frequency. :)dpolt said:I am using Timer A, but cannot find, where I can configure the frequency of the pwm signal.
You specify a clock source for the timer. So each tiemr tick has a certain interval. When teh timer operates in up mode, teh TACCR0 value determines after how many (+1, as 0 counts as a tick) ticks the tiemr overflows.
So the timer counts from 0 to CCR0 and then starts with 0 again., This gives the period length for the PWM.
The other CCR units then can be configured to set/reset/toggle their associated output pin when the tiemr counts to their CCRx value and optionally do a second action when the timer rolls over to 0. This gives you the duty cycle.
There are many examples available and also several threads in thsi forum which discuss this more detailed.
Of course. I got it.
Back to the code:
void init_pwm_motor(void){
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P4DIR |= BIT2; // P4.2 output //Daniel
P4SEL |= PWM_MOTOR; // P4.1 - P4.2 TAx options
TACCR0 = 128 - 1; // PWM Period/2
TACCTL2 = OUTMOD_6; // TACCR2 toggle/set //unchanged //Daniel
TACCR2 = 64; //Vibr.motor // TACCR2 PWM Duty Cycle -->50% high //Daniel
TACTL = TASSEL_2 + MC_1 + ID_2; // SMCLK, up mode, divide through 2 //Daniel
}
void test_pwm_motor(void){
init_pwm_motor();
TACCR2 = 128; //100% high //Daniel: 100%
wait_ms(3000);
TACCR2 = 64; //50% high //Daniel: 50%
wait_ms(3000);
TACCR2 = 0; //100% low //Daniel: 0%
wait_ms(3000);
TACCR2 = 64; //50% high //Daniel: 50%
wait_ms(3000);
TACCR2 = 128; //100% high //Daniel: 100%
wait_ms(3000);
}
I cannot find the mistake. I checked it withe the oscilloscope: No signal output...
:(
??? I despair of it (correct english?) ???
-> edit:
I found the signal: P4.5 and not 4.2 ! Why is it there???
// P4
#define PUSH_L BIT0
#define PUSH_R BIT1
#define PWM_MOTOR BIT2
#define STAT1 BIT4
#define STAT2 BIT5
#define CE_USB BIT7
Sorry just looked like it. Periode is way to long...
PWM period is ~32µs
it isn't. Both, P4.2 and P4.5 output TB2 signal, which is from TBCCR2, not from TACCR2.dpolt said:I found the signal: P4.5 and not 4.2 ! Why is it there???
Great. With Timer B I get a signal. I'll check period soon.
But the Transistor doesn't react (PWM -> Gate). I'll put a new one in. Let´s see...
Or with TimerA on the right pins. So you changed all TAxxx in your code to TBxxx?dpolt said:With Timer B I get a signal.
You should put a resistor (1k or so) between the port pin and the gate. Just to be sure. I fyou didn't get a signal on one of the two TB.2 pins, then maybe you have fried th epin. There was a similar thread just yesterday where someone fried a pin that as driving a FET. Even if I don't knwo why. But better safe than sorry. Those FET gates can have large input capacitances and can generate weird effects.
Yes, that´s what I did.
The FET I´m using is a Philipps PMF400UN.
-> http://www.nxp.com/documents/data_sheet/PMF400UN.pdf
Is this the right figure? Are these capacities high?
No. Th ecapacitance in question is the gate-source or gate-drain capacitance, or rather the gate charge. It is in the range on 1nC = 1nAs. the typical port switching time is 20ns, which would result in a rated current of 5mA during the switch time.
However, the resulting capacitance depends on switching time etc. My calculation above gives 200pF (F=As/V), which isn't much. The FET I used to control the 70A of our laser has more than ten times as much (which really is a problem,a s the FET is not used as a switch but as an adjustable resistor, and the capacitance causes feedback oscillations if you do not properly suppress them)
I'll check the FET and the pins tomorrow, and will also check the R = 1kOhm between µC and Gate.
FET change: no difference
1kOhm: what?! no more signal. Of course also without 1k...
Must be the code or the pin, what makes more sense...
-> edit: can see voltage going up and down on the multimeter, when I go to:
void test_pwm_motor(void){
init_pwm_motor();
TBCCR2 = 128; //100% high //Daniel: 100%
wait_ms(3000);
TBCCR2 = 64; //50% high //Daniel: 50%
wait_ms(3000);
TBCCR2 = 0; //100% low //Daniel: 0%
wait_ms(3000);
TBCCR2 = 64; //50% high //Daniel: 50%
wait_ms(3000);
TBCCR2 = 128; //100% high //Daniel: 100%
wait_ms(3000);
}
and press the "Run"-Button. What does CCS v4 do when I hit "Run" in the debug section? run all? run function the cursor is it or what is selected? Something else? Why didn't I see it on the oscilloscope before?
Maybe it's the code...
edit #2: And why does this not work?
// Only for testing of the motor when programming
P4OUT |= PWM_MOTOR; // Start Feedback
P4OUT &= ~PWM_MOTOR; // Stop Feedback
When PWM_MOTOR = P4.2 ?
ok, now I get an output. But frequency is much too low...
one ^ is about 7.5 ms long...
f should be ~ 32µs:
(TACCR0+1) (SMCLK / divider ) =128 ( 8 MHz / 2)= 32µs
and I´m just getting high and low when checking with the debugger instead of PWMs...
I tlooks like the timer is not running on a divider and in cont mode. Then it counts to 65535 and not TACCR0. And 8MHz/65536 ticks is 8ms. Re-check your timer initialization. You switched from TimerA to TimerB IIRC. Maybe you messed things up there.
Now I got a new PCB. Nearly the same. I had to solder the parts for the vibration circuit, but now it works and is way more handy.
But one ^ is now 20ms [[@ TBCCR1=64, when TBCCR0=128 and up mode, SMCLK and OUTMODE_6]]
This would be 50 Hz. Way to low! I need more than 20 kHz.
But is 50 Hz a right frequency in this config?
Shouldn't it be at this frequency: http://www.wolframalpha.com/input/?i=1%2F%28128%2F%288MHz%29%29 ?
If you get 50Hz 50% DC ouput on the TB.1 pin and TBCCR0 is 128 and TBCCR1 is 64, then the timer is ticking with 6400Hz only. No idea why. Wrong SMCLK configuration? (maybe it is running on XT1/REFO?)
AllI can tell is that I have no problems with my PWM control (1kHz to 10kHz 0-100% Peltier cooling) in out laser supply project. So I know that it is working as it should if done properly. So cnaces are that you're not doing everything properly. Even if you think you do. Double-check your configurations.
Jens-Michael Gross said:If you get 50Hz 50% DC ouput on the TB.1 pin and TBCCR0 is 128 and TBCCR1 is 64, then the timer is ticking with 6400Hz only. No idea why. Wrong SMCLK configuration? (maybe it is running on XT1/REFO?)
AllI can tell is that I have no problems with my PWM control (1kHz to 10kHz 0-100% Peltier cooling) in out laser supply project. So I know that it is working as it should if done properly. So cnaces are that you're not doing everything properly. Even if you think you do. Double-check your configurations.
in pwm.h :
void init_pwm_motor(void){
//WDTCTL = WDTPW + WDTHOLD; // Stop WDT
//P4DIR |= 0x04; // P4.1 - P4.2 output
P4SEL |= PWM_MOTOR; // P4.1 - P4.2 TBx options
TBCCR0 = 128; // PWM Period/2
TBCCTL2 = OUTMOD_6; // TBCCR2 toggle/set
TBCCR2 = 0; //Vibr.motor // TBCCR2 PWM Duty Cycle -->100% high
TBCCR2 = 70; //Vibr.motor ABIISv03, 0R 0F// TBCCR2 PWM Duty Cycle -->100% high
// TBCCR2 = 80; //Coin motor, 0R, no C // TBCCR2 PWM Duty Cycle -->100% high
TBCTL = TBSSEL_2 + MC_3; // SMCLK, updown mode
}
-> this part of the code should be correct, isn't it?
-> But why does it work without configuring the PxDIR? (here: just comment)
Answer?:
in main.c :
// P4 pins setup-------------------------------------------------------------------------------
P4DIR |= PWM_MOTOR; // P4 outputs
and
P4DIR |= BIT1 | BIT3 | PWM_MOTOR | LIS2_INT1; //unused
-----------------------------------------------------------------------
-----------------------------------------------------------------------
in pwm.h :
//Setup internal clock-------------------------------------------------------------------------
BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8MHz (internal clk)
DCOCTL = CALDCO_8MHZ;
-> Should also be correct.
-----------------------------------------------------------------------
-----------------------------------------------------------------------
and it is TBCCR2 not TBCCR1.
--> At least the motor runs, but PWM-frequency isn't correct till now. <--
edit:
Is the period I get wih the formula
(TACCR0+1) / (SMCLK / Divider) = 1/PWM-frequency ? Or is there anything else to observe?
And shouldn't there be rectangles instead of ^^^^^^^^^^ ?
I just quoted from your post :) But it doesn't matter, as long as it is used consistently. :)dpolt said:it is TBCCR2 not TBCCR1.
dpolt said:(TACCR0+1) / (SMCLK / Divider) = 1/PWM-frequency ? Or is there anything else to observe?
You use up/down mode, so it is (TACCR0*2) (no +1) :)
And I don't see you setting any divider.
Let's go through it...
BCSCTL1 = CALBC1_8MHZ; // Set DCO to 8MHz (internal clk)
DCOCTL = CALDCO_8MHZ;
So DCO is 8MHz. And so should be SMCLK?
P4DIR |= PWM_MOTOR; // P4 outputs
P4DIR |= BIT1 | BIT3 | PWM_MOTOR | LIS2_INT1; //unused
So I hope that PWM_MOTOR is 0x04 or 0x20? And you check the signal on Pin 19 or 22 (DA package) or 17 or 20 (RHA package)
P4SEL |= PWM_MOTOR; // P4.1 - P4.2 TBx options
TBCCR0 = 128; // PWM Period/2
TBCCTL2 = OUTMOD_6; // TBCCR2 toggle/set
TBCCR2 = 0; //Vibr.motor // TBCCR2 PWM Duty Cycle -->100% high
TBCCR2 = 70; //Vibr.motor ABIISv03, 0R 0F// TBCCR2 PWM Duty Cycle -->100% high
// TBCCR2 = 80; //Coin motor, 0R, no C // TBCCR2 PWM Duty Cycle -->100% high
TBCTL = TBSSEL_2 + MC_3; // SMCLK, updown mode
I'd add TBCLR to ensure that the timer hasn't passed 128 prior of settign up/down mode, or you'll experience some delay.
However, what should happen is that TB2 is most likely 0 at start. Now TB counts up with 8MHz. after 70 ticks (= ~9 µs), TB2 is toggled. the timer counts further up to 128. When it reaches 128, it continues counting down again. When it reaches 70 (which is 116 ticks later), it toggles again. Then the timer counts further down to 0, TB2 is set (if wasn't already before) and the tiemr counts up again.
This should result in a 32µs / 31250kHz PWM cycle with (after the first, uncertain cycle) 116 ticks = 14.5µs off-time and 140 ticks = 17.5µs on-time = 54.7% DC.
One thing that is that you don't check whether the calibrations values may have been accidentally deleted (are 0xff). Then you misconfigure the DCO and the cpu crashes and what you're observing is the reset cycle frequency :)
TA -> TB: good
Formula for PWM period: "*2" because of up and down is 2 times als long as up in up mode? (Divider is just mentioned because of my documentation. But I cannot see what's the divides benefit; why not set TxCCRx+1 twice as high or set SMCLK 2 times as high)
SMCLK @ 8MHz: ok. thx.
PWM_Motor: is set to P4.2 and at this I soldered the wire.
TBCLR: How exactly can I integrate it? Cannot find it in slau144h...
^^^^^^^^^^^^^^^^^^^^^^^: Yes output on P4.2. Capacity? On P4.2 is only a nMOSFET gate. or do you mean caps in the MSP430?
One thing that is that you don't check whether the calibrations values may have been accidentally deleted (are 0xff). Then you misconfigure the DCO and the cpu crashes and what you're observing is the reset cycle frequency :)
-> ??? I don't understand.
mistake: up mode should be selected.
------------------------------------------------------
Does this work? Enaleing the pullup/dulldown resistor with PxREN =1? Just copy paste in init pwm? (slau144h page 331)
------------------------------------------------------
Is it right that this means 75% of Voltage on Outputpin?
TACCR1 / TACCR0= 128 512 = % on duty cicle @ P1.3 = 25 %
------------------------------------------------------
Should I edit ID_2 in TBCTL in order to activate the divider and get 31,25 kHz instead og 62,5 kHz? Because I need more than 20 kHz to avoid noise.
Ususally, yes.dpolt said:mistake: up mode should be selected.
No. The output is always either VCC or GND. Nothing in between. Unless you apply a low-pass filter to the output signal. On the filter output it will appear as a wave - the lower the cutoff-frequence, the more is the signal converter to an average DC voltage.dpolt said:Is it right that this means 75% of Voltage on Outputpin?
So it means: 75% of time full voltage on output pin, rest of time no voltage.
Well, what you need is your's to define. I can only advise how to get it :)dpolt said:Should I edit ID_2 in TBCTL in order to activate the divider and get 31,25 kHz instead og 62,5 kHz?
Jens-Michael Gross said:Ususally, yes.mistake: up mode should be selected.No. The output is always either VCC or GND. Nothing in between. Unless you apply a low-pass filter to the output signal. On the filter output it will appear as a wave - the lower the cutoff-frequence, the more is the signal converter to an average DC voltage.dpolt said:Is it right that this means 75% of Voltage on Outputpin?So it means: 75% of time full voltage on output pin, rest of time no voltage.
Well, what you need is your's to define. I can only advise how to get it :)dpolt said:Should I edit ID_2 in TBCTL in order to activate the divider and get 31,25 kHz instead og 62,5 kHz?
[/quote]
1. mistake: ok thx
2. Sry. I meant: If the formula says 75%, it means 75% on or 75% off? So 75% on, right.
3. divider: Is my methode to divide the frequency right or does the divider something else? Has the double frequency any pro or contra to the ~31kHz?
new question: I forgot to set the capacity between VBAT and GND, that was included in the old model of the circuit. What does this Capacity do? Filter something? Make the vibrator run smoother? I'll check some Capacitys 2.2, 4.7, 10, 22, 47, 100 µF... Let's see what'll happen...
edit:
Frequency is as configured now (@ ~31kHz).
Voltage is strange now. Negativ pin of vibrator now getting negativ voltage, positiv stays 0... ??? crazy... Perhaps some soldering to do...
Capacitor: no changes at first look. How long should the cap. bypass? -> normal voltage = 3.3 V; lowest voltage 3.0 V; consumation in mW = 210 mW; time to bypass = ???
-> http://www.shosworld.de/Elektronik/pufferkondensator.html [german, but translation in the line above] -> result: cap. in µF....
Depends on the outmode selected. One state runs from 0 to CCRx and the other one runs from CCRx to 0. So if you use reset/set mode, it is set 1 on 0 and reset (off) on CCRx. If you use set/reset mode, output is 0 for 0..CCRx and 1 for CCRx..0.dpolt said:So 75% on, right.
I don't know th ecircuit. If the vibrator is a motor, keep in mind that it will generate a reverse voltage if you switch it off (inductors such as motors want to keep the current constant, even if this means converting their magnetic or mechanic energy into a high voltage). A capacitor will catch this energy (well, mostly), smoothen things.dpolt said:new question: I forgot to set the capacity between VBAT and GND
I don't think I need a translation from German :) But I don't have time to check it out right now...dpolt said:[german, but translation in the line above]
I use OUTMOD_6, so toggle set. -> ???
The circuit with vibration motor:
Oh, yes. Your name sounds german. Ich bleib´ aber allgemein dann doch beim Englischen, damit uns die anderen Nutzer des Forums auch versehen und mein Thema vllt mal jemanden nutzt...
Schöne Grüße
Ganz meine Meinung - nur in den privaten Nachrichten kann man dann auf das doppelte Uebersetzen verzichten - erhoeht u.U. die Verstaendlichkeit im Detail :)dpolt said:Ich bleib´ aber allgemein dann doch beim Englischen, damit uns die anderen Nutzer des Forums auch versehen und mein Thema vllt mal jemanden nutzt...
It does what it tells: If TAR == TACCRx, the current signal output is toggled, then TAR==0, it is set. The problem with the toggle is that you don't know what happens during the first loop. The result of a toggle depends on the current state.dpolt said:I use OUTMOD_6, so toggle set. -> ???
So if you raise TACCRx from, say, 100 to 200 while TAR is between them, the output has been already switched off at 100, and when TAR comes to 200, it will be switched ON, and on TAR=0, it stays on until TAR=200. So you get an overlong on cycle.
If you use OUTMOD_7 instead (reset/set), the output will be set OFF when TAR==TACCRx, no matter whether it was on or off before.
You can still get an overlong ON cycle if you reduce TACCRx while TAR has already passed the new value. Then the output stays on for the complete rest of the cycle, but this also happens with OUTMOD_6. With 7, you just eliminate one of two pitfalls. The other one, well, syncing with TAR overflow might be the key. However, this does not apply to TimerB when you set the CLLD_1 option (then the write to TBCCRx is delayed until TBR counts to 0.)
I wish, TimerA would have the same feature.
About the VBatt and the capacitor,, well, where does VBatt come from? Or rather: what is the inner series resistance of the VBatt voltage source and what is the maximum power consumption of the motor?
For the motor, the interesting part is the indictivity of the motor combined with the pulse width and -frequency. It gives you a resulting impedance of the motor and you know how much current it will draw on a given voltage during ON-time.
With the calculator you can only calculate how much capacitance you need to maintain a certain current over a certain time with a defined maximum voltage drop. Since the power of the motor depends on the voltage (but not linear), the calculator is only of limited use. Also, you have additional current coming from the VBatt supply.
If you want to prevent ripple on VBatt for other parts of the circuitry, you'll need the series R on VBatt. It will limit the current load on VBatt. A following capacitor will provide the peak current of the motor, so VBatt is only loaded with a smoothed-down average current. The higher R the better the smoothing, but R must be low enough to still satisfy the average motor current.
A higher capacitor means lower voltage drop, btu then also a lower voltage over the resistor and therefore lower charging current from VBatt.
You see, it is n equations with m variables, and usually m>n, so there is no 'the solution'.
to be honest, I'll read it again later, when I need it to understand it completely...
Now we recognized, that the SRAM isn't big enough, so we changed our MSP430F2274 to a new MSP430F5508 with 48 Pins.
Is there anything, you know, that changes now, except of more RAM, more Timers, Pins have other numbers, ... ?
Anything in the "register coding"?
Main difference is the clock system. 2x devices have basic clock system, 5x devices have unified clock system. More features, more orthogonal usage (ACLK and SMCLK can now be both used for everything, just that ACLK still has some extra functionality regarding LF crystal usage), internal 32768Hz calibrated oscillator, and an FLL like the 4x devices, only better. So all clock system registers are different than before. Also, the LPMs are affected.dpolt said:Is there anything, you know, that changes now,
The other big difference is the USCI. Its interrupt vectors are arranged differently than on the 2x devices and its IE/IFG bits are placed differently.
Some 5x devices have a separate REF module that per default replaces the reference controls in the ADC module.
The port pins have optional configurable pullups/pulldowns and two driving strengths, but that's optional.
The execution times of some instructions are shorter than on older 2x devices, but this is different within 2x family already (some have a newer MSP430X core, some not).
The WDT has changed and supports a wider range of timings
There is a 32bit hardware multiplier available, backwards compatible to the 16 bit multiplier.
Thx a lot.
But what I actually wanted to know are the changes in code...
Is TBCCRx still available or do I have to change to TB1CCRx or something like that?
...
edit: the percentage TACCR1 / TACCR0 = e.g. 25% means 25% high or 25% low? sorry if I ask again, but I am not sure anymore, because the oscilloscope made some weird measurements... config should be reseted and edited again...
TBCCRx was never equivalent to TB1CCRx, only to TB0CCRx. whether the old notation is still available or not depends on the provided include files.dpolt said:TBCCRx still available or do I have to change to TB1CCRx
However, the more important part is that none of the previous clock module registers is available anymore.
Depends on configuration of TACCTL1. In reset/set mode, 25% is 25% high. In set/reset mode, it means 25% low.dpolt said:TACCR1 / TACCR0 = e.g. 25% means 25% high or 25% low?
Like this:?
#include "msp430x22x4.h" // Microcontroller header file
void init_pwm_motor(void){
//WDTCTL = WDTPW + WDTHOLD; // Stop WDT
//P4DIR |= 0x04; // P4.1 - P4.2 output
P4SEL |= PWM_MOTOR; // P4.1 - P4.2 TBx options
TB0CCR0 = 128 - 1; // PWM Period/2
TB0CCTL2 = OUTMOD_6; // TB0CCR2 toggle/set
TB0CCR2 = 0; //Vibr.motor // TB0CCR2 PWM Duty Cycle -->100% high
TB0CCR2 = 70; //Vibr.motor ABIISv03, 0R 0F// TB0CCR2 PWM Duty Cycle -->100% high
// TB1CCR2 = 80; //Coin motor, 0R, no C // TB0CCR2 PWM Duty Cycle -->100% high
TB0CTL = TB1SSEL_2 + MC_1; // SMCLK, up mode
}
/*
void run_pwm_motor(void){ // After a given time, the motor can be ajusted from
TBCCR2 = 15360; // max power to the lowest running value possible
}
*/
void stop_pwm_motor(void){
TB0CCTL2 = 0x0000; // Reset Capture/Control Register
// TBCCR2 = 128; // PWM 100%
// TBCCR0 = 0; // Set PWM period 0
TB0CTL = MC_0; // Stop Timer_B0 timer
}
void test_pwm_motor(void){
init_pwm_motor();
TB0CCR2 = 128; //100%
wait_ms(3000);
wait_ms(3000);
TB0CCR2 = 0; //0%
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
/*TB0CCR2 = 64; //50%
wait_ms(3000);
TB1CCR2 = 128; //100%
wait_ms(3000);
TB1CCR2 = 32; //25%
wait_ms(3000);
TB0CCR2 = 128; //100%
wait_ms(3000);
*/TB0CCR2 = 96; //75%
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
TB0CCR2 = 64; //50%
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
TB0CCR2 = 13; //11%
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
wait_ms(3000);
TB0CCR2 = 128; //100%
wait_ms(3000);
}
I use up mode + toggle/set, so 25% = 25% high?
Does Timer_B0 in the MSP430F5508 work like Timer_B in the MSP430x2xx family?
Yes. I'd prefer reset/set over toggle/set, but it shoudl give the same.dpolt said:I use up mode + toggle/set, so 25% = 25% high?
However, TB0CCTL2 is configured for immediate update of TB0CCR2. YOu do your updates unsynchronized, so you may experience overlong on or off cycles depending on the moment you change the value of TB0CCR2. Maybe that's what you observed on the scope?
If you additionally set CLLD_2 in TB0CCTL2, any write to TB0CCR2 is delayed until the current cycle is finished and TB0R counts to 0.
Ok, thx, but why would you prefer it? What would be the benefits?
Is this the negative aspect of toggle/set? Or what else causes it?
So I'll have to add TB0CCTL = CLLD_2 to fix the changes in the new MSP430F5508? Then It'll work as one the old MSP430F2274?
Now I've read the guide:
new version:
void init_pwm_motor(void){
//WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P2DIR |= 0x01; // P2.0 output
P2SEL |= PWM_MOTOR; // P2.0 TA1 options
TA1CL0 = 128 - 1; // PWM Period/2
TA1CCTL2 = OUTMOD_6; // TA1CCR2 toggle/set
TA1CL1 = 0; //Vibr.motor // TA1CCR2 PWM Duty Cycle -->100% high
TA1CL1 = 70; //Vibr.motor ABIISv03, 0R 0F // TA1CCR2 PWM Duty Cycle -->100% high
// TB1CCR2 = 80; //Coin motor, 0R, no C // TA1CCR2 PWM Duty Cycle -->100% high
TA0CTL = TA0SSEL_2 + MC_1 + TACLR; // SMCLK, up mode, clearing (<- upgrade to MSP430x5xx)
TA0CCTL = CLLD_2; // fix for MSP430x5xx
}
PS:PWM_Motor is on P2.0/TA1.1
right?
No CLLD_x on TA0CCTL... ;( What does it?
New Version:
void init_pwm_motor(void){
//WDTCTL = WDTPW + WDTHOLD; // Stop WDT
P2DIR |= PWM_MOTOR; // P2.0 output
P2SEL |= PWM_MOTOR; // P2.0 TA1 options
TA1CL0 = 128 - 1; // PWM Period
TA1CCTL2 = OUTMOD_6; // TA1CCR2 toggle/set
TA1CL1 = 0; //Vibr.motor // TA1CCR2 PWM Duty Cycle --> 0% high
TA1CL1 = 70; //Vibr.motor ABIISv04, 0R 0F // TA1CCR2 PWM Duty Cycle --> ~55 % high
// TB1CCR2 = 80; //Motor, 0R, no C // TA1CCR2 PWM Duty Cycle --> 62.5 % high
TA0CTL = TA0SSEL_2 + MC_1 + TACLR; // SMCLK, up mode, clearing (<- upgrade to MSP430x5xx)
TA0CCTL = CLLD_2; // (fix for MSP430x5xx)
}
-> now SMCLK is generally 1.045 MHz and was 1.2 MHz before. But I used the DCO with 8 MHz. How can I config this on the new MSP430F5508?
**Attention** This is a public forum