+ All Categories
Home > Documents > 2006CON Advanced C Programming Hibner Shaul

2006CON Advanced C Programming Hibner Shaul

Date post: 11-Nov-2015
Category:
Upload: aravind-bhombore
View: 226 times
Download: 1 times
Share this document with a friend
Description:
advanced c
53
Advanced C Advanced C Programming Programming Real Time Programming Real Time Programming Like the Pros Like the Pros
Transcript
  • Advanced C ProgrammingReal Time Programming Like the Pros

  • About UsChris HibnerBSME University of Michigan, Ann Arbor (1996) Dynamics and ControlMSME University of Michigan, Ann Arbor (2002) Control Systems and Computational MechanicsTRW Automotive; Algorithm Development and Applications Group, 1996 present.chiefdelphi.com user name: Chris Hibner

    Michael ShaulBSEE Rose-Hulman Institute of Technology (2002) Computer EngineeringMSEE University of Michigan, Dearborn (2005) Control SystemsTRW Automotive; Product Development Group, Software Validation Group, and Core Components Groupchiefdelphi.com user name: Mike Shaul

  • ContentstypedefsFixed-Point MathOverflow ProtectionSwitch DebouncingState MachinesFilteringOversampling

  • Good Coding PracticesSigned (good) vs Unsigned (bad) Math for physical calculationsUse Braces { Always }Simple Readable CodeConcept of Self Documenting CodeCode as if your grandmother is reading itNever use Recursion (watch your stack)Treat Warnings as Errors*Disclaimer: Not all code in this presentation follows these practices due to space limitations

  • TypedefsUsing Naturally Named Data Types

  • Why Typedef?You use variable with logical names, why not use data types with logical names?Is an int 8-bits or 16-bits? Whats a long? Better question: why memorize it?Most integer data types are platform dependent!!!typedefs make your code more portable.

  • How to use typedefsCreate a logical data type scheme. For example, a signed 8-bit number could be s8.Create a typedef.h file for each microcontroller platform you use.#include typedef.h in each of your files.Use your new data type names.

  • typedef.h Exampletypedef unsigned char u8;typedef signed char s8;typedef unsigned short u16;typedef signed short s16;typedef unsigned long u32;typedef signed long s32;

    In your code:unsigned char variable;Is replaced with:u8 variable;

  • Fixed-Point MathFractional Numbers Using Integer Data Types

  • Creating FractionsFractions are created by using extra bits below your whole numbers.The programmer is responsible for knowing where the decimal place is.Move the decimal place by using the shift operator (>).Shifting is multiplying by powers of 2. Ex.: x5 = x*2^-5

  • Fixed Point Fraction Example A/D Sample (10-bit)Fractional partShift left by 6 (i.e. A2D
  • Fractional Example, continuedWe know 5/2 = 2.5If we used pure integers, 5/2 = 2 (i.e. the number is rounded toward negative infinity)Using a fixed-point fractional portion can recover the lost decimal portion.

  • Fractional Example, continued000000000000 0101= 5A/D Sample (10-bit)Fractional partShift left by 6 (i.e. A2D
  • Fractional Example, continuedDivide by 2 (i.e. A2D / 2;):Fractional part Whole part0000001000000001 The whole part: 0000000010(binary) = 2(decimal)The fractional part: 100000(binary) = 32 (huh???)Fractional part Whole part0000010100000000

  • Fractional Example, continuedDivide by 2 (i.e. A2D / 2;):Fractional part Whole part0000001000000001 The fractional part: 100000(binary) = 32 (huh???)

    How many different values can the fractional part be?Answer: we have 6 bits => 2^6 values = 64 values (i.e.) 111111 + 1(binary) = 64(decimal)Therefore:Fractional part is actually 32/64 = 0.5

  • Fractional Example, conclusionDivide by 2 (i.e. A2D / 2;):Fractional part Whole part0000001000000001 By using a fixed-point fractional part, we can have 5/2 = 2.5The more bits you use in your fractional part, the more accuracy you will have.Accuracy is 2^-(fraction bits). For example, if we have 6 bits in our fractional part (like the above example), our accuracy is 2^-6 = 0.015625. In other words, every bit is equal to 0.015625

  • Fractional Example, exampleAdding 2.5 + 2.5 0000001000000001 Once our math operations are complete, we right shift our data to regain our original resolution and data position.If we look diving and adding multiple values using this method we can see the benefit of fixed point math. This example assumes we are adding two 5/2 operations as shown. 0000001000000001 0000010100000000 +000000000000101= 50Without using the fixed point math the result of the addition would have been 4 due to the truncation of the integer division.

  • Overflow ProtectionMaking Sure Your Code Is Predictable

  • What is Overflow? Why is it Bad?Overflow is when you try to store a number that is too large for its data type.For example, what happens to the following code?s8 test = 100;test = test + 50;answer: -105 (thats not good!!!)

  • Integer Data Types: Valid Rangesu8 : 0 - 255s8 : -128 - 127u16 : 0 - 65535s16 : -32768 - 32767u32 : 0 - 4.294967295e9s32 : -2.147483648e9 - 2.147483647e9

    Note: ranges given are decimal.

  • Overflow Protection MethodsCreate a new temporary variable using a data type with a larger range to do the calculation.Compare the sign of the variable before and after the calculation. Did the sign change when it shouldnt have? (for signed variables)Compare the variable after the calculation to the value before. Did the value decrease when it should have increased?

  • Overflow Protection, Example 1s16 add16(s16 adder1, s16 adder2); // prototype

    S16 add16(s16 adder1, s16 adder2){ s32 temp = (s32)adder1 + (s32)adder2; if (temp > 32767) // overflow will occur return 32767; else if (temp < -32768) // underflow return -32768; else return (s16)temp;}*This example uses a s32 (larger) data value for overflow checking

  • Overflow Protection, Example 2// prototypes16 addTo16bit(s16 start, s16 adder);

    S16 addTo16bit(s16 start, s16 adder){ s16 temp = start; start += adder; if ((start > 0) && (adder > 0) && (temp = 0)) return -32768; // Underflow occurred else return start;}*This example uses 16 bit values only to check for overflow on signed values this provides improved efficiency on 16 bit platforms.

  • Overflow Protection, Example 3// prototypeu16 addToUnsigned16bit(u16 start, s16 adder);

    S16 addToUnsigned16bit(u16 start, s16 adder){ u16 temp = start; start += adder; if ((adder > 0) && (start < temp)) return 65536; // Overflow occurred else if ((adder < 0) && (start > temp)) return 0; // underflow occurred else return start;}*This example checks for overflow on unsigned values

  • Switch DebouncingHaving Confidence in Switch Inputs

  • Why Debounce? When to Use It?Debouncing a switch input reduces erroneous inputs.Use debouncing when pressing a switch starts a sequence or changes the state of something.

  • When to Debounce ExamplesDebounce when a single push of the switch changes a state. Examples: - pneumatic gripper - motorized gripper where a single push causes the motor to go until a limit switch is reachedDo not debounce if constant driver input is needed.

  • What is Debouncing?Basically, debouncing means to require a certain number of samples before you confirm the switch input.Various debounce schemes can be used: - require N consecutive samples (i.e. reset the counter if one sample fails) - count up / count down (i.e., if one sample fails, decrement the counter by 1 rather than resetting to zero.

  • Debounce Example // debounce opening gripper if (!pneumaticGripperOpenState) { if (gripperOpenSwitch == ON) gripperOpenDebCount++; else gripperOpenDebCount = 0; if (gripperOpenDebCount >= DEBOUNCE_LIMIT) { gripperOpenDebCount = 0; pneumaticGripperOpenState = TRUE; } }

  • State MachinesSystematic Approach to Complicated Logic

  • What is a state machine?A state machine is a method for organizing complicated logic.A state machine is broken up into discrete states. Logic is defined to switch from one state to another.Only one state can be active at any time.It takes one sample (i.e. one time through the code) to switch from one state to another.

  • When should I use a state machine?When performing an automated routine which has many steps.When the logic is very large and/or difficult to grasp. (Like C programming: break up a large program into smaller functions)When the problem has physical states (like a light it has two states: ON and OFF).

  • What does it look like?Light bulb example:

  • Automated Process Example

  • Automated Process Code/* single shot state machine states */#define START_SINGLE_SHOT 0#define BALL_NOT_AT_SENSOR 1#define BALL_AT_SENSOR 2#define END_SINGLE_SHOT 3static u8 singleShotState = END_SINGLE_SHOT;

    // single shot state machineswitch (singleShotState){ case START_SINGLE_SHOT: singleShotTimer = 0; if (upperBallDebounced) { singleShotState = BALL_AT_SENSOR; } else { singleShotState = BALL_NOT_AT_SENSOR; } break;

  • Automated Process Code, cont. case BALL_NOT_AT_SENSOR: chutePWM = CHUTE_FORWARD; if (upperBallDebounced) { singleShotState = BALL_AT_SENSOR; } break; case BALL_AT_SENSOR: chutePWM = CHUTE_FORWARD; if (singleShotTimer > SINGLE_SHOT_TIMER_LIMIT) { singleShotState = END_SINGLE_SHOT; chutePWM = PWM_OFF; } singleShotTimer++; break; case END_SINGLE_SHOT: // this state does nothing break;}// end single shot state machine

  • FilteringSmoothing Your Signals

  • Filter TypesFilters are classified by what they allow to pass through (NOT what they filter out).For example, a low pass filter (abv. LPF) allows low frequencies to pass through it therefore removes high frequencies.The most common filters are: high pass filters, low pass filters, and band pass filters.We will only cover low pass filters.

  • Low Pass FiltersLow Pass Filters (LPFs) are used to smooth out the signal.Common applications:Removing sensor noiseRemoving unwanted signal frequenciesSignal averaging

  • Low Pass Filters, continuedThere are two basic types of filters:Infinite Impulse Response (IIR)Finite Impulse Response (FIR)FIR filters are moving averagesIIR filters act just like electrical resistor-capacitor filters. IIR filters allow the output of the filter to move a fixed fraction of the way toward the input.

  • Moving Average (FIR) Filter Example#define WINDOW_SIZE 16s16 inputArray[WINDOW_SIZE];u8 windowPtr;s32 filter;

    s16 temp;s16 oldestValue = inputArray[windowPtr];

    filter += input - oldestValue;

    inputArray[windowPtr] = input;

    if (++windowPtr >= WINDOW_SIZE){ windowPtr = 0;}

  • Moving Average Filter ConsiderationsFor more filtering effect, use more data points in the average.Since you are adding a lot of numbers, there is a high chance of overflow take precautions

  • IIR Filter Example (Floating Point)#define FILTER_CONST 0.8static float filtOut;static float filtOut_z;float input;

    // filter codefiltOut_z = filtOut;filtOut = input + FILTER_CONST * (filtOut_z input);

    // optimized filter code (filtOut_z not needed)filtOut = input + FILTER_CONST * (filtOut input);

  • IIR Filter Example (Fixed Point)// filter constant will be 0.75. Get this by// (1 2^-2). Remember X * 2^-2 = X >> 2#define FILT_SHIFT 2static s16 filtOut;s16 input;

    // filter codefiltOut += (input - filtOut) >> FILT_SHIFT;

  • IIR Filter Example (Fixed Point)Whoa! How did we get from

    filtOut = input + FILTER_CONST * (filtOut input);

    To

    filtOut += (input - filtOut) >> FILT_SHIFT;

    Math:filtOut = input + (1 - 2^-2) * (filtOut input) = input + filtOut input 2^-2*filtOut + 2^-2*input = filtOut + 2^-2 * (input filtOut)filtOut += (input filtOut) >> 2

  • IIR Filter Considerations (Fixed Point)For more filtering effect, make the shift factor bigger.Take precautions for overflow.You can get more resolution by using more shift factors. For example, have your filter constant be (1 2^-SHIFT1 2^-2SHIFT2)(youll have to work out the math!)

  • OversamplingGain resolution and make your data more reliable.

  • Oversampling BasicsSimple oversampling: sample more data (i.e. faster sample rate) than you need and average the samples.Even if you dont sample faster, averaging (or filtering the data) can be beneficial.

  • Oversampling EffectsHelps to smooth the data.Helps to hide a bad or unreliable sample.Increases A/D resolution if noise is present.

  • Oversampling Effects0.3!!!

  • OptimizationsMake your code run faster.

  • OptimizationsUse fixed point math, not floating point.If possible, do not use data types larger than the microcontrollers native data type.When possible, use bit-shifts instead of multiplying or dividing.WARNING: some micro/compiler combinations do not properly handle signed shifts (the FRC controller is a good example).For high speed interrupts: use as little code as possible; try and move any processing to the slower code outside of the interrupt.Use overflow to your advantage.

  • Example (Using Overflow)Very efficient 8-sample FIR filter: static u8 filtIndex = 0;

    filtOut += (a2dInput - filtArray[(filtIndex & 0x07)]);filtArray[(filtIndex & 0x07)] = a2dInput;filtIndex++;

    Compare the above filter to the FIR filter example given in the Filtering portion of the presentation. Note that it eliminates the need for if statements. The overflow automatically handles wrapping the array index.

    This concept will work as long as the size of the filter is a power of 2.


Recommended