basil4j got a reaction from KatiePier in Combined PWM with interrupt not interrupting
Hi Guys. Thought I'd responded but its not here! Yeah, I knew about the 2 vectors, CCR0 vector and the everything else vector. TAxCCR0 and TACTL interrupts are so similar in reality that I thought they were the same lol all clear now thanks!
Sent from my SM-G900F using Tapatalk
basil4j reacted to oPossum in Combined PWM with interrupt not interrupting
They are two distinct interrupts, you do not have to enable both.
The TAIE bit in TACTL enables an interrupt that occurs when the timer reaches 0.
The CCIE bit in the TACCTLx registers enables an interrupt that occurs on a match between the compare register or a capture event.
All these interrupt enable bits are completely independent of each other. Enable only those that you are using and have written an ISR for.
The only other interrupt that has to be enabled is the global interrupt flag in the status register. That can be enabled with _enable_interrupts() or a few other methods.
basil4j reacted to KatiePier in Combined PWM with interrupt not interrupting
In addition to @@oPossum 's awesome advice, the final point that always confuses people is that each Timer has TWO different ISRs. One (TIMER0_A0_VECTOR) is a special higher priority one just for TA0CCR0, and its interrupt flag is cleared automatically by entering the ISR at all. The other one (TIMER0_A1_VECTOR) is for all of the other TA0CCRx interrupts and TAIE - this is the one that uses TAIV - its highest-priority pending flag is cleared by reading TAIV.
This code example uses both of them, so you can see: http://dev.ti.com/tirex/#/?link=MSPWare%2FDevices%2FMSP430%2FMSP430G2XX%2FMSP430G2553%2FExamples%2FC%2Fmsp430g2xx3_ta_07.c
It's a common point that trips people up.
If you currently have no ISR defined for TIMER0_A1_VECTOR but have TAIE enabled, if you use CCS for example it defines a trap ISR for all undefined ISRs for just this case (so part doesn't jump off into some random location), so your part is probably hanging out there.
basil4j reacted to Lgbeno in InstaSpin questions
My primary goal was to generate the lowest possible BOM cost for the board so that is why I went with discrete transistors. For a real product like you are suggesting, a proper driver chip is absolutely the right way to go.
FAN7388 looks like an awesome part, it is also very inexpensive compared to other solutions from TI or Allegro. I never did build to pro but thought that it would be much better from a efficiency point of view. Using High side NMOS is also a big improvement which FAN7388 enables.
I think you're on the right track for reliability, keep the solution as cool as possible. It can be a little bit of a delicate balance when specing MOSFETs because RDSon and Gate Capacitance work opposite of one another. So higher gate capacitance means inefficiencies in the driver vs Higher RDSon means losses in the switch. It is however easier to get the heat out of a FET.
About the PWM frequency, I think that I was using ~20kHz, it worked fine, at first we were doing 10kHz and there was some audible sound coming from the motor, I still found some noise but we thought that it was related to the commutation of the motor, that should be better if you actually have a load and also it's a farming truck so it probably is not a quiet environment... Thinking about the timer clocks for MSP430 to know what PWM duty cycle resolution that you could get with a higher frequency. 16MHz=62.5ns 55kHz=18180ns so thats about 290 clock cycles meaning that you have about 8bits resolution and a step size of 0.34% not too bad... Just remember that switching losses go up as frequency increases.
The design is open source so use away! It would be great if you fed some of the code back to the community, understand if you can't though.
basil4j reacted to Lgbeno in InstaSpin questions
Hi Alec, seems to me that of your motor has hall sensors, use them! You will get much better reliability than a sensor less algorithm. They also help with speed. I have a pretty old project called BLDC booster for MSP430g2553 that you can check out of git hub: https://github.com/lgbeno/BLDC-Booster. Don't get me wrong instaspin is cool be no need making if more difficult on yourself...
basil4j reacted to chicken in Optimising math
2K sounds like plenty, if not overkill.
Looking at this table, P0/P will go from 1 to roughly 0.01.
In the lowest 1000m with 2048 samples you get roughly 200 steps, i.e. one every 5 m. At 5km it's one every 7.5m, at 10km one every 10m, at 20km one every 60m, at 30km one every 250m. So accuracy probably drops at very high altitudes.
One countermeasure could be to have a second P/P0 indexed lookup table for anything above 10km or so (P*4 > P0). But I'd first calculate the error of interpolated vs. calculated values before optimizing prematurely.
basil4j reacted to grahamf72 in Optimising math
Over in the Energia libraries forum I have posted a port of the libfixmath 16.16 fixed point math library. It is not Energia specific, so should compile if you are using CCS. It is much smaller and faster than the floating point libraries, and is more than accurate enough for barometric altitude calculations. The whole reason I ported it was because I was using a BMP085 on an MSP430G2553 and the floating point was taking up so much flash I didn't have enough left to do anything useful.
basil4j reacted to enl in Optimising math
(please excuse crummy typing. Cat on lap takes one hand as he has paws wrapped around it)
Last thing first: It is the same. If n is a const, then it really doesn't matter... the compiler will precompute what it can. In a case like this, I use #define for the constant, but a const variable should generally work the same: compiler precomputes where it can, and only makes var if it needs to, such as if you make a pointer to it. Note that to do exponentiation, you need to call a (slow) function. The ^ is exclusive-or. The underlying function uses log and antilog. If you have a fixed power, you can speed it up by either expanding as a Taylor series or a continued fraction, since thst it how the log and the antilog are done. This would go faster as Taylor series. If time isn't a major issue (from your previous posts, it looks like it isn't at 25MHz), use the lib function from math.h.
Trade off: speed vs.range. 32bit takes 4 times as long, but has much more range (signed is 32000 vs 2000000000). For floating point, you have 32 bit no matter what (for float... In general, you don't use double unless you must n an embedded device)
The first questions: What are the types? Both signed and unsigned log are integer types. The div by 2 will be done as a shift if the types are all long and unsigned long. Modern compilers are smart.
If One of them is a float, the arithmetic will be done as float when needed, and from then on. What can be done as integer will be done so. Div by two will be optimized by most compilers as a decrement of hte binary exponent, so no worry about floating point divide there, either. Modern compilers are real smart. Don't break it up. The compiler will make it better than you can, unless there is something you haven't said. If you need the result to be float, and ALL Of the vars are integer, you MUST use a cast to force conversion to floating point where you want the conversion done. Use parenthesis to control exactly when the conversion happens, so it isn't done early. If P is float, and all else is integer, yhe conversion will be done when truncated result i s stored.
basil4j reacted to abecedarian in Optimising math
"P = (D1 * SENS / 2 - OFF) / 2" could become... I think...
"P = (((D1 * SENS) >> 1) - OFF) >> 1"
... or ...
"P = ((D1 * (SENS >> 1)) - OFF) >> 1"
I don't think the result is any different but I'm not sure what the rules of precedence are when dealing with mult/div and bit shifts.
Bit shifting right 1 bit is equivalent to dividing by two, as long as you don't need the remainder.
basil4j reacted to greeeg in Optimising math
Since your MSP430 has a hardware multiplier, the multiply would be quicker. But modern divide function don't take too long.
One interesting trick, since alot of maths (especially with ADC) will involve multiplying by a fraction. you can often factor out the divide when you use a HW multiply.
X = Y * 2/3; // original X = Y * (2*(65536/3))/(3* (65536/3)); // multiply top/bottom to get 65536 on bottom X = Y * (43691/65536); // the result of this adjustment. (Y * 43691); // use the HW multi for this X = RESHI; // take the high word The trick is to get the result stored entirely within the higher word of the result.
To my knowledge, compilers wont do this.
basil4j reacted to enl in Optimising math
If float is used, moderate memory overhead. Most (all?) operations are implemented as function calls, so te functions used must be included. The difference between one add and 20 adds is minimal, tho. Once the function is in the build, calling it isn't a lot of space.
Big thing is time. Software implementations of FP can be slow. A device with hardware mult (integer) can do many FP operations a lot faster than those wihout hardware mult. Hardware div (integer) makes things better yet. A few operations are not going to be a big issue, timewise. The functions that use a lot of operations are the killer, like exponentiation and logs. These can be worth optimizing in many cases. If previous thread hadn't given pretty loose timing for the altitude comp, I would call this a prime candidate for a specialty function for the exponentiation. Might still need it, but my guess is not.
Greeg's methods apply to the integer math (or fixed point), and can be used to avoid FP in cases where the final result needed is integer )or, again, fixed point), but intermediate comps may need FP or fraction.
A question I still have is: Must the altitude be computed in-flight? Or can the sensor date be stored and converted on the ground? Is the altitude needed? Or only some property, such as detecting when max altitude is reached? The answers can make a big difference in what math need be done on MSP430, and on how to doit.
basil4j reacted to jpnorair in Optimising math
I'm replying only to this statement, but in the spirit of the topic.
MSP430 has an average ALU by MCU-standards. Shifting is fast. Addition is pretty fast too. Multiplication, however, occurs through a peripheral and it is quite slow. It is faster than using a software multiplier, but it is still pretty slow because it does not work through registers.
Anyway, often it is much faster to add than to multiply. In particular, one algorithm I wrote once had enormous, enormous, ENORMOUS improvement by taking logarithm (I made a table), then doing additions, then doing antilog (again, a table).
OK, that was just a vignette, but maybe it applies to you, too.
basil4j reacted to enl in Compile questions - Routines within ISR
This warning comes about because it is generally (but not always) bad practice to call a function from within an interrupt handler. Interrupt handlers should generally be as short as possible and as fast as possible. The function call overhead can slow things down, increasing response time to other interrupts, and add to the stack burden, which is a significant thing when you have limited memory or time critical response.
I would ask if you are sure that inlining it (or replacing the function with a #define macro) would increase code size. Incrementing a pointer isn't a big deal. Function calls take a bit of code space for setup and stack space for parameters. I presume that there is more than just incrementing a simple pointer, so.....
That said, there are times when it is perfectly acceptable to call a function within an interrupt handler. For example, if your interrupt is the only one active, and there is no chance of missing the next one because the interrupt rate is known to be low enough the routine will finish before the next interrupt, it is ok. Not best practice, but ok.
If other interrupts are active, and they can wait for this one to finish, and there is no chance of missing one, it is, again, ok, but not best practice.
Things to consider: A good compiler can determine the needed stack depth by tracking the call chain. This is not as easy if there are function calls in an interrupt, and may, in fact, be impossible if interrupts are re-enabled within the routine (not recommended on MSP430, IMHO). I don't know off hand if the compiler you are using does this-- I use CCS and have no idea if it does, as it has never been an issue for me. This is important in many cases, as if allows the compiler to manage RAM usage appropriately based on the context.
A better way to structure things, if you can, is have the interrupt routine do as little as possible, and handle everything else in your general code. The model that is commonly used is to have a main loop to do the work, and goes to sleep when the work is done. The interrupt does what it must, and resets the sleep on return (resets the low power mode bits on the MSP430), signalling what must be done for the main loop if needed. If this is not practical, and you can be sure that you won't lose due to memory or timing in the interrupt, go with it. Nothing says that the 'best' way is always the right way. I have shoved entirely too much into interrupt handlers at times, when it was the most practical solution for one reason or another.
The pragma referenced is likely the FUNC_CANNOT_INLINE pragma. This will tell the compiler that the function is not inlinable, and is will stop yelling at you about it, or DIAG_SUPRESS for the given message (before your function) paired with DIAG_DEFAULT (after your function)