Advanced C Programming - PowerPoint PPT Presentation

About This Presentation
Title:

Advanced C Programming

Description:

BSME University of Michigan, Ann Arbor (1996) Dynamics and Control ... (i.e., if one sample fails, decrement the counter by 1 rather than resetting to zero. ... – PowerPoint PPT presentation

Number of Views:36
Avg rating:3.0/5.0
Slides: 54
Provided by: firs
Learn more at: https://first.wpi.edu
Category:

less

Transcript and Presenter's Notes

Title: Advanced C Programming


1
Advanced C Programming
  • Real Time Programming Like the Pros

2
About Us
  • Chris Hibner
  • BSME University of Michigan, Ann Arbor (1996)
    Dynamics and Control
  • MSME University of Michigan, Ann Arbor (2002)
    Control Systems and Computational Mechanics
  • TRW Automotive Algorithm Development and
    Applications Group, 1996 present.
  • chiefdelphi.com user name Chris Hibner
  • Michael Shaul
  • BSEE Rose-Hulman Institute of Technology (2002)
    Computer Engineering
  • MSEE University of Michigan, Dearborn (2005)
    Control Systems
  • TRW Automotive Product Development Group,
    Software Validation Group, and Core Components
    Group
  • chiefdelphi.com user name Mike Shaul

3
Contents
  • typedefs
  • Fixed-Point Math
  • Overflow Protection
  • Switch Debouncing
  • State Machines
  • Filtering
  • Oversampling

4
Good Coding Practices
  • Signed (good) vs Unsigned (bad) Math
  • for physical calculations
  • Use Braces Always
  • Simple Readable Code
  • Concept of Self Documenting Code
  • Code as if your grandmother is reading it
  • Never use Recursion
  • (watch your stack)
  • Treat Warnings as Errors

Disclaimer Not all code in this presentation
follows these practices due to space
limitations
5
Typedefs
  • Using Naturally Named Data Types

6
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.

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

8
typedef.h Example
  • typedef 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

9
Fixed-Point Math
  • Fractional Numbers Using Integer Data Types

10
Creating Fractions
  • Fractions 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 (ltlt or gtgt).
  • Shifting is multiplying by powers of 2. Ex.
    xltlt5 x25 xgtgt5 x2-5

11
Fixed Point Fraction Example

A/D Sample (10-bit)
Shift left by 6 (i.e. A2D ltlt 6)

Fractional part
Whole part
12
Fractional Example, continued
  • We know 5/2 2.5
  • If 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.

13
Fractional Example, continued
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
5
A/D Sample (10-bit)
Shift left by 6 (i.e. A2D ltlt 6)

0
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0
5.0
Fractional part
Whole part
14
Fractional Example, continued

0
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0
Fractional part
Whole part
Divide by 2 (i.e. A2D / 2)

0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
Fractional part
Whole part
The whole part 0000000010(binary) 2(decimal)
The fractional part 100000(binary) 32
(huh???)
15
Fractional Example, continued
Divide by 2 (i.e. A2D / 2)

0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
Fractional part
Whole part
The fractional part 100000(binary) 32
(huh???) How many different values can the
fractional part be?
Answer we have 6 bits gt 26 values 64 values
(i.e.) 111111 1(binary) 64(decimal)
Therefore Fractional part is actually 32/64 0.5
16
Fractional Example, conclusion
Divide by 2 (i.e. A2D / 2)

0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1
Fractional part
Whole part
  • By using a fixed-point fractional part, we can
    have 5/2 2.5
  • The 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

17
Fractional Example, example
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.
Adding 2.5 2.5

0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1

0
0
0
0
0
0
1
0
0
0
0
0
0
0
0
1


0
0
0
0
0
1
0
1
0
0
0
0
0
0
0
0
Once our math operations are complete, we right
shift our data to regain our original resolution
and data position.
5
0
0
0
0
0
0
0
0
0
0
0
0
1
0
1
0
Without using the fixed point math the result of
the addition would have been 4 due to the
truncation of the integer division.
18
Overflow Protection
  • Making Sure Your Code Is Predictable

19
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!!!)

20
Integer Data Types Valid Ranges
  • u8 0 - 255
  • s8 -128 - 127
  • u16 0 - 65535
  • s16 -32768 - 32767
  • u32 0 - 4.294967295e9
  • s32 -2.147483648e9 - 2.147483647e9
  • Note ranges given are decimal.

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

22
Overflow Protection, Example 1
  • s16 add16(s16 adder1, s16 adder2) // prototype
  • S16 add16(s16 adder1, s16 adder2)
  • s32 temp (s32)adder1 (s32)adder2
  • if (temp gt 32767) // overflow will occur
  • return 32767
  • else if (temp lt -32768) // underflow
  • return -32768
  • else
  • return (s16)temp

This example uses a s32 (larger) data value for
overflow checking
23
Overflow Protection, Example 2
  • // prototype
  • s16 addTo16bit(s16 start, s16 adder)
  • S16 addTo16bit(s16 start, s16 adder)
  • s16 temp start
  • start adder
  • if ((start gt 0) (adder gt 0) (temp lt
    0))
  • return 32767 // Overflow occurred
  • else if ((start lt 0) (adder lt 0) (temp
    gt 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.
24
Overflow Protection, Example 3
  • // prototype
  • u16 addToUnsigned16bit(u16 start, s16 adder)
  • S16 addToUnsigned16bit(u16 start, s16 adder)
  • u16 temp start
  • start adder
  • if ((adder gt 0) (start lt temp))
  • return 65536 // Overflow occurred
  • else if ((adder lt 0) (start gt temp))
  • return 0 // underflow occurred
  • else
  • return start

This example checks for overflow on unsigned
values
25
Switch Debouncing
  • Having Confidence in Switch Inputs

26
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.

27
When to Debounce Examples
  • Debounce 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 reached
  • Do not debounce if constant driver input is
    needed.

28
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.

29
Debounce Example
  • // debounce opening gripper
  • if (!pneumaticGripperOpenState)
  • if (gripperOpenSwitch ON)
  • gripperOpenDebCount
  • else
  • gripperOpenDebCount 0
  • if (gripperOpenDebCount gt
    DEBOUNCE_LIMIT)
  • gripperOpenDebCount 0
  • pneumaticGripperOpenState TRUE

30
State Machines
  • Systematic Approach to Complicated Logic

31
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.

32
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).

33
What does it look like?
  • Light bulb example

34
Automated Process Example
35
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 3
  • static u8 singleShotState END_SINGLE_SHOT
  • // single shot state machine
  • switch (singleShotState)
  • case START_SINGLE_SHOT
  • singleShotTimer 0
  • if (upperBallDebounced)
  • singleShotState BALL_AT_SENSOR
  • else
  • singleShotState BALL_NOT_AT_SENSOR

36
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 gt SINGLE_SHOT_TIMER_LI
    MIT)
  • singleShotState END_SINGLE_SHOT
  • chutePWM PWM_OFF
  • singleShotTimer
  • break
  • case END_SINGLE_SHOT
  • // this state does nothing
  • break

37
Filtering
  • Smoothing Your Signals

38
Filter Types
  • Filters 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.

39
Low Pass Filters
  • Low Pass Filters (LPFs) are used to smooth out
    the signal.
  • Common applications
  • Removing sensor noise
  • Removing unwanted signal frequencies
  • Signal averaging

40
Low Pass Filters, continued
  • There are two basic types of filters
  • Infinite Impulse Response (IIR)
  • Finite Impulse Response (FIR)
  • FIR filters are moving averages
  • IIR 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.

41
Moving Average (FIR) Filter Example
  • define WINDOW_SIZE 16
  • s16 inputArrayWINDOW_SIZE
  • u8 windowPtr
  • s32 filter
  • s16 temp
  • s16 oldestValue inputArraywindowPtr
  • filter input - oldestValue
  • inputArraywindowPtr input
  • if (windowPtr gt WINDOW_SIZE)
  • windowPtr 0

42
Moving Average Filter Considerations
  • For 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

43
IIR Filter Example (Floating Point)
  • define FILTER_CONST 0.8
  • static float filtOut
  • static float filtOut_z
  • float input
  • // filter code
  • filtOut_z filtOut
  • filtOut input FILTER_CONST (filtOut_z
    input)
  • // optimized filter code (filtOut_z not needed)
  • filtOut input FILTER_CONST (filtOut
    input)

44
IIR Filter Example (Fixed Point)
  • // filter constant will be 0.75. Get this by
  • // (1 2-2). Remember X 2-2 X gtgt 2
  • define FILT_SHIFT 2
  • static s16 filtOut
  • s16 input
  • // filter code
  • filtOut (input - filtOut) gtgt FILT_SHIFT

45
IIR Filter Example (Fixed Point)
  • Whoa! How did we get from
  • filtOut input FILTER_CONST (filtOut
    input)
  • To
  • filtOut (input - filtOut) gtgt FILT_SHIFT
  • Math
  • filtOut input (1 - 2-2) (filtOut input)
  • input filtOut input
    2-2filtOut 2-2input
  • filtOut 2-2 (input filtOut)
  • filtOut (input filtOut) gtgt 2

46
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!)

47
Oversampling
  • Gain resolution and make your data more reliable.

48
Oversampling Basics
  • Simple 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.

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

50
Oversampling Effects
0.3!!!
51
Optimizations
  • Make your code run faster.

52
Optimizations
  • Use 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.

53
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.
Write a Comment
User Comments (0)
About PowerShow.com